Using ScalaTest with SBT android-sdk-plugin - scala

I'm trying to use SBT with android-sdk-plugin and ScalaTest, but have no success.
I could run test command in SBT console, but it didn't find any ScalaTest test suite in my src/test/scala folder.
I got the following output from SBT, which seems didn't run any ScalaTest test suite at all.
[info] Compiling 2 Scala sources and 3 Java sources to /home/brianhsu/AndroidProject/FindLost/target/android-bin/classes...
[info] Packaging /home/brianhsu/AndroidProject/FindLost/target/android-bin/classes.jar ...
[info] Done packaging.
[info] Packaging /home/brianhsu/AndroidProject/FindLost/target/scala-2.10/findlost_2.10-0.1-SNAPSHOT-tests.jar ...
[info] Done packaging.
[info] Run completed in 44 milliseconds.
[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] No tests to run for test:test
The following is how I create the project:
Using android create project -g to create an Android project with gradle layout.
Add addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.2.11") to project/plugins.sbt to include android-sdk-plugin to my project.
Add ScalaTest to my libraryDependencies setting in build.sbt, which makes the build file looks like the following:
import android.Keys._
android.Plugin.androidBuild
name := "FindLost"
scalaVersion := "2.10.4"
organization := "org.bone.findlost"
libraryDependencies += "org.scalatest" % "scalatest_2.10" % "2.1.0" % "test"
platformTarget in Android := "android-19"
run <<= run in Android
install <<= install in Android
Add a ScalaTest test case to src/test/scala, which contains example test suite from QuickStart page of ScalaTest.

Place your tests in src/androidTest/scala
The android-sdk-plugin uses androidTest for both Android instrumentation tests as well as regular tests.
See Ordinary scalatests not found from src/test #45 for a discussion on this topic. Note, that since that discussion the plugin changed directory has changed to the path I listed.

Related

scala "console" command gives error "Missing scala-library.jar"

Under sbt, if I give "console" to start a REPL shell, I get the following error.
[error] stack trace is suppressed; run 'last scalaInstance' for the full output
[error] (scalaInstance) Missing scala-library.jar
[error] Total time: 1 s, completed Oct 7, 2019 12:45:07 PM
$ sbt scalaVersion
[info] Loading global plugins from C:..\plugins
[info] Loading settings for project test from plugins.sbt ...
[info] Loading project definition from C:xx\test\project
[info] Loading settings for project root from build.sbt ...
[info] scalaVersion
[info] 2.11.12
$ sbt sbtVersion
[info] sbtVersion
[info] 1.3.0
Try
assemblyOption in set: = (assemblyOption in set) .value.copy (includeScala = true)
Source: https://github.com/sbt/sbt-assembly
if this doesn't solve the issue, it could be a compatibility issue with a plugin which you might have installed, it means that you would have to delete the plugin directory in %HOME%. and %HOME%.ivy2 because it caches some artifacts locally.
If you are not able to find the plugin try deleting %HOME%.ivy2 and running the console again, as it will remove the cached artifacts.
You might want to refer
https://pt.coredump.biz/questions/50313823/why-does-running-tests-through-jenkins-user-on-build-slave-fail-with-missing-scalalibraryjar
I hope it helps.
Somewhat unrelated but I ran into this error on one of my projects and deleting all caches (.m2, .ivy2, coursier) was not enough to fix this. I also had to clear out my .sbt folder (I assume emptying the boot directory). Be sure to backup any settings you still might need.
can you try updating scala version in your sbt build?
for example,
scalaVersion := "2.13.0"

Using sbt run on simple tutorial example does not execute

On a Windows machine, I am running through the getting started tutorial here: https://www.scala-sbt.org/1.x/docs/sbt-by-example.html
I am able to start the sbt shell and compile but using the run command just hangs and I am forced to Ctrl-C to exit sbt.
Running scala against the JAR file directly also works as expected.
Sample output is the following:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from S:\foo-build\project
[info] Loading settings for project foo-build from build.sbt ...
[info] Set current project to foo-build (in build file:/S:/foo-build/)
[info] sbt server started at local:sbt-server-8c6933abcb6848dbd242
sbt:foo-build> about
[info] This is sbt 1.2.8
[info] The current project is ProjectRef(uri("file:/S:/foo-build/"), "foo-build") 0.1.0-SNAPSHOT
[info] The current project is built against Scala 2.12.7
[info] Available Plugins
[info] - sbt.ScriptedPlugin
[info] - sbt.plugins.CorePlugin
[info] - sbt.plugins.Giter8TemplatePlugin
[info] - sbt.plugins.IvyPlugin
[info] - sbt.plugins.JUnitXmlReportPlugin
[info] - sbt.plugins.JvmPlugin
[info] - sbt.plugins.SbtPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.12.7
sbt:foo-build> compile
[success] Total time: 0 s, completed Feb 7, 2019 4:40:45 PM
sbt:foo-build> run
Terminate batch job (Y/N)? Y
This is enough of an answer for my own purposes.
I was able work around this issue by adding a line to my build.sbt file. After adding ThisBuild / scalaVersion := "2.12.8" I was able to use the run command. Following the tutorial linked in the main question I would not expect to have to do this but perhaps someone could shed some light.

