Java自動化測試框架-04 - TestNG之Test Method篇 - 道法自然,法力無邊(詳細教程)
簡介
按照上一篇的計劃,這一篇給小夥伴們分享一下測試方法。
一、設定引數
測試方法是可以帶有引數的。每個測試方法都可以帶有任意數量的引數,並且可以通過使用TestNG的@Parameters向方法傳遞正確的引數。
設定方式有兩種方法:使用testng.xml或者Data Providers 。
(一)使用 testng.xml 設定引數
這種方法讓我們在testng.xml檔案中,定義簡單的引數,然後在原始碼檔案引用這些引數。
1.如果只使用相對簡單的引數,可以在 testng.xml檔案中指定:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ @Parameters({ "first-name" }) @Test public void testSingleString(String firstName) { System.out.println("Invoked testString " + firstName); assert "Cedric".equals(firstName); }
在這段程式碼中,我們讓 firstName 引數能夠接到XML檔案中叫做 first-name 引數的值。這個XML引數被定義在 testng.xml:
<suite name="My suite"> <parameter name="first-name" value="Cedric"/> <test name="Simple example">
類似的,它也可以用在 @Before/After 和 @Factory 註解上:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ @Parameters({ "datasource", "jdbcDriver" }) @BeforeMethod public void beforeTest(String ds, String driver) { m_dataSource = ...; // 查詢資料來源的值 m_jdbcDriver = driver; }
這次有兩個Java引數 ds 和 driver 會分別接收到來自屬性datasource 和 jdbc-driver 所指定的值。
2.引數也可以通過 Optional 註釋來宣告:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ @Parameters("db") @Test public void testNonExistentParameter(@Optional("mysql") String db) { ... }
如果在你的testng.xml檔案中沒有找到"db",你的測試方法就會使用 @Optional 中的值:"MySQL"。
3.@Parameters 可以被放置到如下位置:
(1)在任何已經被 @Test, @Before/After 或 @Factory 註解過的地方。
(2)在測試類中至多被放到一個建構函式籤。這樣,TestNG才能在需要的時候使用 testng.xml 中特定的引數來例項化這個類。這個特性可以被用作初始化某些類中的值,以便稍後會被類中其他的方法所使用。
注意:
XML中的引數會按照Java引數在註解中出現的順序被對映過去,並且如果數量不匹配,TestNG會報錯。
引數是有作用範圍的。在testng.xml 中,你即可以在<suite> 標籤下宣告,也可以在 <test>下宣告。如果兩個引數都有相同的名字,那麼,定義在<test> 中的有優先權。這在你需要覆蓋某些測試中特定引數的值時,會非常方便。
(二)使用DataProviders提供引數
在testng.xml 中指定引數可能會有如下的不足:
1.如果你壓根不用 testng.xml.
2.你需要傳遞複雜的引數,或者從Java中建立引數(複雜物件,物件從屬性檔案或者資料庫中讀取的etc...)或者在testng.xml中指定引數可能不夠
這樣的話,你就可以使用Data Provider來給需要的測試提供引數。所謂資料提供者,就是一個能返回物件陣列的陣列的方法,並且這個方法被@DataProvider註解標註:
DataProvider的定義如下:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ @DataProvider(name = "range-provider") public Object[][] rangeData() { int lower = 5; int upper = 10; return new Object[][] { { lower-1, lower, upper, false }, { lower, lower, upper, true }, { lower+1, lower, upper, true }, { upper, lower, upper, true}, { upper+1, lower, upper, false }, }; }
呼叫DataProvider的方式如下:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ @Test(dataProvider = "range-provider") public void testIsBetween(int n, int lower,int upper, boolean expected){ println("Received " + n + " " + lower + "-"+ upper + " expected: " + expected); Assert.assertEquals(expected, isBetween(n, lower, upper)); }
被@Test標註的方法通過dataProvider屬性指明其資料提供商。這個名字必須與@DataProvider(name="...")中的名字相一致。
DataProvider返回的是一個Object的二維陣列,二維陣列中的每個一維陣列都會傳遞給呼叫函式,作為引數使用。執行的時候,會發現, @Test標識的test method被執行的次數和object[][]包含的一維陣列的個數是一致的,而@Test標識的函式的引數個數,也和object內一維陣列內的元素數是一致的。
執行後的輸出結果如下:
Received 4 5-10expected: false
Received 5 5-10expected: true
Received 6 5-10expected: true
Received 10 5-10expected: true
Received 11 5-10expected: false
===============================================
Parameter Suite
Total tests run: 5,Failures: 0, Skips: 0
===============================================
(三)DataProviders擴充套件
預設的情況下,資料提供者會查詢當前的測試類或者測試類的基類。如果你希望它能夠被其他的類所使用,那麼就要將其指定為static,並且通過 dataProviderClass 屬性指定要使用的類:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-03 - TestNG之Test Method篇 * * 2019年10月23日 */ public static 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) { // ... } }
Data Provider方法可以返回如下兩種型別中的一種:
1.含有多個物件的陣列 (Object[][]),其中第一個下標指明瞭測試方法要呼叫的次數,第二個下標則完全與測試方法中的引數型別和個數相匹配。上面的例子已經說明。
2.另外一個是迭代器 Iterator<Object[]>。二者的區別是迭代器允許你延遲建立自己的測試資料。TestNG會呼叫迭代器,之後測試方法會一個接一個的呼叫由迭代器返回的值。在你需要傳遞很多引數組給測試組的時候,這樣你無須提前建立一堆值。
下面是使用JDK5 的例子 (注意 JDK 1.4的例子不適用泛型):
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ public Iterator createData() { return new MyIterator(DATA); ) @DataProvider(name = "test1") public Iterator
如果你宣告的 @DataProvider 使用 java.lang.reflect.Method 作為第一個引數,TestNG 會把當前的測試方法當成引數傳給第一個引數。這一點在你的多個測試方法使用相同的@DataProvider的時候,並且你想要依據具體的測試方法返回不同的值時,特別有用。
例如,下面的程式碼它內部的 @DataProvider 中的測試方法的名字:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @DataProvider(name = "dp") public Object[][] createData(Method m) { System.out.println(m.getName()); return new Object[][] { new Object[] { "Cedric" }}; } @Test(dataProvider = "dp") public void test1(String s) {} @Test(dataProvider = "dp") public void test2(String s) {}
所以會顯示:
test1
test2
Data provider可以通過屬性 parallel實現並行執行:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @DataProvider(parallel = true) //...
使用XML檔案執行的data provider享有相同的執行緒池,預設的大小是10.你可以通過修改該在 <suite> 標籤中的值來更改:
<suitename="Suite1" data-provider-thread-count="20" > ...
如果你需要讓指定的幾個data provider執行在不同的執行緒中,那麼就必須通過不同的xml檔案來執行。
(四)兩種方法的優缺點
testng.xml
優點:值在testng.xml中指定,這方便修改,不需要重新編譯程式碼 ;
缺點:你需要一個testng.xml檔案,值不能夠動態算出
資料提供者
優點:可以想測試方法傳遞任何有效的Java型別這種方法非常靈活,值可以通過Java程式碼動態算出,或者任何儲存機制中取得
缺點:這種方法需要實現某些邏輯,以返回正確的物件
二、依賴方法
有些時候,需要按照特定順序呼叫測試方法。
1.確保在進行更多的方法測試之前,有一定數量的測試方法已經成功完成。
2.在初始化測試的時候,同時希望這個初始化方法也是一個測試方法( @Before/After 不會出現在最後生成的報告中)。
為此,你可以使用 @Test 中的 dependsOnMethods 或 dependsOnGroups 屬性。
這兩種依賴:
1.Harddependencies(硬依賴)。所有的被依賴方法必須成功執行。只要有一個出問題,測試就不會被呼叫,並且在報告中被標記為SKIP。
2.Softdependencies(軟依賴)。 即便是有些依賴方法失敗了,也一樣執行。如果你只是需要保證你的測試方法按照順序執行,而不關心他們的依賴方法是否成功。那麼這種機制就非常有用。可以通過新增 "alwaysRun=true" 到 @Test 來實現軟依賴。
硬依賴的例子:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @Test public void serverStartedOk() {} @Test(dependsOnMethods = { "serverStartedOk" }) public void method1() {}
此例中,method1() 依賴於方法 serverStartedOk(),從而保證 serverStartedOk() 總是先執行。
也可以讓若干方法依賴於組:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @Test(groups = { "init" }) public void serverStartedOk() {} @Test(groups = { "init" }) public void initEnvironment() {} @Test(dependsOnGroups = { "init.* }) public void method1() {}
本例中,method1()依賴於匹配正則表示式"init.*"的組,由此保證了serverStartedOk()和initEnvironment()總是先於method1()被呼叫。
注意:正如前面所說的那樣,在相同組中的呼叫可是在誇測試中不保證順序的。
如果你使用硬依賴,並且被依賴方法失敗(alwaysRun=false,即預設是硬依賴),依賴方法則不是被標記為FAIL而是SKIP。被跳過的方法會被在最後的報告中標記出來(HTML既不用紅色也不是綠色所表示),主要是被跳過的方法不是必然失敗,所以被標出來做以區別。
無論dependsOnGroups還是dependsOnMethods都可以接受正則表示式作為引數。對於dependsOnMethods,如果被依賴的方法有多個過載,那麼所有的過載方法都會被呼叫。如果你只希望使用這些過載中的一個,那麼就應該使用dependsOnGroups。
三、類級註解
通常 @Test 也可以用來標註類,而不僅僅是方法:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * * java自動化測試交流群:694280102 * * Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @Test public class Test1 { public void test1() { } public void test2() { } }
處於類級的 @Test 會使得類中所有的public方法成為測試方法,而不管他們是否已經被標註。當然,你仍然可以用 @Test 註解重複標註測試方法,特別是要為其新增一些特別的屬性時。
例如:
package hongge; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import hongge.TestSum; /** * @author 北京-巨集哥 * *java自動化測試交流群:694280102 * *Java自動化測試框架-04 - TestNG之Test Method篇 * * 2019年10月23日 */ @Test public class Test1 { public void test1() { } @Test(groups = "g1") public void test2() { } }
上例中 test1() 和 test2() 都被處理,不過在此之上 test2() 現在還屬於組 "g1"。
小結
嘿嘿!今天就分享到這裡。下一篇計劃是測試方法(Factory),希望小夥伴們和童鞋們喜歡和繼續關注巨集哥!
有問題加入java自動化測試交流群:694280102
個人公眾號 微信群 (微信群已滿100,可以加巨集哥的微信拉你進群,請備註:進群)
您的肯定就是我進步的動力。如果你感覺還不錯,就請鼓勵一下吧!記得點波 推薦 哦!!!(點選右邊的小球即可!(^__^) 嘻嘻……)