Category Archives: Software Development

Introducing running-conversions

https://github.com/czeczotka/running-conversions

As part of my preparations for a half-marathon and later the full marathon I was following a training plan which more often than not left me with a pen and paper calculating different paces and times for running activities. For example if you want to run a half-marathon under 2 hours what pace should you aim for? If you run it at 5:20 km/min what would be your finish time? If your plan tells you to run an interval of 600 metres in 2m34s what should be your pace?

After some training I also realised that running trackers have an accuracy which leaves a lot to be desired. They are good at measuring time but your location, distance and as a result pace is more of an approximation than actual measurement. It was a slight disappointment when I missed my first 10k’s finish time by 30s while being convinced I will be spot on with the result. My tracker simply measured 10.3k distance instead of 10k and so the pace was overestimated (i.e.: I thought I was running 4:55 while it was more like 5:05). That’s how I learned that the only reliable way of controlling your pace is following your time and checking it on the marker points. So how do you know your splits? For instance if you want to run the marathon in 3h30min what should be your 5k splits?

In order to answer these questions I could use some of the online calculators but I decided to have my own pet project and implement a Scala tool to solve these problems. That’s how running-conversions project was born. The basic idea that you create an activity which is either based on the distance and time or distance and pace and then you can query its properties. I described the installation and usage in the project and here are some examples of the calculation you can do:

// calculate the total time of the activity
input:  marathon at "5:41" time 
output: 3h59m48s
// calculate the pace
input:  k10 in "49m00s" pace 
output: 4:54
// get 1 kilometre splits for an activity
input:  k10 in "44m30s"  splits
output: Map(1.0 -> 4m27s, 2.0 -> 8m54s, 3.0 -> 13m21s, 4.0 -> 17m48s, 5.0 -> 22m15s, 6.0 -> 26m42s, 7.0 -> 31m09s, 8.0 -> 35m36s, 9.0 -> 40m03s, 10.0 -> 44m30s)
// calculate 5k splits to run the marathon in 3 hours 45 minutes
input:  marathon in "3h45m" splits k5
output: Map(5.0 -> 26m35s, 10.0 -> 53m10s, 15.0 -> 1h19m45s, 20.0 -> 1h46m20s, 25.0 -> 2h12m55s, 30.0 -> 2h39m30s, 35.0 -> 3h06m05s, 40.0 -> 3h32m40s)
// calculate 400m splits to run 2000m in 8 minutes
input:  metres2000 in "8m00s" splits metres400
output: Map(0.4 -> 1m36s, 0.8 -> 3m12s, 1.2 -> 4m48s, 1.6 -> 6m24s, 2.0 -> 8m00s)

https://github.com/czeczotka/running-conversions

With the interface via Scala REPL or by writing your own code it’s a bit rough on the edges but it has solved my problems so far. Let me know you thoughs. I am keen to learn if anybody is doing some work in this area!

Spring MVC integration test with REST Assured and MockMvc

Spring controllers can provide a lot of functionality and in most applications I have seen the web layer code is scattered among java code, annotations and XML config files. Even in the simplest controllers there is a lot that can go wrong – there are request mappings and methods, returned content type, response body, request parameters and calls to services in the layer below. I have always wondered what is the best way to test it all together? Obviously you can get the application up and running in order to execute acceptance tests (headless or via a browser) but this can be a bit of an overkill. Another option is to write a unit test but then arguably you would test the controller out of the context (but you may still want to do this anyway).

Ideally, you would have a test which does not require running a servlet container (memory requirements, start-up time, extra dependencies and good old faff to set it up) and enables testing all functionality (code and meta-code). We want an integration test which will not be limited to a simple Java class (fed with mock HTTP servlet request/response) but will go through the DispatcherServlet and enable us to work with HTTP requests and responses so that we test what is actually produced by our application.

In version 3.2 Spring introduced MockMvc which is a huge improvement and enables us to easily implement this type of tests. When combined with REST Assured (“Java DSL for easy testing of REST services”) we get to use fluent API (including given, when, then) to create code that is expressive as well as easy to read and understand.

Let’s take a look at a ‘hello world’ controller and method:

@RequestMapping(value = "/hello", 
                method = RequestMethod.GET, 
                produces = "application/json;charset=UTF-8")
public @ResponseBody String hello(
            @RequestParam(required = false, 
                defaultValue = "world") String name) {
    return format("Hello {0}!", name);
}

Not much code but emotions are high – we map all GET requests to ‘hello’ url to this method and return JSON content. We can take an optional String parameter called ‘name’, should it not be included in the request we will use “world” value. So how do I test it?

@Test public void 
getHello() {
    given().
    when().
        get(HELLO).
    then().
        statusCode(HttpServletResponse.SC_OK).
        contentType("application/json").
        body(equalTo("Hello world!"));
}  

