【TestNG】testNG傳參的用法和高階應用
一.TestNG用法說明
TestNG的詳細教程請看連結:https://blog.csdn.net/df0128/article/details/83243822
二.直接從類中傳參
此處需要用到註解@DataProvider
來進行傳參,
如下定義了一個測試用例,名為TestNgLearn1
,其有兩個引數傳入,param1
和param2
,都是int
型。其標註@Test
內部含有一個dataProvider = "provideNumbers"
即為指明其引數來源,其中provideNumbers
為引數來源的那個方法的名稱。
除了測試用例外還定義了一個方法叫做provideData
,其標註為@DataProvider
1.name引數
name
指定該引數提供者的名稱,其他測試用例可以通過該名稱呼叫此方法,其實如果此屬性不指定的話,會預設將方法名稱作為該資料提供者的名稱,即其他用例可以通過方法名稱來呼叫此方法;
如下name="provideNumbers"
中的provideNumbers
即為設定的引數提供者的名稱,此名稱和測試方法TestNgLearn1
註解中需要的資料提供者名稱一致,如下是一個最簡單的範例:
public class TestCase1 {
@DataProvider(name = "provideNumbers" )
public Object[][] provideData() {
return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 } };
}
@Test(dataProvider = "provideNumbers", groups= {"gp1"})
public void TestNgLearn1(int param1, int param2) {
System.out.println("this is TestNG test case1, and param1 is:" +param1+"; param2 is:"+param2);
Assert.assertFalse(false);
}
}
此處資料提供者返回的的內容必須為Object[][]
,即一個二維陣列,此處要注意,如上面的例子返回了三組引數,故用例應當會被執行三次,即如下結果:
this is TestNG test case1, and param1 is:10; param2 is:20
this is TestNG test case1, and param1 is:100; param2 is:110
this is TestNG test case1, and param1 is:200; param2 is:210
PASSED: TestNgLearn1(10, 20)
PASSED: TestNgLearn1(100, 110)
PASSED: TestNgLearn1(200, 210)
===============================================
Default test
Tests run: 3, Failures: 0, Skips: 0
===============================================
如上結果符合預期,執行三次,三組值都運行了一次;
2.indices引數
@DataProvider
除了必須定義name外,還有兩個值可以指定,一個是indices
,此值指定返回的引數組中的第幾個會被使用,編號從0開始,如下範例指定了indices= {1}
,name執行結果應當只有第二組引數值,程式碼如下:
public class TestCase1 {
@DataProvider(name = "provideNumbers",indices= {1})
public Object[][] provideData() {
return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 } };
}
@Test(dataProvider = "provideNumbers", groups= {"gp1"})
public void TestNgLearn1(int param1, int param2) {
System.out.println("this is TestNG test case1, and param1 is:"+param1+"; param2 is:"+param2);
Assert.assertFalse(false);
}
}
執行結果如下:
this is TestNG test case1, and param1 is:100; param2 is:110
PASSED: TestNgLearn1(100, 110)
===============================================
Default test
Tests run: 1, Failures: 0, Skips: 0
===============================================
如上結果符合預期,只使用了三組引數中的第二組,即編號為1的那一組;注意編號不要超出你返回的列表的大小;
3.parallel引數
此引數意思是是否併發執行,其值可為true
或者false
,預設為false
,如果為true
則會併發執行,範例如下:
public class TestCase1 {
@DataProvider(name = "provideNumbers",parallel=true)
public Object[][] provideData() {
return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 } };
}
@Test(dataProvider = "provideNumbers", groups= {"gp1"})
public void TestNgLearn1(int param1, int param2) {
System.out.println("this is TestNG test case1, and param1 is:"+param1+"; param2 is:"+param2);
Assert.assertFalse(false);
}
}
結果如下:
this is TestNG test case1, and param1 is:200; param2 is:210
this is TestNG test case1, and param1 is:10; param2 is:20
this is TestNG test case1, and param1 is:100; param2 is:110
PASSED: TestNgLearn1(100, 110)
PASSED: TestNgLearn1(200, 210)
PASSED: TestNgLearn1(10, 20)
===============================================
Default test
Tests run: 3, Failures: 0, Skips: 0
===============================================
因為範例執行較快,而此處TestNG並未列印很詳細的東西,所以看不出來是併發,但是如果是用一個執行較慢的用例來驗證,就可以看出來了。
三、從xml檔案中傳參
除了可以從@DataProvider
傳入引數外,還可以通過testng.xml中傳入引數;
此方法需要在用例上除了@Test
外還要添加註解@Parameters
,同時xml中要有parameter
標籤來輸入對應的引數,如下範例所示:
測試用例:
public class ParameterSample {
@Test
@Parameters({ "dbconfig", "poolsize" })
public void test(String dbconfig, int poolsize)
{
System.out.println("dbconfig : " + dbconfig);
System.out.println("poolsize : " + poolsize);
}
}
xml:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="none">
<test name="Test">
<parameter name="dbconfig" value="db.properties" />
<parameter name="poolsize" value="10" />
<classes>
<class name="com.demo.test.testng.ParameterSample"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
執行xml結果如下:
dbconfig : db.properties
poolsize : 10
===============================================
Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================
四、高階應用範例
前面都是傳參的基本用法,下面介紹一些傳參的稍微高階的用法;
1.@DataProvider
傳入物件
程式碼如下
public class ParameterSample {
@Test(dataProvider = "dbconfig")
public void testConnection(Map<String, String> map) {
for (Map.Entry<String, String> entry : map.entrySet())
{
System.out.println("[Key] : " + entry.getKey() + " [Value] : " + entry.getValue());
}
}
@DataProvider(name = "dbconfig")
public Object[][] provideDbConfig() {
Map<String, String> map = readDbConfig();
return new Object[][] { { map } };
}
public Map<String, String> readDbConfig()
{
Map<String, String> map = new HashMap<String, String>();
try {
map.put("jdbc.driver", "com.mysql.jdbc.Driver");
map.put("jdbc.url", "jdbc:mysql://localhost:3306/test");
map.put("jdbc.username", "root");
map.put("jdbc.password", "root");
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
執行結果:
[Key] : jdbc.password [Value] : root
[Key] : jdbc.username [Value] : root
[Key] : jdbc.url [Value] : jdbc:mysql://localhost:3306/test
[Key] : jdbc.driver [Value] : com.mysql.jdbc.Driver
PASSED: testConnection({jdbc.password=root, jdbc.username=root, jdbc.url=jdbc:mysql://localhost:3306/test, jdbc.driver=com.mysql.jdbc.Driver})
===============================================
Default test
Tests run: 1, Failures: 0, Skips: 0
===============================================
不過這樣的話就會只有一條用例了。
2.同一個@DataProvider
分別對兩個測試用例傳參
程式碼如下:
public class ParameterSample {
@Test(dataProvider = "dataProvider")
public void test1(int number, int expected) {
Assert.assertEquals(number, expected);
}
@Test(dataProvider = "dataProvider")
public void test2(String email, String expected) {
Assert.assertEquals(email, expected);
}
@DataProvider(name = "dataProvider")
public Object[][] provideData(Method method) {
Object[][] result = null;
if (method.getName().equals("test1")) {
result = new Object[][] {
{ 1, 1 }, { 200, 200 }
};
} else if (method.getName().equals("test2")) {
result = new Object[][] {
{ "[email protected]", "[email protected]" },
{ "[email protected]", "[email protected]" }
};
}
return result;
}
}
執行結果如下:
PASSED: test1(1, 1)
PASSED: test1(200, 200)
PASSED: test2("[email protected]", "[email protected]")
PASSED: test2("[email protected]", "[email protected]")
===============================================
Default test
Tests run: 4, Failures: 0, Skips: 0
===============================================
3.同一個@DataProvider
被多個用例使用,但根據分組名稱傳遞引數
程式碼:
public class TestParameterDataProvider4 {
@Test(dataProvider = "dataProvider", groups = {"groupA"})
public void test1(int number) {
Assert.assertEquals(number, 1);
}
@Test(dataProvider = "dataProvider", groups = "groupB")
public void test2(int number) {
Assert.assertEquals(number, 2);
}
@DataProvider(name = "dataProvider")
public Object[][] provideData(ITestContext context) {
Object[][] result = null;
for (String group : context.getIncludedGroups()) {
System.out.println("group : " + group);
if ("groupA".equals(group)) {
result = new Object[][] { { 1 } };
break;
}
}
if (result == null) {
result = new Object[][] { { 2 } };
}
return result;
}
}
xml內容:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Test">
<groups>
<run>
<include name="groupA"/>
</run>
</groups>
<classes>
<class name="com.demo.test.testng.TestParameterDataProvider4"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
執行xml結果如下:
group : groupA
===============================================
Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================
4.@DataProvider
返回迭代器
- 範例一:
程式碼:
public class ParameterSample1 {
@Test(dataProvider = "dp")
public void test(String str, Integer i)
{
System.out.println(str+i);
}
@DataProvider
public Iterator<Object[]> dp()
{
List<Object[]> objList = new ArrayList<Object[]>();
for(int i = 1; i < 5; i++)
{
objList.add(new Object[]{"第" + i + "名得分", new Integer(i) });
}
return objList.iterator();
}
}
執行結果:
第1名得分1
第2名得分2
第3名得分3
第4名得分4
PASSED: test("第1名得分", 1)
PASSED: test("第2名得分", 2)
PASSED: test("第3名得分", 3)
PASSED: test("第4名得分", 4)
===============================================
Default test
Tests run: 4, Failures: 0, Skips: 0
===============================================
- 範例二
測試用例程式碼:
public class ParameterSample1 {
@Test(dataProvider = "dp")
public void test(Demo demo)
{
System.out.println("我從myDataProvider倉庫拿到了名字:" + demo.getName() + ";年齡:" + demo.getAge());
}
@DataProvider
public Iterator<Object[]> dp()
{
List<Demo> list = new ArrayList<Demo>();
Demo demo1 = new Demo();
demo1.setName("david");
demo1.setAge(19);
Demo demo2 = new Demo();
demo2.setName("sansa");
demo2.setAge(20);
list.add(demo1);
list.add(demo2);
List<Object[]> fArrList = new ArrayList<Object[]>();
for (Object f : list)
{
fArrList.add(new Object[] { f });
}
return fArrList.iterator();
}
}
Demo.java:
public class Demo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
執行結果:
我從myDataProvider倉庫拿到了名字:david;年齡:19
我從myDataProvider倉庫拿到了名字:sansa;年齡:20
PASSED: test([email protected])
PASSED: test([email protected])
===============================================
Default test
Tests run: 2, Failures: 0, Skips: 0
===============================================
在上面兩個例子中,分別傳入了Object[]和自定義物件的迭代器,內容都是從類內部直接寫的,其實在實際應用中,對於同一條用例,不同入參的驗證,在整合化的情況下大多會選擇從檔案讀取,那麼,只需要在上面的程式碼中加入讀取檔案的內容並組合的步驟即可;
5.從xml傳不同引數運行同一條用例
其實從xml讀取引數的方法比較死板,不如使用@DataProvider
靈活,實際應用中多用這個來進行全域性引數的設定等;
這裡介紹下如果想從xml讀取引數來運行同一條用例的方法:
程式碼:
public class ParameterSample {
@Test
@Parameters({ "dbconfig", "poolsize" })
public void test(String dbconfig, int poolsize)
{
System.out.println("dbconfig : " + dbconfig);
System.out.println("poolsize : " + poolsize);
}
}
xml:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="none">
<test name="Test">
<parameter name="dbconfig" value="db.properties" />
<parameter name="poolsize" value="10" />
<classes>
<class name=