Specs2 unable to find my tests using sbt

I have build a simple project for Spec2 testing using simple sbt.
package main.specs
import org.specs2._
class QuickStartSpec extends Specification {
def is = s2"""
This is my first specification
it is working $ok
really working! $ok
"""
}
And here is my build.sbt file:
name := "QuickStartSpec"
version := "1.0"
scalaVersion := "2.10.1"
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
scalacOptions in Test ++= Seq("-Yrangepos")
But when I run this command in sbt
testOnly main.specs.QuickStartSpec
I am getting this:
[info] Updating {file:/Users/nabajeet/workspace/SpecsTest/}specstest...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:testOnly
I am following this page to create the example:
https://etorreborre.github.io/specs2/website/SPECS2-3.6.5/quickstart.html
I am unable to figure out the reason why my tests are not detected.
My sbt version in 0.13.8
By declaring
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
You restrict the scope of specs2 to only classes in the test source directories. You won't be able to reference specs2 classes in the production code (all the code under src/main/)
In your comment you indicate that you placed your spec in /Users/nabajeet/workspace/SpecsTest/src/main/specs/quickStartSpec.scala
Try moving your file to /Users/nabajeet/workspace/SpecsTest/src/test/scala/specs/quickStartSpec.scala
The incorrect location is why it you spec not picked up by SBT (and I feel confident to say that it doesn't compile either).
By default, SBT applies maven's standard directory layout adding src/main/scala/ and src/test/scala/ for scala code. This is documented in the SBT tutorial
I just created a project with the following layout
.
./built.sbt
./src
./src/test
./src/test/scala
./src/test/scala/QuickStartSpec.scala
build.sbt contains
name := "QuickStartSpec"
version := "1.0"
scalaVersion := "2.11.4"
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
scalacOptions in Test ++= Seq("-Yrangepos")
and QuickStartSpec.scala contains
package main.specs
import org.specs2._
class QuickStartSpec extends Specification {
def is = s2"""
This is my first specification
it is working $ok
really working! $ok
"""
}
here is the sbt output I get
sbt
[info] Set current project to QuickStartSpec (in build file:/tmp/stack/)
> test:compile
[info] Updating {file:/tmp/stack/}stack...
[info] Resolving jline#jline;2.12 ...
[info] Done updating.
[info] Compiling 1 Scala source to /tmp/stack/target/scala-2.11/test-classes...
[info] 'compiler-interface' not yet compiled for Scala 2.11.4. Compiling...
[info] Compilation completed in 6.372 s
[success] Total time: 9 s, completed 27 nov. 2015 06:38:26
> test
[info] QuickStartSpec
[info] + This is my first specification
[info] it is working
[info] + really working!
[info]
[info] Total for specification QuickStartSpec
[info] Finished in 17 ms
[info] 2 examples, 0 failure, 0 error
[info]
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 1 s, completed 27 nov. 2015 06:38:31
>

Exclude test dependency resolution from `sbt compile`

When running sbt compile, dependencies marked as test are still resolved even though they are not later included later in compilation. It seems like this should only happen during the test:compile task. Is there a way to exclude test dependencies from being resolved and downloaded during the compile task?
Here is an example with the org.mockito#mockito-all dependency. I have it declared as test-only:
"org.mockito" % "mockito-all" % "1.9.0" % "test"
However, when (clearing it from my local Ivy cache and) running sbt compile, it gets needlessly downloaded:
$ sbt compile
[info] Loading global plugins from /Users/rbrainard/.sbt/plugins
[info] Loading project definition from /Users/rbrainard/Development/spitball/project
[info] Set current project to spitball (in build file:/Users/rbrainard/Development/spitball/)
[info] Updating {file:/Users/rbrainard/Development/spitball/}spitball...
[info] Resolving org.mockito#mockito-all;1.9.0 ...
[info] downloading http://repo1.maven.org/maven2/org/mockito/mockito-all/1.9.0/mockito-all-1.9.0.jar ...
[info] [SUCCESSFUL ] org.mockito#mockito-all;1.9.0!mockito-all.jar (2075ms)
[info] Done updating.
[success] Total time: 7 s, completed May 28, 2014 4:51:20 PM
In sbt the update task resolves all dependencies for all configurations. Sbt makes use of Ivy, which promotes a very interesting "configuration" aspect to be able to separately resolve disparate classpaths at the same time.
Sbt is not only resolving your test classpath, but also runtime, the scala-tools (compiler, scaladoc, repl) and more.
Please read: https://ant.apache.org/ivy/history/latest-milestone/terminology.html for more information on the design of Ivy, which is why sbt attempts to do all resolution at once for all configurations.

Running tests from jar with "sbt testOnly" in SBT?

As part of a CI setup the very first step is to create a package/jar using SBT dist. The following steps are to run unit, integration and functional tests with the dist-created jar.
Is it possible to do that with SBT?
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
I'm using ScalaTest and I know there is a runner for it I could use http://www.scalatest.org/user_guide/using_the_runner. But using SBT would be simpler, if that is possible.
As an example, something like this is what I am looking for:
sbt testOnly "Unit.* -jar myjar.jar"
Will my tests even be included in the jar when I use the following:
sbt dist
?
EDIT
I created a new folder
I added build.sbt with the following content:
name := "abc"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
I added the lib folder and copied my tests jar into it
I ran sbt testOnly Unit.*
It could not find any tests
EDIT 2
I tried with the following "proper" SBT file:
name := "ihs2tests"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
unmanagedBase in Test := new java.io.File(".")
and moved test.jar into the root of the project. Again, no tests found.
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
The test-family tasks in SBT (with testOnly as an example) work with compile task that returns a list of compiled files through an sbt.inc.Analysis instance. I couldn't figure out how to amend it and inject the changed Analysis instance to testOnly so it knows the test I'm going to run exists.
I'm proposing another solution - a trick.
Package the tests classes to a jar with test:package task as follows:
[test-lib]> test:package
[info] Updating {file:/Users/jacek/sandbox/so/test-lib/}test-lib...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-classes...
[info] Packaging /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-lib_2.10-0.1-SNAPSHOT-tests.jar ...
[info] Done packaging.
[success] Total time: 9 s, completed Mar 4, 2014 11:34:13 PM
When you have the test jar, you can execute the test framework on the command line without SBT (I assume you use ScalaTest given the scalatest tag, but I'll use Specs2). Read the documentation of the test framework on how to do it and for Specs2 it's specs2.run as described in Console output.
Executing tests from the test jar requires defining a proper CLASSPATH that may or may not be easy to get right. That's where SBT can be of great help - to manage dependencies and hence the CLASSPATH.
Create another SBT project and save the test jar in lib subdirectory to have it on CLASSPATH (as described in Unmanaged dependencies).
Dependencies in lib go on all the classpaths (for compile, test, run, and console).
Add a sample build.sbt where you define your test framework as a dependency of the project. For Specs2 it's as follows (I used the default configuration as described in the Specs2 home page):
libraryDependencies += "org.specs2" %% "specs2" % "2.3.8" % "test"
scalacOptions in Test ++= Seq("-Yrangepos")
The trick is to execute the main class of the test framework, e.g. specs2.run for Specs2, as if the class were executed on the command line. SBT helps with test:runMain.
[my-another-project]> test:runMain specs2.run HelloWorldSpec
[info] Running specs2.run HelloWorldSpec
HelloWorldSpec
The 'Hello world' string should
+ contain 11 characters
+ start with 'Hello'
+ end with 'world'
Total for specification HelloWorldSpec
Finished in 62 ms
3 examples, 0 failure, 0 error
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 5 s, completed Mar 4, 2014 11:15:14 PM
Don't worry about this Exception as it comes from SBT that catches exit from Specs2 (after test execution) so SBT remains up.
It seems that SBT can't read jar file without any additional/manual setup - I might be wrong but I didn't find anything in the docs. So I tried something like this to make the task simpler:
unzip some-test.jar
java -jar sbt-launch.jar \
'set scalaSource in Test := new java.io.File(".")' \
'set fullClasspath in Test += Attributed.blank(file("."))' \
'test'
This runs without errors but does not find tests.
If I add 'set includeFilter in (Test, unmanagedSources) := "*Suite*.class"' to force it to find tests it obviously fails because it expects *.scala files, not the compiled *.class files.
I'm not an SBT expert, but I think this must be close to a solution. There must be a way to read all files from a jar path programmatically and then tell test framework to use *.class files.
At this point is seems more reasonable to run tests using a Scalatest test runner or from sbt using the project.
If you wish to dig deeper take a look at SBT source code and the default sbt shell script that does lots of setup before it runs the sbt launcher jar.