How to resolve "Ambiguous reference to a JS library"? - scala.js

I'm struggling resolving some Javascript library dependency clashes in the following build.sbt file:
lazy val root = project.in(file(".")).enablePlugins(ScalaJSPlugin)
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-java-time" % "0.1.0",
"org.querki" %%% "jquery-facade" % "0.10"
)
jsDependencies ++= Seq(
"org.webjars.bower" % "jquery" % "3.0.0-beta1" / "jquery.js"
)
When running the fastOptJS task I'm getting the following error message:
[trace] Stack trace suppressed: run last compile:resolvedJSDependencies for the full output.
[error] (compile:resolvedJSDependencies) org.scalajs.core.tools.jsdep.JSLibResolveException: Some references to JS libraries could not be resolved:
[error] - Ambiguous reference to a JS library: jquery.min.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/dist/jquery.min.js
[error] - META-INF/resources/webjars/jquery/2.1.4/jquery.min.js
[error] originating from: root:compile
[error] - Ambiguous reference to a JS library: jquery.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/src/jquery.js
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/dist/jquery.js
[error] - META-INF/resources/webjars/jquery/2.1.4/jquery.js
[error] originating from: root:compile, root:compile
[error] Total time: 1 s, completed Mar 2, 2016 12:36:43 PM */
How can I resolve the ambiguous references to Javascript libraries in this case?