@Test public void 
getHelloWithParam() {
    given().
        param("name", "coder").
    when().
        get(HELLO).
    then().
        statusCode(HttpServletResponse.SC_OK).
        contentType("application/json").
        body(equalTo("Hello coder!"));
}

Also, we can test that POST method is not supported:

@Test public void
failPostToHello() {
    given().
    when().
        post(HELLO).
    then().
        statusCode(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}

Now let’s have a look at the test setup:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(
        "classpath:test-mvc-dispatcher-servlet.xml")
public class HelloControllerTest {
    
    private MockMvc mockMvc;
    
    @Autowired
    private WebApplicationContext context;
    
    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context).build();
        RestAssuredMockMvc.mockMvc = mockMvc;
    }
    ...	
}

The ContextConfiguration annotation tells Spring about the location of the config file (test-mvc-dispatcher-servlet.xml) which allows for configuration of the WebApplicationContext which, thanks to WebAppConfiguration annotation, gets auto-wired in the context variable which is used to build mockMvc. To quote the javadoc MockMvc is “main entry point for server-side Spring MVC test support”, basically it encapsulates all your web configuration and makes it available to the test. Note that I modified the context configuration so component scan is limited to controllers only (web package) and I can mock the other beans using Mockito.

<context:component-scan 
        base-package="com.czeczotka.spring.web"/>

<mvc:annotation-driven />

<bean id="newsService" 
        class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg 
        value="com.czeczotka.spring.service.NewsService" />
</bean>

Let’s discuss something a little bit more useful. How about testing controller’s interaction with services as well as the response body (which is a slightly more complicated this time)? I created a simple News class (String headline; String article; LocalDateTime timestamp) and a controller to return the latest news. I think this is where REST Assured and MockMvc combined shine – I can set up controllers interactions with the service using Mockito and still test http response. Note the fully qualified import of Mockito’s org.mockito.Mockito.when() method.

@Test public void
getLatestNews() {
    LocalDateTime dateTime = LocalDateTime.now ();
    String now = formatter.format (dateTime);
    org.mockito.Mockito.
        when (newsService.getLatestNews ()).
        thenReturn (new News ("Some news!", 
                    "These are some news!", dateTime));

    given ().
    when ().
        get (LATEST).
    then ().
        statusCode (HttpServletResponse.SC_OK).
        contentType ("application/json").
        body ("headline",  equalTo ("Some news!")).
        body ("article",   equalTo ("These are some news!")).
        body ("timestamp", equalTo (now));
}

