initializate value only once before all tests runs - scala

I want to initializate value only once before all tests runs
Now the value insertDbScheme create scheme in every test, if it possible to run it only once. Insert scheme from sbt task not suitable
I have two tests
test1:
class Test1 extends Specification with InsertDbScheme {
"test" in {
insertDbScheme
// some code
ok
}
}
test2:
class Test2 extends Specification with InsertDbScheme {
"test" in {
insertDbScheme
// some code
ok
}
}
and a base trait that insert scheme to database
trait InsertDbScheme {
lazy val insertDbScheme = {
println("insert scheme to database")
}
}
result of running tests
insert scheme to database
insert scheme to database
[info] Test1
[info]
[info] + test
[info]
[info]
[info] Total for specification Test1
[info] Finished in 152 ms
[info] 1 example, 0 failure, 0 error
[info]
[info] Test2
[info]
[info] + test
[info]
[info]
[info] Total for specification Test2
[info] Finished in 152 ms
[info] 1 example, 0 failure, 0 error
[info]
[info] ScalaCheck
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 12 s, completed May 18, 2017 6:35:21 PM

You can use an object to make sure it's lazy val is only instantiated once:
trait InsertDbScheme {
import InsertDbScheme._
lazy val insertDbScheme = insertDbSchemeOnce
}
object InsertDbScheme {
lazy val insertDbSchemeOnce = {
println("insert scheme to database")
}
}

The easiest thing is to use a variable in a InsertDbScheme object:
trait InsertDbScheme {
def insertDbScheme = synchronized {
if (!InsertDbScheme.done) {
println("insert scheme to database")
InsertDbScheme.done = true
}
}
}
object InsertDbScheme {
var done = false
}

Related

Running setup/teardown tasks during stb test task

I try to configure sbt to run a setup task at the beginning and a tear down task at the end of myProject/test command.
My build.sbt is here:
name := "ch-2"
version := "1.0"
libraryDependencies += "org.specs2" % "specs2_2.10" % "1.14" % "test"
lazy val common = (
Project("common", file("common")).
settings()
)
lazy val subPro = (
Project("sub", file("subA")).settings(
).dependsOn(common)
settings(libraryDependencies += "org.specs2" % "specs2_2.10" % "1.14" % "test" )
)
val startS = taskKey[Unit]("Start")
val stopS = taskKey[Unit]("Stop")
startS := { println("Running start")}
stopS := { println("Running stop")}
testOptions in Test in subPro += Tests.Setup { () => startS.value }
testOptions in Test in subPro += Tests.Cleanup { () => stopS.value }
The actual dummy test class is here:
import org.specs2.mutable.Specification
/**
* Created by jk on 26.3.2017.
*/
object FooSpec extends Specification {
"The TEST method" should {
"blaa blaa 1" in {
println("test 1 running...")
true
}
"blaa blaa 2" in {
println("test 2 running...")
true
}
}
}
When I run the tests for project sub, I get following output:
> sub/test
Running stop
Running start
[info] Updating {file:/home/jk/workspace/sbt-in-action/ch2/}sub...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /home/jk/workspace/sbt-in-action/ch2/subA/target/scala-2.10/test-classes...
test 1 running...
test 2 running...
[info] FooSpec
[info]
[info] The TEST method should
[info] + blaa blaa 1
[info] + blaa blaa 2
[info]
[info]
[info] Total for specification FooSpec
[info] Finished in 18 ms
[info] 2 examples, 0 failure, 0 error
[info]
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 3 s, completed Mar 26, 2017 7:09:34 PM
Why is stop task run even before compilation is finished and how to fix it so that it is run after all test cases are run (despite the result of the test cases)?
Also the start task should run after successfull compilation but before first test case. How to fix these?
How about doing it like this instead?
def startS(): Unit = { println("Running start")}
def stopS(): Unit = { println("Running stop")}
testOptions in Test in subPro += Tests.Setup { () => startS() }
testOptions in Test in subPro += Tests.Cleanup { () => stopS() }

ScalaCheck specificy minimum successful tests for property

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
}
}
}
}

Why Mockito doesn't handle default Scala parameters properly?