Based on this Github issue, I learned that it is possible to specify a qualifying path to disambiguate references to Javascript libraries.
Let's try to disambiguate the jquery.js reference by adding the path dist.
jsDependencies ++= Seq(
"org.webjars.bower" % "jquery" % "3.0.0-beta1" / "dist/jquery.js"
)
But running fastOptJS again returns the same error
[error] - Ambiguous reference to a JS library: jquery.min.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/dist/jquery.min.js
[error] - META-INF/resources/webjars/jquery/2.1.4/jquery.min.js
[error] originating from: root:compile
[error] - Ambiguous reference to a JS library: jquery.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/src/jquery.js
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/dist/jquery.js
[error] - META-INF/resources/webjars/jquery/2.1.4/jquery.js
[error] originating from: root:compile
[error] Total time: 2 s, completed Mar 2, 2016 7:29:08 PM
This problem is actually created by the libraryDependencies entry "org.querki" %%% "jquery-facade" % "0.10". Using the dependency graph SBT plugin we see the full dependency graph:
[info] root:root_sjs0.6_2.11:0.1-SNAPSHOT [S]
[info] +-org.querki:jquery-facade_sjs0.6_2.11:0.10 [S]
[info] | +-org.querki:querki-jsext_sjs0.6_2.11:0.6 [S]
[info] | | +-org.scala-js:scalajs-library_2.11:0.6.5 (evicted by: 0.6.7)
[info] | | +-org.scala-js:scalajs-library_2.11:0.6.7 [S]
[info] | |
[info] | +-org.scala-js:scalajs-dom_sjs0.6_2.11:0.8.0 [S]
[info] | | +-org.scala-js:scalajs-library_2.11:0.6.0 (evicted by: 0.6.7)
[info] | | +-org.scala-js:scalajs-library_2.11:0.6.5 (evicted by: 0.6.7)
[info] | | +-org.scala-js:scalajs-library_2.11:0.6.7 [S]
[info] | |
[info] | +-org.scala-js:scalajs-library_2.11:0.6.5 (evicted by: 0.6.7)
[info] | +-org.scala-js:scalajs-library_2.11:0.6.7 [S]
[info] | +-org.webjars:jquery:2.1.4
[info] |
[info] +-org.scala-js:scalajs-java-time_sjs0.6_2.11:0.1.0 [S]
[info] | +-org.scala-js:scalajs-library_2.11:0.6.6 (evicted by: 0.6.7)
[info] | +-org.scala-js:scalajs-library_2.11:0.6.7 [S]
[info] |
[info] +-org.scala-js:scalajs-library_2.11:0.6.6 (evicted by: 0.6.7)
[info] +-org.scala-js:scalajs-library_2.11:0.6.7 [S]
[info] +-org.webjars.bower:jquery:3.0.0-beta1
The output shows org.querki:jquery-facade_sjs0.6_2.11:0.10 to depend on org.webjars:jquery:2.1.4. This explains the Ambiguous reference to a JS library error message above because we still have two jquery library versions available in the listed dependencies.
What we can try next is use exclude on the library dependency.
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-java-time" % "0.1.0",
"org.querki" %%% "jquery-facade" % "0.10" exclude("org.webjars","jquery")
)
Running the fastOptJS task now returns
[error] (compile:resolvedJSDependencies) org.scalajs.core.tools.jsdep.JSLibResolveException: Some references to JS libraries could not be resolved:
[error] - Ambiguous reference to a JS library: jquery.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/src/jquery.js
[error] - META-INF/resources/webjars/jquery/3.0.0-beta1/dist/jquery.js
[error] originating from: root:compile
[error] Total time: 2 s, completed Mar 2, 2016 7:47:14 PM
So although we got rid of some errors, we are not quite there yet. I'm not 100% sure here, but it seems this error is a result in how the build.sbt of the jQuery Facade includes jQuery using jsDependencies itself:
jsDependencies += "org.webjars" % "jquery" % "2.1.4" / "jquery.js" minified "jquery.min.js"
So it seems we ran into the same problem we had at the start. A unqualified jquery.js (i.e. without a preceding path) cannot not be resolved unambiguously.
To solve this problem we can use to the jsManifestFilter setting. I found this tip in the Scala.js Gitter room.
jsManifestFilter := {
import org.scalajs.core.tools.jsdep.{JSDependencyManifest, JSDependency}
(seq: Traversable[JSDependencyManifest]) => {
seq map { manifest =>
def isOkToInclude(jsDep: JSDependency): Boolean = {
println(s"jsDep=>$jsDep")
jsDep.resourceName != "jquery.js"
}
new JSDependencyManifest(
origin = manifest.origin,
libDeps = manifest.libDeps filter isOkToInclude,
requiresDOM = manifest.requiresDOM,
compliantSemantics = manifest.compliantSemantics
)
}
}
}
Here we overwrite the jsManitestFilter setting and explicitly filter out the naked jquery.js dependency. The fastOptJS task runs fine now:
[info] Resolving org.eclipse.jetty#jetty-continuation;8.1.16.v20140903 ...
[info] Done updating.
jsDep=>JSDependency(resourceName=dist/jquery.js)
jsDep=>JSDependency(resourceName=jquery.js, minifiedResourceName=Some(jquery.min.js))
[info] Fast optimizing jsdeps/target/scala-2.11/root-fastopt.js
[success] Total time: 3 s, completed Mar 2, 2016 8:27:40 PM
Note that the added println statement also outputs the resourceName for the included dependencies.

Related

Why won't sbt run ScalaTest's example test?

