1. 程式人生 > >【TestNG】testNG傳參的用法和高階應用

【TestNG】testNG傳參的用法和高階應用

一.TestNG用法說明

TestNG的詳細教程請看連結:https://blog.csdn.net/df0128/article/details/83243822

二.直接從類中傳參

此處需要用到註解@DataProvider來進行傳參,
如下定義了一個測試用例,名為TestNgLearn1,其有兩個引數傳入,param1param2,都是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=