TestNG中测试的执行顺序


76

如何自定义TestNG中测试的执行顺序?

例如:

public class Test1 {
  @Test
  public void test1() {
      System.out.println("test1");
  }

  @Test
  public void test2() {
      System.out.println("test2");
  }

  @Test
  public void test3() {
      System.out.println("test3");
  }
}

在上述套件中,测试的执行顺序是任意的。对于一次执行,输出可能是:

test1
test3
test2

如何按照测试的编写顺序执行测试?

Answers:


84

这会起作用。

@Test(priority=1)
public void Test1() {

}

@Test(priority=2)
public void Test2() {

}

@Test(priority=3)
public void Test3() {

}

priority鼓励执行顺序,但不能保证先前的优先级已完成。test3可以在test2完成之前开始。如果需要保证,则声明一个依赖关系。

与声明依赖关系的解决方案不同,priority即使一个测试失败,使用的测试也会执行。有关依赖关系的问题可以@Test(...alwaysRun = true...)根据文档解决


65

在TestNG中,您使用dependsOnMethods和/或dependsOnGroups:

@Test(groups = "a")
public void f1() {}

@Test(groups = "a")
public void f2() {}

@Test(dependsOnGroups = "a")
public void g() {}

在这种情况下,g()仅在f1()和f2()完成并成功后才运行。

您会在文档中找到很多示例:http : //testng.org/doc/documentation-main.html#test-groups


但是,当使用TestNG Eclipse插件版本时,Cedric的解决方案存在一些缺陷。5.9.0.4似乎每次运行TestCase时都会显示消息,表明该插件不支持组。
honzajde

1
dependsOnGroups是非常有用的,但是在我看来,TestNG忽略了priority两者结合在一起的时间。
G. Demecki 2015年

29

要解决有问题的特定方案:

@Test
public void Test1() {

}

@Test (dependsOnMethods={"Test1"})
public void Test2() {

}

@Test (dependsOnMethods={"Test2"})
public void Test3() {

}

7

如果您不想@Test(priority = )在TestNG中使用该选项,则可以利用javaassist库和TestNGIMethodInterceptor来根据在测试类中定义测试方法的顺序对测试进行优先级排序。这基于此处提供的解决方案。

将此侦听器添加到您的测试类:

package cs.jacob.listeners;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;

public class PriorityInterceptor implements IMethodInterceptor {
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {

    Comparator<IMethodInstance> comparator = new Comparator<IMethodInstance>() {
        private int getLineNo(IMethodInstance mi) {
        int result = 0;

        String methodName = mi.getMethod().getConstructorOrMethod().getMethod().getName();
        String className  = mi.getMethod().getConstructorOrMethod().getDeclaringClass().getCanonicalName();
        ClassPool pool    = ClassPool.getDefault();

        try {
            CtClass cc        = pool.get(className);
            CtMethod ctMethod = cc.getDeclaredMethod(methodName);
            result            = ctMethod.getMethodInfo().getLineNumber(0);
        } catch (NotFoundException e) {
            e.printStackTrace();
        }

        return result;
        }

        public int compare(IMethodInstance m1, IMethodInstance m2) {
        return getLineNo(m1) - getLineNo(m2);
        }
    };

    IMethodInstance[] array = methods.toArray(new IMethodInstance[methods.size()]);
    Arrays.sort(array, comparator);
    return Arrays.asList(array);
    }
}

这基本上可以找到方法的行号,并按其行号的升序(即,在类中定义它们的顺序)对它们进行排序。


1
如果您必须从junit迁移数百个测试,那么这是一个真正的解决方案
Vitali Carbivnicii

如果您在代码中未使用依赖项标志,则可以解决保留顺序问题。
Ankit Gupta

6
@Test(dependsOnMethods="someBloodyMethod")

3
我可能会指出这不是一个特别有用的答案-建议您更详细地扩展您的答案!

6

用这个:

public class TestNG
{
        @BeforeTest
        public void setUp() 
        {
                   /*--Initialize broowsers--*/

        }

        @Test(priority=0)
        public void Login() 
        {

        }

        @Test(priority=2)
        public void Logout() 
        {

        }

        @AfterTest
        public void tearDown() 
        {
                //--Close driver--//

        }

}

通常TestNG提供许多批注,我们可以@BeforeSuite, @BeforeTest, @BeforeClass用来初始化浏览器/设置。

如果您在脚本中编写了多个测试用例,并且想要按照分配的优先级执行,那么我们可以分配优先级,然后使用: @Test(priority=0)从0、1、2、3 ...开始。

同时,我们可以将测试用例的数量分组并通过分组执行它。为此,我们将使用@Test(Groups='Regression')

最后,像关闭浏览器一样,我们可以使用@AfterTest, @AfterSuite, @AfterClass注释。


4

如果我正确地理解了您的问题,因为您想按指定的顺序运行测试,则可以使用TestNG IMethodInterceptor。查看有关如何利用它们的http://beust.com/weblog2/archives/000479.html

如果要运行一些预初始化,请查看IHookable http://testng.org/javadoc/org/testng/IHookable.html和关联的线程http://groups.google.com/group/testng-users/browse_thread/线程/ 42596505990e8484 / 3923db2f127a9a9c?lnk = gst&q = IHookable#3923db2f127a9a9c