Please assume the normal "newbie" appologies.
I'm using scala 2.12.10; In build.sbt I added ScalaTest:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
I'm adding some scala.js to an existing java project so my scala source paths are normal but I made some empty directories for java and resources and use a different target so there would be no collision with existing code:
javaSource in Compile := baseDirectory.value / "src/main/scalajs_java"
javaSource in Test := baseDirectory.value / "src/test/scalajs_java"
resourceDirectory in Compile := baseDirectory.value / "src/main/scalajs_resources"
resourceDirectory in Test := baseDirectory.value / "src/test/scalajs_resources"
target := baseDirectory.value / "scalajs_target"
I put the ScalaTest example file ExampleSpec.scala in src/test/scala/ExampleSpec.scala. The example ran fine using org.scalatest.run as described in http://www.scalatest.org/.
The test classpath looks reasonable, I thought:
sbt:RedsPro-ScalaJS> show test:fullClasspath
[info] * Attributed(/Users/tballard/git/redspro/reds/scalajs_target/scala-2.12/test-classes)
[info] * Attributed(/Users/tballard/git/redspro/reds/scalajs_target/scala-2.12/classes)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.10.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-js/scalajs-library_2.12/jars/scalajs-library_2.12-0.6.31.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-js/scalajs-dom_sjs0.6_2.12/jars/scalajs-dom_sjs0.6_2.12-0.9.7.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-js/scalajs-test-bridge_2.12/jars/scalajs-test-bridge_2.12-0.6.31.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-js/scalajs-test-interface_2.12/jars/scalajs-test-interface_2.12-0.6.31.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.8.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.8.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.10.jar)
[info] * Attributed(/Users/tballard/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.2.0.jar)
After compiling, the test is where I would expect it:
> ls scalajs_target/scala-2.12/test-classes/
ExampleSpec.class ExampleSpec.sjsir JS_DEPENDENCIES org/
However, sbt apparently isn't convinced there are any tests:
sbt:RedsPro-ScalaJS> show definedTestNames
[info] *
[success] Total time: 1 s, completed Dec 1, 2019, 11:37:51 AM
sbt:RedsPro-ScalaJS> testOnly ExampleSpec
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for Test / testOnly
[success] Total time: 1 s, completed Dec 1, 2019, 12:44:35 PM
A point in the right direction would be greatly appreciated.
You need to use %%% instead of %% when depending on ScalaTest. In general, you always need to use %%% in Scala.js.

Creating File using `resourceGenerators`

Given:
$cat build.sbt
scalaVersion := "2.12.1"
resourceGenerators in Compile += Def.task {
val file = (resourceManaged in Compile).value / "demo" / "myapp.properties"
val contents = "name=%s\nversion=%s".format(name.value,version.value)
IO.write(file, contents)
Seq(file)
}.taskValue
$sbt compile
[info] Set current project to sbt_testing (in build file:/home/kmeredith/src/sbt_testing/)
[info] Updating {file:/home/kmeredith/src/sbt_testing/}sbt_testing...
[info] Resolving jline#jline;2.14.1 ...
[info] Done updating.
[success] Total time: 1 s, completed Dec 23, 2016 9:14:50 AM
My understanding is that a myapp.properties file should been created during the compile task.
But, I saw no such file created:
$find . -name *.properties
./target/resolution-cache/default/sbt_testing_2.12/0.1-SNAPSHOT/resolved.xml.properties
Please explain to me how to generate the myapp.properties.
You have the wrong expectation regarding the triggering of the resource generation - running compile does not trigger it (compiles existing sources but not generated ones!), but if you execute test or run, it will be generated:
$sbt clean compile
[success] Total time: 0 s, completed Dec 23, 2016 5:39:28 PM
[info] Updating {file:/home/tzachz/dev/sbt_testing/}sbt_testing...
[info] Done updating.
[info] Compiling 25 Scala sources to /home/tzachz/dev/sbt_testing/target/scala-2.11/classes...
[success] Total time: 24 s, completed Dec 23, 2016 5:39:52 PM
$find . -name "*.properties"
zsh: no matches found: *.properties
$sbt run
// ...
$find . -name "*.properties"
./target/scala-2.11/resource_managed/main/demo/myapp.properties
./target/scala-2.11/classes/demo/myapp.properties

Cannot get uTest to see my tests

