如果我们想要在类级别保留执行的顺序,另一方面我们想要使用选项" dependsOnMethods"并且" parallel =" false"",事情出乎意料。使用TestNG 6.8.8至6.11进行测试。此处描述了类似的行为:
https://github.com/cbeust/testng/issues/1291
我已经尝试过TestNG提供的所有可用选项,唯一有用的是将所有测试类(包含" dependsOnGroups")放在testng.xml中自己的标记中配置。但这导致了另一个问题。我们也在使用" dependsOnGroups"这在单独定义的测试(即不同的标签)之间是不可见的。我在TestNG侦听器中使用" ignoreMissingDependencies = true",通过检查依赖链是否存在依赖组的任何故障。
注意:我已尝试过"逐个实例=" true""和其他TestNG调整优先级和threadCount,forkCount等没有任何成功。
这是我们所拥有的片段,目前正在发挥作用。当然,我可以提供任何有用的建议。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite verbose="0" name="Regretion Suite" parallel="false"
preserve-order="true">
<test name="Tests without dependsOnMethods" preserve-order="true">
<classes>
<class name="com.demo.testng.TestSetup" />
<class name="com.demo.testng.TestOne" />
<class name="com.demo.testng.TestTwo" />
</classes>
</test>
<test name="TestThree with dependsOnMethods">
<classes>
<class
name="com.demo.testng.TestThree" />
</classes>
</test>
<test name="TestFour with dependsOnMethods">
<classes>
<class
name="com.demo.testng.TestFour" />
</classes>
</test>
</suite> <!-- Command line suite -->
package com.demo.testng;
import org.apache.log4j.Logger;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author a.kolev
*/
@Listeners(StateVerifierTestNGWatcher.class)
@Test(groups = {"Setup"})
public class TestSetup
{
private static final Logger log = Logger.getLogger(TestSetup.class);
@BeforeClass
public void oneTimeSetUp()
{
log.info("TestSetup:oneTimeSetUp");
}
@AfterClass(alwaysRun = true)
public void oneTimeCleanUp()
{
log.info("TestSetup::oneTimeCleanUp");
}
@Test
public void testOne()
{
log.info("TestSetup::testOne");
}
@Test
public void testTwo()
{
log.info("TestSetup::testTwo");
}
@Test
public void testThree()
{
log.info("TestSetup::testThree");
}
}
package com.demo.testng;
import org.apache.log4j.Logger;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author a.kolev
*/
@Listeners(StateVerifierTestNGWatcher.class)
@Test(groups = {"Execution"}, dependsOnGroups = {"Setup"}, ignoreMissingDependencies = true)
public class TestOne
{
private static final Logger log = Logger.getLogger(TestOne.class);
@BeforeClass
public void oneTimeSetUp()
{
log.info("TestOne::oneTimeSetUp");
}
@AfterClass(alwaysRun = true)
public void oneTimeCleanUp()
{
log.info("TestOne::oneTimeCleanUp");
}
@Test
public void testOne()
{
log.info("TestOne::testOne");
}
@Test
public void testTwo()
{
log.info("TestOne::testTwo");
}
@Test
public void testThree()
{
log.info("TestOne::testThree");
}
}
package com.demo.testng;
import org.apache.log4j.Logger;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author a.kolev
*/
@Listeners(StateVerifierTestNGWatcher.class)
@Test(groups = {"Execution"}, dependsOnGroups = {"Setup"}, ignoreMissingDependencies = true)
public class TestTwo
{
private static final Logger log = Logger.getLogger(TestTwo.class);
@BeforeClass
public void oneTimeSetUp()
{
log.info("TestTwo::oneTimeSetUp");
}
@AfterClass(alwaysRun = true)
public void oneTimeCleanUp()
{
log.info("TestTwo::oneTimeCleanUp");
}
@Test
public void testOne()
{
log.info("TestTwo::testOne");
}
@Test
public void testTwo()
{
log.info("TestTwo::testTwo");
}
@Test
public void testThree()
{
log.info("TestTwo::testThree");
}
}
package com.demo.testng;
import org.apache.log4j.Logger;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author a.kolev
*/
@Listeners(StateVerifierTestNGWatcher.class)
@Test(groups = {"Execution"}, dependsOnGroups = {"Setup"}, ignoreMissingDependencies = true)
public class TestThree
{
private static final Logger log = Logger.getLogger(TestThree.class);
@BeforeClass
public void oneTimeSetUp()
{
log.info("TestThree::oneTimeSetUp");
}
@AfterClass(alwaysRun = true)
public void oneTimeCleanUp()
{
log.info("TestThree::oneTimeCleanUp");
}
@Test(ignoreMissingDependencies = true)
public void testOne() throws InterruptedException
{
log.info("TestThree::testOne");
Thread.sleep(10000);
}
@Test(dependsOnMethods = "testOne", ignoreMissingDependencies = true)
public void testTwo()
{
log.info("TestThree::testTwo");
}
@Test(dependsOnMethods = "testTwo", ignoreMissingDependencies = true)
public void testThree()
{
log.info("TestThree::testThree");
}
}
package com.demo.testng;
import org.apache.log4j.Logger;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author a.kolev
*/
@Listeners(StateVerifierTestNGWatcher.class)
@Test(groups = {"Execution"}, dependsOnGroups = {"Setup"}, ignoreMissingDependencies = true)
public class TestFour
{
private static final Logger log = Logger.getLogger(TestFour.class);
@BeforeClass
public void oneTimeSetUp()
{
log.info("TestFour::oneTimeSetUp");
}
@AfterClass(alwaysRun = true)
public void oneTimeCleanUp()
{
log.info("TestFour::oneTimeCleanUp");
}
@Test(ignoreMissingDependencies = true)
public void testOne()
{
log.info("TestFour::testOne");
}
@Test(dependsOnMethods = "testOne", ignoreMissingDependencies = true)
public void testTwo() throws InterruptedException
{
log.info("TestFour::testTwo");
Thread.sleep(10000);
}
@Test(dependsOnMethods = "testTwo", ignoreMissingDependencies = true)
public void testThree()
{
log.info("TestFour::testThree");
}
}
package com.demo.testng;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.testng.IConfigurationListener2;
import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.annotations.Test;
import com.seeburger.test.api.util.TestNGWatcher;
/**
* @author a.kolev
*/
public class StateVerifierTestNGWatcher extends TestNGWatcher implements IConfigurationListener2
{
private static Logger log = Logger.getLogger(StateVerifierTestNGWatcher.class);
private static final String CONFIGURATION_METHOD = "oneTimeSetUp";
private static final String CLEANUP_METHOD = "oneTimeCleanUp";
private static Set<String> failedGroups = new HashSet<>();
@Override
public void onTestStart(ITestResult result)
{
checkDependencyConditions(result);
}
/**
* @param result
*/
private void checkDependencyConditions(ITestResult result)
{
String[] groupsDependedUpon = result.getMethod().getGroupsDependedUpon();
for (String groupDependedUpon : groupsDependedUpon)
{
skipIfDependencyFound(groupDependedUpon);
}
super.onTestStart(result);
}
/**
* @param groupDependedUpon
*/
private void skipIfDependencyFound(String groupDependedUpon)
{
if (failedGroups.contains(groupDependedUpon))
{
throw new SkipException("Setup phase failed!");
}
}
@Override
public void onTestFailure(ITestResult result)
{
String[] groups = result.getMethod().getGroups();
for (int i = failedGroups.size(); i < groups.length; i++)
{
failedGroups.add(groups[i]);
}
super.onTestFailure(result);
}
@Override
public void onConfigurationSuccess(ITestResult itr)
{
// TODO Auto-generated method stub
}
@Override
public void onConfigurationFailure(ITestResult itr)
{
// TODO Auto-generated method stub
}
@Override
public void onConfigurationSkip(ITestResult itr)
{
// TODO Auto-generated method stub
}
@Override
public void beforeConfiguration(ITestResult tr)
{
if (tr.getMethod().getMethodName().equals(CONFIGURATION_METHOD) || tr.getMethod().getMethodName().equals(CLEANUP_METHOD))
{
checkConfigMethodDependencyConditions(tr);
}
else
{
checkDependencyConditions(tr);
}
}
/**
* @param tr
*/
private void checkConfigMethodDependencyConditions(ITestResult tr)
{
Class< ? extends Object> instanceClass = tr.getInstance().getClass();
if (instanceClass != null)
{
Test[] annotationsByType = instanceClass.getAnnotationsByType(Test.class);
if (annotationsByType.length > 0)
{
String[] dependsOnGroups = annotationsByType[0].dependsOnGroups();
for (String groupDependedUpon : dependsOnGroups)
{
skipIfDependencyFound(groupDependedUpon);
}
}
}
else
{
log.warn(String.format("Configuration method %s instance class is null! Configuration method is not checked for failed dependency groups!", CONFIGURATION_METHOD));
}
}
}
这是预期的结果,真正的结果是什么:
没有变通方法结果:
TestSetup:oneTimeSetUp
TestSetup::testOne
TestSetup::testThree
TestSetup::testTwo
TestSetup::oneTimeCleanUp
TestOne::oneTimeSetUp
TestOne::testOne
TestOne::testThree
TestOne::testTwo
TestOne::oneTimeCleanUp
TestTwo::oneTimeSetUp
TestTwo::testOne
TestTwo::testThree
TestTwo::testTwo
TestTwo::oneTimeCleanUp
TestThree::oneTimeSetUp
TestThree::testOne
TestThree::testTwo
TestFour::oneTimeSetUp
TestFour::testOne
TestThree::testThree
TestThree::oneTimeCleanUp
TestFour::testTwo
TestFour::testThree
TestFour::oneTimeCleanUp
预期结果:
TestSetup:oneTimeSetUp
TestSetup::testOne
TestSetup::testThree
TestSetup::testTwo
TestSetup::oneTimeCleanUp
TestOne::oneTimeSetUp
TestOne::testOne
TestOne::testThree
TestOne::testTwo
TestOne::oneTimeCleanUp
TestTwo::oneTimeSetUp
TestTwo::testOne
TestTwo::testThree
TestTwo::testTwo
TestTwo::oneTimeCleanUp
TestThree::oneTimeSetUp
TestThree::testOne
TestThree::testTwo
TestThree::testThree
TestThree::oneTimeCleanUp
TestFour::oneTimeSetUp
TestFour::testOne
TestFour::testTwo
TestFour::testThree
TestFour::oneTimeCleanUp