Sunday, January 30, 2011

Parametrized JUnit Tests Revisited

In the Parametrized JUnit Tests blog post I explained how to create a parametrized junit test. In this blog post I will discuss the reaction of one of my colleagues.

After reading my blog post about parametrized junit tests a colleague expressed his objections with this way of testing. He was a bit disappointed with one thing in particular. The signature of the public static method that is used to construct the test.

@Parameters
public static Collection<Object[]> data()

Is returns a collection of Object arrays. One Object array for each set of parameters. The reason this should be an Object array becomes clear from it's usage.

List<Object[]> data = new ArrayList<Object[]>();
data.add(new Object[] { 2, new Integer[] { 2 } });
return data;

Because the parameters used are of different type, in this case an Integer and an Integer array, they only super-type they have in common is Object.

The objection of my colleague was that is berefts the compiler of the oppertunity to detect type errors at compile time. The compiler would happily compile the following code. But it would blow up at run time.

List<Object[]> data = new ArrayList<Object[]>();
data.add(new Object[] { 2, new Integer[] { 2 } });
data.add(new Object[] { 2, new Double[] { 2.0 } });
return data;

After some discussion with my colleague we came up with the following solution. Instead of using a lot of parameters in the constructor, use only one. By using the builder pattern one retains the type information. Furthermore because now only one parameter is needed, the nearest super-type of all the parameters is the type of the parameter itself.

The code that follows show the same test as in the previous blog post. The change is reflected in the use of the builder pattern. Note that a fluent interface is used to easily construct a builder for the test.
One could still object that the array is now superfluous. They are correct. One way to deal with their objections is to write an custom runner.

@RunWith(Parameterized.class)
public class FactorizationTest
{
    private int number;

    private List<Integer> expectedResult;

    public FactorizationTest(FactorizationTestBuilder builder)
    {
        this.number = builder.getNumber();
        this.expectedResult = builder.getExpectedResult();
    }

    @Test
    public void factorize()
    {
        assertEquals(expectedResult, Factorization.factor(number));
    }

    @Parameters
    public static Collection<FactorizationTestBuilder[]> data()
    {
        List<FactorizationTestBuilder[]> data = new ArrayList<FactorizationTestBuilder[]>();
        data.add(new FactorizationTestBuilder[] { FactorizationTestBuilder.withNumber(2).expect(2) });
        data.add(new FactorizationTestBuilder[] { FactorizationTestBuilder.withNumber(8).expect(2, 2, 2) });
        data.add(new FactorizationTestBuilder[] { FactorizationTestBuilder.withNumber(9).expect(3, 3) });
        data.add(new FactorizationTestBuilder[] { FactorizationTestBuilder.withNumber(72).expect(2, 2, 2, 3, 3) });
        return data;
      }
}

class FactorizationTestBuilder
{
    private int number;

    private List<Integer> expectedResult = new ArrayList<Integer>();

    public static FactorizationTestBuilder withNumber(int number)
    {
        return new FactorizationTestBuilder(number);
    }

    private FactorizationTestBuilder(int number)
    {
        this.number = number;
    }

    public FactorizationTestBuilder expect(Integer... expectedResult)
    {
        this.expectedResult = Arrays.asList(expectedResult);
        return this;
    }

    public int getNumber()
    {
        return number;
    }

    public List<Integer> getExpectedResult()
    {
        return expectedResult;
    }
}

In this blog post I described the objections of a colleague on the previous Parametrized Junit Test blog. I have shown had to meet these objections by using the builder pattern.

Wednesday, January 26, 2011

Updated old post

In this blog post I announced that I switched to using Mathjax. But I hadn't got to the point of rewriting my old post, with this new interface.

Coming this spring I set out to rectify this point and now all posts are using Mathjax as Latex rendering engine.

The only thing I noticed that not every post is using proper html. So probably I have to go back and change that to.

Saturday, January 15, 2011

Parametrized JUnit tests

In this post I will examine parametrized JUnit tests.

With the introduction of Junit 4, a lot has changed for testing Java software with Junit. One of the more esoteric additions are parametrized tests. It allows a developer to run a great deal of test which differ only in a set of parameters. Without further ado I will show you a parametrized test.

@RunWith(Parameterized.class)
public class FactorizationTest
{
    private int number;

    private List expectedResult;

    public FactorizationTest(int number, Integer[] result)
    {
        this.number = number;
        this.expectedResult = Arrays.asList(result);
    }

    @Test
    public void factorize()
    {
        assertEquals(expectedResult, Factorization.factor(number));
    }

    @Parameters
    public static Collection<Object[]> data()  
    {   
        List<Object[]> data = new ArrayList<Object[]>();
        data.add(new Object[] { 2, new Integer[] { 2 } });
        data.add(new Object[] { 8, new Integer[] { 2, 2, 2 } });
        data.add(new Object[] { 9, new Integer[] { 3, 3 } });
        data.add(new Object[] { 72, new Integer[] { 2, 2, 2, 3, 3 } });   
        return data;
    }
} 

Lets focus on line 17 of the method annotated with @Test. This method asserts that the expectedResult is returned by the static method Factorization.factor(int) which is called with parameter number. Both expectedResult and number are private fields of the class FactorizationTest. The fields are assigned in the constructor.

