testng翻译之五--Test methods, Test classes and Test groups

本文详细介绍 TestNG 测试框架的使用方法,包括测试方法的注解、测试组的定义与使用、依赖关系的配置等内容。同时介绍了如何利用 TestNG 进行复杂的方法分组测试,以及如何设置测试参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Test methods
测试方法用@Test注释。 除非在testng.xml中将allow-return-values设置为true,否则@Test注释的返回值的方法将被忽略:

<suite allow-return-values="true">
or
<test allow-return-values="true">


Test groups
TestNG允许您执行复杂的方法分组测试。 您不仅可以声明方法属于组,而且还可以指定包含其他组的组。 然后可以调用TestNG并要求包括一组特定的组(或正则表达式),同时排除另一组。 这为您提供了如何分区测试的最大灵活性,并且如果要反复运行两组不同的测试,则不需要重新编译任何内容。

groups 在您的testng.xml文件中指定,可以在<test><suite>标记下找到。 <suite>标签中指定的组适用于下面所有的<test>标签。 注意,这些标签中的组是累加的:如果在<suite>中指定组“a”,在<test>中指定“b”,那么在<test>将包括“a”和“b”两个组。

例如,至少有两类测试是常见的:

  • Check-in tests. 这些测试应该在提交新代码之前运行。他们通常能很快地执行,只是用来确保没有基本的功能单元出错崩溃。
  • Functional tests. 这些测试应该涵盖软件的所有功能,并且每天至少运行一次,尽管理想情况下您希望连续运行它们。

通常,check-in tests 是 functional tests 的一个子集。TestNG允许您以非常直观的方式指定测试组。 例如,您可以通过说整个测试类属于“functest”组,并且另外几个方法属于组“checkintest”来构造测试:

public class Test1 {
  @Test(groups = { "functest", "checkintest" })
  public void testMethod1() {
  }

  @Test(groups = {"functest", "checkintest"} )
  public void testMethod2() {
  }

  @Test(groups = { "functest" })
  public void testMethod3() {
  }
}

调用TestNG:

<test name="Test1">
  <groups>
    <run>
      <include name="functest"/>
    </run>
  </groups>
  <classes>
    <class name="example1.Test1"/>
  </classes>
</test>

其中,<groups><include>name=functest,那么僵运行此类中所有的测试方法;而当name=checkintest时,只运行方法testMethod1() and testMethod2()。

这里是另一个例子,这次使用正则表达式。 假设你的一些测试方法不应该在Linux上运行,你的测试将如下所示:

@Test
public class Test1 {
  @Test(groups = { "windows.checkintest" })
  public void testWindowsOnly() {
  }

  @Test(groups = {"linux.checkintest"} )
  public void testLinuxOnly() {
  }

  @Test(groups = { "windows.functest" )
  public void testWindowsToo() {
  }
}

您可以使用以下testng.xml仅启动Windows方法:

<test name="Test1">
  <groups>
    <run>
      <include name="windows.*"/>
    </run>
  </groups>

  <classes>
    <class name="example1.Test1"/>
  </classes>
</test>

Method groups
你还可以排除或包含单个方法:

<test name="Test1">
  <classes>
    <class name="example1.Test1">
      <methods>
        <include name=".*enabledTestMethod.*"/>
        <exclude name=".*brokenTestMethod.*"/>
      </methods>
     </class>
  </classes>
</test>

这可以有效的去停用一个单一的方法,而不必重新编译任何东西,但非常不建议使用这种技术,因为如果你开始重构Java代码,它可能使你的测试框架会被打破(标记中使用的正则表达式可能不再与您的方法匹配)。



Groups of groups
组也可以包括其他组。 这些组称为“MetaGroups”。 例如,您可能想要定义一个包含“checkintest”和“functest”的组“all”。 “functest”本身将包含组“windows”和“linux”,而“checkintest将只包含”windows“。下面是如何在属性文件中定义这个:

<test name="Regression1">
  <groups>
    <define name="functest">
      <include name="windows"/>
      <include name="linux"/>
    </define>

