Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Testing Your Plugin with Multiple Versions of Play

DZone's Guide to

Testing Your Plugin with Multiple Versions of Play

· Java Zone ·
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

So, you’ve written a plugin for Play…are you sure it works?

I’ve been giving Deadbolt some love recently, and as part of the work I’ve added a test application for functional testing. This is an application that uses all the features of Deadbolt, and is driven by HTTP calls by REST-Assured. Initially, it was based on Play 2.3.5 but this ignores the supported Play versions of 2.3.1 through to 2.3.4. Additionally, those hard-working people on the Play team at Typesafe keep cranking out new feature-filled versions.

On top of that, support for Scala 2.10.4 and 2.11.1 is required so cross-Scala version testing is needed.

Clearly, testing your plugin against a single version of Play is not enough. Seems like some kind of continuous integration could help us out here…

Building on Travis CI

Deadbolt builds on Travis CI, a great CI platform that’s free for open-source projects. This runs the tests, and publishs snapshot versions to Sonatype. I’m not going into detail on this, because there’s already a great guide over at Cake Solutions. You can find the guide here:http://www.cakesolutions.net/teamblogs/publishing-artefacts-to-oss-sonatype-nexus-using-sbt-and-travis-ci-here…

I’ve made some changes to the build script because the plugin code is not at the top level of the repositry; rather, it resides one level down. The repository looks like this:

deadbolt-2-java
  |-code        # plugin code lives here
  |-test-app    # the functional test application

As a result, the .travis.yml file that defines the build, looks like this.

language: scala
jdk:
- openjdk6
scala:
- 2.11.1
script:
- cd code
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../test-app
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../code
- sbt ++$TRAVIS_SCALA_VERSION +publish-local
after_success:
- ! '[[ $TRAVIS_BRANCH == "master" ]] && { sbt +publish; };'
env:
global:
- secure: foo
- secure: bar

This sets the Java version (people get angry when I don’t provide Java 6-compatible versions), and defines a script as the build process. Note the cd commands used to switch between the plugin directory and the test-app directory.

This script already covers the cross-Scala version requirement – prefixing a command with +, e.g. +test, will execute that command against all versions of Scala defined in your build.sbt. It’s important to note that although only Scala 2.11.1 is defined in .travis.yml, SBT itself will take care of setting the current build version based on build.sbt.

crossScalaVersions := Seq("2.11.1", "2.10.4")

Testing multiple versions of Play

However, the version of Play used by the test-app is still hard-coded to 2.3.5 in test-app/project/plugins.sbt.

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.5")

Happily, .sbt files are not just configuration files but actual code. This means we can change the Play version based on environment properties. A default value of 2.3.5 is given to allow the tests to run locally without having to set the version.

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % System.getProperty("playTestVersion", "2.3.5"))

Finally, we update .travis.yml to take advantage of this.

language: scala
jdk:
- openjdk6
scala:
- 2.11.1
script:
- cd code
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../test-app
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.1 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.2 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.3 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.4 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.5 +test
- cd ../code
- sbt ++$TRAVIS_SCALA_VERSION +publish-local
after_success:
- ! '[[ $TRAVIS_BRANCH == "master" ]] && { sbt +publish; };'
env:
global:
- secure: foo
- secure: bar

This means the following steps occur during the build:

  • sbt ++$TRAVIS_SCALA_VERSION +test
    • Run the plugin tests against Scala 2.11.1
    • Run the plugin tests against Scala 2.10.4
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.1 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.1
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.1
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.2 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.2
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.2
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.3 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.3
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.3
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.4 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.4
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.4
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.5 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.5
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.5

If all these steps pass, the after_success branch of the build script will execute. If any of the steps fail, the build will break and the snapshots won’t be published.

You can take a look at a repository using this approach here: https://github.com/schaloner/deadbolt-2-java.

The resulting Travis build is available here: https://travis-ci.org/schaloner/deadbolt-2-java.

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}