转自:
http://www.cnblogs.com/rilley/archive/2012/11/09/2762818.html
https://www.cnblogs.com/silence-hust/p/4539363.html
1、测试套件组件层级结构(suite--test--class--method & group)
<suite name="ParametersTest">
<test name="Regression1">
<classes>
<class name="com.example.ParameterSample" />
<class name="com.example.ParameterTest">
<mtehods>
<include name="database.*" />
<exclude name="inProgress" />
</methods>
</class>
</classes>
</test>
<test name="Parameters">
<packages>
<package name="test.parameters.Parameter*" />
</packages>
</test>
</suite>
一个suite(套件) 由一个或多个测试组成。 一个test(测试) 由一个或多个类组成
一个class(类) 由一个或多个方法组成。
@BeforeSuite/@AfterSuite 在某个测试套件开始之前/在某个套件所有测试方法执行之后
@BeforeTest/@AfterTest 在某个测试开始之前/在某个测试所有测试方法执行之后
@BeforeClass/@AfterClass 在某个测试类开始之前/在某个类的所有测试方法执行之后
@BeforeMethod/@AfterMethod 在某个测试方法之前/在某个测试方法执行之后
@BeforeGroup/@AfterGroup 在某个组的所有测试方法之前/在某个组的所有测试方法执行之后
组:测试方法组:
public class Test1 {
@Test(groups = { "functest", "checkintest" })
public void testMethod1() {
}
@Test(groups = {"window.checkintest"} )
public void testMethod2() {
}
@Test(groups = { "functest" })
public void testMethod3() {
}
}
测试类组: @Test(groups = { "checkin-test" })
public class All {
@Test(groups = { "func-test" )
public void method1() { ... }
public void method2() { ... }
}
引用组:定义<suite>全局的组groups:
定义属于某个<test>的组groups:
<suite>
<test name="Regression1">
<groups>
<define name="functest"> -----Groups of groups
<include name="windows"/>
<include name="linux"/>
</define>
<define name="all">
<include name="functest"/>
<include name="checkintest"/>
</define>
<run>
<include name="all"/> -------<run>
</run>
</groups>
<classes>
<class name="test.sample.Test1"/>
</classes>
</test>
</suite>
以上:执行test.sample.Test1类中<include name="all"/>的分组测试执行:略:命令行、ant、maven、Java API...
2、@Test(expectedExceptions
@Test(expectedExceptions = {ReservationException.class, FlightCanceledException.class})
public void shouldThrowIfPlaneIsFull()
{
3、参数化测试---数据驱动式测试 @Parameters("myName")、@DataProvider
两种方法:
利用@Parameters传递参数:
可以在suite--test--class--method & group等不同的层级定义参数,如在suite层级:
测试类:
public class ParameterizedTest1 {
@Test
@Parameters("myName")
public void parameterTest(String myName) {
System.out.println("Parameterized value is : " + myName);
}
}
testng.xml: <suite name="Suite1">
<test name="test1">
<parameter name="myName" value="manisha"/>
<classes>
<class name="ParameterizedTest1" />
</classes>
</test>
</suite>
利用@DataProvider传递参数: 测试类:
@Test(dataProvider = "range-provider")
public void testIsBetWeen(int n, int lower, int upper, boolean expected)
{
println("Received " + n + " " + lower + "-" + upper + " expected: " + expected);
assert.assertEquals(expected, isBetween(n, lower, upper));
}
DataProvider: @DataProvider(name = "range-provider")
public Object[][] rangeData()
{
int lower = 5;
int upper = 10;
return new Object[][] {
{ lower-1, lower, upper, false},
{ lower, lower, upper, true},
{ lower+1, lower, upper, true},
{ upper, lower, upper, true},
{ upper+1, lower, upper, false},
};
}
如何构造一个DataProvider: 入参:数据提供者本身可以接受两个类型的参数:Method和ITestContext
@DataProvider
public Object[][] craete() { ... }
@DataProvider
public Object[][] create(Method method) { ... }
@DataProvider
public Object[][] create(ITestContext context) { ... }
@DataProvider
public Object[][] create(Method method, ITestContext context) { ... }
Method:java.lang.reflect.Method,将调用的测试方法 ITestContext:当前的测试上下文,是运行时刻的信息,不是静态的信息,这使得数据提供者能够知道当前测试执行的运行时刻参数,如context.getIncludeGroups()可以获取测试函数所属的group列表
返回类型:
1、Object[][]
2、Iterator----延迟数据提供者 ***
@DataProvider(name = "generate-accounts-lazy")
public Iterator generateAccountsLazy
{
return new AccountIterator();
}
@Test(dataProvider = "generate-accounts-lazy")
public void testAccount(Account a)
{
System.out.println("Testing account " + a);
}
class AccountIterator implements Iterator
{
private static final int MAX = 4;
private int index = 0;
public boolean hasNext()
{
return index < MAX;
}
public Object next()
{
return new Object[] { new Account(index++); }
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
4、@Factory详解------如何进行参数值变化性测试
采用工厂的方法来创建测试数据并配合完成测试简单使用:
public class SimpleTest {
@Test
public void simpleTest1(){
System.out.println("simple test one");
}
@Test
public void simpleTest2(){
System.out.println("simple test two");
}
}
public class SimpleTestFactory
{
@Factory
public Object[] factoryMethod() {
return new Object[] { new SimpleTest(), new SimpleTest() };
}
}
//被执行的测试类为:SimpleTestFactory。SimpleTestFactory工厂类,在带有@Factory注解的方法中调用被执行的测试类,TestNg会自动调用被执行类中带有@Test注解的方法。
简单使用2:
使用@Factory最大的好处就是可以在初始化的时候将参数传给测试类:
public class SimpleTest {
private int para;
public SimpleTest(int para) {
this.para = para;
}
@Test
public void testMethodOne(){
int value = para + 1;
System.out.println("Test method one output: " + value);
}
@Test
public void testMethodTwo(){
int value = para + 2;
System.out.println("Test method two output: " + value);
}
}
public class SimpleTestFactory {
@Factory
public Object[] factoryMethod(){
return new Object[] { new SimpleTest(0), new SimpleTest(10)};
}
}
结合DataProvider???未测试: public class DataProviderTest
{
private int param;
@Factory(dataProvider = "dataMethod")
public DataProviderTest(int param) {
this.param = param;
}
@DataProvider
public static Object[][] dataMethod() {
return new Object[][] { new Object[]{ 0 }, new Object[]{ 10 } };
}
@Test
public void testMethodOne() {
int opValue = param + 1;
System.out.println("Test method one output: " + opValue);
}
@Test
public void testMethodTwo() {
int opValue = param + 2;
System.out.println("Test method two output: " + opValue);
}
}
5、异步消息测试 @Test(timeOut = 10000 a\预先发消息:@beforexx,send & sleep,#dependon
b\
有回调方法:在测试方法中,监视返回结果
没有回调方法:定期检查预期的值。如果过了一段时间还没有检查到预期值,就失败并退出。
private volatile boolean success = false;
@Test(groups = “send”)
public void sendMessage()
{
// send the message
}
@Test(timeOut = 10000, dependsOnGroups = {“send”})
public void waitForAnswer()
{
while (!success) {
Thread.sleep(1000);
}
}
//sendMessage()是一个@Test方法,他将包含在最终的报告中,如果发送消息失败,TestNG将跳过waitForAnswer测试方法,并把他表示为SKIP。 @Test(timeOut = 10000, invocationCount=100, successPercentage = 98)
public void waitForAnswer ……
//TestNG调用该方法100次,如果98%的调用成功,就认为总体测试通过。
6、并发测试 @Test(invocationCount = 100, threadPoolSize = 10) 、 <suite parallel=“methods” thread-count = “2”>
法一:
private Singleton singleton;
@Test(invocationCount = 100, threadPoolSize = 10)
public void testSingleton()
{
Thread.yield();
Singleton p = Singleton.getInstance();
}
public static Singleton getInstance()
{
if (instance == null) {
Thread.yield();
Assert.assertNull(instance);
instance = new Singleton();
}
return instance;
}
//@invocationCount相当简单,在不考虑并发时也可以使用:他决定了TestNG调用一个测试方法的次数。
//@threadPoolSize要求TestNG分配一定数量的线程,并使用这些线程来调用这个测试方法
法二:
<suite name=”TestNG JDK 1.5” verbose=“1” parallel=“methods” thread-count = “2”>......</suite>
thread-count属性指定了线程数目,TestNG将使用这些线程来执行这个测试套件中的所有测试方法 parallel属性告诉TestNG您在执行这些测试时希望采用的并行模式。
=”methods” 在这种模式下,每个测试方法将在他自己的一个线程中执行。
=”test” 在这种模式下,在某个标签内的所有测试方法将在他们自己的一个线程中执行。
如果希望测试不安全的代码,这一点是非常重要的。在method模式中,所有限制都被取消,无法预测哪些方法将在同一个线程中执行,哪些方法将在不同的测试中执行。
7、依赖测试 @Test(dependsOnGroups、dependsOnMethods)
DRY原则:
public class CreditCardTest
{
@Test(groups = "web.credit-card")
public void test1() {}
@Test(groups = "web.credit-card")
public void test2() {}
}
替换为: @Test(groups = "web.credit-card")
public class CreditCardTest
{
public void test1() {}
public void test2() {}
}
减少维护成本 annotation继承:
@Test(groups = "web.credit-card")
class BaseWebTest {}
public class WebTest extends BaseWebTest
{
public test1() {}
public test2() {}
}
所有扩展自BaseWebTest的类都会看到,他们所有的工有方法都自动成为web.credit-card组的成员。 WebTest变成了一个普通的传统Java对象(POJO),不带任何annotation。