    <define name="all">
      <include name="functest"/>
      <include name="checkintest"/>
    </define>

    <run>
      <include name="all"/>
    </run>
  </groups>

  <classes>
    <class name="test.sample.Test1"/>
  </classes>
</test>


Exclusion groups
TestNG允许你包含或排除 groups。

例如,由于最近的更改,暂时中断的测试是很常见的,你没有时间修复破损。 但是,您确实希望清理运行功能测试,因此您需要停用这些测试,但请记住,需要重新激活这些测试。

一个解决这个问题的简单方法是创建一个名为“broken”的组,并使这些测试方法属于它。 例如,在上面的例子中,我知道testMethod2()现在出错了,所以我想禁用它:

@Test(groups = {"checkintest", "broken"} )
public void testMethod2() {
}

我现在需要做的是从运行中排除此组:

<test name="Simple example">
  <groups>
    <run>
      <include name="checkintest"/>
      <exclude name="broken"/>
    </run>
  </groups>

  <classes>
    <class name="example1.Test1"/>
  </classes>
</test>

这样,我将得到一个干净的测试运行,同时跟踪哪些测试是出错的,需要稍后修复。

注意:您还可以通过使用@Test和@ Before / After注释之间的“enabled”属性来单独禁用测试。



Partial groups
您可以在类级别定义组,然后在方法级别添加组:

@Test(groups = { "checkin-test" })
public class All {

  @Test(groups = { "func-test" )
  public void method1() { ... }

  public void method2() { ... }
}

在这个类中,method2()是在类级别定义的组“checkin-test”的一部分,而method1()属于“checkin-test”和“func-test”。



Parameters
测试方法肯能是有参数的。 您可以在每个测试方法上使用任意数量的参数,并指示TestNG使用@Parameters注解传递正确的参数。

有两种方法来设置这些参数:使用testng.xml或以编程方式。

Parameters from testng.xml
如果对参数使用简单的值,可以在testng.xml中指定它们:

@Parameters({ "first-name" })
@Test
public void testSingleString(String firstName) {
  System.out.println("Invoked testString " + firstName);
  assert "Cedric".equals(firstName);
}

在此代码中,我们指定您的Java方法的参数firstName应接收名为first-name的XML参数的值。 此XML参数在testng.xml中定义:

<suite name="My suite">
  <parameter name="first-name"  value="Cedric"/>
  <test name="Simple example">
  <-- ... -->

相同的技术可以用于@ Before / After和@Factory注解:

@Parameters({ "datasource", "jdbcDriver" })
@BeforeMethod
public void beforeTest(String ds, String driver) {
  m_dataSource = ...;              // look up the value of datasource
  m_jdbcDriver = driver;
}

这一次,两个Java参数ds和driver将分别接收来自属性datasource和jdbc-driver的值。

参数可以声明为可选注释:

@Parameters("db")
@Test
public void testNonExistentParameter(@Optional("mysql") String db) { ... }

如果在testng.xml文件中找不到名为“db”的参数,那么您的测试方法将接收@Optional注释“mysql”中指定的默认值。

@Parameters注释可以放置在以下位置:

  • 在任何已经有@Test,@ Before / After或@Factory注释的方法。
  • 最多只有一个构造函数的测试类。 在这种情况下,当需要实例化测试类时,TestNG将调用此特定构造函数,并将参数初始化为testng.xml中指定的值。 此功能可用于将类中的字段初始化为随后将由测试方法使用的值。

注意

