源于一次测试
最近做了一些业务开发,功能本身还是挺简单的,由于测试资源不足,应测试要求,我就顺道接下了一些测试的活。测试任务也不复杂,无非是一些字段CURD来回变了法子的测试,各个字段分开,组合,批量处理,主要是检测一些前端的校验规则。
问题在于拆开来看,其实逻辑很简单,有校验的字段不同的规则反复保存,根据测试用例验证结果,问题在于组合后需要测试的数据量太多了,如果人为一条一条创建,需要创建几十条相近的数据,测试流程重复性很高,且不可重复验证,如果一不留神出错,当前用例需要重新再来。并且创建一条数据需要填写的字段量可能太多了,即使按10个必填字段,3个测试字段来测试,那么几十条就需要填写几百个字段值,并且这些字段值按用例提供或者一些随机值生成,这个过程本身就很容易出错。
因为是UI级别的自动化测试,所以我本能的就想到使用selenium编写一个自动化测试脚本,selenium本身也比较简单,即使有段时间没写,再看看官方文档,两三个小时就能直接手搓一个自动化测试脚本的大体框架,做了一些简单的配置读取,就实现了25个TestCase的实现。
对于UI自动化的思考
自动化测试用例自然是已经能跑了,测试自然也完成了,但是说实话这个也就只有开发能这样实现。
-
如果要让测试人员来使用,测试人员也不一定懂开发,对于UI元素也不一定了解,而且整体上手成本是比较高的。
- 其次,回过头再看这些自动化脚本,通篇充满了元素选择,无论是xpath还是css或者tag之类的,严重影响了脚本的可读性,又有谁知道这是选择了什么元素,做了什么操作,无论你是用java还是python亦或是nodejs。
WebElement element = driver.findElement(By.xpath("/html/body/div[1]/div[3]/ul/li") );
-
还有大量的时间等待,仅是为了增加一些网络的容忍,保证页面完成加载
这些对于测试人员来说都是无关紧要的东西,他们关心的是测试用例的执行结果。
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:691998057【暗号:csdn999】
模拟场景
为了更加有体感我们模拟一个场景。那我们自动化测试的流程如下:
-
登录
-
进入首页
-
进入测试页面
-
寻找测试页面列表中的某一行(姓名为张三)
-
修改这一行的性别:男,国家:CN,根据输入筛选选择第一个选项
-
点击保存按钮
原生Selenium SDK(Java)
以下是我们使用Java调用selenium的示例
driver.get("http://testcase.com/tc/index.html")
if (!driver.getCurrentUrl().startsWith("http://testcase.com/tc/index.html")) {// doLogindriver.get("http://testcase.com/tc/login.html");// 如果需要登录 WebElement username = driver.findElement(By.xpath("/html/body/div/div[2]/div/div/div/input[1]")); WebElement password = driver.findElement(By.xpath("/html/body/div/div[2]/div/div/div/input[2]")); WebElement submit = driver.findElement(By.xpath("/html/body/div/div[2]/div/div/div/button"));username.sendKeys("zhangsan"); password.sendKeys("password"); submit.click(); Thread.sleep(5000); assertTrue(driver.getCurrentUrl().startsWith("http://testcase.com/tc/index.html"));
}driver.get("http://testcase.com/tc/test.html")
List<WebElement> ths = driver.findElements(By.xpath("xpath@/html/body/div[1]/div/table/tbody/tr/th/div/span"))int nameIndex = -1;
int genderIndex = -1;
int countryIndex = -1;// 找到所需要的列头位置
for (int i = 0; i < elements.size(); i++) {if (StringUtils.equals(elements.get(i).getText(), "姓名")) {nameIndex = i;continue;}if (StringUtils.equals(elements.get(i).getText(), "性别")) {genderIndex = i;continue;}if (StringUtils.equals(elements.get(i).getText(), "国家")) {countryIndex = i;continue;}
}// 遍历行,找到 姓名为张三的数据
List<WebElement> rowNames = driver.findElements(By.xpath("xpath@/html/body/div[1]/div/table/tbody/tr/td["+nameIndex+"]"))
for (int i = 0; i < rowNames.size(); i++) {if(StringUtils.equals(rowNames.get(i).getText(), "张三")) {// 赋值 "男"WebElement gender = driver.findElement(By.xpath("xpath@/html/body/div[1]/div/table/tbody/tr["+i+"]/th/td["+genderIndex+"]"));gender.sendKeys("男");// 赋值 "CN"WebElement country = driver.findElement(By.xpath("xpath@/html/body/div[1]/div/table/tbody/tr["+i+"]/th/td["+countryIndex+"]"));country.sendKeys("CN");Thread.sleep(1000);country.sendKeys(Keys.DOWN);Thread.sleep(200);country.sendKeys(Keys.ENTER);WebElement saveBtn = driver.findElement(By.xpath("xpath@/xpath@/html/body/div[1]/div/input[2]"));saveBtn.click()Thread.sleep(1000)break;}
}// 检测
WebElement messageBox = driver.findElement(By.xpath("xpath@/xpath@/html/body/div[1]/div/span")); assertTrue(StringUtils.equals(messageBox, "success"))
对测试友好的自动化
那么对测试友好的自动化那就必须满足以上几点,更加简单的语法,元素选择与用例执行分离,无太多时间冗余。
语法设计
于是我思考设计了一种前后端分离的语法,来表述更直观的操作。将页面元素与操作分离成两部分配置。
-
foo.page 用于配置页面元素以及页面关系。
-
common.ps 代表通用函数,可被其他同page的脚本调用。
-
testCase1.ps 代表页面自动化脚本。
// File: foo.page
// 定义自动化测试的页面元素配置,以及基础函数page {index {$url: "http://testcase.com/tc/index.html"}login {$url: "http://testcase.com/tc/login.html"username: "xpath@/html/body/div/div[2]/div/div/div/input[1]"password: "xpath@/html/body/div/div[2]/div/div/div/input[2]"submit: "xpath@/html/body/div/div[2]/div/div/div/input[2]"}test_page {$url: "http://testcase.com/tc/test.html"save_btn: "xpath@/xpath@/html/body/div[1]/div/input[2]"message_box: "xpath@/xpath@/html/body/div[1]/div/span"table {$type: "table" $selector: "xpath@/html/body/div[1]/div/table/tbody"headers: "@table/tr/th/div/span"rows: {$selector: "@table/tr"cells : "@rows/td"}}}
}
// File: common.ps
// 基础函数page: foo.page
desc: 测试bar功能
----function login() {// 切换到首页switch @index or {// 切换首页失败 则切换到登录页面switch @login {// 输入用户名@username -> "zhangsan"// 输入密码@password -> "password"// 登录@submit.click()// 切换到首页,再失败则抛出异常switch @index or throw error("登录失败")}}
}
// File: testCase1.ps
// 定义自动化测试脚本流程page: foo.page
desc: 测试bar功能
import: common.ps
----// 登录
login()
// 切换到测试页面
switch @test_page or throw error("切换到测试页面失败")
// 找到对应行
var row = @table.findOneRow({"姓名": "张三"}) or throw error("获取数据失败")
// 对应行进行赋值
row -> {"性别": "男", "国家": ["CN", sleep(1000), Keys.DOWN, sleep(200), Keys.ENTER]}
// 保存
@save_btn.click()// 校验
assert message_box.text == "success"
数据能力
通过自定义函数,可以实现随机字符串,随机数组,以及配置文件读取等功能,方便测试人员配置/生成自动化测试数据,可以使用常见的文件格式,如json,yml,properties等快速获取对应测试用例的数据
// File: testCase1.ps
// 定义自动化测试脚本流程page: foo.page
desc: 测试bar功能
import: common.ps----login()switch @test_page or throw error("切换到测试页面失败")// 读取测试数据
var test_data = load_data("./testCase1.json")// 找到张三行
var zhangsan = @table.findOneRow({"姓名": "张三"})
zhangsan -> test_data["张三"]// 找到李四行
var lisi = @table.findOneRow({"姓名": "李四"})
lisi -> test_data["李四"]@save_btc.click()
所见所想即所得
最终我们可以实现测试用例流程同自动化测试代码的高度统一,通过统一配置Page文件,UI调整对我们测试流程的影响降低到最小,另外通过Page结构化的结构能够体现UI的层级关系,使得自动化测试用例更容易理解和开发。
// 自动化测试流程
1. 登录
2. 进入首页
3. 进入测试页面
4. 寻找测试页面列表中的某一行 姓名为张三
5. 修改这一行的性别:男,国家:CN,根据输入筛选选择第一个选项
6. 点击保存按钮
---------// 自动化测试脚本
// 1/2. 登录并跳转到首页
login()
// 3. 切换到测试页面
switch @test_page or throw error("切换到测试页面失败")
// 4. 找到对应行
var row = @table.findOneRow({"姓名": "张三"}) or throw error("获取数据失败")
// 5. 对应行进行赋值
row -> {"性别": "男", "国家": ["CN", sleep(1000), Keys.DOWN, sleep(200), Keys.ENTER]}
// 6. 保存
@save_btn.click()
下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
最后: 可以在公众号:自动化测试老司机 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!