ScalaTest on sbt not running any tests - scala

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

Related

"No log4j2 configuration file found."

I've isolated this to a very simple test project that has no purpose other than simple log4j2test configuration + usage. The file directory structure:
.
├── build.sbt
└── src
└── main
├── resources
│ └── log4j2.xml
└── scala
└── mycompany
└── myapp
└── SimpleMain.scala
Build.sbt:
name := """log4j2test"""
version := "1.0.0-SNAPSHOT"
scalaVersion := "2.12.1"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
libraryDependencies ++= {
Seq(
"org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.8",
"org.apache.logging.log4j" % "log4j-api" % "2.8",
"org.apache.logging.log4j" % "log4j-core" % "2.8",
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % "2.8.6"
)
}
log4j2.xml contents are copy/pasted from example in official documentation: https://logging.apache.org/log4j/2.x/manual/configuration.html
SimpleMain.scala:
package mycompany.myapp
import org.slf4j.LoggerFactory
object SimpleMain {
val logger = LoggerFactory.getLogger(getClass())
def main(args: Array[String]): Unit = {
println("simple println test")
logger.info("this is a logger.info message")
logger.debug("this is a logger.debug message")
logger.error("this is a logger.error message")
val stream = this.getClass.getClassLoader.getResourceAsStream("log4j2.xml")
if (stream == null) {
println("failed to open log4j2.xml on classpath")
} else {
println("successfully opened log4j2.xml on classpath")
stream.close()
}
}
}
I run with
sbt "run-main mycompany.myapp.SimpleMain"
output:
[info] Running mycompany.myapp.SimpleMain
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
simple println test
14:12:14.508 [run-main-0] ERROR mycompany.myapp.SimpleMain$ - this is a logger.error message
successfully opened log4j2.xml on classpath
[success] Total time: 4 s, completed Feb 10, 2017 2:12:14 PM
Is it possible that the classloader for the SimpleMain application is different from the classloader for slf4j? Please try debugging the Log4j2 initialization by setting system property org.apache.logging.log4j.simplelog.StatusLogger.level to TRAC‌​E.
Is log4j2.xml being placed at the root of your jar? I am surprised getResourceAsStream is working. You have it specified as a relative path so it should be finding /mycompany/myapp/log4j2.xml.

Cannot run tests via sbt in Scala

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.

How to add examples to an SBT project?

I want to add some examples to my Scala library. I prefer a directory layout like this:
examples/
example1/
Main.scala
...
example2/
Main.scala
...
src/
main/
scala/
...
test/
scala/
...
build.sbt
The examples use the packages in src/main/scala/. Is it possible to build and run the examples using SBT? Is it also possible to have dependencies specific to the examples?
It is possible, but you likely have to resort to complete .scala definition. I've put example project on bitbucket.
Here is the showcase:
// [info] Loading global plugins from /Users/omnomnom/.sbt/0.13/plugins
// [info] Loading project definition from /Users/omnomnom/projects/example-of-examples/project
// [info] Set current project to root-project (in build file:/Users/omnomnom/projects/example-of-examples/)
> projects
// [info] In file:/Users/omnomnom/projects/example-of-examples/
// [info] example1
// [info] example2
// [info] * root-project
> project example1
// [info] Set current project to example1 (in build file:/Users/omnomnom/projects/example-of-examples/)
> run
// [info] Updating {file:/Users/omnomnom/projects/example-of-examples/}root-project...
// [info] Resolving org.fusesource.jansi#jansi;1.4 ...
// [info] Done updating.
// [info] Updating {file:/Users/omnomnom/projects/example-of-examples/}example1...
// [info] Resolving org.fusesource.jansi#jansi;1.4 ...
// [info] Done updating.
// [info] Compiling 1 Scala source to /Users/omnomnom/projects/example-of-examples/target/scala-2.10/classes...
// [info] Running Main
I'm example #1
// [success] Total time: 4 s, completed Jul 4, 2014 10:17:54 PM
> project example2
// [info] Set current project to example2 (in build file:/Users/omnomnom/projects/example-of-examples/)
> run
// [info] Updating {file:/Users/omnomnom/projects/example-of-examples/}example2...
// [info] Resolving org.fusesource.jansi#jansi;1.4 ...
// [info] Done updating.
// [info] Compiling 1 Scala source to /Users/omnomnom/projects/example-of-examples/examples/example2/target/scala-2.10/classes...
// [info] Running Main
I'm example #2
// [success] Total time: 3 s, completed Jul 4, 2014 10:18:04 PM
And Build.scala, just for the case:
import sbt._
import Keys._
object Build extends Build {
override lazy val settings = super.settings ++ Seq(
scalacOptions ++= Seq("-unchecked", "-deprecation", "-Xlint"),
organization := "me.lazyval",
scalaVersion := "2.10.4",
initialCommands in console := "import me.lazyval._"
)
// altering source path, since you don't want to replicate usual src/main ... stuff
val exampleSourcePath = scalaSource in Compile := baseDirectory.value / "."
lazy val root = Project(id = "root-project", base = file("."), settings = Project.defaultSettings ++ settings)
lazy val example1 = Project(id = "example1", base = file("./examples/example1"), settings = Project.defaultSettings ++ settings ++ Seq(exampleSourcePath)) dependsOn root
// in `settings= ...` section you can set whatever dependencies you like
lazy val example2 = Project(id = "example2", base = file("./examples/example2"), settings = Project.defaultSettings ++ settings ++ Seq(exampleSourcePath)) dependsOn root
}

Play test-only doesn't ignore tests

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.

Make tests in multi project sbt projects run only if tests pass in dependent projects

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