@Test public void
getLatestNewsWithSeveralResults () {
    int number = 3;
    LocalDateTime dateTime = LocalDateTime.now ();
    String now = formatter.format (dateTime);
    org.mockito.Mockito.
        when (newsService.getLatestNews (number)).
        thenReturn (Arrays.asList (
            new News ("Some news! 0", 
                "These are some news! 0", dateTime),
            new News ("Some news! 1", "
                These are some news! 1", dateTime),
            new News ("Some news! 2", 
                "These are some news! 2", dateTime)
        ));

    given ().
    when ().
        get (LATEST + "/" + number).
    then ().
        statusCode (HttpServletResponse.SC_OK).
        contentType ("application/json").
        body ("size()", equalTo (number)).
        body ("[0].headline",  equalTo ("Some news! 0")).
        body ("[0].article",   
                    equalTo ("These are some news! 0")).
        body ("[0].timestamp", equalTo (now)).
        body ("[1].headline",  equalTo ("Some news! 1")).
        body ("[1].article",   
                    equalTo ("These are some news! 1")).
        body ("[1].timestamp", equalTo (now)).
        body ("[2].headline",  equalTo ("Some news! 2")).
        body ("[2].article",   
                    equalTo ("These are some news! 2")).
        body ("[2].timestamp", equalTo (now));
}

We can ask for some logging information, in the example we can log all or only some elements of the request/response such as params, body, headers, cookies, method or path. There is also an option to log on failed validation (log().ifValidationFails()):

@Test public void
getHelloWithLogging() {
    given ().
        log().all ().
    when ().
        get (HELLO).
    then ().
        log().all ().
        statusCode (HttpServletResponse.SC_OK);
}

I hope you found it helpful, to me the MockMvc and REST Assured combo definitely changes the way I think about testing Spring controllers and gives me much more confidence in the final solution.

The code

The code of this post is on github so follow the link below to browse it.

http://github.com/czeczotka/spring-mvc-integration-test

You can easily clone and play with it locally by simply following these steps.

$ git clone https://github.com/czeczotka/spring-mvc-integration-test.git
$ cd spring-mvc-integration-test
$ mvn test

Links

JUnit rules!

Apologies for the shouty title, I couldn’t stop myself. In JUnit 4.7 a new feature was introduced – rules. They enable us to modify how test methods are executed to provide more flexible and powerful tests. I think the name was chosen so that people would have to search for “junit rules” and google trends seem to (weakly) support this theory. In your face TestNG!

google-trends-for-junit-rules
Google Trends for “junit rules” search term

The functionality is implemented by annotating a field (of class TestRule or MethodRule) with the @Rule annotation.

This is a quick tour of the most useful rules.

What’s your name again?

Would you like to know your test method’s name while executing it? Simple, use TestName.

@Rule
public TestName name = new TestName();

@Test
public void printTestMethodName() {
    System.out.println(
        "Test method name: " + name.getMethodName());
}
Test method name: printTestMethodName

We want quick tests!

Quick as in “not slow”. Let’s say you need to deal with a class full of badly written integration tests, each of which unnecessarily taking several seconds to run. Bad bad panda. You can set up a timeout (Timeout) in your test class which will fail lengthy tests (just note you’re dealing with milliseconds). Another good thing is that it will actually interrupt the test execution thread so your test method will be time-boxed by the timeout.

@Rule
public Timeout timeout = new Timeout(20);

@Test
public void slowTestAskingForTrouble() throws InterruptedException {
    Thread.sleep(1000 * 60);
}
java.lang.Exception: test timed out after 20 milliseconds

Exceptions expected

Sometimes you want to check if an exception is thrown. You can do it without the rules but then you can’t check for the message.

@Test(expected = IllegalArgumentException.class)
public void exceptionExpected(){
    throw new IllegalArgumentException("catch me if you can");
}

Exception messages are important. Sometimes they can tell the whole story, i.e. would you prefer to simply catch UserNotFoundException or would you also like to see the message “Can not load user with id ‘null'” in the production log? Right, let’s check for the exception message with ExpectedException.

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void exceptionWithMessageExpected(){
    thrown.expect(IllegalArgumentException.class);
    thrown.expectMessage("catch me if you can");
    throw new IllegalArgumentException("catch me if you can");
}

This rule is initialised with ExpectedException.none() as by default we don’t expect methods to end up with an exception. We state this behaviour as per method basis.

Note that you can use Timeout and ExpectedException together and have a passing test

@Test
public void slowTestWithExpectedException()
         throws InterruptedException {
    thrown.expect(Exception.class);
    thrown.expectMessage(
        "test timed out after 20 milliseconds");
    Thread.sleep(1000 * 60);
}

Collect your errors (all of them)

Sometimes you end up having several assertions to verify that the returned object is ok. Let’s say you load a user object and the first assertion is for user’s first name and it fails. Fix it, run again to discover that the date of birth assertion fails too. Repeat to discover that their work phone number is empty (who uses these anyway?)… Wouldn’t it be nice to find out all failing assertions after the first execution? This is when ErrorCollector comes in silver armour and on a white horse to rescue the situation.

@Rule
public ErrorCollector collector = new ErrorCollector();

@Test
public void errorCollectorExample() {
    collector.addError(
        new Throwable("trouble here"));
    collector.addError(
        new Throwable("trouble there"));
    collector.addError(
        new Throwable("trouble everywhere"));
}
java.lang.Throwable: trouble here
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:52)

java.lang.Throwable: trouble there
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:53)

java.lang.Throwable: trouble everywhere
	at com.czeczotka.junit.JUnitRulesTest.errorCollectorExample(JUnitRulesTest.java:54)

Watch your tests

Should you be interested in being able to get you hands on test’s lifecycle events you can use TestWatcher. It will not let you change the test but you can register callbacks for different events such as failed, finished, skipped, starting, succeeded. Useful for reporting or if you wanted to take some extra actions, i.e. feedback the problem to you continuous delivery pipeline.

private static StringBuilder report = new StringBuilder();

@Rule
public TestWatcher watcher = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
        report.append("  FAILURE: ").append(
            description.getMethodName()).append("\n");
    }

    @Override
    protected void succeeded(Description description) {
        report.append("  Success: ").append(
            description.getMethodName()).append("\n");
    }
};

@AfterClass
public static void tearDownClass() {
    System.out.println("@AfterClass report");
    System.out.println(report.toString ());
}
@AfterClass report
    Success: exceptionExpected
    Success: printTestMethodName
    FAILURE: errorCollectorExample
    Success: slowTestWithExpectedException
    Success: exceptionWithMessageExpected
    FAILURE: slowTestAskingForTrouble

Other useful stuff

  • TemporaryFolder – enables you to create files and directories (newFile(), newFolder() methods) that will be removed after test execution
  • ExternalResource – useful to access an external resource such as a database or ssh connection (methods before() and after()) but I think I’d prefer to use BeforeClass and AfterClass annotations to do the job
  • Verifier – to potentially fail a test which would otherwise be successful after some extra assertions, i.e.: temporary folder was too big (in conjunction with TemporaryFolder rule)

The code

The code of this post is on github so follow the link below to browse it. Note that it contains failing tests to demonstrate presented ideas.

http://github.com/czeczotka/junit-rules

You can easily clone and play with it locally by simply following these steps.

$ git clone https://github.com/czeczotka/junit-rules.git
$ cd junit-rules
$ mvn test

Links