Conor
Conor

Reputation: 775

multiple test classes for an interface rolled up into a suite in junit 4?

I have an interface that defines the behaviour of an object that does some graph search called say GraphSearcher. I currently have a bunch of different implementations with more variations on the way and so I have defined the test classes as being abstract with concrete test methods and an abstract method that instantiates an implementation of graph searching object.

This is all fine except that I have a bunch of different classes (about 10 at the moment) that each run whole lot of tests based on some real world data. This means that for each concreate implementation I end up writing a whole lot test classes just containing the instantiation method.

This all seemed kind of messy to me and I was wondering if anyone knew of a better solution. I think ideally I would like to be able to pass in a GraphSearcher factory object into some sort of test suite and have all the various test classes run. This would mean that I would only have to write a tiny bit of code to have a new GraphSearcher implementation run against all the tests. I'm just not sure how to go about this using junit 4. I'm sure there must be some fairly standard way to do this but I haven't been able to find anything yet. Any pointers anyone has would be greatly appreciated

Upvotes: 1

Views: 309

Answers (2)

janhink
janhink

Reputation: 5023

If I understand your problem well, you just have some testing code and would like to run it multiple times, each time with a different implementation of GraphSearcher, right? If so, I would probably go with a Paremeterized JUnit runner. It could look like this:

@RunWith(Parameterized.class)
public class GraphSearcherTest
{
    private GraphSearcher testedSearcher;

    public GraphSearcherTest(GraphSearcher searcher)
    {
        this.testedSearcher = searcher;
    }

    @Parameters
    public static Collection<Object[]> getParameters()
    {
        return Arrays.asList(new Object[][] {
                { new GraphSearcherImpl1() },
                { new GraphSearcherImpl2() }
        });
    }

    @Test
    public void testGraphSearcher()
    {
        // execute the test
        testedSearcher.search();

        // make some assertions
    }
}

The key parts are:

  • the @RunWith(Parameterized.class) annotation
  • the constructor which takes the tested implementation of GraphSearcher
  • the @Parameters-annotated method (of arbitrary name) which returns Collection. This method will be called for every item of the collection and the object from the collection will be added to the test's constructor.
  • the size of the Object[] in the collection must match the number of arguments of the constructor

So in this case the test will be called twice. First test will get the GraphSearcherImpl1 instance and the second the GraphSearcherImpl2 instance in its constructor.

Upvotes: 2

Guillaume
Guillaume

Reputation: 5553

You could use the @Parameters annotation to provide you the different interface implementations.

For instance: http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/

Upvotes: 0

Related Questions