I have a code like
test("mockito test") {
class ToTest {
def run(maybe: Option[Int], q: Option[Int] = None): Int = 42
}
val mockTest = mock[ToTest]
when(mockTest.run(None, None)).thenReturn(98)
mockTest.run(None)
verify(mockTest, times(1)).run(None, None)
}
Which fails with
[info] - mockito test *** FAILED ***
[info] org.mockito.exceptions.verification.junit.ArgumentsAreDifferent: Argument(s) are different! Wanted:
[info] toTest$1.run(None, None);
[info] -> at xxx$$anonfun$3.apply$mcV$sp(xxx.scala:55)
[info] Actual invocation has different arguments:
[info] toTest$1.run(None, null);
Or another scenario
test("mockito test") {
class ToTest {
def run(maybe: Option[Int], q: Int = 5): Int = 42
}
val mockTest = mock[ToTest]
when(mockTest.run(None, 5)).thenReturn(101)
mockTest.run(None)
verify(mockTest, times(1)).run(None, 5)
}
which fails with
[info] - mockito test *** FAILED ***
[info] org.mockito.exceptions.verification.junit.ArgumentsAreDifferent: Argument(s) are different! Wanted:
[info] toTest$1.run(None, 5);
[info] -> at xxx$$anonfun$3.apply$mcV$sp(xxx.scala:55)
[info] Actual invocation has different arguments:
[info] toTest$1.run(None, 0);
I guess it's because there are no default parameters in Java. Is there any workaround for it?
Thank you.
I guess that's because of CGLIB (or Byte Buddy in case of 2.0 beta) generates the code in that case, not Scala compiler, hence the default parameters will be always null.
A workaround could be (at least in some cases) to use spy instead:
val mockTest = spy(classOf[ToTest])
Sorry, no sugar syntax for it in ScalaTest.

scala.util.Try does not wrap Exception when used with Future and Play WS

My understanding is that scala.util.Try wraps exceptions thrown any code inside the Try { ... } block.
Here is a simple example that wraps a NullPointerException.
object TryDemo extends App {
import scala.util.{Failure, Success, Try}
def doSomething(i: Int): String = {
if (i > 50) {
println("going to throw NullPointerException at index " + i)
throw new NullPointerException("- Exception at index " + i)
}
else
"some-result"
}
val t: Try[String] = Try {
var x = 0
while (x < 100) {
doSomething(x)
x += 1
}
"result-" + x
}
val result: Option[String] = t match {
case Success(s) => println("success " + s); Some(s)
case Failure(f) => println("failure " + f.getMessage()); None
}
}
This gives the following output as excepted.
going to throw NullPointerException at index 51
failure - Exception at index 51
However, when I try to do the following (with an invalid URL to ensure that it fails every time)
import play.api.libs.ws._
val wsURL = "http://invalidurl:9000/something"
val wsres: Try[Future[Response]] = Try {
WS.url(wsURL).withRequestTimeout(200).withQueryString(("param", value)).get
}
Exceptions are thrown instead of getting an error that is wrapped inside a Try.
Can anyone please explain why it works in the first case and not in the second ?
[info] java.net.ConnectException: http://invalidurl:9000/something
[info] at com.ning.http.client.providers.netty.NettyConnectListener.operationComplete(NettyConnectListener.java:103)
[info] at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:427)
[info] at org.jboss.netty.channel.DefaultChannelFuture.addListener(DefaultChannelFuture.java:145)
[info] at com.ning.http.client.providers.netty.NettyAsyncHttpProvider.doConnect(NettyAsyncHttpProvider.java:1068)
[info] at com.ning.http.client.providers.netty.NettyAsyncHttpProvider.execute(NettyAsyncHttpProvider.java:890)
[info] at com.ning.http.client.AsyncHttpClient.executeRequest(AsyncHttpClient.java:520)
[info] at play.api.libs.ws.WS$WSRequest.execute(WS.scala:177)
[info] at play.api.libs.ws.WS$WSRequestHolder.get(WS.scala:386)
[info] at controllers.geojson.GeoJsonTransfomer$$anonfun$9.apply(GeoJsonTransformer.scala:155)
[info] at controllers.geojson.GeoJsonTransfomer$$anonfun$9.apply(GeoJsonTransformer.scala:155)
[info] ...
[info] Cause: java.nio.channels.UnresolvedAddressException:
[info] at sun.nio.ch.Net.checkAddress(Net.java:127)
[info] at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:640)
[info] at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink.connect(NioClientSocketPipelineSink.java:108)
[info] at org.jboss.netty.channel.socket.nio.NioClientSocketPipelineSink.eventSunk(NioClientSocketPipelineSink.java:70)
[info] at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:54)
[info] at org.jboss.netty.handler.codec.http.HttpClientCodec.handleDownstream(HttpClientCodec.java:97)
[info] at org.jboss.netty.handler.stream.ChunkedWriteHandler.handleDownstream(ChunkedWriteHandler.java:109)
[info] at org.jboss.netty.channel.Channels.connect(Channels.java:634)
[info] at org.jboss.netty.channel.AbstractChannel.connect(AbstractChannel.java:207)
[info] at org.jboss.netty.bootstrap.ClientBootstrap.connect(ClientBootstrap.java:229)