  • XML参数以与在注释中找到的顺序相同的顺序映射到Java参数,如果数字不匹配,TestNG将发出错误。
  • 参数范围。 在testng.xml中,可以在标签下或下声明它们。 如果两个参数具有相同的名称,则它是在中定义的具有优先级的参数。 如果需要指定适用于所有测试的参数,并且仅对某些测试覆盖其值,则这样的设计很方便。

Parameters with DataProviders
如果需要传递复杂参数或需要从Java(复杂对象,从属性文件或数据库读取的对象等)创建的参数,在testng.xml中指定参数可能不够。在这种情况下,您可以使用 数据提供程者 提供需要测试的值。数据提供者 是您的类上的一个方法,它返回对象数组。 此方法用@DataProvider注解:

//This method will provide data to any test method that declares that its Data Provider
//is named "test1"
@DataProvider(name = "test1")
public Object[][] createData1() {
 return new Object[][] {
   { "Cedric", new Integer(36) },
   { "Anne", new Integer(37)},
 };
}

//This test method declares that its data should be supplied by the Data Provider
//named "test1"
@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
 System.out.println(n1 + " " + n2);
}

将打印

Cedric 36
Anne 37

@Test方法使用dataProvider属性指定其数据提供程者。 此名称必须与使用匹配名称@DataProvider(name =“…”)注解的同一类上的方法相对应。

默认情况下,将在当前测试类或其基类中查找数据提供者。 如果要将数据提供者放在不同的类中,则需要使用静态方法具有non-arg构造函数的类,并指定可在dataProviderClass属性中找到的类:

public class StaticProvider {
  @DataProvider(name = "create")
  public static Object[][] createData() {
    return new Object[][] {
      new Object[] { new Integer(42) }
    };
  }
}

public class MyTest {
  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
  public void test(Integer n) {
    // ...
  }
}

数据提供程者也支持注入。 TestNG将使用测试上下文进行注入。 数据提供者方法可以返回以下两种类型之一:

  • 对象数组数组(Object [] []),其中第一个维度的大小是调用测试方法的次数,第二个维度大小包含必须与测试方法的参数类型兼容的对象数组。 这是上面的例子说明的。
  • 一个迭代器<Object []>。 与Object [] []的唯一区别是,迭代器允许您慢慢创建测试数据。 TestNG将调用迭代器,然后使用该迭代器返回的参数逐个调用测试方法。 如果您有很多参数集要传递给方法,并且您不想预先创建所有参数集,这将非常有用。
    下面就此功能举个例子:
@DataProvider(name = "test1")
public Iterator<Object[]> createData() {
  return new MyIterator(DATA);
}

如果你声明的@DataProvider为一个java.lang.reflect.Method作为第一个参数,TestNG将为第一个参数传递当前的测试方法。(此处翻译可能不准确)。当几个测试方法使用相同的@DataProvider并且您希望它根据为其提供数据的测试方法返回不同的值时,这是特别有用的。

例如,以下代码在其@DataProvider中打印测试方法的名称:

@DataProvider(name = "dp")
public Object[][] createData(Method m) {
  System.out.println(m.getName());  // print test method name
  return new Object[][] { new Object[] { "Cedric" }};
}

@Test(dataProvider = "dp")
public void test1(String s) {
}

@Test(dataProvider = "dp")
public void test2(String s) {
}

结果:

test1
test2

属性数据提者可以与属性parallel并行运行:

@DataProvider(parallel = true)
// ...

默认情况下,从XML文件运行的并行数据提供者共享相同的线程池,其大小为10。 您可以在XML文件的标记中修改此值:

<suite name="Suite1" data-provider-thread-count="20" >
...

如果要在不同的线程池中运行几个特定的数据提供程序,则需要从不同的XML文件运行它们。


Parameters in reports
用于调用测试方法的参数显示在由TestNG生成的HTML报告中。 这里是一个例子:
这里写图片描述



Dependencies
有时,您需要以特定顺序调用您的测试方法。 这里有几个例子:

  • 在运行更多测试方法之前,确保一定数量的测试方法已完成并成功。
  • 初始化你的测试,同时希望这个初始化方法也是测试方法(用@ Before / After标记的方法不会成为最终报告的一部分)。

TestNG允许您使用注解或XML指定依赖性。


Dependencies with annotations
您可以使用属性dependsOnMethods或dependsOnGroups,在@Test注释中找到。

有两种依赖关系:

