jasmine-maven-plugin
what have we here?

As one might intuit, the jasmine-maven-plugin is a Maven plugin for the JavaScript testing framework, Jasmine.

If you're using Maven, you're probably writing Java (but, hey, you could be using it for any JVM-language). And if you're anything like me, you're here to figure out how to treat your client-side code with the same degree of professionalism that you already show server-side code. Maybe that means you want a painless way to test-drive your JavaScript. Maybe you're trying to figure out how to incorporate JavaScript tests on your continuous integration server without requiring any browser shenanigans.

the good news
the 30 second version

First run this:


mvn archetype:generate -DarchetypeRepository=http://searls-maven-repository.googlecode.com/svn/trunk/snapshots -DarchetypeGroupId=com.github.searls -DarchetypeArtifactId=jasmine-archetype -DarchetypeVersion=1.1.0.1-SNAPSHOT -DgroupId=com.acme -DartifactId=my-jasmine-project -Dversion=0.0.1-SNAPSHOT
    

And then this:


cd my-jasmine-project && mvn jasmine:bdd
    

Then go here and you should see:

adding it to your project

If you're already familiar with adding Maven plugins to POM files, then this should be a breeze. If it's new to you, then take a deep breath and contemplate adding this XML to your project's "pom.xml" file:


  <build>
    …
    <plugins>
      …
      <plugin>
        <groupId>com.github.searls</groupId>
        <artifactId>jasmine-maven-plugin</artifactId>
        <version>1.1.0</version>
        <executions>
          <execution>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <!-- configuration properties will go here -->
        </configuration>
      </plugin>
      …
    </plugins>
    …
  </build>
      

writing Jasmine specs

Ready to try it out? Once you've added the plugin to your project, just run the following in a terminal:


mvn jasmine:bdd
    

You should see some output like this


[INFO]

Server started--it's time to spec some JavaScript! You can run your
 specs as you develop by visiting this URL in a web browser:

  http://localhost:8234

The server will monitor these two directories for scripts
 that you add, remove, and change:

  source directory: src/main/javascript

  spec directory: src/test/javascript

Just leave this process running as you test-drive your code,
refreshing your browser window to re-run your specs.
You can kill the server with Ctrl-C when you're done.
    

Now visit http://localhost:8234 in your browser of choice and you should see a Jasmine spec runner with 0 specs, 0 failures. Sort of like this one:

And that's it! When you add source scripts to the source directory and spec scripts to the specs directory and refresh the page, your specs will be executed.

Running the jasmine:bdd goal and refreshing an actual browser will always provide substantially faster feedback than the headless jasmine:test goal. As a result, I strongly recommend you use it to drive development of your JavaScript and only worry about running the headless execution when you would otherwise perform full Maven builds (like before you push your code or in CI).

running a build

If you've added the plugin as shown above (that is, with an execution of the test goal) to your POM, it's already set up execute your Jasmine specs every time your build goes through the test lifecycle phase!

So when you run this:


mvn clean test
    

A happy build might output:


[INFO] Executing Jasmine Specs
[INFO]
-------------------------------------------------------
 J A S M I N E   S P E C S
-------------------------------------------------------
[INFO]
the ElementMover object
  instantiation
    throws an exception if you forget "new"
  moving around two divs
    initially sees that div1 is above div2
    moves div1 after div2
    moves div2 before div1
    adding a third div to the mix
      moves div1 betwixt div2 & div3
      moves div3 before div1

Results: 6 specs, 0 failures

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.607s
[INFO] Finished at: Mon Jul 04 15:01:58 EDT 2011
[INFO] Final Memory: 9M/81M
[INFO] ------------------------------------------------------------------------
    

And a failing build might output:


[INFO] Executing Jasmine Specs
[INFO]
-------------------------------------------------------
 J A S M I N E   S P E C S
-------------------------------------------------------
[INFO]
HelloWorld
  should say hello
  wins
  wins
  wins
  loses <<< FAILURE!
    * Expected 'sad' to be 'panda'.

1 failure:

  1.) HelloWorld it loses <<< FAILURE!
    * Expected 'sad' to be 'panda'.

Results: 5 specs, 1 failures

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.020s
[INFO] Finished at: Mon Jul 04 15:03:47 EDT 2011
[INFO] Final Memory: 8M/81M
[INFO] ------------------------------------------------------------------------
    

The plugin relies on HtmlUnit for headless (which is to say, GUI-less) execution. It's not a perfect emulation of a browser, but for moderately well-isolated unit testing (e.g. only pedestrian interactions with the DOM), it works really well.

tailoring it

The plugin makes numerous assumptions about how you've structured your project. To compensate for the fact that its defaults won't suit your project perfectly, it comes with a (confusingly vast) array of configuration properties. While you can find all of the properties in the project's source code, here are some of the popular ones.

(Also: for help seeing how these and other properties might be used, you can find a number of example projects in the project's github repo, which are used to support its Cucumber features.)

name purpose default notes
sourceIncludes an ordered list of filters to match script source files [**/*.js, **/*.coffee] Often, you'll want to use sourceIncludes to control the ordering of your sources. If your external dependencies need to be loaded first, you might:

<sourceIncludes>
  <include>vendor/**/*.js</include>
  <include>myBootstrapFile.js</include>
  <include>**/*.js</include>
  <include>**/*.coffee</include>
</sourceIncludes>
            
specIncludes an ordered list of filters to match script spec files [**/*.js, **/*.coffee] I often find myself needing control of the spec include order when I have some global spec helpers or spec-scoped dependencies, like:

<specIncludes>
  <include>jasmine-jquery.js</include>
  <include>spec-helper.js</include>
  <include>**/*.js</include>
  <include>**/*.coffee</include>
</specIncludes>
            
jsSrcDir directory storing your JavaScript src/main/javascript serving a Java webapp? You might set this to "${project.basedir}/src/main/webapp/js"
serverPort the port that the jasmine:bdd goal binds to 8234
skipTests when true, specs won't be executed during the build false will most likely come in handy when set on the command line, like so: mvn package -DskipTests
format the style with which the plugin outputs results during the build documentation setting this to "progress" will print your specs in a much more succinct "....FF.." style
sourceExcludes just like sourceIncludes, but will exclude anything matching the provided patterns (none)
specExcludes just like specIncludes, but will exclude anything matching the provided patterns (none)
jsTestSrcDir directory storying your Jasmine Specs src/test/javascript
browserVersion the type of browser HtmlUnit emulates when your specs run during the build FIREFOX_3 valid values also include: FIREFOX_3_6, INTERNET_EXPLORER_6, INTERNET_EXPLORER_7, INTERNET_EXPLORER_8
haltOnFailure when true, failing specs break the build true you might want to set this to false temporarily when you have a known failing spec but you don't want to turn off spec execution altogether.
customRunnerTemplate an HTML file that defines how the spec runner pages are rendered for an example, consider starting from the plugin's default template.
preloadSources a list of relative-paths to scripts that need to be loaded before any others. this property is only rarely neceesary. It might help in a situation where a spec file needs to be loaded above production sources, or when a remote dependency needs to be included (ex. <preloadSources><source>http://a.com/lib.js</source></preloadSources>)
timeout when spec execution exceeds the timeout (in seconds), the build fails 300 if you have a lot of specs or if you're using Jasmine for integration testing, you may find that you need to increase this limit.
junitXmlReportFileName the name of the generated JUnit XML report TEST-jasmine.xml the plugin generates XML of the same brand JUnit does; this is handy for when your CI server is capable of aggregating these XML files (like Jenkins freestyle projects)