About Tomasz Nurkiewicz

Java EE developer, Scala enthusiast. Enjoying data analysis and visualization. Strongly believes in the power of testing and automation.

FitNesse your ScalaTest with custom Scala DSL

This article won’t be about FitNesse. As matter of fact I don’t like this tool very much and it seems to be loosing momentum, judging by the traffic on an official mailing list. Instead we will implement trivial internal DSL on top of Scala to simplify testing code, inspired by DoFixture. DoFixture in FitNesse allows one to write very readable acceptance tests almost in plain English using Wiki pages:
 
 
 
 
 
 

!|CarRegistrationFixtureTest|
 
!1 Registering car
!2 Registering brand new car for the first time
 
| register | brand new car | by | any owner | in | any country |

What might not be obvious is that the last line is actually executable and calls good old Java (or Scala for that matter) method:

class CarRegistrationFixtureTest extends DoFixture {
 
    val carService = new CarService
 
    def registerByIn(car: Car, owner: Owner, where: Country) = {
        //...
    }
 
}

Notice how oddly named registerByIn method maps to “ register brand new car by any owner in any country” wiki syntax. What we will learn today is writing very simple, custom Scala DSL that is even more readable and does not require new tool and testing framework.

The same test written in ScalaTest would look something like this:

class CarRegistrationSpec extends FeatureSpec with GivenWhenThen {
 
    val carService = new CarService()
 
    feature("Registering car") {
 
        scenario("Registering brand new car for the first time") {
            Given("Owner and brand new car")
            //...
 
            When("Car registered")
            carService.registerCar(brandNewCar, anyOwner, anyCountry)
 
            //...
        }
    }
}

Nothing fancy, ordinary registerCar() method call. The rest of the test (as well as the declaration of brandNewCar, anyOwner and anyCountry) is not relevant to our discussion. We can make it a little bit more readable by explicitly naming parameters:

carService.registerCar(car = brandNewCar, owner = anyOwner, where = anyCountry)

However it’s not clear whether this is actually more readable for e.g. non-programmers. But since we already use descriptive FeatureSpec, can we make Scala code a little bit more human eye-friendly? Of course! Our biggest friends are infix notation and fluent API pattern:

def register(car: Car) = new {
    def by(owner: Owner) = new {
        def in(country: Country) =
            carService.registerCar(car, owner, country)
    }
}

Looks weird, but put this code in your test and enjoy much more fluent call:

register(brandNewCar).by(anyOwner).in(anyCountry)

This is as far as Java can go, but Scala has infix method call syntax, which is equivalent and looks beautiful:

register(brandNewCar) by anyOwner in anyCountry

Why couldn’t we skip first parentheses? It is a limitation on where infix notation can be used (only one-argument method calls on an object). Fortunately we can easily refactor our internal testing DSL by pushing noun (owner) onto first place and using implicit conversion:

implicit def fluentCarRegister(owner: Owner) = new {
    def registers(car: Car) = new {
        def in(country: Country) =
            carService.registerCar(car, owner, country)
    }
}

…which can be used as follows:

anyOwner registers brandNewCar in anyCountry

If you got lost, the line of code above is still Scala and is still executable. If you don’t quite get what’s happening, here is a desugared syntax:

fluentCarRegister(anyOwner).registers(brandNewCar).in(anyCountry)

Tests are all about readability and maintainability. Many people are scared of DSLs because often they are hard to implement and debug. As I showed in this short article, writing really simple yet impressive test DSL in Scala is both simple and rewarding. Moreover there is no reflection or magic meta-programming.
 

Reference: FitNesse your ScalaTest with custom Scala DSL from our JCG partner Tomasz Nurkiewicz at the NoBlogDefFound blog.

Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

Leave a Reply


× six = 42



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close