I'm trying to get uTest to work with ScalaJS and SBT. SBT is compiling the files, and uTest is running, but it simply ignores my tests. Try as I might I cannot find any difference between my code and the tutorial examples.
build.sbt:
enablePlugins(ScalaJSPlugin)
name := "Scala.js Stuff"
scalaVersion := "2.11.5" // or any other Scala version >= 2.10.2
scalaJSStage in Global := FastOptStage
libraryDependencies += "com.lihaoyi" %% "utest" % "0.3.0"
testFrameworks += new TestFramework("utest.runner.Framework")
src/test/scala/com/mysite/jovian/GeometryTest.scala:
package com.mysite.jovian
import utest._
object GeometryTest extends TestSuite {
def tests = TestSuite {
'addPoints {
val p: Point = new Point(3,4)
val q: Point = new Point(4,3)
val expected: Point = new Point(8,8)
assert(p.plus(q).equals(expected))
throw new Exception("foo")
}
'fail {
assert(1==2)
}
}
}
Output:
> reload
[info] Loading project definition from /Users/me/Dropbox (Personal)/mysite/flocks/project
[info] Set current project to Scala.js Stuff (in build file:/Users/me/Dropbox%20(Personal)/mysite/flocks/)
> test
[success] Total time: 1 s, completed Mar 6, 2015 7:01:41 AM
> test-only -- com.mysite.jovian.GeometryTest
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:testOnly
[success] Total time: 1 s, completed Mar 6, 2015 7:01:49 AM
If I introduce a syntax error, sbt test does see it:
> test
[info] Compiling 1 Scala source to /Users/me/Dropbox (Personal)/mysite/flocks/target/scala-2.11/test-classes...
[error] /Users/me/Dropbox (Personal)/mysite/flocks/src/test/scala/com/mysite/jovian/GeometryTest.scala:21: not found: value blablablablabla
[error] blablablablabla
[error] ^
[error] one error found
[error] (test:compile) Compilation failed
[error] Total time: 1 s, completed Mar 6, 2015 7:03:54 AM
So it's definitely seeing the code, it just doesn't seem to think that "tests" contains any tests.
Otherwise, in the non-test code, SBT+ScalaJS seems to be working fine...
Thanks for any help, I am mystified.
Your mistake lies in the dependency on uTest:
libraryDependencies += "com.lihaoyi" %% "utest" % "0.3.0"
This is a JVM dependency. To use the Scala.js-enabled dependency, use %%% instead of %%, like this:
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0"
Additionally, you probably want this dependency only in the Test configuration, so add % "test" a the end:
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"

How to display entire stack trace for thrown exceptions from ScalaCheck tests?

