测试框架设计学习笔记

Part One

开始学习Udemy上的一个课程Design Selenium Test framework from scratch-Architect level,随手写一些笔记。

课程第一部分主要在讲testNG,在项目上目前一直接触的是JUnit,用起来还比较方便,小结一下,用到了JUnit里以下特性:

  • Category,进行test case分类,方便同一份代码在不同环境下选择执行不同的test case
  • Rule,解决test case执行失败时,进行截图并上传至Jenkins
  • Runner,解决执行中动态决定是否skip特定的test case

目前在课程中学习到testNG的以下特点:

  • testNG本身是测试框架,功能比较丰富
  • testNG在Eclipse上有插件支持,使用方便
  • testNG可以使用testing.xml来控制测试执行控制,从上到下分了Suit -> test -> classes -> methods这样几个分层
  • methods标签下可以使用include、exclude标签来包含或排除某些 method,也即test case
  • method,也即test case命名的时候要遵循一个统一的规则,比如FunctionOneLogin(), FunctionTwoOpen()等,方便后续在选择执行的时候,用正则表达式筛选test case,例如name=”Fun.*”表示相应的class里所有以”Fun”开头的test case

Part Two

学习到第12节课程,了解到testNG的anotation有以下(and more):

  • @BeforeSuite suite是testNG使用的xml文件中的一个概念,也许可以理解为最上层的一个测试用例套件,一个suite可以包含有多个test
  • @BeforeTest test这里可以理解成一个测试模块(test module),一个test可包含多个测试类class
  • @BeforeClass class是指测试类,BeforeClass用来标记在一整个class测试类里的所有测试方法执行之前优先执行
  • @BeforeMethod method,就是一个测试用例,或者说是一个test类中的单个测试方法
  • @Test 用来注释某个测试类里的方法是一个测试方法,也即测试用例
  • @AfterMethod
  • @AfterClass
  • @AfterTest
  • @AfterSuite
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Test suite - 1">
<test thread-count="5" name="My Test module 1">
<classes>
<class name="com.main.MainTest01" />
<class name="com.test.NGTest01" />
</classes>
</test>
<test name="My Test module - 2">
<classes>
<class name="com.test.NGTest02" />
</classes>
</test>
</suite>

补充一下,testNG中的xml还可以使用package标签,含义不言自明。

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="My Test Suite">
<test thread-count="5" name="My Test module">
<packages>
<package name="com.main"></package>
</packages>
</test>
</suite>

Part Three

学习到18节,完成了testNG的部分,其中包括了以下testNG的特性:

  • group,例如加上tag @Test(groups={“smoke”}),就表示这个test属于smoke group,可以属于多个group,然后相应的在xml文件中,做如下定义,即可使用group,这里可以include也可以exclude。
1
2
3
4
5
6
7
8
9
10
11
12
13
<suite name="Test - 1">
<test name="My Test modul">
<groups>
<run>
<include name="smoke" />
</run>
</groups>
<classes>
<class name="com.main.MainTest01" />
<class name="com.test.NGTest01" />
</classes>
</test>
</suite>
  • 定义test之间的依赖执行,例如加上tag @Test(dependsOnMethods={“Main03”}),即表示这个test依赖于另一个test Main03,将在其之后执行。
  • 参数化,例如以下tag的定义,和xml里的定义,这样即可让Main03 test使用xml里定义的变量值。
1
2
3
4
5
6
7
8
// 属于 com.main package里的 MainTest class
@Parameters({"URL1", "URL2"})
@Test
public void Main03(String url1, String url2) {
System.out.println("main 03");
System.out.println(url1);
System.out.println(url2);
}
1
2
3
4
5
6
7
8
9
10
<suite name="My Tet Suite">  
<parameter name="URL1" value="www.google.com" />
<parameter name="URL2" value="www.facebook.com" />

<test name="My Test modul">
<packages>
<package name="com.main" />
</packages>
</test>
</suite>
  • @DataProvider特性,具体还是见代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@DataProvider
public String[][] getData() {
String[][] data = new String[2][2];
data[0][0] = "1st-username";
data[0][1] = "1st-password";

data[1][0] = "2nd-username";
data[1][1] = "2nd-password";

return data;
}

//这个test会被执行2次,以便使用getData()里提供的,所有的2组测试数据
@Test(dataProvider="getData")
public void Main05(String username, String password) {
System.out.println(username);
System.out.println(password);
}
  • Listeners特性,有点像JUnit里的TestWatcher,典型用法就是失败后截图,具体见代码..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.main;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class Listeners implements ITestListener {

@Override
public void onTestStart(ITestResult result) {
// do something when a test just start

}

@Override
public void onTestSuccess(ITestResult result) {
// do something when a test success
}

@Override
public void onTestFailure(ITestResult result) {
// do something when a test fail
}

@Override
public void onTestSkipped(ITestResult result) {
// do something when a test is skipped
}

@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
// TODO Auto-generated method stub
}

@Override
public void onStart(ITestContext context) {
// TODO Auto-generated method stub
}

@Override
public void onFinish(ITestContext context) {
// TODO Auto-generated method stub
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="My Tet Suite">
<listeners>
<listener class-name="com.main.Listeners" />
</listeners>

<parameter name="URL1" value="www.google.com" />
<parameter name="URL2" value="www.facebook.com" />

<test thread-count="5" name="My Test modul">
<packages>
<package name="com.main"></package>
</packages>
</test>
</suite>