Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

Entries in chariot-news (45)

Wednesday
May142014

Coming up May 22-23 - AngularJS Training at Chariot Solutions

If you were looking to take an AngularJS course, now is the time. We're offering a two-day fundamentals course on May 22-23 that covers:

  • A primer on modern Javascript
  • Modules
  • Views and Routing
  • The Controller
  • Services
  • Directives

Register Today!

All of this and testing, focusing on Jasmine and the Karma test runner. You'll learn a lot in a short period of time. I hope to see some of you there.

If you are interested in a private training course offering, drop us a line at our website and we can discuss.

Sunday
Jul082012

Spock's data tables are sweet!

I'm working with Spock again for updating my CoffeeScript plugin for Roo 1.2.3. There have been a few helpful additions to the add-on APIs (unless I missed them in 1.2.2...) and so my code is getting a tad simpler.

The coolest thing is that converting my tests to Spock, I had an easy way to do a truth table testing condition when I wanted to try out a number of scenarios. Check out this snippet, specifically the "where:" block and the values from the where block variables within the test conditions.

I've switched this test to the more formal given: when: then: syntax, and added the where: section for the data tables settings. I think I was using setup: instead of given: and I also didn't put my expectations in the then: section, which they evaluate in regardless. It's more readable this way.

Note, the version of the coffeescript add-on listed in the test is irrelevant, as the method called to fetch the plugin ignores it but the Plugin constructor requires a version.

