当前位置: 代码迷 >> 综合 >> TestNG 测试框架-尚学堂
  详细解决方案

TestNG 测试框架-尚学堂

热度:53   发布时间:2024-02-09 22:24:26.0

第七章 TestNG 测试框架

一、 什么是测试框架
?
自动化测试框架是由一个或多个自动化测试基础模块、自动化测试管理模块、自动
化测试统计模块等组成的工具集合。
二、 搭建 TestNG 框架环境
1 什么是 TestNG
?
是一个开源自动化测试框架, TestNG 表示下一代。
?
用于设置测试前的准备代码,测试代码,测试完毕后的处理代码。
2 安装 testng-6.14.zip
?
离线安装
?
(先断网)帮助→安装新软件→添加,位置选择 achive ,选择 zip 文件即可。
?
网络安装
?
帮 助 → 安 装 新 软 件 → 联 网 安 装 testing Work with 下 输 入 :
http://beust.com/eclipse →添加→勾选 TestNG
三、 使用 TestNG 中注解进行测试
1 什么是注解
?
表示“在某些阶段必然被调用的代码”;
?
下面的注解一般用于修饰测试方法,测试方法名随意。
2 常用注解
2.1 @BeforeClass 注解
?
在调用当前类的第一个测试方法之前运行。
@BeforeClass
public void setup() throws Exception {
System.setProperty("webdriver.ie.driver", "C:\\...\\IEDriverServer.exe");
driver= new InternetExplorerDriver();
driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
} 2.2 @AfterClass 注解
?
在调用当前类的最后一个测试方法之后运行。
@AfterClass
public void tearDown() throws Exception {
driver.quit();
}
2.3 @BeforeMethod 注解
?
在每个测试方法之前运行。
2.4 @AfterMethod 注解
?
在每个测试方法之后运行。
2.5 @Test( 属性 1= 1 ,属性 2= 2 ...) 注解
?
用于修饰测试方法,表示要对被测试类的某个或某些方法进行测试。
?
属性
? description=" 测试描述 "
? priority= 优先级(从 0 开始)
? enabled=false false 表示忽略测试)
? timeOut=?ms (限时测试,一旦测试的内容运行超过了该时间长度,那么将会
终止,同时标记为 failed
? dataProvider="Dataprovider 的名称或方法名 "
? dataProviderClass= 产生测试数据的类
2.6 @DataProvider(name=" 参数集名 ") 注解
?
用于修饰获得参数的方法。
?
此方法用于生成测试数据。
? @Listeners({TestReport.class})
// 监听测试报告类
3 断言
?
用来断定程序中是否存在缺陷。
3.1 Assert.assertTrue(boolean 型结果 )
?
写法类似于正则表达式,使用更方便。
? Boolean rs=driver.findElement(By.tagName("body")).getText().contains("Welcome
to the Web Tours site");
? Assert.assertTrue(rs); 3.2 Assert.assertEquals( 实际结果,预期结果 )
?
用于测试期望结果的断言,即测试两个对象是否相等。
? String actual=driver.getTitle();
? String expected="Web Tours";
? Assert.assertEquals(actual, expected);
4 参数化
4.1 @DataProvider(name=" 测试数据集名 ") 注解
? name 项可省略,括号无所谓
4.2 创建获取参数的方法
@DataProvider
public Object[][] getParam() throws Exception{
Object data[][]={ {"London","Paris"},{"Denver","London"},{"Paris","Denver"} };
return data;
}
4.3 使用 dataProvider 访问参数
@Test(description=" 订票 ",priority=2,dataProvider="getParam")
public void book(String cong , String dao){
new Select(drv.findElement(By.name("depart"))).selectByVisibleText(cong);
new Select(drv.findElement(By.name("arrive"))).selectByVisibleText(dao);
Boolean
rs=drv.findElement(By.tagName("body")).getText().contains("leaves
"+cong+" for "+dao);
assertTrue(rs);
drv.findElement(By.name("Book Another")).click();
}
4.4 不使用列表获取文件中的参数
@DataProvider
public Object[][] getParam() throws Exception{
File file=new File("C:\\...\\flights.txt");
// 打开文件,计算文件行数
FileReader bytes=new FileReader(file);
BufferedReader chars=new BufferedReader(bytes);
String row=null;
int lineCount=0;
while((row=chars.readLine())!=null) lineCount++;
chars.close();
// 重新打开文件,读取每行
bytes=new FileReader(file);
chars=new BufferedReader(bytes);
Object[][] data=new Object[lineCount][];
int i=0;
while((row=chars.readLine())!=null){
String cols[]=row.split("\t");
data[i++]=cols;
}
// 测试查看每行
/*
for(Object x[]:data){
for(Object y:x)
System.out.print(y+" ");
System.out.println();
}
*/
chars.close();
return data;
}
4.5 分离获得参数的类
?
定义获得参数的类
public class Param{
@DataProvider(name=?)
public Object[][] getParam() throws Exception{
...
}
}
?
引用参数类中的参数
@Test(description=" 订票 ",priority=2,dataProvider="getParam",dataProviderClass=
加引号的其他类名 .class
public void book(String cong , String dao){
new Select(drv.findElement(By.name("depart"))).selectByVisibleText(cong);
new Select(drv.findElement(By.name("arrive"))).selectByVisibleText(dao);
Boolean
rs=drv.findElement(By.tagName("body")).getText().contains("leaves
"+cong+" for "+dao);
assertTrue(rs);
drv.findElement(By.name("Book Another")).click();
} 4.6 使用列表获取文件中的参数
@DataProvider
public Object[][] getParam() throws Exception{
List<String[]> rows=new ArrayList<String[]>();
File file=new File("C:/.../flights.txt");
FileReader reader=new FileReader(file);
BufferedReader buffer=new BufferedReader(reader);
String row=null;
while((row=buffer.readLine())!=null){
String columns[]=row.split("\t");
rows.add(columns);
}
reader.close();
Object[][] data=new Object[rows.size()][];
for(int i=0;i<rows.size();i++)
data[i]=rows.get(i);
return data;
}
5 生成测试报告
?
测试报告默认存储位置
? Java 项目名 \test-output
?
可以自己编写并优化 TestReport.java
?
测试类中添加监听器 @Listeners({TestReport.class}) 即可
? class 是固定关键字
?
放到测试类名的上一行
@Listeners({TestReport.class})
// 监听测试报告类
public class WebTest {
...
}
6 测试套件
6.1 测试 test
一个 test 可以包含一系列的测试方法,测试方法由 @Test 注解。
6.2 测试套件 suite
一个 suite 可以包含多个独立的 test 6.3 定义测试套件
?
首先定义多个测试类,可以在同一个包中,也可以在不同包中。
?
右击 Java 项目 →TestNg→Convert to TestNG
?
Suite 命名
?
为测试命名
? Class selection
? Classes
?
使用类名表示一个测试
?
包中的类可以写成“包名 . 类名”
? Parallel mode
? tests
?
表示并行运行测试
? Thread count
?
用于设置并行线程数量
?
必须与 Parallel mode 同时使用
?
一般设置为并行测试的数量
6.4 修正 testng.xml
<suite thread-count="2" name=" 测试套件名称 " annotations="JDK" parallel="tests">
<test name=" 自定义测试名 1">
<classes>
<class name=" 测试类 1 的名字 "/>
</classes>
</test>
<test name=" 自定义测试名 2">
<classes>
<class name=" 测试类 2 的名字 "/>
</classes>
</test>
</suite>
?
首先定义多个测试类,可以自同一个包中,也可以在不同包中。
? annotations 表示注解
?
不能省略
? JDK 必须大写
6.5 运行测试套件
打开 testng.xml →点击工具栏运行按钮→选择“ TestNG Suite ”。 7 为测试方法传递参数
7.1 定义参数
?
修改 testng.xml
<suite>
<parameter name=" 参数名 " value=" 参数值 " />
<test name=" 测试名 ">
<parameter name=" 参数名 " value=" 参数值 " />
<classes>
<class name=" 测试类的名字 "/>
</classes>
</test>
</suite>
?
Suite 范围内定义某个参数的值,对所有的 Test 都有效。
?
Test 范围内定义某个参数的值,只是针对该 Test 有效。
?
如果同时在 Suite Test 中定义某个参数, Test 范围的值会屏蔽 Suite 的值。
?
这种方式的参数值必须直接指定,不如 DataProvider 灵活。
7.2 引用参数
@Test
@Parameters({ " 参数名 1", " 参数名 2" })
public void 测试方法 (String 参数名 1){
}
四、 执行 Excel 测试用例
1 准备 Excel 测试用例
至少包括输入数据和预期结果。
2 Excel
?
首先导入 jxl.jar
?
Excel 的代码
InputStream file=new FileInputStream("e:\\cases.xls");
// 创建输入流
Workbook excel=Workbook.getWorkbook(file);
// 获取 Excel 文件对象
Sheet sheet=excel.getSheet(0);
// 获取文件的指定工作表,默认第一个
List<String[]> list=new ArrayList<String[]>();
Cell cell=null;
// 单元格
for (int i=0; i<sheet.getRows();i++) { //0 表示第 1
String[] rowi_col=new String[sheet.getColumns()]; // 创建数组存储一行的多列值 for (int j= 0;j<sheet.getColumns();j++) {
cell=sheet.getCell(j,i);
// 获取第 i 行第 j 列的值
rowi_col[j]=cell.getContents();
}
list.add(rowi_col);// 把刚获取的列存入 list
}
file.close();
3 返回 Object 对象作为参数
Object[][] data=new Object[list.size()][];
for(int i=0;i<list.size();i++)
data[i]=list.get(i);
4 断言失败时输出实际结果
?
断言失败时,断言语句后面的语句将停止运行。
String result=driver.findElement(By.tagName("body")).getText();
Boolean loginResult=result.contains(expect);
try{
Assert.assertTrue(loginResult);
}catch(AssertionError e){
Assert.fail(result);
}
五、 访问数据库
1 导入相关数据库的包
?
网上下载对应数据库的 .jar
? Eclipse 中的操作
? JAR 系统库→构建路径→配置构建路径→添加外部 JAR
2 加载数据库驱动包
? Class.forName(" 数据库驱动类名 ");
?
返回类,作用是加载要连接的数据库的驱动到 JVM Java 虚拟机)。
?
成功加载后,会将 Driver 类的实例注册到 DriverManager 类中。
? mysql 数据库驱动类名
? com.mysql.jdbc.Driver
3 连接数据库
? Connection conn=DriverManager.getConnection ("jdbc:DBMS 类型 :// 地址 : 端口号 / 数据库名 ", " 用户名 ", " 密码 ");
? Connection 是一个接口;
? DriverManager 是一个类,用于通过驱动程序连接数据库;
? getConnection 方法返回 Connection 接口。
4 执行 SQL 语句
?
数据查询
?
预编译形式的 SQL 语句
?
数据库可以把编译后的执行代码缓存在内存中,当再次执行相同的 SQL
语句时就不需要重新编译了,只要将参数直接传入编译过的语句执行代码
中就会得到执行。
?
预编译可以提高数据库性能,还可以防范 SQL 注入。
? String sql="select ... where 列名 1=? and 列名 2=?";
? ? 是固定写法
? PreparedStatement state=conn.prepareStatement(sql);
? state.setString(1 ,值 1);
? 1 表示第 1 个参数,值是参数值,依次类推
?
获得结果集
? ResultSet rs=state.executeQuery( );
?
只能执行查询操作,返回一个结果集,不能用于增删改。
? ResultSet 是一个接口,用于暂存结果集,但无法获得行数。
?
移动行指针,读取一行数据
? rs.next( )
?
指针移至下一行,成功返回 true ,初始位置在第一行之前。
?
获得列值
? rs.getString( 列号或列名 )/getDate/getByte/getShort/getInt/getLong/getFloat
?
列号从 1 开始
?
列名用双引号括起来
?
使用此句之前需先用 rs.next( ) 读取一行
?
结果集已耗尽
?
原因是 rs 中没有数据
?
增删改
? int n=state.executeUpdate(String sql)
?
执行增删改操作,返回影响的行数。
5 批量插入多行数据
for( ){
state.setString(1,...);
state.setString(2,...);
...
state.addBatch();
}
state.executeBatch(); 6 关闭数据库连接
? rs.close( );
? state.close( );