I'm running ScalaCheck tests in sbt, and if my test fails because the code under test throws an exception, the test report shows the failed test, the thrown exception and the message, but not the entire stack trace (note the mere Exception: java.lang.NullPointerException: exception exception message below).
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to scalacheck (in build file:/Users/jacek/sandbox/scalacheck/)
[info] Updating {file:/Users/jacek/sandbox/scalacheck/}scalacheck...
[info] Resolving jline#jline;2.11 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/scalacheck/target/scala-2.11/test-classes...
[info] ! String.throw exception: Exception raised on property evaluation.
[info] > ARG_0: ""
[info] > Exception: java.lang.NullPointerException: exception
[error] Error: Total 1, Failed 0, Errors 1, Passed 0
[error] Error during tests:
[error] StringSpecification
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 5 s, completed Jun 25, 2014 3:25:47 AM
I found https://groups.google.com/forum/#!msg/scalacheck/AGBgE_JlqpI/B2eSG84_QzYJ from 2008 which seems to report the same issue, and indicates it should be fixed in the next release. I'm currently using the latest release 1.11.4.
I also found http://www.scala-sbt.org/release/docs/Testing.html which indicates sbt has a testOptions key which I suppose seems reasonable to use, and I know ScalaTest has a setting for full stack traces, "-F", but that doesn't work for ScalaCheck. Even the example from the above page, testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-d", "-g") gives me an error:
[error] Could not run test org.example.myproject.MyTestClass: java.lang.Exception: [1.1] failure: option name expected
[error]
[error] -d -g
[error] ^
How do I use these test arguments, is there a list of these arguments anywhere, and finally, is it possible to get a stacktrace out of it all, or am I chasing a red herring?
tl;dr There's no support for verbosity under sbt with the released version of ScalaCheck. You'd have to build a version from the sources yourself to have the feature.
The available options for ScalaCheck are described in Test Execution:
Available options:
-workers, -w: Number of threads to execute in parallel for testing
-minSize, -n: Minimum data generation size
-verbosity, -v: Verbosity level
-minSuccessfulTests, -s: Number of tests that must succeed in order to pass a property
-maxDiscardRatio, -r: The maximum ratio between discarded and succeeded tests allowed before ScalaCheck stops testing a property. At least minSuccessfulTests will always be tested, though.
-maxSize, -x: Maximum data generation size
The source code of org.scalacheck.util.Pretty tells us more about the different levels of vebosity:
implicit def prettyThrowable(e: Throwable) = Pretty { prms =>
val strs = e.getStackTrace.map { st =>
import st._
getClassName+"."+getMethodName + "("+getFileName+":"+getLineNumber+")"
}
val strs2 =
if(prms.verbosity <= 0) Array[String]()
else if(prms.verbosity <= 1) strs.take(5)
else strs
e.getClass.getName + ": " + e.getMessage / strs2.mkString("\n")
}
So, 0 gives nothing, 1 takes 5 lines out of a stack trace, whereas a number greater than 1 gives you the entire stack trace as follows:
➜ scalacheck scala -cp .:/Users/jacek/.ivy2/cache/org.scalacheck/scalacheck_2.11/jars/scalacheck_2.11-1.11.4.jar StringSpecification -verbosity 3
+ String.startsWith: OK, passed 100 tests.
Elapsed time: 0.242 sec
! String.concatenate: Falsified after 0 passed tests.
> ARG_0: ""
> ARG_1: ""
Elapsed time: 0.003 sec
+ String.substring: OK, passed 100 tests.
Elapsed time: 0.126 sec
! String.throw exception: Exception raised on property evaluation.
> ARG_0: ""
> Exception: java.lang.NullPointerException: exception
StringSpecification$$anonfun$14.apply(StringSpecification.scala:19)
StringSpecification$$anonfun$14.apply(StringSpecification.scala:18)
scala.Function1$$anonfun$andThen$1.apply(Function1.scala:55)
org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$3.apply(Prop.scala:622
)
org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$3.apply(Prop.scala:622
)
org.scalacheck.Prop$.secure(Prop.scala:473)
org.scalacheck.Prop$$anonfun$forAllShrink$1.org$scalacheck$Prop$$anonfun$$r
esult$1(Prop.scala:622)
org.scalacheck.Prop$$anonfun$forAllShrink$1.apply(Prop.scala:659)
org.scalacheck.Prop$$anonfun$forAllShrink$1.apply(Prop.scala:616)
org.scalacheck.Prop$$anon$1.apply(Prop.scala:309)
org.scalacheck.Test$.org$scalacheck$Test$$workerFun$1(Test.scala:335)
org.scalacheck.Test$$anonfun$org$scalacheck$Test$$worker$1$1.apply(Test.sca
la:316)
org.scalacheck.Test$$anonfun$org$scalacheck$Test$$worker$1$1.apply(Test.sca
la:316)
org.scalacheck.Test$.check(Test.scala:385)
org.scalacheck.Test$$anonfun$checkProperties$1.apply(Test.scala:402)
org.scalacheck.Test$$anonfun$checkProperties$1.apply(Test.scala:395)
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala
:245)
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala
:245)
scala.collection.immutable.List.foreach(List.scala:383)
scala.collection.generic.TraversableForwarder$class.foreach(TraversableForw
arder.scala:35)
scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:45)
scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
scala.collection.AbstractTraversable.map(Traversable.scala:104)
org.scalacheck.Test$.checkProperties(Test.scala:395)
org.scalacheck.Properties.mainRunner(Properties.scala:62)
org.scalacheck.Prop$class.main(Prop.scala:106)
org.scalacheck.Properties.main(Properties.scala:27)
StringSpecification.main(StringSpecification.scala:-1)
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:
-2)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:5
7)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImp
l.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClas
sLoader.scala:68)
scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoad
er.scala:31)
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(Scala
ClassLoader.scala:99)
scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.sca
la:68)
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassL
oader.scala:99)
scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94)
scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala:-1)
Elapsed time: 0.000 sec
You're right that the documentation for sbt is incorect. There are no "-d", "-g" options and I believe they're simply a copy-and-paste error in the documentation. It was already fixed in a pull request that's soon to be accepted.
The verbosity option is not supported under sbt in the recent version of ScalaCheck 1.11.4. The following is the entire build definition of a sample project.
build.sbt
scalaVersion := "2.11.1"
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.11.4" % "test"
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "3")
Even when the verbosity parameter is properly specified in build.sbt, test execution won't print more than a single line.
➜ scalacheck xsbt test
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to scalacheck (in build file:/Users/jacek/sandbox/scalacheck/)
[info] + String.startsWith: OK, passed 100 tests.
[info] ! String.concatenate: Falsified after 0 passed tests.
[info] > ARG_0: ""
[info] > ARG_1: ""
[info] + String.substring: OK, passed 100 tests.
[info] ! String.throw exception: Exception raised on property evaluation.
[info] > ARG_0: ""
[info] > Exception: java.lang.NullPointerException: exception
[error] Error: Total 4, Failed 1, Errors 1, Passed 2
[error] Error during tests:
[error] StringSpecification
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 1 s, completed Jun 25, 2014 2:57:08 AM
The reason is that org.scalacheck.ScalaCheckFramework has the following implementation and assumes verbosity always be 0:
override def onTestResult(n: String, r: Test.Result) = {
for (l <- loggers) {
import Pretty._
l.info(
(if (r.passed) "+ " else "! ") + n + ": " + pretty(r, Params(0))
)
}
handler.handle(asEvent((n,r)))
}
A pull request to fix it has already been accepted to the repo under Support verbosity under sbt for TestFrameworks.ScalaCheck. You'd have to build ScalaCheck yourself with sbt publishLocal in the directory where you cloned the repo. Don't forget to use 1.12.0-SNAPSHOT version in build.sbt to pick up the changes.
Since the issue that Jacek Laskowski noted has been resolved, you can now get stack traces from ScalaCheck in sbt by adding a line to your build.sbt file to set ScalaCheck's verbosity level.
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "2")
As Jacek Laskowski noted, a verbosity of 0 will give you just the exception.
[info] ! RandomAccessFile.readWriteInt: Exception raised on property evaluation.
[info] > ARG_0: 0
[info] > ARG_0_ORIGINAL: -2073744736
[info] > Exception: java.lang.UnsupportedOperationException: null
A verbosity of 1 will give you the first five lines of the stack trace.
[info] ! RandomAccessFile.readWriteInt: Exception raised on property evaluation.
[info] > ARG_0: 0
[info] > ARG_0_ORIGINAL: 2147483647
[info] > Exception: java.lang.UnsupportedOperationException: null
[info] java.nio.IntBuffer.array(IntBuffer.java:994)
[info] csc365a01.RandomAccessFile.readInt(RandomAccessFile.scala:22)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply$mcZI$sp(RandomAccessFileSpec.scala:14)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply(RandomAccessFileSpec.scala:11)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply(RandomAccessFileSpec.scala:11)
A verbosity greater than one will give you the full stack trace.
[info] ! RandomAccessFile.readWriteInt: Exception raised on property evaluation.
[info] > ARG_0: 0
[info] > ARG_0_ORIGINAL: 1693735989
[info] > Exception: java.lang.UnsupportedOperationException: null
[info] java.nio.IntBuffer.array(IntBuffer.java:994)
[info] csc365a01.RandomAccessFile.readInt(RandomAccessFile.scala:22)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply$mcZI$sp(RandomAccessFileSpec.scala:14)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply(RandomAccessFileSpec.scala:11)
[info] RandomAccessFileProps$$anonfun$1$$anonfun$apply$1.apply(RandomAccessFileSpec.scala:11)
[info] scala.Function1$$anonfun$andThen$1.apply(Function1.scala:52)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$3.apply(Prop.scala:712)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$3.apply(Prop.scala:712)
[info] org.scalacheck.Prop$.secure(Prop.scala:456)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1.org$scalacheck$Prop$$anonfun$$result$1(Prop.scala:712)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$4.apply(Prop.scala:719)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1$$anonfun$4.apply(Prop.scala:719)
[info] scala.collection.immutable.Stream.map(Stream.scala:418)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1.getFirstFailure$1(Prop.scala:719)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1.shrinker$1(Prop.scala:729)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1.apply(Prop.scala:751)
[info] org.scalacheck.Prop$$anonfun$forAllShrink$1.apply(Prop.scala:706)
[info] org.scalacheck.Prop$$anonfun$apply$5.apply(Prop.scala:292)
[info] org.scalacheck.Prop$$anonfun$apply$5.apply(Prop.scala:291)
[info] org.scalacheck.PropFromFun.apply(Prop.scala:22)
[info] org.scalacheck.Prop$$anonfun$delay$1.apply(Prop.scala:461)
[info] org.scalacheck.Prop$$anonfun$delay$1.apply(Prop.scala:461)
[info] org.scalacheck.Prop$$anonfun$apply$5.apply(Prop.scala:292)
[info] org.scalacheck.Prop$$anonfun$apply$5.apply(Prop.scala:291)
[info] org.scalacheck.PropFromFun.apply(Prop.scala:22)
[info] org.scalacheck.Test$.org$scalacheck$Test$$workerFun$1(Test.scala:294)
[info] org.scalacheck.Test$$anonfun$3.apply(Test.scala:323)
[info] org.scalacheck.Test$$anonfun$3.apply(Test.scala:323)
[info] org.scalacheck.Platform$.runWorkers(Platform.scala:40)
[info] org.scalacheck.Test$.check(Test.scala:323)
[info] org.scalacheck.ScalaCheckRunner$$anon$2$$anonfun$execute$3$$anonfun$apply$2.apply(ScalaCheckFramework.scala:102)
[info] org.scalacheck.ScalaCheckRunner$$anon$2$$anonfun$execute$3$$anonfun$apply$2.apply(ScalaCheckFramework.scala:100)
[info] scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:733)
[info] scala.collection.immutable.List.foreach(List.scala:381)
[info] scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
[info] scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:45)
[info] scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:732)
[info] org.scalacheck.ScalaCheckRunner$$anon$2$$anonfun$execute$3.apply(ScalaCheckFramework.scala:100)
[info] org.scalacheck.ScalaCheckRunner$$anon$2$$anonfun$execute$3.apply(ScalaCheckFramework.scala:97)
[info] scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
[info] scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
[info] scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
[info] scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
[info] scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241)
[info] scala.collection.mutable.ArrayOps$ofRef.flatMap(ArrayOps.scala:186)
[info] org.scalacheck.ScalaCheckRunner$$anon$2.execute(ScalaCheckFramework.scala:97)
[info] sbt.TestRunner.runTest$1(TestFramework.scala:76)
[info] sbt.TestRunner.run(TestFramework.scala:85)
[info] sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:202)
[info] sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:202)
[info] sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:185)
[info] sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:202)
[info] sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:202)
[info] sbt.TestFunction.apply(TestFramework.scala:207)
[info] sbt.Tests$$anonfun$9.apply(Tests.scala:216)
[info] sbt.Tests$$anonfun$9.apply(Tests.scala:216)
[info] sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:44)
[info] sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:44)
[info] sbt.std.Transform$$anon$4.work(System.scala:63)
[info] sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
[info] sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226)
[info] sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
[info] sbt.Execute.work(Execute.scala:235)
[info] sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
[info] sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226)
[info] sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
[info] sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
[info] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[info] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[info] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[info] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[info] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
[info] java.lang.Thread.run(Thread.java:745)
[info] Elapsed time: 0.047 sec

