已经写到了第四篇了,也是selenium自动化的末了一篇了。
当然了,自动化不止这些,还有很多很多的内容,学无止境。

前情回顾

一、搭建自动化测试环境

项目>>浏览器+浏览器驱动+selenium(措辞)

selenium导出php代码selenium主动化测试04 GraphQL

PHP的web项目>>Firefox+geckodriver+selenium-Java(Java+maven+testng)

二、测试代码

WebDriver driver = new FirefoxDriver();打开浏览器,获取驱动driver工具

driver.manage().window().maximize();窗口最大化

driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);隐式等待15s,建议不要太长

driver.get("网址");访问对应页面,自带壅塞效果

driver.findElement(定位办法)定位元素,只能定位符合规则的第一个,必须定位到,否则报错

driver.findElements(定位办法),定位所有符合规则的元素,可以定位0-n个,常常判断定位是不是0判断元素是否存在

By.id\\name\className\xpath\linkText\tagName\cssSelector\partialLinkText

xpath和cssSelector(xpath效率低,元素支持率高;cssSelector效率高,元素支持率低)

.click点击

.cleaar 清空输入框

Actions类,selenium中各种操作

Select类,操作下拉框:selectByIndex选择;deselectByIndex;不选

driver.switchTo().alert().accept();确定.dismiss();取消.sendKeys("");输入.window("新窗口的handle");.frame(索引);.frame("frame元素的id或name值");.frame(frame元素);.defaultContent();.parentFrame();

driver.getCurrentUrl();获取网址

driver.getTitle(); 获取标题

driver.getPageSource();获取页面源码

driver.close();关闭当前的窗口,如果是末了一个,会同时关闭浏览器

driver.quit(); 关闭驱动,关闭所有窗口,退出浏览器

搭建环境

testng--自动化测试>>功能自动化

testng实现自动化测试>>用于编写和实行自动化测试用例。
主理法中的代码,一条崩溃,都不实行,但是用例希望一条缺点,其它不受影响。
掌握用例的实行顺序,自动化测试报告天生,.....

搭建testng的编写和运行环境:在项目中导入testng的jar文件,紧张用于编写脚本

在pom.xml里面添加依赖,然后保存

<!--testng依赖 --><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.8.8</version><scope>test</scope></dependency><!--/testng依赖 -->

<!--feed4testng依赖 --><dependency><groupId>org.databene</groupId><artifactId>feed4testng</artifactId><version>0.6.2</version><scope>test</scope></dependency>

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.2</version><scope>test</scope></dependency><!--/feed4testng依赖 -->

然后右边库会涌现几个文件

testng插件呢我们idea自带,不用下载

编写自动化测试用例

编写的是实行测试用例的步骤,一样平常编写用例时,不干系的用例不会写到一起

一、一个class中写入1条用例,实行1遍,实行写去世的数据

创包autotest04,创建class类 Testng1.class

在类里面声明一个变量,让方法可以共用

