TestNG的參數化測試

軟件測試往往需要測試大量的數據集,這樣才能保證軟件的穩定性和魯棒性。JUnit沒有提供方便傳遞測試參數的機制,所以,針對每個測試數據集,都需要單獨寫代碼進行測試。這樣浪費很多時間和精力重複寫測試代碼,它們只是參數不一樣,測試邏輯完全一樣。同時,測試代碼和測試數據沒有分離,爲今後的維護埋下隱患。

TestNG在參數化測試方面,比JUnit有較大的優勢。提供了兩種傳遞參數的方式。testng.xml方式使代碼和測試數據分離,方便擴展和維護。@DataProvider能夠提供比較複雜的參數,同時方便產生具有一定規律的測試數據集。

1. testng.xml

可以通過<parameter>標籤,在testng.xml中定義參數的值。對於同一參數,可以在不同地方定義不同值,因此需要注意testng.xml中的測試範圍的問題。

<suite>和<test>標籤定義了suite和test兩種測試範圍:一個test可以包含一系列的測試方法,一個suite可以包含多個獨立的test。這兩種測試範圍有什麼區別呢?一個test的所有測試方法都是針對同一測試對象,測試方法之間可以相互影響。而一個suite的每個test都是針對一個單獨測試對象,兩個test中的測試方法不會相互影響。

在這兩種測試範圍定義的參數,滿足如下規律:

1)在Suite範圍內定義某個參數的值,對所有的Test都有效。

2)在Test範圍內定義某個參數的值,只是針對該Test有效。

3)如果同時在Suite和Test中定義某個參數,Test範圍的值會屏蔽Suite的值。

示例代碼如下:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Suite" verbose="1">
	<parameter name="username" value="root" />
	<parameter name="password" value="pwd" />
	<parameter name="param" value="param" />

	<test name="test1">
		<parameter name="username" value="root2" />
		<parameter name="password" value="pwd2" />
		<classes>
			<class name="HelloWorld" />
		</classes>
	</test>

	<test name="test2">
		<packages>
			<package name="com.ibm.testng.test"></package>
		</packages>
	</test>
<suite>
在suite中都定義了username和password兩個參數,同時也在test1中也定義了這兩個參數,但是在test2中沒有定義。因此,test1中所有測試方法的username和password分別爲“root2”和“pwd2”,而test2中所有測試方法的username和password分別爲“root”和“pwd”。

在java代碼中,給測試方法傳遞參數的示例代碼如下:

    @Parameters({"username"})
    @Test(groups = "login")
    public void inputUsername(String username) {
        System.out.println("Input Username: " + username); 
    }
    
    @Parameters({"password"})
    @Test(groups = "login")
    public void inputPassword(String password) {
        System.out.println("Input Password: " + password); 
    }
如果帶參的函數被@Test標記爲測試函數,但是沒有被@Parameters標記,或者被@Parameters標記了,但是沒有指定傳遞參數的名字,都會拋出一個TestNGException,這個函數就會被認爲fail掉。

testng.xml只能傳輸簡單類型的參數,不能傳遞Object類型。可以通過間接的方式,傳遞Object類型的參數。將所有參數化放到一個xml文件中,然後將該xml文件名作爲參數,傳遞到一個XML解析器中。將xml解析的參數作爲屬性,創建所需的Object對象,然後對這些對象執行測試方法。

2. @DataProvider

一個使用 @DataProvider傳遞參數的例子,代碼如下:

    @DataProvider(name = "user")
    public Object [][] createUser(Method m) {
        System.out.println(m.getName());
        return new Object[][] { 
                {"root", "root"},
                {"test", "root"},
                };
    }
    
    @Test(groups = "login", dependsOnGroups = "launch", dataProvider = "user")
    public void verifyUser(String username, String password) {
        System.out.println("Verify User : " + username + ":" + password); 
        assert username.equals(password);
    }
示例代碼說明:

1)@DataProvider標記的createUser()提供名稱爲user的參數,同時輸出接受參數的測試函數的名字。

2)@Test標記的測試函數verifyUser()接受名稱爲user的參數,同時判斷參數username和password是否相等。

@DataProvider標記專門爲測試方法提供參數的方法。這類方法必須返回Object[ ][ ]類型的二維數組,Object[]的每一行,都是測試方法的一個測試數據集,測試方法會爲每個測試數據集執行一次。如果沒有指定參數的名稱,則默認爲方法的名稱,方法的名稱沒有限制。

@DataProvider標記的方法一般情況下沒有參數,其實也可以帶參數,但是這些參數的傳遞受到下面的兩個限制:

1)@DataProvider標記的方法不可能是測試函數,因此不能通過@Parameters傳遞參數。

2)@DataProvider標記的方法只能被TestNG調用,因此用戶不能通過調用的方式傳遞參數。

基於上面兩個限制,@DataProvider標記的方法的參數化必須是特殊類型的,即TestNG在調用該方法時,可以通過反射機制獲得。例如,例子中傳遞的參數是java.lang.reflect.Method類型,TestNG會將當前測試函數的名稱傳遞給這個參數。當多個測試函數同時使用相同@DataProvider提供的參數時,需要根據測試方法提供不同的測試數據集時,這種特殊類型參數就顯得非常有用。


發佈了34 篇原創文章 · 獲贊 22 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章