一、testNG
TestNG是Java中的一个测试框架。Java中已经有一个JUnit的测试框架了。 TestNG比JUnit功能强大的多。 测试人员一般用TestNG来写自动化测试。 开发人员一般用JUnit写单元测试。
上一篇已经提过,我们在pom.xml里面添加了testNG的依赖
二、testNG注解:
@BeforeSuite
被@BeforeSuite注解的方法,将会在testng定义的xml根元素里面的所有执行之前运行
@AfterSuite
被@AfterSuite注解的方法,将会在testng定义的xml根元素里面的所有执行之后运行。
@BeforeTest
被@BeforeTest注解的方法,将会在一个元素定义的所有里面所有测试方法执行之前运行。
@AfterTest
被@AfterTest注解的方法,将会在一个元素定义的所有里面所有的测试方法执行之后运行。
@BeforeClass
被@BeforeClass注解的方法,将会在当前测试类的第一个测试方法执行之前运行。
@AfterClass
被@AfterClass注解的方法,将会在当前测试类的最后一个测试方法执行之后运行。
@BeforeMethod
被@BeforeMethod注解的方法,将会在当前测试类的每一个测试方法执行之前运行。
@AfterMethod
被@AfterMethod注解的方法,将会在当前测试类的每一个测试方法执行之后运行
@Test 注解
@Test 注解是TestNG的核心注解,被打上该注解的方法,表示为一个测试方法
暂时我们先主要记住:
- @BeforeClass
被@BeforeClass注解的方法,将会在当前测试类的第一个测试方法执行之前运行。 - @AfterClass
被@AfterClass注解的方法,将会在当前测试类的最后一个测试方法执行之后运行。 - @Test 注解
@Test 注解是TestNG的核心注解,被打上该注解的方法,表示为一个测试方法
二、如何使用testNG
我们给设置环境变量、打开浏览器这个方法,添加注解@BeforeClass,表示在第一个测试方法执行之前运行。给关闭浏览器这个方法添加注解@AfterClass,表示在最后一个测试方法执行之后运行。
@BeforeClass
public void startUp() {
//设置环境变量,指定chromedriver的路径
System.setProperty("webdriver.chrome.driver",
"src/main/resources/driver_2_38_v65-67/chromedriver.exe");
//设置浏览器的参数
ChromeOptions options = new ChromeOptions();
//最大化浏览器
options.addArguments("--test-type", "--start-maximized");
//打开浏览器
driver = new ChromeDriver();
}
@AfterClass
public void shutDown(){
//关闭浏览器
driver.close();
//关闭浏览器驱动
driver.quit();
}
@Test
public void openUrl(){
//打开要测的登录页面
driver.get("http://www.guoyasoft.com:8080/guoya-client");
}
@Test
//登录
public void login() {
//定位用户名框
WebElement userName= driver.findElement(By.id("userName"));
userName.clear();
//输入用户名
userName.sendKeys("wuling");
//定位密码框
WebElement password= driver.findElement(By.id("password"));
password.clear();
//输入密码
password.sendKeys("0000");
//定位并点击登录
driver.findElement(By.id("loginBtn")).click();
}
给我们要测试的方法添加@test注解,上述代码给打开网页方法和登录方法添加@test注解
如何使用:
在给方法添加testNG注解后,直接右键类run as -> testNG test**
但是执行@test的顺序是怎样的呢?
1、按照字母表顺序执行测试方法
如果需要测试的方法只有@Test,那么它将通过方法名的首字母按照字母表顺序执行
2、给方法添加priority属性
根据业务逻辑,给各个方法添加priority属性,按照@Test(priority = 0)——>@Test(priority = 1)——>……@Test(priority = N)执行。
3、在testNG.xml配置顺序(推荐)
testNG.xml的基本结构如下:
将testNG.xml拖到包下面。
testNG.xml右键,run as -> testNG Suit
观察执行结果:
三、Java封装
实际的工作中,我们避免在业务流有过多的代码干扰,我们的业务操作,基本是定位元素-操作元素,比如输入用户名、密码、校验码的基本套路都是,定位文本框-清除文本框-向输入文本内容,那我们是否可以把这个套路封装成一个方法,需要用时,只用填几个参数,而节省空间去写几行代码。
//定位用户名框
WebElement userName= driver.findElement(By.id("userName"));
//清除
userName.clear();
//输入用户名
userName.sendKeys("wuling");
将他封装成一个方法,
public void textInput(String xp,String texts) {
WebElement textInp= driver.findElement(By.xpath(xp));
textInp.clear();
textInp.sendKeys(texts);
}
当我们需要操作文本框时,只要调用这个方法,并且写入文本框的地址,和要输入的内容作为参数即可。
textInput("//input[@id=userName]","wuling");
原本的三行代码,写成一行即可。
我们新建一个class文件来专门写工具流,用一个专门写业务流,这样代码更清晰明了。而且,工具流以后可以重复使用。业务逻辑更改,直接更改业务流即可,提高效率。
我们将工具流新建为AutoBasic.class,
public class AutoBasic {
public WebDriver driver; //将driver设置为全局变量
//启动浏览器
public void startUp() {
//设置环境变量,指定chromedriver的路径
System.setProperty("webdriver.chrome.driver",
"src/main/resources/driver_2_38_v65-67/chromedriver.exe");
//设置浏览器的参数
ChromeOptions options = new ChromeOptions();
//最大化浏览器
options.addArguments("--test-type", "--start-maximized");
//打开浏览器
driver = new ChromeDriver(options);
sleep() ;
}
//关闭浏览器
public void shutDown(){
//关闭浏览器
sleep() ;
driver.close();
//关闭浏览器驱动
driver.quit();
}
public void sleep() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void openUrl(String url){
//打开要测的登录页面
driver.get(url);
sleep();
}
//input文本
public void textInput(String xp,String texts) {
WebElement textInp= driver.findElement(By.xpath(xp));
textInp.clear();
textInp.sendKeys(texts);
sleep();
}
//点击按钮
public void buttonInput(String xp) {
WebElement buttonInp= driver.findElement(By.xpath(xp));
buttonInp.click();
}
//下拉框
public void selectFunction(String xp, int i) {
Select select =new Select(driver.findElement(By.xpath(xp)));
select.selectByIndex(i);
}
//刷新
public void navRefresh() {
driver.navigate().refresh();
sleep();
}
新建一个class文件是业务流,SearchAuto.java
public class SearchAuto {
AutoBasic fz =new AutoBasic();//要使用AutoBasic.class的方法,先要实例化
//打开浏览器
@BeforeClass
public void startUp() {
fz.startUp();
}
@AfterClass
public void shutDown() {
fz.shutDown();
}
//打开网页
@Test
public void openUrl() {
fz.openUrl("http://47.98.226.232:8080/guoya-medium/jsp/user/login.jsp");
}
@Test
//登录
public void login() {
//输入用户名
fz.textInput("//input[@id=\"userName\"]","guoya");
//输入密码
fz.textInput("//input[@id=\"password\"]","Aa123!");
//输入验证码
fz.textInput("//input[@id=\"checkCode\"]","12345");
// 点击登录
fz.buttonInput("//input[@id=\"loginBtn\"]");
}
@Test
//查询
public void searchUN() {
fz.textInput("//input[@name=\"userName\"]","guoya");
//点击查询
fz.buttonInput("//tr[2]/td[8]/input");
}
@Test
public void navRefresh() {
fz.navRefresh();
}
@Test
public void searchEdu() {
fz.selectFunction("//tr[1]/td[6]/select", 2);
fz.buttonInput("//tr[2]/td[8]/input");
}
可以看到,按照业务逻辑,使用工具流里的方法,简单清晰不迷糊。
四、java封装_参数化
public void login() {
fz.textInput("//input[@id=\"userName\"]","guoya");
fz.textInput("//input[@id=\"password\"]","Aa123!");
fz.textInput("//input[@id=\"checkCode\"]","12345");
fz.buttonInput("//input[@id=\"loginBtn\"]");
}
我们可以进一步讲这套代码封装,将可能需要更改的数据写成参数
public void login(String um,String pwd) {
fz.textInput("//input[@id=\"userName\"]",um);
fz.textInput("//input[@id=\"password\"]",pwd);
fz.textInput("//input[@id=\"checkCode\"]","12345");
fz.buttonInput("//input[@id=\"loginBtn\"]");
}
这样我们完成整个登录,就只需要写:
login("guoya","Aa123!");
五、testNG参数化及断言
(一)断言
在Jmeter里我们已经了解过断言,它相当于预期结果,一条测试用例,除了测试步骤,测试数据,必须要有断言,与Jmeter相同的,如果不设置断言,如果不设置判断,那自动化没有意义。
语句:
Assert.assertEquals(result, true);
result是实际结果和true为预期结果,实际结果与预期结果做比较,一般用Boolean值做断言数据。
在工具流AutoBasic.java写入一个新的方法,得到实际的结果,返回一个boolean值。
public boolean assertPage(String s) {
boolean result=driver.getPageSource().contains(s);
return result;
}
@test
//登录成功测试用例
public void loginSuccess(String um, String pwd){
//打开网页
openUrl();
//登录
login("guoya","Aa123!");
//实际结果,如果登录成功跳转到查询页面,故以“查询”来做断言,
//如果登录成功,应该返回true,如果登录不成功,应该返回false
boolean result1=fz.assertPage("查询");
//实际结果与预期结果比较
Assert.assertEquals(result1, true);
}
(二)参数化
testNG有两种参数化方式
- Parameters
- 在testNG.xml里面配置参数化数据
<parameter name="userName" value="guoya"></parameter>
<parameter name="password" value="Aa123!"></parameter>
name后面是变量名,value后面是变量值,成对,即
userName="guoya"
password="Aa123!"
- 那如何使用呢
@Parameters({"userName","password"})
public void loginSuccess( String um, String pwd){
openUrl();
login(um,pwd);
boolean result1=fz.assertPage("查询");
Assert.assertEquals(result1, true);
将原本的@test改为@Parameters({"userName","password"})即可。
代码进一步可以修改为
@Parameters({"userName","password"})
public void loginSuccess( String um, String pwd, String exp1){
//exp1就是断言,用断言结果与true做比较,
//如果断言结果为true,exp结果为true,如果断言结果为false,exp结果为false
boolean exp=exp1.equals("true");
openUrl();
login(um,pwd);
boolean result1=fz.assertPage("查询");
if(result1){
Assert.assertEquals(result1, exp);
}else{
Assert.assertEquals(result1, exp);
}
}
- dataprovider
步骤
(1)使用@Test(dataProvider="sdata")给测试方法添加注解使用参数化的数据;
(2)需要自己写一个方法来存储数据
方法1:二维数组存数据
@DataProvider(name="dataLogin")
public Object[][] dataLogin() {
Object[][] ob = new Object[4][3];//一组数据组成一条测试用例
//一条测试用例
//测试数据
ob[0][0]="wuling";
ob[0][1]="0000";
//断言
ob[0][2]="true";
//一条测试用例
ob[1][0]="wuling1";
ob[1][1]="0000";
ob[1][2]="false";
//一条测试用例
ob[2][0]="wuling";
ob[2][1]="0001";
ob[2][2]="false";
//一条测试用例
ob[3][0]="wuling12";
ob[3][1]="0022";
ob[3][2]="false";
return ob;
}
方法2:csv文件存数据
保存为csv文件,
@DataProvider(name="dataLogin")
public static Object[ ][ ] dataLogin() {
Object[ ][ ] obData = CSVReader.readCSV("E:/softwareData/dataLogin.csv");
return obData;
}