TestNg学习
参考:https://www.yiibai.com/testng/junit-vs-testng-comparison.html#article-start
1、JUnit缺点:
- 最初的设计,使用于单元测试,现在只用于各种测试。
- 不能依赖测试
- 配置控制欠佳(安装/拆卸)
- 侵入性(强制扩展类,并以某种方式命名方法)
- 静态编程模型(不必要的重新编译)
- 不适合管理复杂项目应用,JUnit复杂项目中测试非常棘手。
2、TestNG的特点
- 注解
- TestNG使用Java和面向对象的功能
- 支持综合类测试(例如,默认情况下,不用创建一个新的测试每个测试方法的类的实例)
- 独立的编译时测试代码和运行时配置/数据信息
- 灵活的运行时配置
- 主要介绍“测试组”。当编译测试,只要要求
TestNG
运行所有的“前端”的测试,或“快”,“慢”,“数据库”等 - 支持依赖测试方法,并行测试,负载测试,局部故障
- 灵活的插件API
- 支持多线程测试
二、TestNg基本注解
三、TestNG预期异常测试
1、@Test(expectedExceptions = ArithmeticException.class)
2、@Test(expectedExceptions = { OrderUpdateException.class, OrderNotFoundException.class })
四、TestNG忽略测试
1、@Test(enabled = false)
来忽略测试方法
五、TestNG超时测试
1、@Test(timeOut = 5000) // time in mulliseconds
六、TestNG分组测试
1、测试方法也可以同时属于多个分组,如下代码所示 -@Test(groups = {"mysql","database"})
public void testConnectMsSQL() {
System.out.println("testConnectMsSQL");
}
2、分组测试是TestNG中的一个新的创新功能,它在JUnit框架中是不存在的。 它允许您将方法调度到适当的部分,并执行复杂的测试方法分组。 您不仅可以声明属于某个分组的方法,还可以指定包含其他组的组。 然后调用TestNG
,并要求其包含一组特定的组(或正则表达式),同时排除另一个分组。 组测试提供了如何分区测试的最大灵活性,如果您想要背靠背运行两组不同的测试,则不需要重新编译任何内容。
使用<groups>
标记在testng.xml
文件中指定分组。 它可以在<test>
或<suite>
标签下找到。 <suite>
标签中指定分组适用于其下的所有<test>
标签
public class TestGroup { @BeforeGroups("database") public void setupDB() { System.out.println("setupDB()"); } @AfterGroups("database") public void cleanDB() { System.out.println("cleanDB()"); } @Test(groups = "selenium-test") public void runSelenium() { System.out.println("runSelenium()"); } @Test(groups = "selenium-test") public void runSelenium1() { System.out.println("runSelenium()1"); } @Test(groups = "database") public void testConnectOracle() { System.out.println("testConnectOracle()"); } @Test(groups = "database") public void testConnectMsSQL() { System.out.println("testConnectMsSQL"); } @Test(dependsOnGroups = { "database", "selenium-test" }) public void runFinal() { System.out.println("runFinal"); }
七、TestNG套件测试
<suite>
是testng.xml
的根标记。 它描述了一个测试套件,它又由几个<test>
部分组成。
下表列出了<suite>
接受的所有定义的合法属性。
八、TestNG依赖测试
有时,我们可能需要以特定顺序调用测试用例中的方法,或者可能希望在方法之间共享一些数据和状态。 TestNG支持这种依赖关系,因为它支持在测试方法之间显式依赖的声明。
TestNG允许指定依赖关系:
在TestNG中,我们使用dependOnMethods
和dependsOnGroups
来实现依赖测试。 如果依赖方法失败,则将跳过所有后续测试方法。
九、TestNG参数化测试
TestNG中的另一个有趣的功能是参数化测试。 在大多数情况下,您会遇到业务逻辑需要大量测试的场景。 参数化测试允许开发人员使用不同的值一次又一次地运行相同的测试。
TestNG可以通过两种不同的方式将参数直接传递给测试方法:
- 使用
testng.xml
- 使用数据提供者
在本教程中,我们将向您展示如何通过XML @Parameters
或@DataProvider
将参数传递给@Test
方法。
1、使用XML传递参数
在此示例中,filename
属性从testng.xml
传递,并通过@Parameters
注入到该方法中。
package com.yiibai; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class TestParameterXML { Connection con; @Test @Parameters({ "dbconfig", "poolsize" }) public void createConnection(String dbconfig, int poolsize) { System.out.println("dbconfig : " + dbconfig); System.out.println("poolsize : " + poolsize); Properties prop = new Properties(); InputStream input = null; try { // get properties file from project classpath String path = System.getProperty("user.dir")+"\\"+dbconfig; System.out.println("path => "+path); //input = getClass().getClassLoader().getResourceAsStream(path); //prop.load(input); prop.load(new FileInputStream(dbconfig)); String drivers = prop.getProperty("jdbc.driver"); String connectionURL = prop.getProperty("jdbc.url"); String username = prop.getProperty("jdbc.username"); String password = prop.getProperty("jdbc.password"); System.out.println("drivers : " + drivers); System.out.println("connectionURL : " + connectionURL); System.out.println("username : " + username); System.out.println("password : " + password); Class.forName(drivers); con = DriverManager.getConnection(connectionURL, username, password); } catch (Exception e) { //e.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (IOException e) { //e.printStackTrace(); } } } } }
2、通过@DataProvider传递参数
(1)查看一个简单的@DataProvider
示例,传递一个int
参数。
package com.yiibai; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestParameterDataProvider { @Test(dataProvider = "provideNumbers") public void test(int number, int expected) { Assert.assertEquals(number + 10, expected); } @DataProvider(name = "provideNumbers") public Object[][] provideData() { return new Object[][] { { 10, 20 }, { 100, 110 }, { 200, 210 } }; } }
@DataProvider
支持传递一个对象参数。 下面的例子显示了如何传递一个Map对象作为参数
package com.yiibai; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestParameterDataProvider2 { @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() { Properties prop = new Properties(); InputStream input = null; Map<String, String> map = new HashMap<String, String>(); try { input = getClass().getClassLoader().getResourceAsStream("db.properties"); prop.load(input); map.put("jdbc.driver", prop.getProperty("jdbc.driver")); map.put("jdbc.url", prop.getProperty("jdbc.url")); map.put("jdbc.username", prop.getProperty("jdbc.username")); map.put("jdbc.password", prop.getProperty("jdbc.password")); } catch (Exception e) { e.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } return map; } }
3、 @DataProvider + 方法
此示例显示如何根据测试方法名称传递不同的参数。
public class TestParameterDataProvider3 { @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[][] { { "test@gmail.com", "test@gmail.com" }, { "test@yahoo.com", "test@yahoo.com" } }; } return result; } }
4、 @DataProvider + ITestContext
在TestNG中,我们可以使用org.testng.ITestContext
来确定调用当前测试方法的运行时参数。 在最后一个例子中,我们将演示如何根据包含的分组名称传递参数
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; //get test name //System.out.println(context.getName()); 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; } }
十、TestNG+SELENIUM负载测试
如何使用@Test
属性invocationCount
和threadPoolSize
在网站上执行负载测试或压力测试
1、@Test(invocationCount =?)
这个invocationCount
确定TestNG应该运行这个测试方法的次数。
import org.testng.annotations.Test; public class TestRepeatThis { @Test(invocationCount = 10) public void repeatThis() { System.out.println("repeatThis " ); } }
2、@Test(invocationCount = ?, threadPoolSize = ?)
threadPoolSize
属性告诉TestNG创建一个线程池以通过多个线程运行测试方法。 使用线程池,会大大降低测试方法的运行时间
启动包含3
个线程的线程池,并运行测试方法10
次。
public class TestMultipleThreads3 { @Test(invocationCount = 10, threadPoolSize = 3) public void testThreadPools() { System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } }