Parameterized Unit Test

When you are writing unit tests, you want to test all the border cases. You can create a method for every border case, but sometimes this is a very repetitive job.

JUnit has a more pragmatic approach for these sorts of tests, called Parameterized tests. The idea is simple. You create your testcase with your test methods. You define a list of parameters that is given to the constructor and all the tests inside the testcase are executed for every parameter.

See this example. A simple class: Calculator

package be.styledideas.blog;

public class Calculator {
    public Long add(Long a, Long b){
        return a+b;
    }
}

I want to test this method with more than one parameter. I have created this parameterized unit test.

package be.styledideas.blog;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.ArrayList;
import java.util.Collection;

@RunWith(Parameterized.class)
public class CalculatorAddTestCase {
    private Long a;
    private Long b;
    private Long expected;

    public CalculatorAddTestCase(Long a, Long b, Long expected) {
        this.a = a;
        this.b = b;
        this.expected = expected;
    }

    @Test
    public void add() {
        Long actual = new Calculator().add(a, b);
        Assert.assertEquals(expected, actual);
    }

    @Parameterized.Parameters
    public static Collection<Object[]> getParameters(){
        Collection<Object[]> parameters = new ArrayList<Object[]>();
        parameters.add(new Object[]{1L, 2L, 3L});
        parameters.add(new Object[]{-1L, 2L, 1L});
        parameters.add(new Object[]{2L, 2L, 3L});
        parameters.add(new Object[]{4L, 0L, 4L});
        return parameters;
    }
}

The first thing that is different about this test is the @RunWith annotation at the top. Instead of the Junit4 runner, we use the Parameterized runner. This annotations looks for a static method that is annotated with the @Parameters annotation.
When we look closer at the getParameters method, we see that every item in the List maps to the constructor of the TestCase, so every item represents a running test. This concrete example results in equal to 4 unit tests.

Now you can be wondering what is the added value of this annotation over a list that you pass to your test. If you are just giving a test method a List with parameters, and one parameter creates a failure in your test, you will have to search for the test that is failing. When you execute it this way, any modern IDE will point which parameter is incorrect.

Gmail habits in Jira 4

Some time ago I learned about the keyboard shortcuts of gmail. This was a tremendous win for me. I spend a day learning the most common shortcuts. Now I can check my email much faster. When you enable these shortcuts, you get to see a pointer in front of your mail you are on.

I noticed that when our version of jira was updated from 3 to 4 (v4.2.2), here were also pointers in my issue navigation frame.

I just tried j and k and it worked (navigating up and down). Then I tried g + i (goto inbox) and it brought me back to the ‘Find Issues’ page.
Allright, so my known gmail shortcuts help me navigate trough jira. Here’s a complete list of shortcuts for jira:

If your hotkeys are not enabled, goto the account dropdown in the corner and choose keyboard shortcuts.

At the bottom you can enable or disable them.

Smoketest Dogs

When working on a very large project, quality is of the essence. One key part of adding quality to a software project, is by testing.

You have several ways of testing an application. We used unit testing, integration testing, selenium testing. But due to a big difference between our local testing environment (tomcat server) and our test teams environment (websphere), we have to check our release when it is deployed on the test teams environment.
We used the principle of smoke testing. Doing some basic actions and see that the application is still stable. Only big failures are fixed in the release. When we discover a bug, we register it in our bug tracker and it is fixed in the next release.

I think we could also used Arquillian. Arquillian is a framework that wraps your integration test into the container you run them in. Unfortunately Arquillian wasn’t an option. We had to do the test manually.

We started with creating a checklist that is hosted on our local wiki.
checklist
This way, we make sure that everything is checked before we migrate our release to the testers. Simple, but very efficient.

We are using this checklist, but every release, everyone tests the same features. This leads into cases where someone always tests the same way. This way, some essential things could be forgotten.

We wanted to create a system where we cycle over test, so each group of test is executed by someone else, with enough rotation to make sure no testing habit is developed.

We wanted to keep this a bit fun, because no one really likes doing smoke tests.

The smoke test dogs came to life.
The idea is simple, the tests on the checklist have a certain color. there are as many colors as there are characters in Quentin Tarantino‘s movie, Reservoir dogs.

The day of the release, everyone picks a card in the scrum stand-up meeting. This indicates what test should be executed.
We have a placeholder in our office where the cards should hang when all the test are succeeded. When all the cards are back, we are ready to release to our testers.

This is a very simple way to keep testing fun for everyone. The only disclaimer, this could lead to some role playing đŸ˜‰
Big thanks to my collegues @erwinravau, @jordanvermeir, @jaspervdm, Cindy and Maarten

And if you aren’t there, you’re mr. pink!
If you're not there, you're mr Pink!

Why you should never use getSingleResult() in JPA

As long as I’m using JPA I notice that the use of getSingleResult and getResultList is often confused. In the javadoc there is no clear specification of what to use.
getResultList()

Execute a SELECT query and return the query results as an untyped List.

getSingleResult()

Execute a SELECT query that returns a single untyped result.

