並行(多線程)技術在軟件術語裏被定義爲軟件、操做系統或者程序能夠並行地執行另一段程序中多個部分或者子組件的能力。TestNG容許咱們以並 行(多線程)的方式來執行測試。這就意味着基於TestNG測試組件的配置,多個線程能夠被同時啓動而後分別執行各自的測試方法。相對於傳統的單線程執行 測試的方式,這種多線程方式擁有很大的優點,主要是它能夠減小測試運行時間,而且能夠驗證某段代碼在多線程環境中運行的正確性。html
並行(多線程)執行測試能夠給用戶帶來不少好處,主要包括如下兩點:java
1)減小了執行時間:並行測試也就意味着多個測試能夠在同一時間被同時執行,從而減小了總體測試所花費的時間。瀏覽器
2)容許多個線程並行地測試同一個測試組件:有了這個特性,咱們就可以寫出相應的測試用例來驗證應用程序中包含多線程部分的代碼的正確性。多線程
以上特性被普遍地應用在QA領域的自動化功能測試方面。經過簡單的配置,QA人員就能夠很輕鬆地使得他們的測試用例在多個瀏覽器或者操做系統中並行地執行。eclipse
TestNG提供了三種不一樣類型的配置方案來實現並行測試。學習
TestNG爲咱們提供了多種方式來實現並行測試,其中一種就是每個獨立的線程分別執行各自的測試方法。這種方式可以顯著地減小測試執行時間,這是由於當有越多的測試方法被並行執行時,整體測試消耗時間將會越少。測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package com.howtodoinjava.parallelism;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class ParallelMethodTest
{
@BeforeMethod
public void beforeMethod() {
long id = Thread.currentThread().getId();
System.out.println( "Before test-method. Thread id is: " + id);
}
@Test
public void testMethodsOne() {
long id = Thread.currentThread().getId();
System.out.println( "Simple test-method One. Thread id is: " + id);
}
@Test
public void testMethodsTwo() {
long id = Thread.currentThread().getId();
System.out.println( "Simple test-method Two. Thread id is: " + id);
}
@AfterMethod
public void afterMethod() {
long id = Thread.currentThread().getId();
System.out.println( "After test-method. Thread id is: " + id);
}
}
|
上述測試類包含了兩個測試方法,每一個測試方法在執行時都會在控制檯中打印出一條信息。每一個測試方法以及它們各自的beforeMehod、 afterMethod方法都會經過Thread.currentThread.getId()這段代碼打印出執行該測試方法的線程的ID。ui
在項目中新建一個名爲methods-test-testng.xml的文件並將下述代碼寫入該文件中。this
1
2
3
4
5
6
7
|
< suite name = "Test-method Suite" parallel = "methods" thread-count = "2" >
< test name = "Test-method test" group-by-instances = "true" >
< classes >
< class name = "com.howtodoinjava.parallelism.ParallelMethodTest" />
</ classes >
</ test >
</ suite >
|
在Eclipse中選中該文件而且以TestNG測試套件方式運行它。你將會在控制檯中看到如下輸出信息:spa
1
2
3
4
5
6
|
Before test-method. Thread id is: 10
Before test-method. Thread id is: 9
Simple test-method Two. Thread id is: 10
Simple test-method One. Thread id is: 9
After test-method. Thread id is: 10
After test-method. Thread id is: 9
|
注意:上述截圖中的ThreadId可能與你本地控制檯中輸出的ThreadId不一樣,這是由於ThreadId的值是在程序運行時由JVM動態指派的。
從上述測試結果中咱們能夠很清晰地看出:上述兩個測試方法以及各自相應的beforeMethod和afterMethod方法是在兩個獨立的線程中執行的。咱們能夠經過在控制檯中輸出的ThreadId來證實這一點。
在下個例子中,咱們會說明如何並行地執行測試類:同一個測試組件(test execution)中的各個測試類將會在獨立的線程中並行地執行。
ParallelClassesTestOne.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class ParallelClassesTestOne
{
@BeforeClass
public void beforeClass() {
long id = Thread.currentThread().getId();
System.out.println( "Before test-class. Thread id is: " + id);
}
@Test
public void testMethodOne() {
long id = Thread.currentThread().getId();
System.out.println( "Sample test-method One. Thread id is: " + id);
}
@Test
public void testMethodTwo() {
long id = Thread.currentThread().getId();
System.out.println( "Sample test-method Two. Thread id is: " + id);
}
@AfterClass
public void afterClass() {
long id = Thread.currentThread().getId();
System.out.println( "After test-class. Thread id is: " + id);
}
}
|
ParallelClassesTestTwo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class ParallelClassesTestTwo
{
@BeforeClass
public void beforeClass() {
long id = Thread.currentThread().getId();
System.out.println( "Before test-class. Thread id is: " + id);
}
@Test
public void testMethodOne() {
long id = Thread.currentThread().getId();
System.out.println( "Sample test-method One. Thread id is: " + id);
}
@Test
public void testMethodTwo() {
long id = Thread.currentThread().getId();
System.out.println( "Sample test-method Two. Thread id is: " + id);
}
@AfterClass
public void afterClass() {
long id = Thread.currentThread().getId();
System.out.println( "After test-class. Thread id is: " + id);
}
}
|
在項目中新建一個名爲classes-test-testng.xml的文件並將下述代碼寫入該文件中:
1
2
3
4
5
6
7
8
|
< suite name = "Test-class Suite" parallel = "classes" thread-count = "2" >
< test name = "Test-class test" >
< classes >
< class name = "com.howtodoinjava.parallelism.ParallelClassesTestOne" />
< class name = "com.howtodoinjava.parallelism.ParallelClassesTestTwo" />
</ classes >
</ test >
</ suite >
|
在Eclipse中選中該文件而且以TestNG測試套件方式運行它。你將會在控制檯中看到如下輸出信息:
1
2
3
4
5
6
7
8
|
Before test- class . Thread id is: 10
Before test- class . Thread id is: 9
Sample test-method One. Thread id is: 9
Sample test-method One. Thread id is: 10
Sample test-method Two. Thread id is: 10
After test- class . Thread id is: 10
Sample test-method Two. Thread id is: 9
After test- class . Thread id is: 9
|
從上述測試結果中咱們能夠很清晰地看出:上述兩個測試類以及各自相應的beforeClass和afterClass方法是在獨立的兩個線程中執行的。咱們能夠經過在控制檯中輸出的ThreadId來證實這一點。
接下來咱們會一塊兒學習如何並行地執行同一個測試套件內的各個測試組件,即各個測試組件會分別在獨立的線程中執行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.howtodoinjava.parallelism;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParallelSuiteTest
{
String testName = "" ;
@BeforeTest
@Parameters ({ "test-name" })
public void beforeTest(String testName) {
this .testName = testName;
long id = Thread.currentThread().getId();
System.out.println( "Before test " + testName + ". Thread id is: " + id);
}
@BeforeClass
public void beforeClass() {
long id = Thread.currentThread().getId();
System.out.println( "Before test-class " + testName + ". Thread id is: "
+ id);
}
@Test
public void testMethodOne() {
long id = Thread.currentThread().getId();
System.out.println( "Sample test-method " + testName
+ ". Thread id is: " + id);
}
@AfterClass
public void afterClass() {
long id = Thread.currentThread().getId();
System.out.println( "After test-method " + testName
+ ". Thread id is: " + id);
}
@AfterTest
public void afterTest() {
long id = Thread.currentThread().getId();
System.out.println( "After test " + testName + ". Thread id is: " + id);
}
}
|
在項目中新建一個名爲suite-test-testng.xml的文件並將如下代碼寫入該文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
< suite name = "Test-class Suite" parallel = "tests" thread-count = "2" >
< test name = "Test-class test 1" >
< parameter name = "test-name" value = "test-method One" />
< classes >
< class name = "com.howtodoinjava.parallelism.ParallelSuiteTest" />
</ classes >
</ test >
< test name = "Test-class test 2" >
< parameter name = "test-name" value = "test-method One" />
< classes >
< class name = "com.howtodoinjava.parallelism.ParallelSuiteTest" />
</ classes >
</ test >
</ suite >
|
在Eclipse中選中該文件而且以TestNG測試套件方式運行它。你將會在控制檯中看到如下輸出信息:
1
2
3
4
5
6
7
8
9
10
|
Before test Test One. Thread id is: 9
Before test Test Two. Thread id is: 10
Before test- class Test One. Thread id is: 9
Before test- class Test Two. Thread id is: 10
Sample test-method Test One. Thread id is: 9
Sample test-method Test Two. Thread id is: 10
After test-method Test Two. Thread id is: 10
After test-method Test One. Thread id is: 9
After test Test One. Thread id is: 9
After test Test Two. Thread id is: 10
|
從上述測試結果中咱們能夠很清晰地看出:上述兩個測試組件是在獨立的兩個線程中分別執行的。咱們能夠經過在控制檯中輸出的ThreadId來證實這一點。
以前咱們討論瞭如何並行(多線程)地執行測試方法,測試類以及測試組件。TestNG同時也提供了一種靈活的方式來配置須要在多線程環境下運行的測試方法:只要在該測試方法的@Test註解上配置一些信息,咱們就能啓用多線程模式。
1
2
3
4
5
6
7
8
9
|
public class IndependentTest
{
@Test (threadPoolSize = 3 , invocationCount = 6 , timeOut = 1000 )
public void testMethod()
{
Long id = Thread.currentThread().getId();
System.out.println( "Test method executing on thread with id: " + id);
}
}
|
上述測試方法是經過在@Test註解中配置threadPoolSize這個屬性來進入多線程模式的。threadPoolSize被設爲3,這就 說明了該測試方法將會在三個不一樣的線程中同時執行。剩餘兩個屬性:invocationCount配置的是該測試方法應被執行的總次數,timeOut配 置的是每次執行該測試方法所耗費時間的閾值,超過閾值則測試失敗。
在項目中新建一個名爲independent-test-testng.xml的文件,並寫入下述代碼:
1
2
3
4
5
6
7
|
< suite name = "Independent test Suite" >
< test name = "Independent test" >
< classes >
< class name = "com.howtodoinjava.parallelism.IndependentTest" />
</ classes >
</ test >
</ suite >
|
在Eclipse中選中該文件並以TestNG測試套件方式運行。你將會在控制檯中看到如下輸出信息
1
2
3
4
5
6
|
Test method executing on thread with id: 11
Test method executing on thread with id: 10
Test method executing on thread with id: 9
Test method executing on thread with id: 11
Test method executing on thread with id: 11
Test method executing on thread with id: 10
|
在這裏,咱們能夠看出該測試方法被執行了屢次,並且它的執行次數跟invocationCount所指定的次數相同。並且從輸出信息中,咱們也能夠 很清晰地看到該測試方法每次執行都是在不一樣的線程中完成的。當咱們須要按照某一固定次數,在多線程環境下運行某些測試方法時,上述特性會頗有幫助,由於它 避免了咱們把整個測試套件都並行執行屢次的代價。
原文連接: Lokesh Gupta 翻譯: ImportNew.com - 楊 崑崙
譯文連接: http://www.importnew.com/14508.html
[ 轉載請保留原文出處、譯者和譯文連接。]