一、前言
隨着企業內部自動化資產的持續積累以及持續集成的推進,對自動化測試的運行速度要求越來越高,某些應用的自動化測試用例可能多達幾千條,如何加速這些自動化用例的運行速度,讓自動化落實到每一次版本變更和持續集成當中,是一個需要解決的問題。
二、TestNG 中的多線程使用姿勢
1、測試方法中的併發
有些時候,我們需要對一個測試用例,比如一個 http 接口,執行併發測試,即一個接口的反覆調用,TestNG 中也提供了優雅的支持方式。
@Test(threadPoolSize = 5,invocationCount = 10) public void test1(){ Assert.assertEquals(2,2); System.out.println("this is thread"+ Thread.currentThread().getId()); }
說明: threadPoolSize 表明用於調用該方法的線程池容量,該例就是同時起 5 個線程並行執行該方法;invocationCount 表示該方法總計需要被執行的次數。
該例子中 5 個線程同時執行,當總計執行次數達到 10 次時停止,執行結果如下:
2、XML中的併發
通常,在 TestNG 的執行中,測試的級別由上至下可以分爲suite -> test -> class -> method,箭頭的左邊元素跟右邊元素的關係是一對多的包含關係。
這裏的 test 指的是 testng.xml 中的 test tag,而不是測試類裏的一個@Test。測試類裏的一個@Test實際上對應這裏的 method。所以我們在使用@BeforeSuite、@BeforeTest、@BeforeClass、@BeforeMethod這些標籤的時候,它們的實際執行順序也是按照這個級別來的。
1) test, class, method級別的併發,可以通過在 testng.xml 中的 suite tag 下設置,如:
<suite name="Testng Parallel Test" parallel="tests" thread-count="5"> <suite name="Testng Parallel Test" parallel="classes" thread-count="5"> <suite name="Testng Parallel Test" parallel="methods" thread-count="5">
說明:它們的共同點都是最多起 5 個線程去同時執行不同的用例。
它們的區別如下:
- tests 級別:不同 test tag 下的用例可以在不同的線程執行,相同 test tag 下的用例只能在同一個線程中執行。
- classes 級別:不同 class tag 下的用例可以在不同的線程執行,相同 class tag 下的用例只能在同一個線程中執行。
- methods 級別:所有用例都可以在不同的線程去執行。
搞清楚併發的級別非常重要,可以幫我們合理地組織用例,比如將非線程安全的測試類或 group 統一放到一個 test 中,這樣在併發的同時又可以保證這些類裏的用例是單線程執行。也可以根據需要設定 class 級別的併發,讓同一個測試類裏的用例在同一個線程中執行。
2)實例演示
測試代碼:TestMethods.java
package com.test.extent; import org.testng.Assert; import org.testng.Reporter; import org.testng.annotations.Test; public class TestMethods { @Test public void test1(){ Assert.assertEquals(2,2); System.out.println("this is thread"+ Thread.currentThread().getId()); } @Test public void test2(){ Assert.assertEquals(1,1); System.out.println("this is thread"+ Thread.currentThread().getId()); } @Test public void test3(){ Assert.assertEquals("sss","sss"); System.out.println("this is thread"+ Thread.currentThread().getId()); } }
xml設置:tests級別併發示例
<?xml version="1.0" encoding="UTF-8" ?> <suite name="Suite1" parallel="tests" thread-count="2"> <test name="測試用例1"> <classes> <class name="com.test.extent.TestMethods"></class> </classes> </test> <test name="測試用例2"> <classes> <class name="com.test.extent.TestMethods"></class> </classes> </test> <test name="測試用例3"> <classes> <class name="com.test.extent.TestMethods"></class> </classes> </test> </suite>
說明:在當前測試規劃的執行過程中,爲每個測試用例(指的是xml中的<test>)的執行使用單獨的線程(該測試用例中的測試方法共享一個線程),
最多併發2個線程,執行結果如下圖:<test name="測試用例1">的3個方法的線程id均爲16
xml設置:classes級別併發示例
<?xml version="1.0" encoding="UTF-8" ?> <suite name="Suite1" parallel="classes" thread-count="2"> <test name="測試用例1"> <classes> <class name="com.test.extent.TestMethods"></class> <class name="com.test.extent.TestMethods2"></class> </classes> </test> </suite>
說明:在當前測試規劃的執行過程中,爲每個測試類(指的是xml中的<class>)的執行使用單獨的線程(該測試類中的測試方法共享一個線程),最多併發2個線程。執行結果如下圖:
xml設置:methods級別併發示例
<?xml version="1.0" encoding="UTF-8" ?> <suite name="Suite1" parallel="methods" thread-count="2"> <test name="test1"> <classes> <class name="com.test.extent.TestMethods"></class> </classes> </test> </suite>
說明:在當前測試規劃的執行過程中,爲每個測試方法(指的是每個@Test)的執行使用單獨的線程,最多併發2個線程,執行結果如下圖: