Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Enabling writing and running of tests with scalatest. #789
Conversation
codecov-io
commented
Jan 21, 2017
•
Codecov Report
@@ Coverage Diff @@
## master #789 +/- ##
===============================================
- Coverage 64.882% 64.844% -0.038%
+ Complexity 7198 7191 -7
===============================================
Files 527 527
Lines 31781 31781
Branches 5424 5424
===============================================
- Hits 20620 20608 -12
- Misses 9016 9035 +19
+ Partials 2145 2138 -7
|
tfenne
referenced
this pull request
Jan 21, 2017
Open
Thoughts on using scala for writing tests in htsjdk? #781
tfenne
changed the title from
WIP/Experimental: Enabling writing and running of tests with scalatest. to Enabling writing and running of tests with scalatest.
Jan 22, 2017
|
@lbergelson Would you be up for taking a look at this PR? Particularly with an eye towards the changes I've made in the gradle build? I'm not a gradle expert, and there may be better ways to do what I did, but I believe it is working now (with SRA tests being skipped locally and run on travis). |
tfenne
requested review from nh13, yfarjoun, and lbergelson
Jan 22, 2017
tfenne
referenced
this pull request
in maiflai/gradle-scalatest
Jan 22, 2017
Closed
Plugin causes double-addition of jacoco agent to test command line #44
| @@ -5,7 +5,7 @@ | ||
| import java.io.IOException; | ||
| -public class AbstractBAMFileIndexTest { | ||
| +public class AbstractBAMFileIndexTest extends org.scalatest.testng.TestNGSuite { |
| +import org.scalatest.{FlatSpec, Matchers} | ||
| + | ||
| +/** Base class for all Scala tests. */ | ||
| +class UnitSpec extends FlatSpec with Matchers |
yfarjoun
Jan 23, 2017
Contributor
why "UnitSpec"? if the java class is HtsjdkTest, shouldn't the scala version be close to that? perhaps HtsjdkScalaTest? Or at least HtsjdkSpec...
tfenne
Jan 25, 2017
Owner
The idea is that scalatest offers different styles of test writing, and one might choose to use one style for unit testing, and a different one for integration or larger functional testing. So the convention is to name the base class by the type of test it is intended for, in this case unit testing.
yfarjoun
Jan 25, 2017
Contributor
I see. OK. thanks. I was confused since you used Htsjdk in the baseclass of the java tests
| + StringUtil.hammingDistance("", "") shouldBe 0 | ||
| + } | ||
| + | ||
| + Seq(("ATAC", "GCAT", 3), ("ATAGC", "ATAGC", 0)).foreach { case (s1, s2, distance) => |
yfarjoun
Jan 23, 2017
Contributor
should we request a default case here to assure that this isn't a silent failure? (I mean from a stylistic point of view..)
tfenne
Jan 25, 2017
Owner
No. This is an example of a partial function (not to be confused with a partially applied function) in scala. It's the easiest/clearest way to do tuple-decomposition as part of an anonymous function invocation.
Also, it will fail if handed something it can't match and we can also see all the inputs to the left and see that they are three-tuples.
| + } | ||
| + | ||
| + Seq(("ATAC", "GCAT", 3), ("ATAGC", "ATAGC", 0)).foreach { case (s1, s2, distance) => | ||
| + it should s"return distance ${0} between $s1 and $s2" in { |
yfarjoun
Jan 23, 2017
Contributor
also, why did you switch the order between the data and the test? everywhere else it's "test" in "data and here it's data => test.... I don't mind...I just want to understand if it matters...
tfenne
Jan 25, 2017
Owner
The ${0} is a mistake - should be ${distance}.
I'm not sure I understand your second comment.
| +import htsjdk.UnitSpec | ||
| + | ||
| +class StringUtilTest extends UnitSpec { | ||
| + "StringUtil.split" should "should behave like String.split(char)" in { |
yfarjoun
Jan 23, 2017
Contributor
This seems to be a place where the reverse order makes more sence, since you are using the same data for two tests...wouldn't it make better sense to have
data.foreach(s=> test1; test2) ?
| + | ||
| + "StringUtil.isWithinHammingDistance" should "agree with StringUtil.hammingDistance" in { | ||
| + Seq(("ATAC", "GCAT", 3), ("ATAC", "GCAT", 2), ("ATAC", "GCAT", 1), ("ATAC", "GCAT", 0)).foreach { case (s1, s2, within) => | ||
| + StringUtil.isWithinHammingDistance(s1, s2, within) shouldBe (StringUtil.hammingDistance(s1, s2) <= within) |
tfenne
Jan 25, 2017
Owner
Same as above - it's normal not to have default cases in situations like this.
| + } | ||
| + | ||
| + "StringUtil.intValuesToString(int[])" should "generate a CSV string of ints" in { | ||
| + val ints = Array[Int](1,2,3,11,22,33,Int.MinValue, 0, Int.MaxValue) |
| @@ -0,0 +1,111 @@ | ||
| +package htsjdk.samtools.util |
yfarjoun
Jan 23, 2017
Contributor
the original has a license...can we leave it on? (I know that many tests do not have license...)
|
After all the discussion about how much better scala for writing tests, I was surprised that the tests didn't become much shorter...but the length of the code isn't the only factor. I think that this satisfies most (if not all) the requirements of the issue. but I think it would be good to finish that conversation in the issue and not here. Once the small issues I raise here are dealt with, I'm fine with this PR, assuming that we are OK about scala for tests in htsjdk....but would need others to chime in.. I did NOT look at the specifics of the build system (gradle, jacoco, codecov, etc.) |
|
Thanks. this answers my issues. @lbergelson can you take a look at the changes to the build system? |
|
Thanks for the review @yfarjoun; I've pushed up some changes. I'd like to address your comment re: length of the tests. Maybe I shot myself in the foot there by adding a whole bunch more tests? Looking at the old vs. new I think that a fair count would put the equivalent set of tests (from class declaration through to the last ported test) at ~90 lines for Java and ~54 for Scala. So that's about 40% fewer lines of code, which is non-trivial. I think what's important though is how easy it is to a) write the tests, b) understand them again quickly at a later date, c) add one more similar test case. I might also add d) how good the reporting is when a failure occurs. I find the scalatest version easier to read overall, and much easier to divine the intent of. I've never been a big fan of the TestNG style of separating |
|
@tfenne Thanks for pointing out the addition of new tests. I didn't see that originally. I agree regarding readability, though I looked at the options for Matchers and was a little horrified at the differences between:
Not that it isn't good to have all these matchers, but rather that it will be more difficult to write correct tests and review them. |
yfarjoun
closed this
Jan 25, 2017
yfarjoun
reopened this
Jan 25, 2017
| + println "Excluding SRA Tests." | ||
| + } | ||
| + | ||
| + tags { |
lbergelson
Jan 25, 2017
Contributor
I didn't know about this tags syntax, that's much better than the if-else chain
| @@ -41,6 +38,9 @@ dependencies { | ||
| compile "org.tukaani:xz:1.5" | ||
| compile "gov.nih.nlm.ncbi:ngs-java:1.2.4" | ||
| + testCompile "org.scala-lang:scala-library:2.12.1" | ||
| + testCompile "org.scalatest:scalatest_2.12:3.0.1" | ||
| + testRuntime 'org.pegdown:pegdown:1.4.2' |
tfenne
Feb 10, 2017
Owner
Will do. FYI it's used to generate the pretty HTML reports from scalatest.
| // set heap size for the test JVM(s) | ||
| minHeapSize = "1G" | ||
| maxHeapSize = "2G" | ||
| jvmArgs '-Djava.awt.headless=true' //this prevents awt from displaying a java icon while the tests are running | ||
| - if (System.env.CI == "true") { //if running under a CI output less into the logs |
lbergelson
Feb 7, 2017
Contributor
We added this toggle here because the test output was growing so large that travis was failing.
It seems like travis is passing with this now, so they may have increased their log file size limit, or the new output is less verbose than it was. However, I think it's still valuable to have the cleaner output format on travis that only displays some progress indicator + failed/skipped tests. It makes it much easier to diagnose what went wrong at a glance.
tfenne
Feb 10, 2017
Owner
I don't disagree @lbergelson, though I've just spent the last two hours trying to make this work and am running out of ideas. It seems like the combination of gradle + scalatest + TestNG make this rather hard to figure out. The code that was in the build file previously doesn't seem to suppress much of anything (I changed the test to if (true) to test locally).
How critical do you think this is?
lbergelson
Feb 13, 2017
Contributor
It's only critical if it starts killing travis runs again due to the verbosity. If it's a horrible pain to figure out (which I certainly imagine it could be... I'm not even sure what's generating test output now, is it scalatest, testNG being invoked by scalatest?) then I'd say it's fine as is. Thanks for looking into it. If it really becomes problematic on travis we can pipe the test output into dev/null or grep fail or something like that.
|
@tfenne I had a few minor comments about the build. I think it would be useful to maintain the minimal test output on travis due to the potential for long test output to a) kill jobs and b) be annoying to read. |
|
Ok, why don't I wait until the next release is cut, then rebase and merge this PR. If we run into problems with travis I'm sure we can find a not-so-elegant way to cut the verbosity of the tests. |
|
We just released a version. Feel free to rebase. we would also appreciate a first draft of guidelines as to what is an acceptable style of scala tests to use. Perhaps in a wiki page? |
yfarjoun
added the
Review-party candidate
label
Feb 21, 2017
|
@yfarjoun I've just rebased and squashed. Apologies for taking so long on that. I'd like to get this merged if at all possible. I'm still happy to write the wiki page, but I've sort of forgotten what it was supposed to address ;) Obviously some examples, anything else? |
tfenne
referenced
this pull request
Apr 14, 2017
Closed
Expose a couple of protected methods and replace hard coded strings w… #853
|
Regarding the wiki-page, some examples would be good as well as an explanation of the different kinds of comparisons that can be done (shouldBe vs should equal vs. ???) The page would also lay out what is reasonable scala to use and what is out of scope. We would like to avoid having Haskel-like scala, and stick to java-like scala, so that fluency in scala is not a requirement for adding tests. |
|
@yfarjoun I've started a wiki page here: https://github.com/samtools/htsjdk/wiki/Writing-tests-in-HTSJDK . Please feel free to both edit it yourself, and suggest additions. It's a little hard for me having been working so much in scala over the last couple of years to think about what features are more or less readable to Java developers etc. I'm going to click merge now! |
tfenne
merged commit 656dc24
into
master
Apr 15, 2017
3 of 5 checks passed
tfenne
deleted the
tf_scala_testing branch
Apr 15, 2017
|
looks good thanks!
…
|
|
@tfenne I tried (and failed) to run the tests from within intelliJ. Are there special settings that need to be set? could you clarify what they would be? |
|
The only things I had to do were:
If that doesn't work, can you see what version of IntelliJ and the Scala plugin you're using? |
|
Thanks. it was the 2.12.x scala version (I had 2.10) |
tfenne commentedJan 20, 2017
•
edited
Description
An experimental branch that enables writing and running of tests using scala test, in both Java and Scala. Making a PR so that I can test CI builds and code coverage.
Checklist