I have a play application and I need to ignore my functional tests when I compile and build, then later run only the integration tests.
This is my test code:
ApplicationSpec.scala
#RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
"Application" should {
"send 404 on a bad request" in new WithApplication {
route(FakeRequest(GET, "/boum")) must beNone
}
}
IntegrationSpec.scala
#RunWith(classOf[JUnitRunner])
class IntegrationSpec extends Specification {
"Application" should {
"work from within a browser" in {
running(TestServer(9000), FIREFOX) { browser =>
browser.goTo("http://localhost:9000/app")
browser.pageSource must contain("Your new application is ready.")
}
}
} section "integration"
}
The docs tells me I can use something like this from the command line:
play "test-only -- exclude integration"
The only problem is that this doesn't actually exclude any tests and my integration tests invoke firefox and start running. What am I doing wrong? How can I exclude the integration tests and then later run them by themselves?
sbt's Testing documentation describes several ways to define separate test configurations.
For instance, the Additional test configurations with shared sources example could be used in this situation:
In this approach, the sources are compiled together using the same classpath and are packaged together. However, different tests are run depending on the configuration.
In a default Play Framework 2.2.2 application created with play new, add a file named project/Build.scala with this content:
import sbt._
import Keys._
object B extends Build {
lazy val root =
Project("root", file("."))
.configs(FunTest)
.settings(inConfig(FunTest)(Defaults.testTasks) : _*)
.settings(
libraryDependencies += specs,
testOptions in Test := Seq(Tests.Filter(unitFilter)),
testOptions in FunTest := Seq(Tests.Filter(itFilter))
)
def itFilter(name: String): Boolean = (name endsWith "IntegrationSpec")
def unitFilter(name: String): Boolean = (name endsWith "Spec") && !itFilter(name)
lazy val FunTest = config("fun") extend(Test)
lazy val specs = "org.specs2" %% "specs2" % "2.0" % "test"
}
To run standard unit tests:
$ sbt test
Which produces:
[info] Loading project definition from /home/fernando/work/scratch/so23160453/project
[info] Set current project to so23160453 (in build file:/home/fernando/work/scratch/so23160453/)
[info] ApplicationSpec
[info] Application should
[info] + send 404 on a bad request
[info] + render the index page
[info] Total for specification ApplicationSpec
[info] Finished in 974 ms
[info] 2 examples, 0 failure, 0 error
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 3 s, completed Apr 22, 2014 12:42:37 PM
To run tests for the added configuration (here, "fun"), prefix it with the configuration name:
$ sbt fun:test
Which produces:
[info] Loading project definition from /home/fernando/work/scratch/so23160453/project
[info] Set current project to so23160453 (in build file:/home/fernando/work/scratch/so23160453/)
[info] IntegrationSpec
[info] Application should
[info] + work from within a browser
[info] Total for specification IntegrationSpec
[info] Finished in 0 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 6 s, completed Apr 22, 2014 12:43:17 PM
You can also test only a particular class, like this:
$ sbt "fun:testOnly IntegrationSpec"
See this example in GitHub.
Related
I'm trying to make sure that my ScalaCheck property runs 500 times instead of the default 100 times. I'm having trouble configuring this though.
class BlockSpec extends Properties("BlockSpec") with BitcoinSLogger {
val myParams = Parameters.default.withMinSuccessfulTests(500)
override def overrideParameters(p: Test.Parameters) = myParams
property("Serialization symmetry") =
Prop.forAll(BlockchainElementsGenerator.block) { block =>
logger.warn("Hex:" + block.hex)
Block(block.hex) == block
}
}
However when I actually run this test it only says 100 tests passed successfully
EDIT:
$ sbt
[info] Loading project definition from /home/chris/dev/bitcoins-core/project
[info] Set current project to bitcoin-s-core (in build file:/home/chris/dev/bitcoins-core/)
> test-only *BlockSpec*
[info] + BlockSpec.Serialization symmetry: OK, passed 100 tests.
[info] Elapsed time: 1 min 59.775 sec
[info] ScalaCheck
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[info] ScalaTest
[info] Run completed in 2 minutes.
[info] Total number of tests run: 0
[info] Suites: completed 0, aborted 0
[info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0
[info] No tests were executed.
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 123 s, completed Aug 1, 2016 11:36:17 AM
>
How do I actually pass this to my property?
As far as I understand you can specify the test parameters at two levels and they don't seem to communicate.
The first option is within the property as you're trying to do:
import org.scalacheck.Properties
import org.scalacheck.Test.{ TestCallback, Parameters }
import org.scalacheck.Prop.{ forAll, BooleanOperators }
import org.scalacheck.Test
class TestFoo extends Properties("BlockSpec") {
override def overrideParameters(p: Parameters) =
p.withMinSuccessfulTests(1000000)
property("Serialization symmetry") = forAll { n: Int =>
(n > 0) ==> (math.abs(n) == n)
}
}
This will have no impact as long as you don't call .check on the property.
Can be from the sbt shell or directly within the class.
Now if you want to impact the number of tests run when calling the sbt:test target, it seems you have to play with options build.sbt (taken from here):
name := "scalacheck-demo"
scalaVersion := "2.11.5"
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.2" % "test"
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-maxSize", "5", "-minSuccessfulTests", "33", "-workers", "1", "-verbosity", "1")
There's definitely an easier way to achieve that than overriding any kind of global test config:
class SampleTest extends FlatSpec
with Matchers with GeneratorDrivenPropertyChecks {
it should "work for a basic scenario" in {
// This will require 500 successful tests to succeed
forAll(minSuccessful(500)) { (d: String) =>
whenever (d.nonEmpty) {
d.length shouldBe > 0
}
}
}
}
I am trying to run my tests with:
sbt and then test.
My build.sbt looks like this
lazy val scalatest = "org.scalatest" % "scalatest_2.11" % "2.2.4" % "test"
lazy val root = (project in file(".")).
settings(
name := "highlight2pdf",
version := "0.1",
scalaVersion := "2.11.6",
libraryDependencies += scalatest
)
And i just put the example test on test/scala
import collection.mutable.Stack
import org.scalatest._
class ExampleSpec extends FlatSpec with Matchers {
"A Stack" should "pop values in last-in-first-out order" in {
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
stack.pop() should be (2)
stack.pop() should be (1)
}
it should "throw NoSuchElementException if an empty stack is popped" in {
val emptyStack = new Stack[Int]
a [NoSuchElementException] should be thrownBy {
emptyStack.pop()
}
}
}
Still it always show:
[info] No tests were executed.
Any thoughts on why it's not working?
The directory structure isn't the correct convention for sbt to find ExampleSpec.scala by default.
├── built.sbt
├── src
│ └── test
│ └── scala
│ ├── ExampleSpec.scala
Change it to the structure above and run sbt test in the top level directory and it should work. Likewise, scala source would go in src/main/scala and would get compiled.
> test
[info] Compiling 1 Scala source to /tmp/TestsWontRun/target/scala-2.11/test-classes...
[info] ExampleSpec:
[info] A Stack
[info] - should pop values in last-in-first-out order
[info] - should throw NoSuchElementException if an empty stack is popped
[info] Run completed in 289 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 7 s, completed Apr 30, 2015 8:54:30 AM
I am trying out a simple HelloWorld example. Here is my directory structure:
hello
build.sbt
main
scala
Hello.scala
test
scala
HelloTest.scala
Hello.scala contains a sayHello function that I am trying to call from a simple test in HelloTest.scala. Here is my build.sbt:
name := "Hello"
organization := "tycon"
scalaVersion := "2.11.2"
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.1" % "test"
And here is an sbt run that does not run any tests:
$ sbt
[info] Set current project to scala (in build
file:~/git/scala/hello/main/scala/)
> compile
[info] Updating
{file:~/git/scala/hello/main/scala/}scala...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to
~/git/scala/hello/main/scala/target/scala-2.10/classes...
[success] Total time: 3 s, completed Sep 17, 2014 9:04:00 AM
> test
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:test
[success] Total time: 0 s, completed Sep 17, 2014 9:04:03 AM
I tried suggestions from other answers: replaced %% with % and substituted scalatest_2.10 for scalatest in libraryDependencies, and changed scalaVersion to 2.10.0. None of them worked. And yes, I was reloading each time build.sbt changed.
I believe that I am missing something very basic. I would appreciate any help. I am new to Scala.
Edit: For the sake of completeness, here are the two scala files:
Hello.scala:
trait Hello {
def sayHello () = {
println ("Hello, World!")
}
}
HelloTest:scala:
import org.scalatest.FunSuite
class HelloTest extends FunSuite with Hello {
test("say hello") {
sayHello()
}
}
Edit2: I changed the directory structure as suggested by ajozwik and Gabriele, but sbt still doesn't run the test:
~/git/scala/hello/src/main/scala$ sbt
[info] Set current project to scala (in build
file:~/git/scala/hello/src/main/scala/)
> test
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:test
[success] Total time: 1 s, completed Sep 17, 2014 9:36:24 AM
The directory structure should be
hello
build.sbt
src
main
scala
Hello.scala
test
scala
HelloTest.scala
i.e. you're missing the outer src directory.
Also, you need to run sbt from the root of your project, and not from within a subfolder.
The following test should pass, but it doesn't
class EngineTest extends FunSuite {
test("engine should not be null") {
val manager: ScriptEngineManager = new ScriptEngineManager
val engine: ScriptEngine = manager.getEngineByName("nashorn")
assert(engine != null)
}
}
The manager.getEngineFactories() seems to be empty. Why? How to init the context?
You need to explicitly pass in a ClassLoader to the ScriptEngineManager constructor. If you don't then it uses Thread.currentThread().getContextClassLoader() which is set to something weird when running under SBT. We just pass in null in our code to get it to work. You can also pass in getClass.getClassLoader:
class EngineTest extends FunSuite {
test("engine should not be null - null classloader") {
val manager: ScriptEngineManager = new ScriptEngineManager(null)
val engine: ScriptEngine = manager.getEngineByName("nashorn")
assert(engine != null)
}
test("engine should not be null - getClass.getClassLoader classloader") {
val manager: ScriptEngineManager = new ScriptEngineManager(getClass.getClassLoader)
val engine: ScriptEngine = manager.getEngineByName("nashorn")
assert(engine != null)
}
}
Both of those tests pass for me:
[info] EngineTest:
[info] - engine should not be null - null classloader
[info] - engine should not be null - getClass.getClassLoader classloader
[info] Run completed in 186 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
What versions are you using? This is sbt .13.
> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.0 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import javax.script._
import javax.script._
scala> new ScriptEngineManager().getEngineByName("scala")
res0: javax.script.ScriptEngine = scala.tools.nsc.interpreter.IMain#7078c799
scala> new ScriptEngineManager().getEngineByName("rhino")
res1: javax.script.ScriptEngine = com.sun.script.javascript.RhinoScriptEngine#5c854934
scala> new ScriptEngineManager().getEngineFactories
res2: java.util.List[javax.script.ScriptEngineFactory] = [com.sun.script.javascript.RhinoScriptEngineFactory#454ee4c0, scala.tools.nsc.interpreter.IMain$Factory#354e3bce]
Wait, you asked about test context --
Well, before I lost interest in decoding more sbt, adding to libraryDependencies:
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "test",
enables locating the Scala script engine:
#Test def engines: Unit = {
import javax.script._
val all = new ScriptEngineManager().getEngineFactories
Console println s"Found ${all.size}: $all"
assert(all.size > 0)
}
No doubt there's a simple way to add runtime:full-classpath to test:full-classpath directly. Because it's the simple build tool, right?
For Nashorn on Java 8, note the location:
> set fullClasspath in Test += Attributed.blank(file(s"${util.Properties.javaHome}/lib/ext/nashorn.jar"))
[info] Defining test:fullClasspath
[info] The new value will be used by test:console, test:executeTests and 5 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to goofy (in build file:/home/apm/goofy/)
> test
Found 1: [jdk.nashorn.api.scripting.NashornScriptEngineFactory#7fa2239d]
[info] Passed: Total 10, Failed 0, Errors 0, Passed 10
Update: https://github.com/sbt/sbt/issues/1214
Also I guess it's still considered black art:
// Somehow required to get a js engine in tests (https://github.com/sbt/sbt/issues/1214)
fork in Test := true
The only thing I had to change was to use:
fork in Test := true
as mentioned above - from here: https://github.com/sbt/sbt/issues/1214
Assuming a multiproject SBT project with a foo-project and bar-project, such that foo-project depends on bar-project for code etc.
I would like tests in foo-project to run iff the tests in bar-project pass.
How?
You may provide explicit dependencies between projects. For example root -> A -> B
Test case on GitHub. Project definition:
val commonSettings = Seq(libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1")
lazy val a: Project = (project in file("a")) settings(commonSettings: _*) settings(
name := "a",
test in Test <<= test in Test dependsOn (test in Test in b)
)
lazy val b: Project = (project in file("b")) settings(commonSettings: _*) settings(
name := "b"
)
lazy val root: Project = (project in file(".")) settings(commonSettings: _*) settings(
name := "root",
test in Test <<= test in Test dependsOn (test in Test in a)
)
Beginning from B and complete them successful:
ezh#mobile ZZZZZZ % sbt-0.13
[info] Set current project to root (in build file:/home/ezh/ZZZZZZ/)
> root/test
[info] Compiling 1 Scala source to /home/ezh/ZZZZZZ/b/target/scala-2.10/test-classes...
[info] TestSpecB:
[info] This test
[info] - should fail
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[info] Compiling 1 Scala source to /home/ezh/ZZZZZZ/a/target/scala-2.10/test-classes...
[info] TestSpecA:
[info] This test
[info] - should succeed
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for root/test:test
[success] Total time: 5 s, completed 28.11.2013 16:20:12
Beginning from B but fail:
ezh#mobile ZZZZZZ % sbt-0.13
[info] Set current project to root (in build file:/home/ezh/ZZZZZZ/)
> test
[info] Compiling 1 Scala source to /home/ezh/ZZZZZZ/b/target/scala-2.10/test-classes...
[info] TestSpecB:
[info] This test
[info] - should fail *** FAILED ***
[info] 2 did not equal 3 (Test.scala:5)
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0
[error] Failed tests:
[error] TestSpecB
[error] (b/test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 3 s, completed 28.11.2013 16:20:35
>
as already noted this is probably evil, however this should probably work:
import sbt._
import sbt.Keys._
object Build extends Build {
lazy val projectA = project
lazy val myTest = taskKey[Seq[Option[Tests.Output]]]("my test")
lazy val root: Project = project in file(".") settings (myTest <<= myTestTask) dependsOn projectA
def myTestTask = Def.task {
val state: State = Keys.state.value
val log: Logger = streams.value.log
val extracted = Project.extract(state)
import extracted._
def noTestsMessage(scoped: ScopedKey[_])(implicit display: Show[ScopedKey[_]]): String =
"No tests to run for " + display(scoped)
def f(ref: ProjectReference) = for {
state Pair Value(r) <- Project.runTask(executeTests in(ref, Test), state)
_ = Tests.showResults(log, r, noTestsMessage(test in ref))
} yield r
val depsTests = currentProject.dependencies.map(_.project).map(f)
val passed = depsTests.forall(_.forall(_.overall == TestResult.Passed))
if (passed) depsTests :+ f(ThisProject) else depsTests
}
}
http://scastie.org/3319