Sunday, February 6, 2011

Parametrized Junit Tests: Postscript

In two earlier blog posts I commented on parametrized junit tests. This blog post will complement these post with an example of a piece of code.

Because all the important points are made in the other posts I will only present the Junit runner I created. A Maven project demonstrating this technique can be found code at my minimal examples repository

Without further ado: the Junit runner.

package org.junit.runners;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;

public class ParameterizedWithBuilder extends Suite
{
        private class TestClassRunnerForParametersWithBuilder extends BlockJUnit4ClassRunner
        {
                private final int fParameterSetNumber;

                private final List<Object> fParameterList;

                TestClassRunnerForParametersWithBuilder(Class<?> type, List<Object> parametersList, int i)
                        throws InitializationError
                {
                        super(type);
                        fParameterList = parametersList;
                        fParameterSetNumber = i;
                }

                @Override
                public Object createTest() throws Exception
                {
                        return getTestClass().getOnlyConstructor().newInstance(computeParams());
                }

                private Object computeParams() throws Exception
                {
                        try
                        {
                                return fParameterList.get(fParameterSetNumber);
                        }
                        catch (ClassCastException e)
                        {
                                throw new Exception(String.format("%s.%s() must return a Collection of objects.", getTestClass()
                                        .getName(), getParametersMethod(getTestClass()).getName()));
                        }
                }

                @Override
                protected String getName()
                {
                        return String.format("[%s]", fParameterSetNumber);
                }

                @Override
                protected String testName(final FrameworkMethod method)
                {
                        return String.format("%s[%s]", method.getName(), fParameterSetNumber);
                }

                @Override
                protected void validateConstructor(List<Throwable> errors)
                {
                        validateOnlyOneConstructor(errors);
                }

                @Override
                protected Statement classBlock(RunNotifier notifier)
                {
                        return childrenInvoker(notifier);
                }
        }

        private List<Runner> runners = new ArrayList<Runner>();

        public ParameterizedWithBuilder(Class<?> klass) throws Throwable
        {
                super(klass, Collections.<Runner> emptyList());
                List<Object> parametersList = getParametersList(getTestClass());
                for (int i = 0; i < parametersList.size(); i++)
                        runners.add(new TestClassRunnerForParametersWithBuilder(getTestClass().getJavaClass(), parametersList, i));

        }

        @Override
        protected List<Runner> getChildren()
        {
                return runners;
        }

        @SuppressWarnings("unchecked")
        private List<Object> getParametersList(TestClass testClass) throws Throwable
        {
                return (List<Object>) getParametersMethod(testClass).invokeExplosively(null);
        }

        private FrameworkMethod getParametersMethod(TestClass testClass) throws Exception
        {
                List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Parameters.class);
                for (FrameworkMethod each : methods)
                {
                        int modifiers = each.getMethod().getModifiers();
                        if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
                                return each;
                }

                throw new Exception("No public static parameters method on class " + testClass.getName());
        }

}

Tuesday, February 1, 2011

Sexism in Language

In this blog I will point out a an examples of sexism in language.

As I pointed out in an earlier post I adapted my wife's name after we married. Although this is legally possible since the year 1998, not everybody adapted accordingly.

There are a lot of forms in which you have to fill out your name. It is often the case that the name should be the same name as found in your passport i.e. your birth name. But the forms ask to fill in your maiden name. Well the last time I checked, I never was a maiden. Furthermore, I have no intention of ever becoming one. So I regard this as a strange question.

The origins of the use of this language are clear to me. A long time ago only women could take on an other name. So if someone wanted to know your birth name she could reason as follows:

  1. Males can be asked for their name, regardless of their marital status.
  2. Females can be asked for their name, unless they are married. Then they should be asked for their maiden name.

But since the 1998 this rule does not apply any more. And if you want to know my birth name ask for it. It is been twelve years, everybody had enough time change their forms. I regard this as a very sexist use of language.