使用TestNG使每个测试方法在其自己的测试类实例中运行?

时间:2011-04-30 14:10:52

标签: java unit-testing testing testng

所以我认为以下代码在TestNG中运行良好,尽管它没有:

public class Tests {
    int i = 0;

    @Test
    public void testA() {
        Assert.assertEquals(0, i);
        ++i;
    }

    @Test
    public void testB() {
        Assert.assertEquals(0, i);
        ++i;
    }
}

有没有办法让TestNG为每个测试方法启动一个新的Tests类?

2 个答案:

答案 0 :(得分:4)

常见的解决方案是使用@BeforeMethod方法设置测试状态,

@BeforeMethod
public void setup() {
   i = 0; 
}

答案 1 :(得分:0)

到目前为止,我发现这个问题最常见的解决方案是使用ThreadLocal,并且只处理每个Test Class只有一个实例的事实。这涉及有关如何处理并行/线程测试的所有问题。这有效,但有点难看。

private ThreadLocal<Integer> i = new ThreadLocal<>();

@BeforeMethod
public void setup() {
    i.set(0);
}

@Test
public void testA() {
    Integer i1 = i.get();
    Assert.assertEquals(0, i.get().intValue());
    i.set(i1 + 1);
}

@Test
public void testB() {
    Integer i1 = i.get();
    Assert.assertEquals(0, i.get().intValue());
    i.set(i1 + 1);
}

现在回到你的问题的根,每个方法的新实例。 我已经研究了几周类似的主题,我发现这是我个人在TestNG上遇到的头号问题。它实际上让我发疯了。

如果我忽略了你的测试有很多复杂性的事实,那么你可能会破解你的工作以满足你列出的要求。

TestNG @Factory Factory允许您创建测试类的新实例。

@Factory
public Object[] factory(){
    return new Object[]{new Tests(), new Tests()};
}

我现在已经创建了两个Tests实例,由testNG

运行

然后问题是您的测试仍然失败,因为它将尝试在您的测试类上运行所有测试方法。为了解决这个问题,您可以实现IMethodInterceptor,并将解决方案混合在一起,以强制每个Tests实例只运行一个方法。维护一个方法列表,并一次一个地浏览它们。

这是我一起攻击的一个野蛮例子。

public class TestFactory implements IMethodInterceptor {
    private List<String> methodsToRun = new ArrayList<>();
    private List<Object> testInstances = new ArrayList<>();

    @Factory
    public Object[] factory(){
        return new Object[]{new Tests(), new Tests()};
    }

    @Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        ArrayList<IMethodInstance> tempList = new ArrayList<>();
        for(IMethodInstance i: methods){
            if(testInstances.contains(i.getInstance())){
                continue;
            }
            String mName = i.getMethod().getConstructorOrMethod().getName();
            if(!methodsToRun.contains(mName)){
                tempList.add(i);
                methodsToRun.add(mName);
                testInstances.add(i.getInstance());
            }
        }
        return tempList;
    }
}

然后将您的听众添加到Tests班级

的顶部
@Listeners(TestFactory.class)

您可以通过在工厂中动态创建测试的新实例来改进这一点。同时打破了聆听者自己的文件和许多其他改进,但你得到了要点。

也许像上面这样疯狂的解决方案对你或其他人有用。