By annotating the class with the @RunWith(Parameterized.class) we are telling Junit to run this class with the Parameterized Runner. By implementing a Runner you can specify how to run the tests.

For the Parameterized this means the following. (The following section is paraphrased. See https://github.com/KentBeck/junit for the details.)

  1. Get an Collection of Object-arrays.
  2. Repeat for every Object-array in the collection:
    1. Construct an instance of FactorizationTest passing as parameters the various elements in the Object-array.
    2. Run all methods annotated with @Test.

The collection mentioned in step 1 is obtained by calling a method annotated with @Parameters. So in this example the following facts will be asserted.

numberfactors
22
82, 2, 2
93, 3
722, 2, 2, 3, 3

In this blog post I made clear how to use parameterized test in the Junit test framework.

Thursday, November 18, 2010

Determine when to accept a double in backgammon

In this blog post I will examine the precise conditions when to accept a double in backgammon.

The question and it's answer whether to accept a double probably is a classical result in backgammon. Guided by mathematics it is primarily concerned with the expected value of a game.

To recap: If you win a game normally you win the amount indicated by the doubling cube. If you win a gammon i.e. without your opponent bearing off a single checker, you win twice the amount on the doubling cube. If the opponent hasn't borne off any checkers and still has checkers in your home board you win a backgammon and gain triple the amount indicated by the doubling cube.

Let's assume the change of winning the game normally is \(p_{n}\), that of winning a gammon is \(p_{g}\) and that of winning a backgammon is \(p_{b}\). In similar fashion define the chances of losing as \(q_{n},\,q_{g}\) and \(q_{b}\).
Furthermore, let\(v\) be the current value of the doubling cube.

If your opponent offers you a double and you refuse you lose \(-v\) points, guaranteed. But if you accept the double the expected value will be

\[
2vp_{n} + 4vp_{g} + 6vp_{b} - 2vq_{n} - 4vq_{g} - 6vq_{b} = 2v((p_{n} - q_{n}) + 2(p_{g} - q_{g}) + 3(p_{b} - q_{b}))
\]

So you should accept a double if the above expression is greater then \(-v\).

Lets further assume that the changes of losing are winning a gammon are backgammon are zero. Then the above equality simplifies (using the relation \(q_{n} = 1-p_{n}\)) to \(2p_{n}-1 \ge -\frac{1}{2}\) or \(p_{n} \ge \frac{1}{4}\). This is a very classic result of backgammon. For example, it is stated, without proof, in 501 essential backgammon problems, considered to be the bible of backgammon.

In order to gain an other insight we assume that the changes of winning or losing a backgammon or winning a gammon are zero, but losing a backgammon is a possibility. (For example your trapped on the bar while your opponent already beared off succesfully at least one checker.)
The above equations reduces to \(p_{n}-q_{n}-2q_{g} \ge -\frac{1}{2}\). Now the relation \(p_{n} + q_{n} + q_{g} = 1\) tells use that \(q_{n} = 1 - p_{n} - q_{g}\). This simplifies our equations to \(p_{n} \ge \frac{1}{4} + \frac{1}{2}q_{g}\). This tells use you have to have a greater change of winning if your are to accept a double when there is a change of losing a gammon.

The above equations and a keen insight in the chances at the backgammon board can help to guide your decision of taking a double or not.
In an other blog I will investigate the conditions of offering a double.

MinuteMath: A bite size math problem a day

I Recently subscribed to the The Mathematical Association of America twitter feed. The most important reason for me is their daily MinuteMath.

The MinuteMath is a daily bite size mathematical problem of varying difficulty. All the problems are multiple choice and hints, solutions and classifications are given.

It is a fun way to distract your mind for a moment and figure out a interesting little problem. If your interested start following @maanow.

Sunday, October 24, 2010

MathJax: Include mathematics non-obtrusively

In this blog post I will explain the use of MathJax, a javascript based display engine for mathematics.

In an early post I pointed out that yourequations.com has a very nice solution for producing beautiful LaTeX on the web. Unfortunately as of October 31 2010 their service has shut down. As a result the LaTeX on my blog did not render any more.

So a tweet alerted me to mathjax, a display engine for mathematics. With mathjax it is possible to write mathematics in LaTeX or MathML and the javascript based engine will make a beautiful image.
As a bonus mathjax allows you to scale the mathematics, view the source in LaTeX or MathML and choice the rendermode i.e. straight to MathML or via their custom fonts.

Seeing their beautiful examples I decided that use mathjax for this blog. So once again, mathematics can be viewed in splendid glory.

\[
e^{i\pi}+1=0
\]

Saturday, October 16, 2010

Why I changed my twitter picture

In this blog I will explain why I changed my twitter picture.

After a presentation I gave at the University of Utrecht someone in the audience came up to me and asked the following question: "Can I follow you on twitter?"

This flattering request made one thing clear. My twitter pictures has no relation with me. How could anybody know my account from the following picture?

In order to be more accessible, I changed my picture. For now I have changed it to the picture I use for my blog. Maybe in the future I will pick a fancier picture.