public class Testng1 {// 声明一个变量在类中 浸染于类中所有方法 希望3个方法共用一个driverWebDriver driver;

利用@Test

/ 一个利用@Test润色的普通方法便是一条测试用例 用例中没有报错,用例通过 用例中报错崩溃,用例失落败 /@Test

创建方法a

public void a() {//用例的实行步骤 调用driver操作浏览器实行测试//用例的结果判断--1.用例通过,不能报错; 2.用例失落败,必须崩溃---断言}

创建两个方法

/ 为了担保无论用例实行结果如何, 是否报错,浏览器打开必须关闭 添加2个方法 无论用例结果如何必定实行 /// 一个运行于用例前 打开浏览器等一系列前置操作@BeforeMethodpublic void beforeMethod() {//给driver赋值,设置最大化,隐式等待//this.driver 表示类中的变量driverthis.driver = new FirefoxDriver();}// 一个运行于用例后 关闭浏览器等一系列后置操作@AfterMethodpublic void afterMethod() {//把driver给关闭}

代码整合,一个大体框架就出来了

package org.example.autotest04;import org.openqa.selenium.WebDriver;import org.openqa.selenium.firefox.FirefoxDriver;import org.testng.annotations.AfterMethod;import org.testng.annotations.BeforeMethod;import org.testng.annotations.Test;public class Testng1 { // 声明一个变量在类中 浸染于类中所有方法 希望3个方法共用一个driver WebDriver driver; / 一个利用@Test润色的普通方法便是一条测试用例 用例中没有报错,用例通过 用例中报错崩溃,用例失落败 / @Test public void a(){ //用例的实行步骤 调用driver操作浏览器实行测试 //用例的结果判断--1.用例通过,不能报错; 2.用例失落败,必须崩溃---断言 } / 为了担保无论用例实行结果如何, 是否报错,浏览器打开必须关闭 添加2个方法 无论用例结果如何必定实行 / // 一个运行于用例前 打开浏览器等一系列前置操作 @BeforeMethod public void beforeMethod(){ //给driver赋值,设置最大化,隐式等待 //this.driver 表示类中的变量driver this.driver = new FirefoxDriver(); } // 一个运行于用例后 关闭浏览器等一系列后置操作 @AfterMethod public void afterMethod(){ //把driver给关闭 }}

接下来开始实操,以登录功能进行测试

创包autotest04.case,创建class LoginTest.java,登录测试用例

把之前testng1里面的代码复制过来,然后在上面进行补充

首先,先编写用例实行前和用例实行后的操作,前置+后置操作

在@BeforeMethod处开始写前置操作

@BeforeMethod public void beforeMethod(){ //给driver赋值,设置最大化,隐式等待 //this.driver 表示类中的变量driver this.driver = new FirefoxDriver(); this.driver.manage().window().maximize(); this.driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); }

在@AfterMethod处写后置操作

@AfterMethod public void afterMethod(){ //把driver给关闭 driver.quit(); }

中间的@Test开始写用例实行步骤

@Test public void login() throws InterruptedException { //用例的实行步骤 调用driver操作浏览器实行测试 driver.get("http://localhost:8088/index.php?m=user&c=public&a=login"); driver.findElement(By.id("username")).sendKeys("test111"); driver.findElement(By.id("password")).sendKeys("123456"); driver.findElement(By.className("login_btn")).click(); //用例的结果判断--1.用例通过,不能报错; 2.用例失落败,必须崩溃---断言 Thread.sleep(5000); Assert.assertEquals(driver.getCurrentUrl(),"http://localhost:8088/index.php?m=user&c=index&a=index"); }

这里面assert引用的testng,不是junit

最后代码整合,开始实行测试用例

package org.example.autotest04.cases;import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.firefox.FirefoxDriver;import org.testng.Assert;import org.testng.annotations.AfterMethod;import org.testng.annotations.BeforeMethod;import org.testng.annotations.Test;import java.util.concurrent.TimeUnit;public class LoginTest { // 声明一个变量在类中 浸染于类中所有方法 希望3个方法共用一个driver WebDriver driver; / 一个利用@Test润色的普通方法便是一条测试用例 用例中没有报错,用例通过 用例中报错崩溃,用例失落败 / @Test public void login() throws InterruptedException { //用例的实行步骤 调用driver操作浏览器实行测试 driver.get("http://localhost:8088/index.php?m=user&c=public&a=login"); driver.findElement(By.id("username")).sendKeys("test111"); driver.findElement(By.id("password")).sendKeys("123456"); driver.findElement(By.className("login_btn")).click(); //用例的结果判断--1.用例通过,不能报错; 2.用例失落败,必须崩溃---断言 Thread.sleep(5000); Assert.assertEquals(driver.getCurrentUrl(),"http://localhost:8088/index.php?m=user&c=index&a=index"); } / 为了担保无论用例实行结果如何, 是否报错,浏览器打开必须关闭 添加2个方法 无论用例结果如何必定实行 / // 一个运行于用例前 打开浏览器等一系列前置操作 @BeforeMethod public void beforeMethod(){ //给driver赋值,设置最大化,隐式等待 //this.driver 表示类中的变量driver this.driver = new FirefoxDriver(); this.driver.manage().window().maximize(); this.driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); } // 一个运行于用例后 关闭浏览器等一系列后置操作 @AfterMethod public void afterMethod(){ //把driver给关闭 driver.quit(); }}

我这里编写的是缺点用例,输出结果是测试失落败,用例不通过

实行精确的用例,通过

二、一个class中写入多条用例,实行1遍,实行写去世的数据

在autotest04创建class Testng2.java

和Testng1里面大体相似

类里面声明变量

public class Testng2 { WebDriver driver;

@Test

由于要写多条用例,可以写多条@Test。
为了让用例之间有顺序的去实行,在@Test后添加dependsOnMethods={"依赖的用例方法名"}

@Test public void a(){ } @Test(dependsOnMethods = {"a"}) // a是方法名 也是用例名 // a成功b实行 a失落败b跳过 public void b(){ }

用例实行前和实行后方法

// 2条用例实行在同一浏览器 @BeforeClass public void beforeClass(){ // 类中所有方法实行前运行1次 } @AfterClass public void afterClass(){ // 类中所有方法实行后运行1次 }

有关于beforeclass,beforemethod,afterclass,aftermethod的差异可以查看这位大佬的文章TestNG 基本表明@BeforeMethod、@AfterMethod 和@BeforeClass、@AfterClass 的差异以及实际问题的办理 - 别动让左佐来 - 博客园

代码整合,一个测试多条用例的大体框架完成了

package org.example.autotest04;import org.openqa.selenium.WebDriver;import org.testng.annotations.AfterClass;import org.testng.annotations.BeforeClass;import org.testng.annotations.Test;public class Testng2 { WebDriver driver; @Test public void a(){ } @Test(dependsOnMethods = {"a"}) // a是方法名 也是用例名 // a成功b实行 a失落败b跳过 public void b(){ } // 2条用例实行在同一浏览器 @BeforeClass public void beforeClass(){ // 类中所有方法实行前运行1次 } @AfterClass public void afterClass(){ // 类中所有方法实行后运行1次 }}

接下来实操,用添加会员编写测试用例,实行测试用例。
添加会员有两步:登录+添加

在包autotest04创建class AddVip.java

编写前置和后置操作

@BeforeClass public void beforeClass(){ // 类中所有方法实行前运行1次 this.driver = new FirefoxDriver(); this.driver.manage().window().maximize(); this.driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); } @AfterClass public void afterClass(){ // 类中所有方法实行后运行1次 driver.quit();// 方法中没有声明 driver this可以省略 }

编写测试用例

@Test public void login() throws InterruptedException { String url="http://localhost:8088/index.php?&m=admin&c=public&a=login"; driver.get(url); driver.findElement(By.name("username")).sendKeys("admin"); driver.findElement(By.name("userpass")).sendKeys("password"); driver.findElement(By.name("userverify")).sendKeys("1234"); driver.findElement(By.className("Btn")).click(); //断言 Thread.sleep(5000); Assert.assertNotEquals(driver.getCurrentUrl(), url); } @Test(dependsOnMethods = {"login"})// login是方法名 也是用例名 public void addVip() throws InterruptedException { driver.findElement(By.linkText("会员管理")).click(); driver.findElement(By.linkText("添加会员")).click(); Thread.sleep(2000); driver.switchTo().frame("mainFrame"); //会员用户名 driver.findElement(By.name("username")).sendKeys("Tony"); //手机号 driver.findElement(By.name("mobile_phone")).sendKeys("15123564689"); //会员性别 driver.findElement(By.xpath("//input[@value = '1']")).click(); //会员邮箱 driver.findElement(By.name("email")).sendKeys("110122119@163.com"); //会员QQ driver.findElement(By.name("qq")).sendKeys("110120119"); //提交 driver.findElement(By.className("button_search")).click(); //判断 Thread.sleep(5000); Assert.assertTrue(driver.getPageSource().contains("注册韶光")); // 字符串1.contains(字符串2) 1包含2 true 反之false }

代码整合,实行测试

package org.example.autotest04.cases;import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.firefox.FirefoxDriver;import org.testng.Assert;import org.testng.annotations.AfterClass;import org.testng.annotations.BeforeClass;import org.testng.annotations.Test;import java.util.concurrent.TimeUnit;public class AddVip { WebDriver driver; @Test public void login() throws InterruptedException { String url="http://localhost:8088/index.php?&m=admin&c=public&a=login"; driver.get(url); driver.findElement(By.name("username")).sendKeys("admin"); driver.findElement(By.name("userpass")).sendKeys("password"); driver.findElement(By.name("userverify")).sendKeys("1234"); driver.findElement(By.className("Btn")).click(); //断言 Thread.sleep(5000); Assert.assertNotEquals(driver.getCurrentUrl(), url); } @Test(dependsOnMethods = {"login"})// login是方法名 也是用例名 public void addVip() throws InterruptedException { driver.findElement(By.linkText("会员管理")).click(); driver.findElement(By.linkText("添加会员")).click(); Thread.sleep(2000); driver.switchTo().frame("mainFrame"); //会员用户名 driver.findElement(By.name("username")).sendKeys("Tony"); //手机号 driver.findElement(By.name("mobile_phone")).sendKeys("15123564689"); //会员性别 driver.findElement(By.xpath("//input[@value = '1']")).click(); //会员邮箱 driver.findElement(By.name("email")).sendKeys("110122119@163.com"); //会员QQ driver.findElement(By.name("qq")).sendKeys("110120119"); //提交 driver.findElement(By.className("button_search")).click(); //判断 Thread.sleep(5000); Assert.assertTrue(driver.getPageSource().contains("注册韶光")); // 字符串1.contains(字符串2) 1包含2 true 反之false } @BeforeClass public void beforeClass(){ // 类中所有方法实行前运行1次 this.driver = new FirefoxDriver(); this.driver.manage().window().maximize(); this.driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); } @AfterClass public void afterClass(){ // 类中所有方法实行后运行1次 driver.quit();// 方法中没有声明 driver this可以省略 }}

两条精确用例,两条全通过

缺点的login用例,第一条用例不通过,第二条不实行,直接跳过

精确的login用例,缺点的addvip用例

三、一个class中写入用例,实行n遍,实行配置的数据

便是说把用例中所有写去世的数据变成变量--参数化。
测试用例实行的次数由供应的测试数据多少决定--数据驱动测试

在包autotest04创建class LoginTest2.java

把LoginTest里面代码复制到LoginTest2里面

第一步,构建测试用例,设计用例,把用例中写去世数据都变成变量, 声明在用例的方法的小括号中,成为用例的参数

修正两处

第二步,构建测试数据,设计数据文件,测试数据和测试用例分离管理。

打开项目目录

在项目目录下创建文本文档a.txt,然后修正后缀,a.csv。
(一定要纯文本文件,其他文件转换会乱码)

选中a.csv右键记事本打开,每一行不同的数据用逗号隔开,一行一组测试数据,用例须要几个写几个,位置要对应,每一行结尾直接回车换行,第一行是标题--不读

我这边写了一个精确的用例,四个缺点用例

点击文件--另存为选择编码为UTF-8,点击确定提示是否更换--是

第三步,测试用例和测试数据关联到一起

指定读取的文件所在的位置:用例方法上加@Source("文件路径")

指定读取文件的方法:办法是feeder 写法 @Test(dataProvider="feeder"),feeder属于FeedTest类,当前用例所在类须要继续FeedTest

代码整合,进行测试

package org.example.autotest04.cases;import org.databene.benerator.anno.Source;import org.databene.feed4testng.FeedTest;import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.firefox.FirefoxDriver;import org.testng.Assert;import org.testng.annotations.AfterMethod;import org.testng.annotations.BeforeMethod;import org.testng.annotations.Test;import java.util.concurrent.TimeUnit;public class LoginTest2 extends FeedTest { // 声明一个变量在类中 浸染于类中所有方法 希望3个方法共用一个driver WebDriver driver; / 一个利用@Test润色的普通方法便是一条测试用例 用例中没有报错,用例通过 用例中报错崩溃,用例失落败 / @Test(dataProvider = "feeder")// 测试用例 @Source("a.csv")//只能读取项目目录 public void login(String username,String password) throws InterruptedException { //用例的实行步骤 调用driver操作浏览器实行测试 driver.get("http://localhost:8088/index.php?m=user&c=public&a=login"); driver.findElement(By.id("username")).sendKeys(username); driver.findElement(By.id("password")).sendKeys(password); driver.findElement(By.className("login_btn")).click(); //用例的结果判断--1.用例通过,不能报错; 2.用例失落败,必须崩溃---断言 Thread.sleep(5000); Assert.assertEquals(driver.getCurrentUrl(),"http://localhost:8088/index.php?m=user&c=index&a=index"); } / 为了担保无论用例实行结果如何, 是否报错,浏览器打开必须关闭 添加2个方法 无论用例结果如何必定实行 / // 一个运行于用例前 打开浏览器等一系列前置操作 @BeforeMethod public void beforeMethod(){ //给driver赋值,设置最大化,隐式等待 //this.driver 表示类中的变量driver this.driver = new FirefoxDriver(); this.driver.manage().window().maximize(); this.driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); } // 一个运行于用例后 关闭浏览器等一系列后置操作 @AfterMethod public void afterMethod(){ //把driver给关闭 driver.quit(); }}

实行结果

OK了,selenium自动化测试就告一段落了,接下来还会连续学习其他软件测试的内容,例如Java、Linux、appnium等其他学习内容,会在后续更新。

感谢您看到这里,GOOD LUCK