TestNG系列教程:并行執行測試
并行(多線程)技術在軟件術語里被定義為軟件、操作系統或者程序可以并行地執行另外一段程序中多個部分或者子組件的能力。TestNG允許我們以并行(多線程)的方式來執行測試。這就意味著基于TestNG測試組件的配置,多個線程可以被同時啟動然后分別執行各自的測試方法。相對于傳統的單線程執行測試的方式,這種多線程方式擁有很大的優勢,主要是它可以減少測試運行時間,并且可以驗證某段代碼在多線程環境中運行的正確性。
目錄
- 并行執行測試的優勢
- 如何并行地執行測試方法
- 如何并行地執行測試類
- 如何并行地執行同一測試套件內的各個測試組件
- 如何配置需要在多線程環境中執行的測試方法 </ol>
并行執行測試的優勢
并行(多線程)執行測試可以給用戶帶來很多好處,主要包括以下兩點:
1)減少了執行時間:并行測試也就意味著多個測試可以在同一時間被同時執行,從而減少了整體測試所花費的時間。
2)允許多個線程并行地測試同一個測試組件:有了這個特性,我們就能夠寫出相應的測試用例來驗證應用程序中包含多線程部分的代碼的正確性。
以上特性被廣泛地應用在QA領域的自動化功能測試方面。通過簡單的配置,QA人員就可以很輕松地使得他們的測試用例在多個瀏覽器或者操作系統中并行地執行。
TestNG提供了三種不同類型的配置方案來實現并行測試。
如何并行地執行測試方法
TestNG為我們提供了多種方式來實現并行測試,其中一種就是每一個獨立的線程分別執行各自的測試方法。這種方式能夠顯著地減少測試執行時間,這是因為當有越多的測試方法被并行執行時,總體測試消耗時間將會越少。
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); }
}</pre>
上述測試類包含了兩個測試方法,每個測試方法在執行時都會在控制臺中打印出一條信息。每個測試方法以及它們各自的beforeMehod、afterMethod方法都會通過Thread.currentThread.getId()這段代碼打印出執行該測試方法的線程的ID。
在項目中新建一個名為methods-test-testng.xml的文件并將下述代碼寫入該文件中。
<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測試套件方式運行它。你將會在控制臺中看到以下輸出信息:
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
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); }
}</pre>
ParallelClassesTestTwo.java
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); }
}</pre>
在項目中新建一個名為classes-test-testng.xml的文件并將下述代碼寫入該文件中:
<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測試套件方式運行它。你將會在控制臺中看到以下輸出信息:
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來證明這一點。
如何并行地執行同一測試套件內的各個測試組件
接下來我們會一起學習如何并行地執行同一個測試套件內的各個測試組件,即各個測試組件會分別在獨立的線程中執行。
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的文件并將以下代碼寫入該文件中:
<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測試套件方式運行它。你將會在控制臺中看到以下輸出信息:
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注解上配置一些信息,我們就能啟用多線程模式。
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的文件,并寫入下述代碼:
<suite name="Independent test Suite" > <test name="Independent test"> <classes> <class name="com.howtodoinjava.parallelism.IndependentTest" /> </classes> </test> </suite>在Eclipse中選中該文件并以TestNG測試套件方式運行。你將會在控制臺中看到以下輸出信息
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