繁体   English   中英

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

[英]Making each test method run in its own instance of a test class with 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 为每种测试方法启动一个新的测试 class ?

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

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

到目前为止,我发现这个问题最常见的解决方案是使用 ThreadLocal 并处理这样一个事实,即每个测试 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 实例只运行一个方法。 维护一个方法列表,go 一次一个地通过它们。

这是我一起破解的一个粗略的例子。

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顶部 class

@Listeners(TestFactory.class)

您可以通过在工厂中动态创建测试的新实例来改进这一点。 还将侦听器分解为它自己的文件和许多其他改进,但你明白了要点。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM