一、并行性和超時
您可以指示TestNG以各種方式在單獨的線程中運行測試。
可以通過在suite標簽中使用 parallel 屬性來讓測試方法運行在不同的線程中。這個屬性可以帶有如下這樣的值:
二、并行套件(suites)
如果您正在運行多個套件文件(例如“ java org.testng.TestNG testng1.xml testng2.xml”),并且希望每個套件在單獨的線程中運行,則這個很有用。您可以使用以下命令行標志來指定線程池的大?。?
java org.testng.TestNG -suitethreadpoolsize 3 testng1.xml testng2.xml testng3.xml
相應的ant任務名稱為suitethreadpoolsize。
三、并行測試,類和方法
在并行于<suite>標記屬性可以取下列值之一:
<suite name="My suite" parallel="methods" thread-count="5">
<suite name="My suite" parallel="tests" thread-count="5">
<suite name="My suite" parallel="classes" thread-count="5">
<suite name="My suite" parallel="instances" thread-count="5">
parallel =“ methods”:TestNG將在單獨的線程中運行所有測試方法。依賴方法也將在單獨的線程中運行,但是它們將遵循您指定的順序。parallel =“ tests”:TestNG將在同一線程中的同一<test>標記中運行所有方法,但是每個<test>標記將位于單獨的線程中。這樣,您就可以將所有不是線程安全的類歸入同一個<test>中,并確保它們都將在同一線程中運行,同時利用TestNG使用盡可能多的線程來運行測試。平行=“類”:TestNG的將運行在相同的線程相同的類的所有方法,但每個類將在單獨的線程中運行。parallel =“ instances”:TestNG將在同一線程中的同一實例中運行所有方法,但是在兩個不同實例中的兩個方法將在不同線程中運行。此外,屬性 thread-count允許您指定應為此執行分配多少個線程。注意:@Test屬性timeOut在并行和非并行模式下均可工作。您還可以指定從不同的線程調用@Test方法。您可以使用屬性threadPoolSize來實現以下結果:
@Test(threadPoolSize = 3, invocationCount = 10, timeOut = 10000)
public void testServer() {
在此示例中,將從三個不同的線程調用函數testServer十次。此外,十秒的超時保證沒有任何線程將永遠在該線程上阻塞。
四、重新運行失敗的測試
每當套件中的測試失敗時,TestNG都會在輸出目錄中創建一個名為testng-failed.xml的文件。此XML文件包含必要的信息,以僅重新運行失敗的這些方法,從而使您可以快速重現失敗,而不必運行整個測試。因此,典型的會話如下所示:
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs test-outputs\testng-failed.xml
請注意,testng-failed.xml將包含所有必需的依賴方法,因此可以確保您運行失敗的方法而不會出現任何SKIP失敗。
有時,您可能希望TestNG在測試失敗時自動重試。在這種情況下,您可以使用重試分析器。當您將重試分析器綁定到測試時,TestNG會自動調用重試分析器,以確定TestNG是否可以再次重試測試用例,以查看是否剛剛通過的測試現在通過。這是使用重試分析器的方法:
構建接口org.testng.IRetryAnalyzer的實現
將此實現綁定到@Test注釋,例如@Test(retryAnalyzer = LocalRetry.class)
以下是重試分析器的示例實現,該示例最多重試一次測試三次。
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
/**
* @author 北京-宏哥
*
* Java自動化測試框架-08 - TestNG之 TestNG之并行性和超時篇
*
* 2019年11月7日
*/
public class MyRetry implements IRetryAnalyzer {
private int retryCount = 0;
private static final int maxRetryCount = 3;
@Override
public boolean retry(ITestResult result) {
if (retryCount < maxRetryCount) {
retryCount++;
return true;
}
return false;
}
}
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* @author 北京-宏哥
*
* Java自動化測試框架-08 - TestNG之 TestNG之并行性和超時篇
*
* 2019年11月7日
*/
public class TestclassSample {
@Test(retryAnalyzer = MyRetry.class)
public void test2() {
Assert.fail();
}
}
五、JUnit測試
TestNG可以運行JUnit 3和JUnit 4測試。所有你需要做的就是把JUnit的jar文件在類路徑中,在指定JUnit測試類,testng.classNames 屬性和設置testng.junit屬性設置為true:
<test name="Test1" junit="true">
<classes>
<!-- ... -->
在這種情況下,TestNG的行為類似于JUnit,這取決于在類路徑上找到的JUnit版本:
JUnit 3:
您的課程中所有以test *開頭的方法都將運行
如果您的測試類上有一個方法setUp(),它將在每個測試方法之前調用
如果您的測試類上有一個方法tearDown(),它將在每個測試方法之后被調用
如果您的測試類包含方法suite(),則將調用此方法返回的所有測試
JUnit 4:
TestNG將使用org.junit.runner.JUnitCore運行程序運行測試
六、以編程的方式運行testng
您可以從自己的程序中輕松調用TestNG:
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { Run2.class });
testng.addListener(tla);
testng.run();
本示例創建一個TestNG對象并運行測試類Run2。它還添加了一個TestListener。您可以使用適配器類org.testng.TestListenerAdapter或自己實現org.testng.ITestListener。此接口包含各種回調方法,可讓您跟蹤測試的開始時間,成功時間,失敗時間等。
同樣,您可以在testng.xml文件上調用TestNG,也可以自己創建一個虛擬的testng.xml文件。為此,您可以使用發現包org.testng.xml的類: XmlClass,XmlTest等。這些類中的每一個都對應于它們的XML標記對應物。
例如,假設您要創建以下虛擬文件:
<suite name="TmpSuite" >
<test name="TmpTest" >
<classes>
<class name="test.failures.Child" />
<classes>
</test>
</suite>
您將使用以下代碼:
XmlSuite suite = new XmlSuite();
suite.setName("TmpSuite");
XmlTest test = new XmlTest(suite);
test.setName("TmpTest");
List<XmlClass> classes = new ArrayList<XmlClass>();
classes.add(new XmlClass("test.failures.Child"));
test.setXmlClasses(classes) ;
然后,您可以將此XmlSuite傳遞給TestNG:
List<XmlSuite> suites = new ArrayList<XmlSuite>();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.run();
有興趣的:請參閱JavaDocs了解整個API。
七、BeanShell和高級組選擇
如果testng.xml中的<include>和<exclude>標記不足以滿足您的需要,則可以使用BeanShell表達式來確定是否應在測試運行中包括某種測試方法。您可以在<test>標記下指定此表達式:
<test name="BeanShell test">
<method-selectors>
<method-selector>
<script language="beanshell"><![CDATA[
groups.containsKey("test1")
]]></script>
</method-selector>
</method-selectors>
<!-- ... -->
當<SCRIPT>標記中發現的testng.xml,TestNG的將忽略隨后的<包括>和<排除>在當前組和方法的<試驗>標記:你的BeanShell的表達將是決定是否一個測試方法的唯一方式是否包含在內。
以下是有關BeanShell腳本的其他信息:
它必須返回一個布爾值。除了此約束之外,還允許使用任何有效的BeanShell代碼(例如,您可能希望在工作日返回true,在周末返回false,這將允許您根據日期以不同的方式運行測試)為了方便起見,TestNG定義了以下變量:1、java.lang.reflect.Method method:當前的測試方法。2、org.testng.ITestNGMethod testngMethod:當前測試方法的描述。3、java.util.Map <String,String> groups:當前測試方法所屬的組的映射。您可能希望用CDATA聲明包圍表達式(如上所示),以避免冗長的保留XML字符引用。
八、Annotation Transformers
TestNG允許您在運行時修改所有注釋的內容。如果源代碼中的注釋大多數時候都是正確的,則這特別有用,但是在某些情況下,您想覆蓋它們的值。
為了實現此目的,您需要使用注釋轉換器。
Annotation Transformer是一個實現以下接口的類:
public interface IAnnotationTransformer {
/**
* This method will be invoked by TestNG to give you a chance
* to modify a TestNG annotation read from your test classes.
* You can change the values you need by calling any of the
* setters on the ITest interface.
*
* Note that only one of the three parameters testClass,
* testConstructor and testMethod will be non-null.
*
* @param annotation The annotation that was read from your
* test class.
* @param testClass If the annotation was found on a class, this
* parameter represents this class (null otherwise).
* @param testConstructor If the annotation was found on a constructor,
* this parameter represents this constructor (null otherwise).
* @param testMethod If the annotation was found on a method,
* this parameter represents this method (null otherwise).
*/
public void transform(ITest annotation, Class testClass,
Constructor testConstructor, Method testMethod);
}
像所有其他TestNG偵聽器一樣,您可以在命令行或使用ant來指定此類:
java org.testng.TestNG -listener MyTransformer testng.xml
或以編程方式:
TestNG tng = new TestNG();
tng.setAnnotationTransformer(new MyTransformer());
// ...
調用 方法transform()時,可以在TestNG繼續進行之前,調用ITest測試參數上的任何設置方法來更改其值。
例如,這是您如何重寫屬性invocationCount的方法,但僅在其中一個測試類的測試方法invoke()上:
/**
* @author 北京-宏哥
*
* Java自動化測試框架-08 - TestNG之 TestNG之并行性和超時篇
*
* 2019年11月7日
*/
public class MyTransformer implements IAnnotationTransformer {
public void transform(ITest annotation, Class testClass,
Constructor testConstructor, Method testMethod)
{
if ("invoke".equals(testMethod.getName())) {
annotation.setInvocationCount(5);
}
}
}
IAnnotationTransformer僅允許您修改@Test注釋。如果需要修改另一個TestNG批注(配置批注@Factory或@DataProvider),請使用IAnnotationTransformer2。
九、方法攔截器
一旦TestNG 計算好了測試方法會以怎樣的順序調用,那么這些方法就會分為兩組:
1.按照順序運行的方法。這里所有的方法都有相關的依賴,并且所有這些方法按照特定順序運行。
2.不定順序運行的方法。這里的方法不屬于第一個類別。方法的運行順序是隨機的,下一個說不準是什么(盡管如此,默認情況下TestNG會嘗試通過類來組織方法)。
為了能夠讓你更好的控制第二種類別,TestNG定義如下接口:
/**
* @author 北京-宏哥
*
* Java自動化測試框架-08 - TestNG之 TestNG之并行性和超時篇
*
* 2019年11月7日
*/
public interface IMethodInterceptor {
List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context);
}
方法中叫做methods的那個列表參數包含了所有以不定序運行的方法。你的 intercept 方法也要返回一個 IMethodInstance列表,它可能是下面情況之一:
1.內容與參數中接收的一致,但是順序不同
2.一組 IMethodInstance 對象
3.更大的一組 IMethodInstance對象
一旦你定義了攔截器,就把它傳遞個TestNG,用下面的方式:
java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor
-testclass test.methodinterceptors.FooTest
有關等效的ant語法,請參見ant文檔中的listeners屬性。
例如,這是一個方法攔截器,它將對方法進行重新排序,以便始終首先運行屬于“快速”組的測試方法:
/**
* @author 北京-宏哥
*
* Java自動化測試框架-08 - TestNG之 TestNG之并行性和超時篇
*
* 2019年11月7日
*/
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
List<IMethodInstance> result = new ArrayList<IMethodInstance>();
for (IMethodInstance m : methods) {
Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class);
Set<String> groups = new HashSet<String>();
for (String group : test.groups()) {
groups.add(group);
}
if (groups.contains("fast")) {
result.add(0, m);
}
else {
result.add(m);
}
}
return result;
}
十、TestNG偵聽器
有幾個接口可讓您修改TestNG的行為。這些接口廣泛地稱為“ TestNG偵聽器”。以下是一些聽眾:
IAnnotationTransformer(doc,javadoc)
IAnnotationTransformer2(doc,javadoc)
IHookable(doc,javadoc)
IInvokedMethodListener(doc,javadoc)
IMethodInterceptor(doc,javadoc)
IReporter(doc,javadoc)
ISuiteListener(doc,javadoc)
ITestListener(doc,javadoc)
當實現這些接口之一時,可以通過以下兩種方式之一讓TestNG知道它:
在命令行上使用-listener。
將<listeners>與ant一起使用。
在您的testng.xml文件中使用<listeners> 。
在任何測試類上使用@Listeners批注。
使用ServiceLoader。
十一、使用的testng.xml或Java的指定監聽器
這是在testng.xml文件中定義偵聽器的方法:
<suite>
<listeners>
<listener class-name="com.example.MyListener" />
<listener class-name="com.example.MyMethodInterceptor" />
</listeners>
...
或者,如果您更喜歡用Java定義這些偵聽器,則:
@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class })
public class MyTest {
// ...
}
該@Listeners注釋可以包含任何擴展類org.testng.ITestNGListener 除了 IAnnotationTransformer和IAnnotationTransformer2。原因是這些偵聽器需要在過程的早期就知道,以便TestNG可以使用它們來重寫您的注釋,因此您需要在testng.xml文件中指定這些偵聽器。
請注意,@ Listeners批注將應用于您的整個套件文件,就像您在testng.xml文件中指定的一樣。如果要限制其范圍(例如,僅在當前類上運行),則偵聽器中的代碼可以首先檢查將要運行的測試方法,然后決定要做什么。這是可以完成的。
1、首先定義一個新的自定義注釋,可用于指定此限制:
@Retention(RetentionPolicy.RUNTIME)
@Target ({ElementType.TYPE})
public @interface DisableListener {}
2、在常規偵聽器中添加如下所示的編輯檢查:
public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
ConstructorOrMethod consOrMethod =iInvokedMethod.getTestMethod().getConstructorOrMethod();
DisableListener disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableListener.class);
if (disable != null) {
return;
}
// else resume your normal operations
}
3、注釋測試類,其中不調用偵聽器:
@DisableListener
@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class })
public class MyTest {
// ...
}
十二、使用的ServiceLoader指定偵聽器
最后,JDK提供了一種非常優雅的機制,可以通過ServiceLoader類在類路徑上指定接口的實現。使用ServiceLoader,您要做的就是創建一個包含偵聽器和一些配置文件的jar文件,在運行TestNG時將該jar文件放在類路徑中,TestNG會自動找到它們。
這是其工作方式的具體示例。
讓我們從創建一個監聽器開始(任何TestNG監聽器都可以工作):
package test.tmp;
public class TmpSuiteListener implements ISuiteListener {
@Override
public void onFinish(ISuite suite) {
System.out.println("Finishing");
}
@Override
public void onStart(ISuite suite) {
System.out.println("Starting");
}
}
編譯該文件,然后在META-INF / services / org.testng.ITestNGListener位置創建一個文件,該文件將命名您想要此接口的實現。您應該以以下目錄結構結束,只有兩個文件:
$ tree
|____META-INF
| |____services
| | |____org.testng.ITestNGListener
|____test
| |____tmp
| | |____TmpSuiteListener.class
$ cat META-INF/services/org.testng.ITestNGListener
test.tmp.TmpSuiteListener
創建此目錄的jar:
$ jar cvf ../sl.jar .
added manifest
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/org.testng.ITestNGListener(in = 26) (out= 28)(deflated -7%)
adding: test/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/TmpSuiteListener.class(in = 849) (out= 470)(deflated 44%)
接下來,在調用TestNG時,將此jar文件放在類路徑中:
$ java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml
Starting
f2 11 2
PASSED: f2("2")
Finishing
通過此機制,您只需將jar文件添加到類路徑即可將相同的一組偵聽器應用于整個組織,而不是要求每個開發人員都記住在其testng.xml文件中指定這些偵聽器。
十三、小結
好了,今天關于TestNG之并行性和超時,就分享到這里。
轉載自://www.cnblogs.com/du-hong/p/11810569.html