将JUnit测试动态添加到测试类

时间:2011-08-24 09:57:44

标签: java junit junit4

我发现自己现在写了很多很多锅炉板测试,我希望以一种干净的方式优化掉很多这些基本测试,这些测试可以添加到所有当前的测试类中而不会有太多麻烦。

这是一个基本的测试类:

class MyClassTest {

    @Test
    public void doesWhatItDoes() {
        assertEquals("foo",new MyClass("bar").get());
    }

}

让我们说如果MyClass实现了Serializable,那么我们希望确保它确实是可序列化的。所以我构建了一个可以扩展的类,其中包含一系列标准测试,这些测试将与其他测试一起运行。

我的问题是,如果MyClass没有实现Serializable,我们仍然在类中进行序列化测试。我们可以使它成功用于非可序列化的类,但它仍然坚持在测试列表中,一旦这个类开始构建它将变得越来越混乱。

我想要做的是找到一种方法来动态添加那些与现有测试类相关的测试。我知道其中一些可以通过TestSuit完成,但是你必须为每个类维护两个测试类,这很快就会变成麻烦。

如果有人知道一种不需要eclipse插件的方法,那么我将永远感激。

编辑:添加了我上面描述的内容的简短示例;

class MyClassTest extend AutoTest<MyClass> {

    public MyClassTest() {
        super(MyClass.class);
    }

    @Test
    public void doesWhatItDoes() {
        assertEquals("foo",new MyClass("bar").get());
    }

}

public abstract class AutoTest<T> {
    private final Class<T> clazz;
    protected AutoTest(Clazz<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Test
    public void serializes() {
        if (Arrays.asList(clazz.getInterfaces()).contains(Serializable.class)) {
        /* Serialize and deserialize and check equals, hashcode and other things... */
        }
    }
}

3 个答案:

答案 0 :(得分:3)

两个想法。

创意1: 使用Assume

  

一组方法,用于说明关于测试有意义的条件的假设。失败的假设并不意味着代码被破坏,而是测试没有提供有用的信息。默认的JUnit运行器将失败假设的测试视为忽略。

@Test
public void serializes() {
    assumeTrue(Serializable.class.isAssignableFrom(clazz));
    /* Serialize and deserialize and check equals, hashcode and other things... */
}

创意2:实施自己的测试运行器。

http://junit.sourceforge.net/javadoc/

处查看@RunWithRunner

答案 1 :(得分:0)

JUnit现有功能中最实用的解决方案是进行单一注释测试:

@Test
void followsStandardJavaLibraryProtocols() {
    if (implementsInterface(Serializable.class) {
         testSerialisableInterface       

...

打破TDD的各种抽象原则,但有效,没有不必要的聪明。

也许,Junit可以扩展为对子测试的这种层次测试提供更直接的支持,而不是测试用例的平面列表。类似@Subtest注释的东西,它确定了一个不能直接调用的测试,而是在结果树中添加一个节点,并使用什么参数。

答案 2 :(得分:0)

你的方法对我来说似乎是有效的。我没有问题。

我的做法略有不同。我将创建另一个测试所有Seri​​alizable类的测试:

public class SerializablesTest {
    @Test
    public void serializes() {
        testSerializable(MyClass.class);
        testSerializable(MyClass2.class);
    }

    private testSerializable(Class clazz) {
        // do the real test here
        /* Serialize and deserialize and check equals, hashcode and other things... */
    }
}

这给你带来了什么?对我来说,显而易见。我知道我正在测试MyClass类的可序列化。没有任何魔法涉及。您不需要污染其他测试。

如果你真的需要测试所有实现Serializable的类,你可以使用反射找到所有类。

我使用这种方法很多,使用反射来构建对象。例如,我可以测试所有字段是否持久保存到&amp;正确地从数据库重新读取。我一直都在使用这种东西。