@Unroll("evalto #evalto for project available #available, 
         packaging #packaging and pluginList #pluginList")
def "test isPluginInstalled with scenarios"() {
    given:
    def projectOperations = Mock(ProjectOperations.class)
    coffeescriptOperations.projectOperations = projectOperations
    def pom = Mock(Pom.class)

    when:
    def result = coffeescriptOperations.isPluginInstalled()

    then:
    coffeescriptOperations.projectOperations
            .isFocusedProjectAvailable() >> available
    coffeescriptOperations.projectOperations.getFocusedModule() >> pom
    pom.getPackaging() >> packaging
    pom.getBuildPluginsExcludingVersion(_) >> pluginList

    result == evalto

    where:
    pluginList | available | packaging  | evalto
    [] | false | "foo" | false
    [] | true  | "war" | false
    [] | true  | "pom" | false
    [new Plugin("com.theoryinpractise",
            "coffee-maven-plugin", "1.2.0") ] | true | "war" | true
    [new Plugin("com.theoryinpractise",
            "coffee-maven-plugin", "1.2.0")] | true | "pom" | false
}

I was able to fold five specific test cases checking whether the project contains the Coffeescript plugin into one test with five data settings (all false except one):

  • The focused project is not available
  • The packaging is a war, the focused project is available, the add-on is not installed
  • The packaging is a "pom" and the project is available
  • The plugin exists, the type is a war, the focused module is available (happy!)
  • The plugin exists (mounted by hand perhaps) on a pom project which is the current module

I used @Unroll to turn the data table results into five separate tests, each of which listed separately in the test results. Note the method name of the test is comprised of literal strings with data from the datatable columns starting with '#'. Nice, eh?

So I was able to collapse five test scenarios into one with the data tables. Nice.

You can pull the git repository for this add-on by using:

git clone git://git.cloudbees.com/sillyweasel/coffeescript-roo-addon.git
Thursday
Jun212012

Now on java.net : my article on WebFlow and Roo from the "Cutting Room Floor" of Roo in Action

You can read my first java.net article, posted on our behalf from Manning's author articles series, entitled Spring Roo and WebFlow, on Java.Net's technical articles series starting today.

Thanks to Manning's Nermina Miller for helping me get it finished, java.net's Kevin Farnham for publishing it, and Manning's Candace Gillhooley for getting the project going.

I anticipate a few more "cutting room floor" articles, since the book took some twisty turns while Srini and I were formulating the content for the final book.

Thursday
May242012

Spock and Roo = easier add-on testing, part 2

Moving on to some more interesting tests. Given this method:


public boolean isInstalljQueryCommandAvailable() {
    String jsLocation = pathResolver.getFocusedIdentifier(
        Path.SRC_MAIN_WEBAPP, "/js");

    return fileManager.findMatchingAntPath(
        jsLocation + "**/jquery-1.*.min.js").isEmpty();
  }

I want to use Spock to test it. The challenge is the somewhat more nested set of objects. My add-on extends the AbstractOperations class (to get the embedded fileManager), so I need to mock that, plus mock the path resolver I've mounted with @Reference in my add-on as well.

To set it up I do this:

class JqueryuiOperationsImplTest extends spock.lang.Specification {

    JqueryuiOperationsImpl operations;

    def setup() {
        operations = new JqueryuiOperationsImpl();

        operations.pathResolver = Mock(PathResolver);
        operations.fileManager = Mock(FileManager);
    }

Spock mocks are similar to EasyMock, in that we then detail our assertions of what should happen before the test runs. In fact, based on a really interesting thread I found this AM while banging my head against the wall (don't do that, it hurts), if you put any mocking assertions in the when: part of a Spock test, it moves them to the setup: block. Anyway, here is my set of assertions:

    def "isJqueryInstallAvailable called and happy path"() {

        setup:
        1* operations.pathResolver.getFocusedIdentifier(
                _, _) >> "src/main/webapp/js"

        1* operations.fileManager.findMatchingAntPath(
                _ as String) >> new TreeSet<FileDetails>()

I'm using Spock's matchers to eat the expressions - I don't really care what we pass to the getFocusedIdentifier or findMatchingAntPath methods, I just want them mocked and I want them to return values.

The >> is what tells us that we're stubbing the return output.

Here is the full test:

    def "isJqueryInstallAvailable called and happy path"() {
        setup:
        1* operations.pathResolver.getFocusedIdentifier(
                _, _) >> "src/main/webapp/js"

        1* operations.fileManager.findMatchingAntPath(
                _ as String) >> new TreeSet<FileDetails>()

        when:
        def result = operations.isInstalljQueryCommandAvailable();

        then:
        result == true
    }

Don't do what I did to get my head bruised. I originally wrote this:


1* operations.fileManager.findMatchingAntPath(
                _ as String).empty() >> false

I got my brain mixed up because I saw the line:

    return fileManager.findMatchingAntPath(
        jsLocation + "**/jquery-1.*.min.js").isEmpty();

And that's going to throw a tasty NullPointerException because you're mocking the return of the method in fileManager, not the return statement! Oh, bother.

Tuesday
May222012

Spock and Roo = easier add-on testing, part 1

Hey all...

I've been working on my add-ons. If you're reading this from my website, head over to the Silly Weasel menu and get the repository OBR to install my Spock add-on when trying this.

You are running Groovy in Roo? Shame on you!

Hey, before I was a Roo in Action author, I was a huge fan of Grails. I still am, because Groovy + your favorite APIs is so much more concise to program against than with stock Java. So, one of my backburner projects was getting Groovy to work on Roo.

Roo doesn't like Groovy (yet)

It turns out the reason is AspectJ. Right now, our projects are all compiling against the AspectJ API (version 1.2.x if memory serves). The problem is that Groovy's bytecode is not compatible with AspectJ, at least in terms of getting it to compile in the same Maven compiler step. I looked on the AspectJ timeline, and saw AspectJ 1.5 and 2.0 will support Groovy as a target for weaving. Coolness!

But that doesn't stop us from using it to test!

Yep, that's right. Turns out you can attach the Groovy compiler to your test phase, and it works. By the time your tests are compiling, the main classes have been compiled and weaved with that AspectJ goodness. So your ITD methods are there, and you can use any old testing tool you want to test 'em.

Note, I think you may have issues with my approach, if you are going to use the DataOnDemand testing framework, but so far, it seems like it works well.

My example for the evening - testing with mocks for Add-on Commands

Ok, here's a practical example. My jQueryUI add-on command class delegates the isAvailable and install commands to the Operations Implementation class, JqueryuiOperationsImpl. I wanted to start working up the test coverage for this add-on, because right now I am failing my hudson build due to a lack of test coverage.

So, here is a Groovy Spock specification, which I named JQueryuiCommandsTest.groovy and placed in src/test/groovy (after installing the maven script I'll reference below it). I've even created a Spock Roo add-on for you to use to set this up in your own projects.



package org.sillyweasel.addons.jqueryui

class JQueryuiCommandsTest extends spock.lang.Specification {

    JqueryuiCommands commands
    JqueryuiOperations operations

    def setup() {
        operations = Mock()
        commands = new JqueryuiCommands();
        commands.operations = operations;
    }

    def "when calling availability we defer to implementation" () {
        when:
        boolean result = commands.isApiInstallCommandAvailable()

        then:
        1*operations.isInstalljQueryCommandAvailable()
    }

    def "when calling ui availability we defer to implementation" () {
        when:
        boolean result = commands.isInstalljQueryUIAvailable()

        then:
        1*operations.isInstalljQueryUICommandAvailable()
    }

    def "when calling installjQueryApi we defer to jquery operations method" () {
        when:
        commands.installjQueryApi()

        then:
        1*operations.installjQueryApi();
    }

    def "when calling installjQueryUI we defer to jquery operations method"() {
        when:
        commands.installjQueryUIApi()

        then:
        1*operations.installjQueryUIApi();
    }


}

How did you get this to work?

I basically stole the configuration for Spock and Maven, and tweaked it a bit. Here are the relevant bits of my Maven build:

<dependency>
    <groupId>org.spockframework</groupId>
    <artifactId>spock-core</artifactId>
    <version>0.6-groovy-1.8</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.spockframework</groupId>
    <artifactId>spock-spring</artifactId>
    <version>0.6-groovy-1.8</version>
    <scope>test</scope>
</dependency>

...

<plugin>
   <groupId>org.codehaus.gmaven</groupId>
   <artifactId>gmaven-plugin</artifactId>
   <version>1.4</version>
   <configuration>
       <providerSelection>1.8</providerSelection>
       <source>src/test/groovy</source>
   </configuration>
   <executions>
       <execution>
           <goals>
               <goal>testCompile</goal>
           </goals>
       </execution>
   </executions>
   <dependencies>
       <dependency>
           <groupId>org.codehaus.gmaven.runtime</groupId>
           <artifactId>gmaven-runtime-1.7</artifactId>
           <version>1.3</version>
           <exclusions>
               <exclusion>
                   <groupId>org.codehaus.groovy</groupId>
                   <artifactId>groovy-all</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>org.codehaus.groovy</groupId>
           <artifactId>groovy-all</artifactId>
           <version>1.8.6</version>
       </dependency>
       <dependency>
           <groupId>org.spockframework</groupId>
           <artifactId>spock-core</artifactId>
           <version>0.6-groovy-1.8</version>
       </dependency>
       <dependency>
           <groupId>org.spockframework</groupId>
           <artifactId>spock-spring</artifactId>
           <version>0.6-groovy-1.8</version>
       </dependency>
   </dependencies>
</plugin>