Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added test coverage for text, tuples, numeric, OpSparkListener #53

Merged
merged 3 commits into from
Aug 15, 2018
Merged

Added test coverage for text, tuples, numeric, OpSparkListener #53

merged 3 commits into from
Aug 15, 2018

Conversation

ajayborra
Copy link
Contributor

  • Added test coverage for text, tuples, numeric, OpSparkListener classes

@codecov
Copy link

codecov bot commented Aug 14, 2018

Codecov Report

Merging #53 into master will increase coverage by 0.88%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #53      +/-   ##
==========================================
+ Coverage   84.79%   85.67%   +0.88%     
==========================================
  Files         298      298              
  Lines        9753     9753              
  Branches      329      540     +211     
==========================================
+ Hits         8270     8356      +86     
+ Misses       1483     1397      -86
Impacted Files Coverage Δ
...es/src/main/scala/com/salesforce/op/OpParams.scala 85.41% <0%> (-4.17%) ⬇️
...a/com/salesforce/op/utils/date/DateTimeUtils.scala 100% <0%> (+4.34%) ⬆️
...om/salesforce/op/utils/spark/OpSparkListener.scala 92.2% <0%> (+92.2%) ⬆️
...scala/com/salesforce/op/utils/numeric/Number.scala 100% <0%> (+100%) ⬆️
...ala/com/salesforce/op/utils/tuples/RichTuple.scala 100% <0%> (+100%) ⬆️
...scala/com/salesforce/op/utils/text/TextUtils.scala 100% <0%> (+100%) ⬆️
.../com/salesforce/op/utils/version/VersionInfo.scala 100% <0%> (+100%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d6fe1c3...2dcd58a. Read the comment docs.

Copy link
Collaborator

@tovbinm tovbinm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None, None case is missing

import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class NumberTest extends FlatSpec with TestCommon {
Copy link
Collaborator

@tovbinm tovbinm Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try using PropSpec. This is a classical example for property testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. But, Since we are already taking in a Double as a parameter here, Which already established the properties of the parameter are numerics. Seems like we are merely providing an API to validate if it is valid Number by checking for NaN (or) Infinity.

Tying to understand the ask here, Seems like the idea here is to restrict the Number type to have 2 more properties

  1. Number type should never be a NaN.
  2. Number type should never be Infinity.
    Does that not require isValid to be implicitly called during type checking at compile time?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Number.isValud check is there to prevent invalid / unexpected computation results between numeric feature values at runtime. Property based test can be as simple as this:

@RunWith(classOf[JUnitRunner])
class NumberTest extends PropSpec {
  property("validate numbers") should {
    forAll(d: Double) { d => Number.isValid(d) shouldBe (!d.isNaN || !d.isInfinity) }
  }
}

@RunWith(classOf[JUnitRunner])
class OpSparkListenerTest extends FlatSpec with TestSparkContext {
val listener = new OpSparkListener(sc.appName, sc.applicationId, "testRun", Some("tag"), Some("tagValue"), true, true)
sc.addSparkListener(listener)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: can we somehow assert logs? Perhaps set a special log appender programmatically that would collect log messages. Do you its doable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we have a way to extract event log from EventLoggingListener  will check that and get back.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if it's doable in the scope if the test. I think that would be a great check as well: collect log messages and assert them at the end.

Copy link
Contributor Author

@ajayborra ajayborra Aug 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spent some time evaluating options around this and following are the observations.

  • EventLoggingListener is private to spark package and doesn't seem to expose any API to read the events.
  • Since we are planning to assert based on the logs, Log appender looks to be the best approach here and it would be convenient if we can expose an InMemory log appender util for testing in general across the modules. Log4j doesn't provide this out of the box, We have to implement one similar to this example MemoryAppender

Once we have the above appender available, We can register it with spark context and start using it for assertions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MemoryAppender can be good. We can define one in tests, collect log lines, then assert the results. Lets do it in a separate PR.

}

it should "not support mapping for more than 2 arguments" in {
assertDoesNotCompile("(Some(1), Some(2), Some(3)).map((x, y) => x + y)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an extension for a Tuple2 so it's implied. I think you can remove this test case.

Copy link
Collaborator

@tovbinm tovbinm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff. See comments.

@tovbinm
Copy link
Collaborator

tovbinm commented Aug 15, 2018

I will merge this one for now. Look some minor corrections in a separate PR. @ajayborra

Copy link
Collaborator

@tovbinm tovbinm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@tovbinm tovbinm merged commit 4ab7c7b into salesforce:master Aug 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants