TestNG教程

TestNG教程

1、快速入门

1.1、TestNG是什么?

TestNG的定义:

  1. TestNG是一个测试框架,其灵感来自JUnit和NUnit,但引入了一些新的功能,使其功能更强大,使用更方便。
  2. TestNG是一个开源自动化测试框架。
  3. TestNG消除了大部分的旧框架的限制,使开发人员能够编写更加灵活和强大的测试。因为它在很大程度上借鉴了Java注解(JDK5.0引入的)来定义测试,它也可以显示如何使用这个新功能在真实的Java语言生产环境中。

TestNG的特点:

  1. 注解
  2. TestNG使用Java和面向对象的功能
  3. 支持综合类测试(例如,默认情况下,不用创建一个新的测试每个测试方法的类的实例)
  4. 独立的编译时测试代码和运行时配置/数据信息
  5. 灵活的运行时配置
  6. 主要介绍“测试组”
  7. 支持依赖测试方法,并行测试,负载测试,局部故障
  8. 灵活的插件API
  9. 支持多线程测试

1.2、入门示例

TestNG下载并安装:

  1. 下载:https://testng.org/doc/download.html
  2. 插件安装地址
    1. 对于Eclipse 3.4及更高版本,请输入 http://beust.com/eclipse
    2. 对于Eclipse 3.3及更低版本,请输入 http://beust.com/eclipse1

示例:

  1. 在 pom.xml 中添加依赖
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.8.7</version>
    <scope>test</scope>
</dependency>
  1. 创建TestNg类
package com.test.testng;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

import org.testng.annotations.Test;

public class TestHelloWorld {
	
  @Test
  public void test() {
	  RandomEmailGenerator randomEmailGenerator = new RandomEmailGenerator();
	  String email = randomEmailGenerator.generate();
	  
	  assertNotNull(email);
	  assertEquals(email, "feedback@test.com");
  }
}

//创建一个简单的Java类,它在方法中返回一个固定电子邮件
package com.test.testng;

public class RandomEmailGenerator {

	public String generate() {
		return "feedback@test.com";
	}
}

2、注解介绍

2.1、基本注解

TestNG支持的注释列表:

注解描述
@BeforeSuite在该套件的所有测试都运行在注释的方法之前,仅运行一次。
@AfterSuite在该套件的所有测试都运行在注释方法之后,仅运行一次。
@BeforeClass在调用当前类的第一个测试方法之前运行,注释方法仅运行一次。
@AfterClass在调用当前类的第一个测试方法之后运行,注释方法仅运行一次
@BeforeTest注释的方法将在属于<test>标签内的类的所有测试方法运行之前运行。
@AfterTest注释的方法将在属于<test>标签内的类的所有测试方法运行之后运行。
@BeforeGroups配置方法将在之前运行组列表。 此方法保证在调用属于这些组中的任何一个的第一个测试方法之前不久运行。
@AfterGroups此配置方法将在之后运行组列表。该方法保证在调用属于任何这些组的最后一个测试方法之后不久运行。
@BeforeMethod注释方法将在每个测试方法之前运行。
@AfterMethod注释方法将在每个测试方法之后运行。
@DataProvider标记一种方法来提供测试方法的数据。 注释方法必须返回一个Object [] [],其中每个Object []可以被分配给测试方法的参数列表。 要从该DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称。
@Factory将一个方法标记为工厂,返回TestNG将被用作测试类的对象。 该方法必须返回Object []
@Listeners定义测试类上的侦听器。
@Parameters描述如何将参数传递给@Test方法。
@Test将类或方法标记为测试的一部分。

使用注解的好处:

  1. TestNG通过查找注释/注解来识别它感兴趣的方法。
  2. 可以将其他参数传递给注释。
  3. 注释是强类型的,所以编译器会马上标记任何错误。
  4. 测试类不再需要扩展任何东西(如TestCase,对于JUnit3)。

3、特色功能

3.1、预期异常测试

  1. 运行时异常
//如果divisionWithException()方法抛出一个运行时异常 — ArithmeticException,它会获得通过。

public class TestRuntime {
	
	@Test(expectedExceptions=ArithmeticException.class)
	public void divisionWithException() {
		int i = 1/0;
		System.out.println("After division the value of i is :"+ i);
	}
}
  1. 检查异常
public class OrderBo {

	public void save(Order order) throws OrderSaveException {
		if(order == null) {
			throw new OrderSaveException("Order is empty!");
		}
	}
	
	public void update(Order order) throws OrderUpdateException,OrderNotFoundException  {
		if(order == null) {
			throw new OrderUpdateException("Order is empty!");
		}
		
		throw new OrderNotFoundException("Order is not exists");
	}
}

//自定义异常
public class OrderSaveException extends Exception{

	public OrderSaveException(String string) {
		// TODO Auto-generated constructor stub
	}

}

//预期抛出自定义异常
@Test(expectedExceptions=OrderSaveException.class)
public void throwIfOrderIsNull() throws OrderSaveException {
    orderBo.save(data);
}

@Test(expectedExceptions = { OrderUpdateException.class, OrderNotFoundException.class })
public void throwIfOrderIsNotExists() throws OrderUpdateException, OrderNotFoundException {
    orderBo.update(data);
}

3.2、忽略测试

  1. 我们编写的代码并没有准备就绪,忽略没有准备好的测试代码;
  2. 注释@Test(enabled = false)有助于禁用此类的测试用例。
public class TestIgnore {

	@Test
	public void test1() {
		System.out.println("测试方法1");
	}
	
	//忽略测试
	@Test(enabled = false)
	public void test2() {
		System.out.println("测试方法2");
	}
	
	@Test
	public void test3() {
		System.out.println("测试方法3");
	}
}

3.2、超时测试

  1. 超时”表示如果单元测试花费的时间超过指定的毫秒数,那么TestNG将会中止它并将其标记为失败。
public class TestTimeout {

    //PASS
	@Test(timeOut = 5000)
	public void test1() throws InterruptedException{
		Thread.sleep(4000);
	}
	
	//超过4000ms后自动标记失败
	@Test(timeOut = 4000)
	public void test2() {
		while(true) {
			//do nothing
		}
	}
}

3.4、分组测试

  1. 分组测试是TestNG中的一个新的创新功能,它在 JUnit框架中是不存在的。 它允许您将方法调度到适当的部分,并执行复杂的测试方法分组。

  2. 使用<groups>标记在testng.xml文件中指定分组。 它可以在<test><suite>标签下找到。 <suite>标签中指定分组适用于其下的所有<test>标签。

1、在方法上分组:

public class GroupsTest {

	@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");
    }
}

2、在类上的分组

//注解在类上面
@Test(groups = "selenium-test")
public class TestSelenium {

	public void runTest1() {
		System.out.println("测试runTest1");
	}
	
	public void runTest2() {
		System.out.println("测试runTest2");
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="TestAll" parallel="false">
	<test name="case1">
		<classes>
			<class name="com.test.testng.TestSelenium" />
			<class name="com.test.testng.GroupsTest" />
		</classes>
	</test>

	<test name="case2">
		<groups>
			<run>
				<include name="selenium-test" />
			</run>
		</groups>

		<classes>
			<class name="com.test.testng.TestSelenium" />
			<class name="com.test.testng.GroupsTest" />
		</classes>
	</test>
</suite> 

3、其他分组

//测试方法也可以属于多个分组
@Test(groups = {"mysql","database"})
public void testConnectMsSQL() {
    System.out.println("testConnectMsSQL");
}

3.5、套件测试

  1. 测试套件是用于测试软件程序的行为或一组行为的测试用例的集合。
  2. 在TestNG中,我们无法在测试源代码中定义一个套件,但它可以由一个XML文件表示,因为套件是执行的功能。
  3. <suite>testng.xml的根标记。 它描述了一个测试套件,它又由几个<test>部分组成。

下表列出了< suite >接受的所有定义的合法属性:

属性描述
name套件的名称,这是一个强制属性。< suite name = “TestSuite”>
verbose运行的级别或详细程度。
parallelTestNG是否运行不同的线程来运行这个套件。
thread-count如果启用并行模式(忽略其他方式),则要使用的线程数。
annotations在测试中使用的注释类型。
time-out在本测试中的所有测试方法上使用的默认超时。

1、测试例子:

//测试类1:
public class TestConfig {

	@BeforeSuite
	public void testBeforeSuite() {
		System.out.println("testBeforeSuite");
	}
	
	@AfterSuite
	public void testAfterSuite() {
		System.out.println("testAfterSuite");
	}
	
	@BeforeTest
	public void testBeforeTest() {
		System.out.println("testBeforeTest");
	}
	
	@AfterTest
	public void testAfterTest() {
		System.out.println("testAfterTest");
	}
}

//测试类2
public class TestDatabase {
	@Test(groups = "db")
	public void testConnectOracle() {
		System.out.println("testConnectOracle()");
	}

	@Test(groups = "db")
	public void testConnectMsSQL() {
		System.out.println("testConnectMsSQL");
	}

	@Test(groups = "db-nosql")
	public void testConnectMongoDB() {
		System.out.println("testConnectMongoDB");
	}

	@Test(groups = { "db", "brokenTests" })
	public void testConnectMySQL() {
		System.out.println("testConnectMySQL");
	}
}

//测试类3
public class TestOrder {
	
	@Test(groups = { "orderBo", "save" })
	public void testMakeOrder() {
		System.out.println("testMakeOrder");
	}

	@Test(groups = { "orderBo", "save" })
	public void testMakeEmptyOrder() {
		System.out.println("testMakeEmptyOrder");
	}

	@Test(groups = "orderBo")
	public void testUpdateOrder() {
		System.out.println("testUpdateOrder");
	}

	@Test(groups = "orderBo")
	public void testFindOrder() {
		System.out.println("testFindOrder");
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="TestAll" parallel="false">
	<test name="order">
		<classes>
			<class name="com.test.testng.TestConfig" />
			<class name="com.test.testng.TestOrder" />
		</classes>
	</test>
	<test name="database">
		<classes>
			<class name="com.test.testng.TestConfig" />
			<class name="com.test.testng.TestDatabase" />
		</classes>
	</test>
</suite> 

2、其他例子:

  1. 指定包名称而不是类名称
<suite name="TestAll">
    <test name="order">
        <packages>
            <package name="com.test.testng.*" />
        </packages>
    </test>
</suite>
  1. 指定包含或排除的方法
<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestAll">
  <test name="order">
    <classes>
        <class name="com.test.testng.TestConfig" />
        <class name="com.test.testng.TestOrder">
            <methods>
                <include name="testMakeOrder" />
                <include name="testUpdateOrder" />
                <!--
                    <exclude name="testMakeOrder" />
                 -->
            </methods>
        </class>
    </classes>
  </test>
</suite>
  1. 指定要包括或排除某个分组
<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestAll">
  <test name="database">
    <groups>
        <run>
            <exclude name="brokenTests" />
            <include name="db" />
        </run>
    </groups>

    <classes>
        <class name="com.test.testng.TestDatabase" />
    </classes>
  </test>
</suite>

3.6、依赖测试

  1. 有时,我们可能需要以特定顺序调用测试用例中的方法,或者可能希望在方法之间共享一些数据和状态。 TestNG支持这种依赖关系,因为它支持在测试方法之间显式依赖的声明。
  2. 在TestNG中,我们使用dependOnMethodsdependsOnGroups来实现依赖测试。

1、dependOnMethods示例

// 1.1. 如果method1()通过,那么将执行method2()。
public class TestDedenpOnMethods {
	
	@Test
	public void method1() {
		System.out.println("测试方法:method1()");
	}
	
	@Test(dependsOnMethods = "method1")
	public void method2() {
		System.out.println("测试方法:method2()");
	}
}

// 1.2. 如果method1()失败,则将跳过method2()。
public class TestDedenpOnMethods {
	
	@Test
	public void method1() {
		System.out.println("测试方法:method1()");
		throw new RuntimeException();
	}
	
	@Test(dependsOnMethods = "method1")
	public void method2() {
		System.out.println("测试方法:method2()");
	}
}

2、dependsOnGroups示例

//测试代码1
public class TestServer {

	@Test(groups = "deploy")
	public void deployServer() {
		System.out.println("Deploying Server...");
	}

	@Test(groups = "deploy",dependsOnMethods = "deployServer")
	public void deployBackUpServer() {
		System.out.println("Deploying Backup Server...");
	}
}

//测试代码2
public class TestApp {

	@Test(dependsOnGroups = { "deploy", "db2" })
	public void method1() {
		System.out.println("This is method1");
	}

	@Test(dependsOnMethods = "method1")
	public void method2() {
		System.out.println("This is method2");
	}
}

//测试代码3
public class TestDatabase2 {

	@Test(groups = "db2", dependsOnGroups = "deploy")
	public void initDB() {
		System.out.println("This is initDB()");
	}

	@Test(groups = "db2", dependsOnMethods = { "initDB" })
	public void testConnection() {
		System.out.println("This is testConnection()");
	}
}

3.7、参数化测试

  1. 在大多数情况下,会遇到业务逻辑需要大量测试的场景。 参数化测试允许开发人员使用不同的值一次又一次地运行相同的测试。
  2. TestNG可以通过两种不同的方式将参数直接传递给测试方法:
    1. 使用testng.xml
    2. 使用数据提供者

1、使用XML传递参数

  1. filename属性从testng.xml传递,并通过@Parameters注入到该方法中。
@Test
@Parameters({ "dbconfig", "poolsize" })
public void createConnection(String dbconfig, int poolsize) {
	...
    Properties prop = new Properties();
    prop.load(new FileInputStream(dbconfig));
}
<?xml version="1.0" encoding="UTF-8"?>
<suite name="test-parameter">
    <test name="example1">
        <parameter name="dbconfig" value="db.properties" />
        <parameter name="poolsize" value="10" />

        <classes>
            <class name="com.yiibai.TestParameterXML" />
        </classes>
    </test>
</suite>

2、通过@DataProvider传递参数

  1. 基本数据类型:Object[ ] [ ]
// 传入基本数据类型
@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 } };
}
  1. 引用数据类型:对象参数,Map等等
// 传入Map
@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 } };
}

3、@DataProvider + 方法

  1. 根据测试方法名称传递不同的参数。
@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;
}
  1. @DataProvider + ITestContext

  2. 在TestNG中,我们可以使用org.testng.ITestContext来确定调用当前测试方法的运行时参数。

@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;

    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
课程介绍你是否在寻找机会进入自动化测试领域? 你是否渴望学习selenium webdriver + Java以及最新的框架和技术进行web自动化测试? 你是否感兴趣学习Selenium如何用在你现有的项目里的? 这门课带你从Selenium搭建环境开始讲起,然后学习selenium,TestNG, logback, maven, jenkins。 我们假设学员没有任何自动化经验,来设计的这套课程。每个课题都从最基础的开始讲起。Selenium相关的该覆盖的课题都覆盖了。 例子都是来自于真实的web应用项目,帮助你理解不同的组件怎么用上自动化,这将展示给你一个行业层面的框架,增加自信心。 全网没有其他课程像这门课涵盖到如此之深的细节。 您将会学到什么 学完课程以后,你将拥有完整的Selenium Webdriver知识 你将具备从头开始设计Page Object、Page Factory、DATADRIVEN等搭建自动化框架的能力 用100多个实例对Selenium现实场景应用进行深入理解 全面了解TestNG, Maven, Jenkins, HTML报告,多浏览器并行测试 了解数据库测试和使用Selenium进行性能测试 你将彻底了解testNG框架 你从网上随便选择一个网站,都可以实现自动化,用所有可能的测试用例进行自动化测试 将提高你的编码技能,以编写最优化的自动化测试用例代码 你基本可以搞定任何Selenium面试,并能从设计阶段开始领导整个Selenium自动化项目 你应该能够使用应用程序的GUI来验证数据完整性 你将能够创建漂亮的报告来打动客户或领导 更深入地理解自动化指南和代码质量标准 会附带一个练习网站,可以用上所有可用的WebDriver功能,实现自动化 【适合人群】 软件手动测试人员想转为自动化测试的人员 自动化软件测试人员想加强专业技能的 刚毕业学生想从事软件行业 QA 组长或项目经理 【课程优势】 学完课程以后,你将拥有完整的Selenium Webdriver知识 【讲师介绍】 资质介绍: 12年以上软件测试工作经验,其中7年以上自动化测试开发经验 新书“Python3+Selenium3自动化测试项目实战”作者
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值