How to run task before all tests from all modules in sbt

I have a multi-module Play! application built with sbt and I have a problem on CI server with parallel tests and evolutions: when sbt starts tests and first starts evolution script, other fails because of "Database 'default' is in inconsistent state" for a while (until evolution script stops).
I know how to execute evolutions manually and how to run them from sbt, but I don't know how can I plug this configuration to sbt to ensure evolutions are applied only once and before all tests from all modules.
For reference I'm using following for running evolutions:
object ApplyEvolutions extends App {
OfflineEvolutions.applyScript(
new File("."),
this.getClass.getClassLoader,
args.headOption.getOrElse("default"))
}
And my sbt settings:
val runEvolution = taskKey[Unit]("Applies evolutions")
lazy val runEvolutionTask = runEvolution := {
val log = streams.value.log
val dbName = "default"
Run.executeTrapExit( {
log.info(s"Applying evolutions for database $dbName")
Run.run("controllers.ApplyEvolutions",
(fullClasspath in Compile).value.map { _.data },
Seq(dbName),
log
)(runner.value)
}, log )
}
lazy val runEvolutionsBeforeTests = Seq(
Tasks.runEvolutionTask,
(test in Test) <<= (test in Test) dependsOn Tasks.runEvolution
)
tl;dr Use alias
I use SBT 0.13.2-M3.
[task-dependson]> about
[info] This is sbt 0.13.2-M3
[info] The current project is {file:/Users/jacek/sandbox/so/task-dependsOn/}task-dependson 0.1-SNAPSHOT
[info] The current project is built against Scala 2.10.3
[info] Available Plugins: sbt.plugins.IvyModule, sbt.plugins.JvmModule, sbt.plugins.GlobalModule, com.typesafe.sbt.SbtGit, com.typesafe.sbt.SbtProguard, growl.GrowlingTests, org.sbtidea.SbtIdeaPlugin, sbtman.Plugin, np.Plugin, com.timushev.sbt.updates.UpdatesPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.3
Here's an example of a task - sayHelloT - that's executed once before test in all subprojects. I use Specs2 as the testing framework.
import java.util.concurrent._
lazy val a = project
lazy val b = project
lazy val sayHelloT = taskKey[Unit]("Say Hello")
sayHelloT := {
val log = streams.value.log
log.info("Sleeping for 5 secs...")
TimeUnit.SECONDS.sleep(5)
log.info("Hello, my friend")
}
libraryDependencies in ThisBuild += "org.specs2" %% "specs2" % "2.3.10" % "test"
scalacOptions in Test ++= Seq("-Yrangepos")
addCommandAlias("sht", ";sayHelloT; test")
As you can see there are two subprojects - a and b - and a single alias sht that will execute sayHelloT and only after it finishes successfully which takes 5 secs, test kicks in.
[task-dependson]> sht
[info] Sleeping for 5 secs...
[info] Hello, my friend
[success] Total time: 5 s, completed Mar 12, 2014 10:19:39 PM
[info] ASpec
[info]
[info] A project should
[info] + contain 11 characters
[info]
[info] Total for specification ASpec
[info] Finished in 205 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for task-dependson/test:test
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[info] BSpec
[info]
[info] B project should
[info] + contain 11 characters
[info]
[info] Total for specification BSpec
[info] Finished in 240 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 3 s, completed Mar 12, 2014 10:19:42 PM