Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  1. Start TestServer with FakeApplication. Use an alternative integration test conf file
  2. Run Integration tests (can filter by package or what not here)
  3. 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!

like image 890
noplay Avatar asked May 01 '13 12:05

noplay


2 Answers

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.

like image 127
noplay Avatar answered Nov 01 '22 19:11

noplay


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
like image 41
mundacho Avatar answered Nov 01 '22 18:11

mundacho