  • 硬依赖。 所有依赖的方法都必须运行并成功运行。 如果您的依赖项中至少出现一个失败,则不会在报告中调用并标记为SKIP。
  • 软依赖。 你将总是在依赖的方法之后运行,即使它们中的一些失败。 当你只想确保你的测试方法以一定的顺序运行时,这是有用的,但是它们的成功并不取决于他人的成功。 通过在@Test注释中添加“alwaysRun = true”可以获得软依赖。

这里是一个硬依赖的例子:

@Test
public void serverStartedOk() {}

@Test(dependsOnMethods = { "serverStartedOk" })
public void method1() {}

在这个例子中,method1()被声明为依赖于方法serverStartedOk(),它保证serverStartedOk()始终被首先调用。

您还可以具有依赖于整个组的方法:

@Test(groups = { "init" })
public void serverStartedOk() {}

@Test(groups = { "init" })
public void initEnvironment() {}

@Test(dependsOnGroups = { "init.*" })
public void method1() {}

在此示例中,method1()被声明为取决于与正则表达式“init.*”匹配的任何组,这保证在method1()之前始终调用serverStartedOk()和initEnvironment()方法。

注意:如前所述,属于同一组的方法的调用顺序不能保证在测试运行中是相同的。

如果一个方法依赖于失败,并且对它有一个硬依赖(alwaysRun = false,这是默认值),依赖它的方法不会被标记为FAIL,而是标记为SKIP。 跳过的方法将在最终报告中报告(在HTML中既不是红色也不是绿色),这是重要的,因为跳过的方法不一定是失败的。

有关依赖方法的更高级示例,请参阅 [本文]

其中为使用继承多个依赖关系的问题提供一个优雅的解决方案。

默认情况下,依赖方法按类分组。 例如,如果方法b()依赖于方法a(),并且您有几个包含这些方法的类的实例(因为数据提供者的工厂),那么调用顺序如下:

a(1)
a(2)
b(2)
b(2)

TestNG不会运行b(),直到所有实例都调用了他们的a()方法。

在某些情况下,这种行为可能不是期望的,例如测试针对各个国家的web浏览器的登录和退出。 在这种情况下,您需要以下顺序:

signIn("us")
signOut("us")
signIn("uk")
signOut("uk")

对于此排序,可以使用XML属性分组实例。 此属性在或上有效:

<suite name="Factory" group-by-instances="true">
or
<test name="Factory" group-by-instances="true">

Dependencies in XML
或者,您可以在testng.xml文件中指定组依赖关系。 您可以使用标记来实现:

<test name="My suite">
  <groups>
    <dependencies>
      <group name="c" depends-on="a  b" />
      <group name="z" depends-on="c" />
    </dependencies>
  </groups>
</test>
<think>好的,用户现在想详细了解TestNG的配置文件testng.xml,特别是如何配置suitetest、class以及运行参数,以避免之前的SocketTimeoutException错误。用户之前遇到了TestNG的异常,可能是在配置或依赖方面有问题,现在希望通过正确配置testng.xml来解决。 首先,我需要回顾之前给出的解决方案,其中提到了升级TestNG版本、优化XML配置、检查依赖等。用户现在更关注XML配置的细节,所以需要详细解释testng.xml的结构和各个元素的作用。 根据用户提供的引用内容,testng.xml用于配置测试套件,可以控制测试的类、方法、参数、并发等。引用中提到了suitetestclasses等标签,以及如何设置并行参数和线程池大小。用户可能想了解如何正确编写这个文件,特别是suitetest的关系,以及如何设置参数来避免超时问题。 用户可能遇到的问题包括:XML文件结构错误导致测试无法正确运行,或者配置不当引发超时。需要详细说明每个标签的用法和常见配置,比如suite的parallel属性,test的time-out参数,classes的包含方式,以及如何通过参数传递数据。 另外,用户提到想避免运行时错误,如SocketTimeoutException,这可能与测试执行时间过长有关。因此,需要解释如何在testng.xml中设置超时参数,如suite级别的time-out,或者test方法中的timeOut属性。 还需要注意用户可能在使用Maven或IDE时遇到的路径问题,确保testng.xml被正确识别。可能需要提到文件的位置和构建工具的配置。 最后,要确保回答结构清晰,分点解释,并提供示例代码,这样用户可以直接参考并应用。同时,结合之前的解决方案,强调正确配置XML文件如何帮助避免超时错误,比如合理设置超时时间和并发策略。</think>### TestNG XML 配置文件详解 出现$SocketTimeoutException$等运行时错误时,正确配置`testng.xml`文件是解决问题的关键[^1]。以下从**套件结构**、**核心参数**和**优化技巧**三方面详细说明: --- #### 一、套件层级结构 TestNG通过XML文件定义测试执行逻辑,基本结构为: $$suite \rightarrow test \rightarrow classes \rightarrow methods$$ ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="CustomSuite" parallel="tests" thread-count="3" time-out="180000"> <test name="RegressionTest" time-out="60000"> <classes> <class name="com.example.TestClassA"/> <class name="com.example.TestClassB"> <methods> <include name="testLogin"/> <exclude name="testPayment"/> </methods> </class> </classes> </test> </suite> ``` 1. **`<suite>` 根元素** - `parallel`: 并发模式(`tests|classes|methods|instances`) - `thread-count`: 最大并发线程数 - `time-out`: 全局超时时间(单位:毫秒) 2. **`<test>` 子模块** - 可嵌套多个`<test>`,每个模块独立配置 - `preserve-order`: 是否保持执行顺序(默认`true`) - `group-by-instances`: 按实例分组执行 3. **`<classes>` 选择器** - `<class name="完整类路径">`指定具体测试类 - `<methods>`支持正则表达式过滤方法 --- #### 二、关键运行参数配置 1. **并发控制** ```xml <!-- 方法级并发 --> <suite name="ConcurrentSuite" parallel="methods" thread-count="5"> <test name="APITest"> <classes> <class name="com.example.APITestSuite"/> </classes> </test> </suite> ``` 2. **参数化数据驱动** ```xml <suite name="DataDrivenSuite"> <parameter name="env" value="staging"/> <test name="DBTest"> <parameter name="dbUrl" value="jdbc:mysql://localhost:3306/test"/> <classes> <class name="com.example.DatabaseTest"/> </classes> </test> </suite> ``` 3. **失败重试机制** ```xml <suite name="RetrySuite"> <listeners> <listener class-name="com.example.RetryListener"/> </listeners> <test name="FlakyTest"> <classes> <class name="com.example.FlakyTests"/> </classes> </test> </suite> ``` --- #### 三、避免超时错误的配置技巧 1. **分层设置超时** ```xml <suite name="SafeSuite" time-out="300000"> <!-- 全局5分钟 --> <test name="CriticalPath" time-out="120000"> <!-- 单个测试模块2分钟 --> <classes> <class name="com.example.CriticalTests"/> </classes> </test> </suite> ``` 2. **资源隔离配置** ```xml <suite name="IsolationSuite" parallel="classes" thread-count="2"> <test name="ChromeTests" preserve-order="true"> <parameter name="browser" value="chrome"/> <classes> <class name="com.example.ChromeTestCases"/> </classes> </test> <test name="FirefoxTests"> <parameter name="browser" value="firefox"/> <classes> <class name="com.example.FirefoxTestCases"/> </classes> </test> </suite> ``` 3. **动态排除不稳定用例** ```xml <test name="SanityTest"> <groups> <run> <exclude name="broken"/> </run> </groups> <classes> <class name="com.example.SanityChecks"/> </classes> </test> ``` --- #### 四、验证配置有效性 1. **IDE直接运行**:在IntelliJ/Eclipse右键运行XML文件 2. **Maven命令验证**: ```bash mvn test -DsuiteXmlFile=src/test/resources/testng.xml ``` 3. **Schema校验**:确保包含`<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">` --- ### 相关问题 1. 如何在TestNG中实现跨测试类的依赖管理? 2. TestNG数据驱动测试的最佳实践是什么? 3. 如何通过testng.xml配置多环境参数切换?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值