Run check before tests - scala

I have tests which are run against a real database (not an in-memory or mocked up one). Before the tests run, I want to check the environment variables to make sure that the TEST database is not the same as the PROD database. If they do match I want to stop the tests.
I thought I could do something like this:
class Main extends Suites (
new EnvironmentTest, // This needs to run first!!
new Tests1,
new Tests2,
new Tests3
)
#DoNotDiscover
class EnvironmentTest extends PlaySpec {
"Environment variables" should {
"PROD SQL DB should be different from TEST SQL DB" in {
// Do check and stop execution
throw new EnvironmentVariableException("TEST and PROD are the same!")
}
}
}
When I run this code, the exception is thrown and the first test fails, but the rest of the tests will run.
Is it possible to stop the execution of the tests (or do a check before hand to prevent them from running at all) ?

Related

Any idea why flaky plugin is not triggered on failed tests decorated with #pytest.mark.flaky(max_runs=...)

I have a pytest suite running in this env:
Test session starts (platform: linux, Python 3.6.1, pytest 3.3.1, pytest-sugar 0.9.1)
plugins: flaky-3.5.3, dependency-0.3.2, forked-0.2, logger-0.4.0, sugar-0.9.1, xdist-1.24.1
I have a parametrized test, decorated with flaky, and it is supposed to be re-run max three times if it fails.
#pytest.mark.flaky(max_runs=3) # re-run this test in case it fails
def test_cucubau(getBauBau_fixture):
assert cucubau(getBauBau_fixture) == True
However, it fails only once, it is not re-run, and my flaky test report is empty.
===Flaky Test Report===
===End Flaky Test Report===
Based on what I read about flaky plugin, the usage should be trivial.. but I'm not able to see what is wrong with my code.
any idea?
I believe you need the pytest-rerunfailures plugin for that to work. Then you should be able to annotate your test with #pytest.mark.flaky(reruns=3).

pytest-xdist indirect fixtures with class scope

I have some complicated and heavy logic to build a test object and the tests are very long running. They are integration tests and I wanted to try and parallelize them a bit. So i found the pytest-xdist library.
Because of the heavy nature of building the test object, I am using pytests indirection capability on fixtures to build them at test time rather than at collection. Some code I am using for testing can be found below.
#run.py
import pytest
#pytest.mark.parametrize("attribute",(
["pid1", ["pod1", "pod2", "pod3"]],
["pid2", ["pod2", "pod4", "pod5"]]
), indirect=True)
class TestSampleWithScenarios(object):
#pytest.fixture(scope="class")
def attribute(request):
# checkout the pod here
# build the device object and yield
device = {}
yield device
# teardown the device object
# release pod
def test_demo1(self, attribute):
assert isinstance(attribute, str)
def test_demo2(self, attribute):
assert isinstance(attribute, str)
My run command is currently pytest run.py -n 4 --dist=loadscope
When I do no use loadscope, all the tests are sent to their own worker. I do not want this because I would like to only build the device object once and use it for all related tests.
When I use loadscope, all the tests are executed against gw0 and I am not getting any parallelism.
I am wondering if there is any tweaks that I am missing or is this functionality not implemented currently.

Setting DNS lookup's TimeToLive in Scala Play

I am trying to set the TimeToLive setting for DNS Lookup in my Scala-Play application. I use Play 2.5.9 and Scala 2.11.8 and follow the AWS guide. I tried the following ways:
in application.conf
// Set DNS lookup time-to-live to one minute
networkaddress.cache.ttl=1
networkaddress.cache.negative.ttl=1
in AppModule or EagerSingleton (the code would be similar)
class AppModule() extends AbstractModule {
Security.setProperty("networkaddress.cache.ttl", "1")
Security.setProperty("networkaddress.cache.negative.ttl", "1")
...
}
passing as environment variable:
sbt -Dsun.net.inetaddr.ttl=1 clean run
I have the following piece of test code in the application:
for (i <- 1 to 25) {
System.out.println(java.net.InetAddress.getByName("google.com").getHostAddress())
Thread.sleep(1000)
}
This always prints the same IP address, e.g. 216.58.212.206. To me it looks like none of the approaches specified above have any effect. However, maybe I am testing something else and not actually the value of TTL. Therefore, I have two questions:
what is the correct way to pass a security variable into a Play application?
how to test it?
To change the settings for DNS cache via java.security.Security you have to provide a custom application loader.
package modules
class ApplicationLoader extends GuiceApplicationLoader {
override protected def builder(context: Context): GuiceApplicationBuilder = {
java.security.Security.setProperty("networkaddress.cache.ttl", "1")
super.builder(context)
}
}
When you build this application loader you can enable it in your application.conf
play.application.loader = "modules.ApplicationLoader"
after that you could use your code above and check if the DNS cache is behaving like you set it up. But keep in mind that your system is accessing a DNS server which is caching itself so you wont see change then.
If you want to be sure that you get different addresses for google.com you should use an authority name server like ns1.google.com
If you want to write a test on that you could maybe write a test which requests the address and then waits for the specified amount of time until it resolves again. But with a DNS system out of your control like google.com this could be a problem, if you hit a DNS server with caching.
If you want to write such a check you could do it with
#RunWith(classOf[JUnitRunner])
class DnsTests extends FlatSpec with Matchers {
"DNS Cache ttl" should "refresh after 1 second"
in new WithApplicationLoader(new modules.ApplicationLoader) {
// put your test code here
}
}
As you can see you can put the custom application loader in the context of the application starting behind your test.

Integration Test in Play Framework