So this doesn’t get us much further. So lets explore the problem. Both methods are used to retrieve Entities from our database. We use the getResultList() if there is no guarantee how many results we want to retrieve, the getSingleResult is used to retrieve exactly one row.
So the only doubt for what method to use, is when we retrieve 1 row from our database. A perfect example for this use-case is a findById query, where we retrieve an Entity based upon its ID.
There are 3 ways to do this. The most appropriate way is to use the EntityManger.find() method. This method returns a typed instance of the entity when it is found, null when it is not found.
The other 2 ways is by a NamedQuery. Why would we want to use a NamedQuery when we have the find method? Sometimes we need to retrieve a lazy collection, by adding a fetch join. An other example is when we have a composite key, we can still use the EntityManager.find() method, but I often see the use of a named query in this case. (don’t do this, bad programming)
So we created our named query

final Query query = getEntityManager().createNamedQuery("Entity.findById");
query.setParameter("id", id);

The most natural reaction is to call the getSingleResult() method on the query. This returns only one row and the result of a ‘findById’ query should only be one row. But what if the row isn’t in the database (anymore)? We get an unchecked exception: NoResultException. Is this what we expect?
If you look in Effective Java by Joshua Bloch, we read: ‘Use checked exceptions for conditions from wich the caller can reasonably be expected to recover. Use runtime exceptions to indicate programming errors’.
So what does this tell us? When a getSingleResult Query returns no rows, we get an unchecked exception, thus a programmer error, there is no way to recover from this. This is not correct. We never know for sure what we can expect from our database, so throwing an unchecked exception seems the wrong choice for this use-case.
The only use for getSingleResult() is when we are executing a scalar (count, sum, avg) query. This is a query wich will alway return a row, otherwise we are in an exceptional case, so the exception is allowed.
So, how do we solve our example with our named query? Simple

List results = query.getResultList();
Entity foundEntity = null;
if(!results.isEmpty()){
    // ignores multiple results
    foundEntity = results.get(0);
}

Extending Spring JUnit Runner

For our integration tests we had to use the development database. On that database there are some batch parameters stored and one of those parameters is a cutoffTime. As the name suggest, our business logic can not be processed after that time, so we had to create a mechanism to make sure that the tests are not executed, else the build would fail.
The first thing we did was a quick fix. We added an if-statement to the test to see what time it is and if the test can be executed. As some of you already know, an empty method annotated with @Test will execute and be successful. This is not correct, when someone breaks code that is in those tests, the test should not be marked as successful. We should be able to add the @Ignore annotation on the tests when the cutOffTime is passed.

I looked into this problem and the first thing that came to my mind was to use Annotations, because it is meta-data and not test functionality. JUnit4 has a very easy way to handle annotations, so I decided to go that way.

/**
 * The CutOffTime annotation..
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CutOffTime {
    String cutOffTime();
}

I want this annotation to cancel all my tests in a testcase, not just a method, that is why i put the ElementType on TYPE.

Our integration tests are running with the SpringJUnit4ClassRunner so I extended this. I have overridden the invokeTestMethod method, because this is the one executing each test. Here is the source code

/**
 * The Class IntegrationTestClassRunner. This class is a specific class runner
 * for the payments. There is a cutoffTime defined in the database that decides
 * if a payment that can be made or not. This can be applied by the
 * {@link CutOffTime} annotation
 *
 * @author Jelle Victoor
 * @version 14-apr-2010
 */
public class IntegrationTestClassRunner extends SpringJUnit4ClassRunner {

    /**
     * The Constructor.
     *
     * @param clazz
     *            the clazz
     *
     * @throws InitializationError
     *             the initialization error
     */
    public IntegrationTestClassRunner(final Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    /** {@inheritDoc} */
    @Override
    protected void invokeTestMethod(final Method method, final RunNotifier notifier) {
        Annotation[] classAnnotations = classAnnotations();
        Boolean ignore = Boolean.FALSE;
        for (Annotation classAnnotation : classAnnotations) {
            if (classAnnotation instanceof CutOffTime) {
                if (shouldIgnore(((CutOffTime) classAnnotation).cutOffTime())) {
                    ignore = Boolean.TRUE;
                }
                break;
            }
        }
        if (!ignore) {
            super.invokeTestMethod(method, notifier);
        } else {
            notifier.fireTestIgnored(methodDescription(method));
        }
    }

    /**
     * Decides to ignore the test
     *
     * @param cuttOffTime
     *            the cutt off time
     *
     * @return true, if should ignore
     */
    private boolean shouldIgnore(final String cuttOffTime) {
        int hour = Integer.parseInt(StringUtils.substring(cuttOffTime, 0, 2));
        int minutes = Integer.parseInt(StringUtils.substring(cuttOffTime, 2, 4));
        return new LocalTime().isAfter(new LocalTime(hour, minutes));
    }
}

As you can see, the classAnnotation() method will give you all the annotations that are on your class *and are specified with @Retention(RetentionPolicy.RUNTIME)*. I simply check if the annotation is found on the class. When I’m done checking if the annotation is found and if the test should be ignored, i can fireTestIgnored on the notifier or execute the test. We just annotate our tests with @RunWith(IntegrationTestClassRunner.class).
This way the test should not fail or succeed, but now you can simply see that the test is ignored. The statistics are clean :-).

I know that the whole purpose of this extention is odd, but we are forced into this position. With this post I’m trying to show you that extending a test framework like JUnit isn’t hard at all and you can use it in every way you want to.