如何在单一方法测试和可排序测试数据的情况下订购TestNG Factory执行?

首先,您应该知道我正在使用TestNG v6.8.8和Java JDK 6.我遇到了在不同版本的Linux和Mac OS 10.9.4上运行的这个问题。 到代码清单。

工厂类

import org.testng.annotations.Factory; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author rcourtright * Date: 8/5/14 * Time: 4:50 PM */ public class ErsatzFactory { private final List testData; public ErsatzFactory() { testData = new ArrayList(); int order = 0; for (int i = 0 ; i < 9; i++) { testData.add(order++ + "-Test"); } Collections.sort(testData); } @Factory public Object[] setUp() { List objects = new ArrayList(); int order = 0; for (String testDatum : testData) { objects.add( order, new ErsatzTest(testDatum) ); order++; } return objects.toArray(); } } 

考试class

 import org.testng.ITest; import org.testng.annotations.Listeners; import org.testng.annotations.Test; /** * @author rcourtright * Date: 8/5/14 * Time: 4:45 PM */ //@Listeners(ErsatzListener.class) public class ErsatzTest implements ITest { private String order; public ErsatzTest(String order) { this.order = order; } @Test public void justDoIt() { System.out.println(order); } @Override public String getTestName() { return order; } } 

TestNG XML

         

所以你可以在我的构造中看到我有一个自然顺序的列表,我对该集合进行排序。 工厂的工作是按顺序执行单个测试方法。 通过调试,我发现Factory返回的集合是按照所需的顺序。 但这不是他们的执行方式。

使用TestNG支持的ant目标,这是执行顺序:

检测结果

 ersatz-test-executor: [testng] 5-Test [testng] 2-Test [testng] 7-Test [testng] 6-Test [testng] 4-Test [testng] 8-Test [testng] 1-Test [testng] 0-Test [testng] 3-Test [testng] [testng] =============================================== [testng] ersatz-testing [testng] Total tests run: 9, Failures: 0, Skips: 0 [testng] =============================================== [testng] 

这既意外也不可取。 显然,这个测试是微不足道的,但它是一个相当复杂的系统测试的代理,我必须得到正确的执行顺序。

虽然这里没有列出,但我必须使用TestNG Listener进行后期测试结果处理,看来我必须使用Factory而不是独立的DataProvider。 (我已经在测试类声明中注释掉了Listener注释。)我应该注意到Listener的工作没有发生任何事故。

因为只有一种方法,所以我不能使用优先级注释或方法依赖性。 测试完全由数据驱动。 数据是可排序的,如果内存服务,当我在测试类中使用DataProvider时,我得到了该顺序。 但我还需要Listener来装饰测试结果报告,这促使我使用工厂。 我应该注意,无论我是否使用监听器,都存在执行问题。 如果您编译并运行此代码,我希望您会看到列出的结果似乎是随机顺序。

在此先感谢您对此问题的考虑。

好的,我怀疑了。 我不理解方法拦截器的预处理能力。 所以我创建了一个,我得到了我的有序测试。 为了寻求解决方案的任何人的利益,我将在此列出我的代码更改。

方法拦截器

 import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * @author rcourtright * Date: 8/11/14 * Time: 2:37 PM */ public class ErsatzMethodInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { Map orders = new TreeMap(); for (IMethodInstance iMethodInstance : methods) { if (!iMethodInstance.getMethod().getMethodName().equals("justDoIt")) { continue; } Object obj = iMethodInstance.getInstance(); if (!(obj instanceof ErsatzTest)) { continue; } ErsatzTest ersatzTest = (ErsatzTest)obj; String order = ersatzTest.getOrder(); orders.put(order,iMethodInstance); } List tests = new ArrayList(orders.size()); for (String order : orders.keySet()) { IMethodInstance test = orders.get(order); tests.add(test); } return tests; } } 

将测试类连接到拦截器类

  import org.apache.log4j.Logger; import org.testng.ITest; import org.testng.annotations.Listeners; import org.testng.annotations.Test; /** * @author rcourtright * Date: 8/5/14 * Time: 4:45 PM */ @Listeners( { ErsatzMethodInterceptor.class, ErsatzListener.class } ) public class ErsatzTest implements ITest { private Logger logger = Logger.getLogger(ErsatzTest.class); private String order; public ErsatzTest(String order) { this.order = order; } public String getOrder() { return order; } @Test public void justDoIt() { logger.info(order); } @Override public String getTestName() { return order; } } 

奖励听众将漂亮的打印结果报告给报告

  import org.apache.log4j.Logger; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.internal.BaseTestMethod; import org.testng.internal.TestResult; import java.lang.reflect.Field; /** * @author rcourtright * Date: 7/29/14 * Time: 12:03 PM */ public class ErsatzListener extends TestListenerAdapter { private Logger logger = Logger.getLogger(ErsatzListener.class); private void setTestNameInXml(ITestResult tr) { try { Field mMethod = TestResult.class.getDeclaredField("m_method"); mMethod.setAccessible(true); mMethod.set(tr, tr.getMethod().clone()); Field mMethodName = BaseTestMethod.class.getDeclaredField("m_methodName"); mMethodName.setAccessible(true); mMethodName.set(tr.getMethod(), tr.getTestName()); } catch (IllegalAccessException ex) { logger.error(ex.getLocalizedMessage(), ex); } catch (NoSuchFieldException ex) { logger.error(ex.getLocalizedMessage(), ex); } } @Override public void onTestSuccess(ITestResult tr) { setTestNameInXml(tr); super.onTestSuccess(tr); } @Override public void onTestFailure(ITestResult tr) { setTestNameInXml(tr); super.onTestFailure(tr); } @Override public void onTestSkipped(ITestResult tr) { setTestNameInXml(tr); super.onTestSkipped(tr); } } 

测试执行结果

我假设你现在有了log4j,所以在类路径上只有一个可用的log4j.xml,这里我们订购了测试结果:

 $ java org.testng.TestNG testng.xml [TestNG] Running: /Users/rcourtright/Desktop/ersatz/testng.xml 0 [main] INFO ErsatzTest - 0-Test 2 [main] INFO ErsatzTest - 1-Test 3 [main] INFO ErsatzTest - 2-Test 4 [main] INFO ErsatzTest - 3-Test 5 [main] INFO ErsatzTest - 4-Test 6 [main] INFO ErsatzTest - 5-Test 7 [main] INFO ErsatzTest - 6-Test 8 [main] INFO ErsatzTest - 7-Test 9 [main] INFO ErsatzTest - 8-Test =============================================== ersatz-testing Total tests run: 9, Failures: 0, Skips: 0 =============================================== 

最后,我没有意识到方法拦截器的强大function,并且它在工厂做任何事情之后运行。 也就是说,工厂方法不控制顺序,但这可以通过使用拦截器来改变。