How do you use play scala specs2 matchers across multiple files

I am using Play 2.2.1 with scala and trying to test with Specs2 matchers across multiple files. Everything works fine in one very large ApplicationSpec.scala file but I would like to move the code to separate files.
The following code is what I am using to test across multiple files but it is very intermittent.
ApplicationSpec.scala file
import org.specs2.mutable._
import org.specs2.mutable.Specification
import org.specs2.matcher.JsonMatchers
import org.specs2.runner._
import org.junit.runner._
#RunWith(classOf[JUnitRunner])
class ApplicationSpec extends PlaySpecification with JsonMatchers {
"Test using another file" should {
testing
"End of test" in {"End" must beEqualTo("End")}
}
This function is located inside the ApplicationSpec.scala file
def testing() {
"Multiple files" should {
"Testing testFile1" in {
testFile1.test1
testFile1.test2
"Test1 and Test2 should print before this line" in { 1 must beEqualTo(1)}
}
"Testing testFile2" in {
testFile2.test3
testFile2.test4
"Test3 and Test4 should print before this line" in { 1 must beEqualTo(1)}
}
}
}
testFile1.scala
object testFile1 extends ApplicationSpec {
def test1 {
"testFile1 - test1" in {1 must beEqualTo(1)}
}
def test2 {
"testFile1 - test2" in {1 must beEqualTo(1)}
}
}
testFile2.scala
object testFile2 extends ApplicationSpec {
def test3 {
"testFile2 - test3" in {1 must beEqualTo(1)}
}
def test4 {
"testFile2 - tes4" in {1 must beEqualTo(1)}
}
}
Test results Each time "play test" is run test1, test2, and test3, test4 may or may not print out. Sometimes all four tests show up or none of the tests are printed.
+ test WS logic
[info]
[info] Test using another file should
[info]
[info] Multiple files should
[info]
[info] Testing testFile1
[info] + Test1 and Test2 should print before this line
[info]
[info] Testing testFile2
[info] + testFile2 - test3
[info] + testFile2 - tes4
[info] + Test3 and Test4 should print before this line
[info] + End of test
[info]
[info] Total for specification testFile2
[info] Finished in 1 second, 713 ms
[info] 6 examples, 0 failure, 0 error
[info] testFile1
[info]
[info] Application should
[info] + test WS logic
[info]
[info] Test using another file should
[info]
[info] Multiple files should
[info]
[info] Testing testFile1
[info] + testFile1 - test1
[info] + testFile1 - test2
[info] + Test1 and Test2 should print before this line
[info]
[info] Testing testFile2
[info] + Test3 and Test4 should print before this line
[info] + End of test
[info]
[info] Total for specification testFile1
[info] Finished in 111 ms
[info] 6 examples, 0 failure, 0 error
[info] ApplicationSpec
[info]
[info] Application should
[info] + test WS logic
[info]
[info] Test using another file should
[info]
[info] Multiple files should
[info]
[info] Testing testFile1
[info] + Test1 and Test2 should print before this line
[info]
[info] Testing testFile2
[info] + Test3 and Test4 should print before this line
[info] + End of test
[info]
[info] Total for specification ApplicationSpec
[info] Finished in 99 ms
[info] 4 examples, 0 failure, 0 error
You can use traits to declare examples then import them to the main specification by mixing them in:
class TestSpec extends org.specs2.mutable.Specification with testFile1 with testFile2 {
"Test using another file" should {
testing
"End of test" in {"End" must beEqualTo("End")}
}
def testing {
"Multiple files" should {
"Testing testFile1" in {
tests1
"Test1 and Test2 should print before this line" in { 1 must beEqualTo(1)}
}
"Testing testFile2" in {
tests2
"Test3 and Test4 should print before this line" in { 1 must beEqualTo(1)}
}
}
}
trait testFile1 extends org.specs2.mutable.Specification {
def tests1 = {
"testFile1 - test1" in {1 must beEqualTo(1)}
"testFile1 - test2" in {1 must beEqualTo(1)}
}
}
trait testFile2 extends org.specs2.mutable.Specification {
def tests2 = {
"testFile2 - test3" in {1 must beEqualTo(1)}
"testFile2 - tes4" in {1 must beEqualTo(1)}
}
}