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

Sunday
Oct212012

STS 3.1.0.RELEASE - not loving Spock / Groovy for ADJT projects

At SpringOne/2GX I tried the updated Springsource Tool Suite, 3.1.0, running a pre-4.0 Eclipse (as the STS 3.1.0 version is a bit tricky on Eclipse 4 until the 3.x - 4.0 migration bugs settle down).

Turns out there is a new error that shows up if you try to run anything Groovy within a AJDT project (which is the AspectJ Developer Tools plug-in Roo requires to compile all *.aj files when you're using them in the IDE).

You'll get:

Error compiling Groovy project: Either the Groovy-JDT patch is not installed or JavaBuilder is not being used.

I realize from talking to one of the developers at SpringOne that there have been some issues with the way Groovy handles AspectJ compiled classes, and that using Groovy within a Spring Roo project as general code it won't work properly, but this puts a damper on Spock at least from within the STS IDE. I can still run my tests from IntelliJ, however.

I'm going to post a request in the forums that we can turn off this error, so that we can use Spock for testing. So far, at least with Roo add-ons, I have used it to great effect and productivity, so at least for that use case I'd like to have an option to turn it off.

More soon.

Ken

Thursday
Oct042012

More Spock love - how I tested complex install scenarios

I'm in love. Officially. With Spock.

Ok, we've only been hanging out for a little bit, here and there. But one of the things I'm doing is prepping for an updated talk on Spring Roo add-ons at SpringOne/2GX. Rather than repeat the same things again, I wanted to show some practical help for people writing add-ons, things like how to write good tests.

Also, I wanted to point out a few things that need more work, bring up some issues for the JIRA queue, so that we can improve Roo further after SpringOne. We'll get to that later in this article.

Testing add-on availability

Testing whether an add-on setup command is available to expose to the Roo shell can be a bit tricky. For example, in the Spock Roo add-on, I expect that the user's shell is:

  • running in a project context
  • the project has to contain two maven dependencies for spock-core and spock-spring
  • the project has to contain one dependency for the gmaven-plugin to run Spock tests

So, there are several scenarios to test. I started down the road to testing them all individually. Bad developer. First off, there is a sort of truth table here:

installedDependenciesinstalledPluginsexpectedResult
nonenonetrue
depa, depbnonetrue
depaplugintrue
baddepnonetrue
depa, depbpluginfalse
depabadversion, depbplugintrue

Given:

  • depa and depb = the correct two Maven dependencies,
  • baddep is a Maven dependency completely unrelated
  • depabadversion is the same dependency but a different version
  • plug-in is the gmaven-plugin from codehaus
  • expectedResult is whether or not we can go ahead and install the add-on (i.e. replace what is there)

As I started the third method I saw so much duplication I started to back off. First I removed whatever extra calls I was making to various methods (such as projectOperations.getDependencies()) which made it easier to test (and debug). Then, I pulled out the data table syntax.

Here is what I ended up with. Totally boss, BTW:

package org.sillyweasel.roo.addons.spock
import org.springframework.roo.project.Dependency
import org.springframework.roo.project.Plugin
import org.springframework.roo.project.ProjectOperations
import org.springframework.roo.project.maven.Pom
import spock.lang.Unroll

class SpockOperationsImplTest extends spock.lang.Specification {

  static def depa = 
    new Dependency("org.springframework", "spock-core", "0.6-groovy-1.8")
  static def depb = 
    new Dependency ("org.springframework", "spock-spring", "0.6-groovy-1.8")
  static def depabadversion =
    new Dependency("org.springframework", "spock-core", "0.6-groovy-1.0")
  static def baddep = 
    new Dependency ("org.springframework", "sbad", "0.6-groovy-1.8")
  static def plugin = 
    new Plugin("org.codehaus.gmaven", "gmaven-plugin", "1.4")


  @Unroll
  def "install check - #situation"() {
    given:
      def pom = Mock(Pom.class)
      def operations = new SpockOperationsImpl()
      def projectOperations = Mock(ProjectOperations.class)
      operations.projectOperations = projectOperations

    when:
      def commandAvailable = operations.isSetupCommandAvailable()

    then:
      1 * projectOperations.isFocusedProjectAvailable() >> true
      1 * projectOperations.getFocusedModule() >> pom
      1 * pom.getDependencies() >> deps
      pom.getBuildPlugins() >> plugins
      assert commandAvailable == res

    where:
    deps          | plugins | res   | situation
    []            | []      | true  | "no installedDependencies or installedPlugin"
    [ depa, depb] | []      | true  | "all installedDependencies...
                                      but no installedPlugin"
    [ depa ]      | [plugin]| true  | "some installedDependencies...
                                       and installedPlugin"
    [ baddep ]    | []      | true  | "a different dependency and no plugins"
    [ depa, depb ]| [plugin]| false | "all installedDependencies and installedPlugin"
    [ depabadversion, depb ] 
                  | [plugin] | true | "bad version of a plugin"
  }
}

What's even better...

See the method name at the top? It has an embedded hash mark, and uses the `situation` field, plus the `@Unroll` annotation, to turn the method into five separate test methods on the fly at test time. Niiiice!

Roo's challenges - addon testing

Why am I doing all of my testing in Groovy when Roo is a Java-based framework? Three reasons:

  • I want to get rolling on add-ons,
  • I need to understand the weaknesses of the add-on API so I can try to help improve it,
  • I need to make sure I test the most code for the least effort!

To the middle point: Roo is based on Maven and Spring. It manages a Maven `pom.xml` file, as well as Spring, Java and other artifacts.

Because the Maven files are managed by some Java wrapper classes, written for the purpose of generating Maven POMs, they are currently good enough - you can fill them via an Xml DOM, for example, but they aren't inherently testable.

For example, the Pom class can't be mocked, so I can't inject a fake set of dependencies or plugins. That is, unless I install two Maven test dependencies, both of which Spock told me to use as a helpful hint! They are: `cglib-nodep` for mocking interface-less classes, and `objenesis` for creating instances of classes as Mocks without no-arg constructors. To wit:

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib-nodep</artifactId>
  <version>2.2.2</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.objenesis</groupId>
  <artifactId>objenesis</artifactId>
  <version>1.2</version>
  <scope>test</scope>
</dependency>

With that, I can use:

def pom = Mock(Pom.class)

See you at SpringOne/2GX

I'll be talking about this and other techniques at SpringOne/2GX in two weeks, and I'll post my presentation later as well. I hope to see some of you there.

Tuesday
Sep112012

My Roo add-ons talk at SpringOne/2GX is approved

Hello there. I'll be speaking about Spring Roo add-ons again at SpringOne/2GX this year. If you're heading to the show and want to talk shop on Roo and other things, seek me out. I'll be happy to chat.

Here is a link to the talk.

Thursday
Aug232012

Speaking at SpringOne/2GX - topic - Roo add-ons

Hello, viewers. I've just received word that I'll be speaking at SpringOne/2GX this year. No link yet but I'm working on that. I'll be down there all week, so I hope to see you there.

Sunday
Aug192012

Watch my SpringSource Roo add-ons video w/Srini Penchikala and SpringSource's Josh Long