2

小猪退回user1927494的答案,如果要在所有其他测试之前运行单个测试,则可以执行以下操作:

@Test()
public void testOrderDoesntMatter_1() {
}

@Test(priority=-1)
public void testToRunFirst() {
}

@Test()
public void testOrderDoesntMatter_2() {
}

2

通过指定要在testNg.xml中执行的测试方法,我们可以按期望的顺序执行测试用例

<suite>
<test name="selenium1">
 		<classes>
			<class name="com.test.SeleniumTest" >
			    <methods><include name="methodB"></include>
			        <include name="methodA"></include>
			    </methods>    
			 </class>
		</classes>
 
	</test>
</suite>


1

通过对@Test使用优先级参数,我们可以控制测试执行的顺序。


2
不幸的是在TestNG中没有。
Mariusz Jamro

@MariuszJamro我不明白为什么?Priority参数在2012年还不存在?
G. Demecki 2015年

1

类文件中方法的顺序是不可预测的,因此您需要使用依赖关系或将方法显式包含在XML中。

默认情况下,TestNG将按照在XML文件中找到的顺序运行测试。如果您希望此文件中列出的类和方法以不可预测的顺序运行,则将keep-order属性设置为false


1

我也遇到过同样的问题,可能的原因是由于testng的并行执行,而解决方案是在您的testng.xml中添加Priority选项或简单地更新prepare-order =“ true”。

<test name="Firefox Test" preserve-order="true">

1
prepare-order =“ true”,是testng.xml中的默认值,并且仅适用于您在testng.xml中定义的顺序,因此,解决问题的方法仅是将优先级添加到@Tests
Kiran

1

有重要解释的答案:

TestNG ”有两个参数,它们可以确定测试的执行顺序:

@Test(dependsOnGroups= "someGroup")

和:

@Test(dependsOnMethods= "someMethod")

在这两种情况下,这些功能均取决于方法或组,

但是区别:

在这种情况下:

@Test(dependsOnGroups= "someGroup")

该方法将取决于整个组,因此不一定在执行依赖函数后立即也将执行此方法,但是它可能会在运行后期甚至在其他测试运行后发生。

重要的是要注意,如果此参数在同一组测试中有多个用途,这是解决问题的安全方法,因为整个测试集的相关方法将首先运行,然后才运行依赖于他们的方法。

但是,在这种情况下:

@Test(dependsOnMethods= "someMethod")

即使在同一组测试中多次使用此参数,在立即执行从属方法后,依从方法仍将执行。

希望它是明确的和帮助。


0

有按给定顺序执行测试的方法。但是,通常情况下,测试必须是可重复且独立的,以确保它仅测试所需的功能,并且不依赖于所测试内容之外的代码副作用。

因此,要回答您的问题,您将需要提供更多信息,例如,为什么按特定顺序运行测试很重要。


19
在许多情况下,依赖项很有用,尤其是对于集成和功能测试。例如,测试一个网站:您要先测试登录页面,然后再测试下一页,等等。。。一直清除和重新创建状态是不切实际的,并且会导致测试非常缓慢。此外,依赖项还可以为您提供更好的诊断信息,例如“ 1个测试失败,跳过99个测试”,而不是传统的“ 100个测试失败”,这无助于意识到所有这些失败实际上是因为一个测试失败了。
Cedric Beust

0

如果您碰巧使用了诸如之类的其他内容dependsOnMethods,则可能需要在testng.xml文件中定义整个@Test流。AFAIK,套件XML文件(testng.xml)中定义的顺序将覆盖所有其他顺序策略。


0

使用:preserve-order =“ true” enabled =“ true”,它将以您编写的方式运行测试用例。

<suite name="Sanity" verbose="1" parallel="" thread-count="">   
<test name="Automation" preserve-order="true"  enabled="true">
        <listeners>
            <listener class-name="com.yourtest.testNgListner.RetryListener" />
        </listeners>
        <parameter name="BrowserName" value="chrome" />
        <classes>
            <class name="com.yourtest.Suites.InitilizeClass" />
            <class name="com.yourtest.Suites.SurveyTestCases" />
            <methods>
                <include name="valid_Login" />
                <include name="verifyManageSurveyPage" />
                <include name="verifySurveyDesignerPage" />
                <include name="cloneAndDeleteSurvey" />
                <include name="createAndDelete_Responses" />
                <include name="previewSurvey" />
                <include name="verifySurveyLink" />
                <include name="verifySurveyResponses" />
                <include name="verifySurveyReports" />
            </methods>
        </classes>
    </test>
</suite>

-5

像单元测试一样的测试?做什么的?测试必须是独立的,否则....您不能单独运行测试。如果他们是独立的,为什么还要干涉?另外-如果您在多个内核的多个线程中运行它们,那是什么“订单”?


2
实际上很有可能将依赖项和并行性混合在一起,请看一下本文以了解TestNG的工作方式: beust.com/weblog/2009/11/28/hard-core-multicore-with-testng
Cedric Beust

人们使用JUnit进行单元测试以外的许多事情。几乎所有这些其他用途都有需要您按特定顺序执行操作的时间。这是开发TestNG,BTW的主要原理之一。
Jeffiekins,2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.