I am trying to get Integration Tests to work in Play Framework 2.1.1
My goal is to be able to run Integration Tests after unit tests to test component level functionality with the underlying database. The underlying database will have stored procedures, so it is essential that I am able to do more than just the "inMemoryDatabase" that you can configure in the Fake Application.
I would like the process to be:
Start TestServer with FakeApplication. Use an alternative integration test conf file
Run Integration tests (can filter by package or what not here)
Stop TestServer
I believe the best way to do this is in the Build.scala file.
I need assistance for how to setup the Build.scala file, as well as how to load the alternative integration test config file (project/it.conf right now)
Any assistance is greatly appreciated!
I have introduced a method that works for the time being. I would like to see Play introduce the concept of separate "Test" vs "IntegrationTest" scopes in sbt.
I could go into Play and see how they build their project and settings in sbt and try to get IntegrationTest scope to work. Right now, I spent too much time trying to get it functioning.
What I did was to create a Specs Around Scope class that gives me the ability to enforce a singleton instance of a TestServer. Anything that uses the class will attempt to start the test server, if it is already running, it won't be restarted.
It appears as though Play and SBT do a good job of making sure the server is shut down when the test ends, which works so far.
Here is the sample code. Still hoping for some more feedback.
class WithTestServer(val app: FakeApplication = FakeApplication(),
val port: Int = Helpers.testServerPort) extends Around with Scope {
implicit def implicitApp = app
implicit def implicitPort: Port = port
synchronized {
if ( !WithTestServer.isRunning ) {
WithTestServer.start(app, port)
}
}
// Implements around an example
override def around[T: AsResult](t: => T): org.specs2.execute.Result = {
println("Running test with test server===================")
AsResult(t)
}
}
object WithTestServer {
var singletonTestServer: TestServer = null
var isRunning = false
def start(app: FakeApplication = FakeApplication(), port: Int = Helpers.testServerPort) = {
implicit def implicitApp = app
implicit def implicitPort: Port = port
singletonTestServer = TestServer(port, app)
singletonTestServer.start()
isRunning = true
}
}
To take this a step further, I simply setup two folders (packages) in the play/test folder:
- test/unit (test.unit package)
- test/integration (test.integration pacakage)
Now, when I run from my Jenkins server, I can run:
play test-only test.unit.*Spec
That will execute all unit tests.
To run my integration tests, I run:
play test-only test.integration.*Spec
That's it. This works for me for the time being until Play adds Integration Test as a lifecycle step.
The answer for this is shared in this blog post https://blog.knoldus.com/integration-test-configuration-in-play-framework/
Basically, in build.sbt:
// define a new configuration
lazy val ITest = config("it") extend(Test)
/// and add it to your project:
lazy val yourProject = (project in file("yourProject"))
.configs(ITest)
.settings(
inConfig(ITest)(Defaults.testSettings),
ITest / scalaSource := baseDirectory.value / "it",
[the rest of your configuration comes here])
.enablePlugins(PlayScala)
Just tested this in 2.8.3 and works like a charm.
Lauch your ITs from sbt using:
[yourProject] $ it:test

Code coverage on Play! project

I have a Play! project where I would like to add some code coverage information. So far I have tried JaCoCo and scct. The former has the problem that it is based on bytecode, hence it seems to give warning about missing tests for methods that are autogenerated by the Scala compiler, such as copy or canEqual. scct seems a better option, but in any case I get many errors during tests with both.
Let me stick with scct. I essentially get errors for every test that tries to connect to the database. Many of my tests load some fixtures into an H2 database in memory and then make some assertions. My Global.scala contains
override def onStart(app: Application) {
SessionFactory.concreteFactory = Some(() => connection)
def connection() = {
Session.create(DB.getConnection()(app), new MySQLInnoDBAdapter)
}
}
while the tests usually are enclosed in a block like
class MySpec extends Specification {
def app = FakeApplication(additionalConfiguration = inMemoryDatabase())
"The models" should {
"be five" in running(app) {
Fixtures.load()
MyModels.all.size should be_==(5)
}
}
}
The line running(app) allows me to run a test in the context of a working application connected to an in-memory database, at least usually. But when I run code coverage tasks, such as scct coverage:doc, I get a lot of errors related to connecting to the database.
What is even more weird is that there are at least 4 different errors, like:
ObjectExistsException: Cache play already exists
SQLException: Attempting to obtain a connection from a pool that has already been shutdown
Configuration error [Cannot connect to database [default]]
No suitable driver found for jdbc:h2:mem:play-test--410454547
Why is that launching tests in the default configuration is able to connect to the database, while running in the context of scct (or JaCoCo) fails to initialize the cache and the db?
specs2 tests run in parallel by default. Play disables parallel execution for the standard unit test configuration, but scct uses a different configuration so it doesn't know not to run in parallel.
Try adding this to your Build.scala:
.settings(parallelExecution in ScctPlugin.ScctTest := false)
Alternatively, you can add sequential to the beginning of your test classes to force all possible run configurations to run sequentially. I've got both in my files still, as I think I had some problems with the Build.scala solution at one point when I was using an early release candidate of Play.
A better option for Scala code coverage is Scoverage which gives statement line coverage.
https://github.com/scoverage/scalac-scoverage-plugin
Add to project/plugins.sbt:
addSbtPlugin("com.sksamuel.scoverage" % "sbt-scoverage" % "1.0.1")
Then run SBT with
sbt clean coverage test
You need to add sequential in the beginning of your Specification.
class MySpec extends Specification {
sequential
"MyApp" should {
//...//
}
}