10月29日
Coding UI 测试的那些事儿

一般来说对一个网站做测试,最直接的方法就是用手点,眼睛看。用手点和眼睛看把网站的功能点都过一遍,比如在百度首页的搜索框里输入 “coding”,点击“百度一下”,用眼睛看会不会弹出有关 “coding” 的搜索页面。不过,你点了2天之后就会发现,这些点击和“眼睛确认”是一个机械式重复的过程。

当你遇到重复操作的事情,你就要想想如何让机器去做这些事。用人脑去从事这种低等人工智能的活动绝对是种浪费。

设想下,如果有段程序,自动把你打开浏览器,然后跳转到百度首页。再输入框里填充 “coding”,点击搜索,套转到搜索结果页面之后,自动确认这个页面上是否有 “coding” 的字样。若有,输出“测试通过”。若无,输出“测试失败”。你只需要点开程序,然后去吃个晚饭,然后回来看测试结果就好了(我就是这么干的),一切都如此简单和美妙。

那么,需要什么工具来实现这个美妙的过程呢?首先你需要一双“手”来点击和一对“眼”来获取信息 —— Selenium。 还需要一个脑子来操纵“手和眼”判断测试对错 —— Junit。 其实,Selenium 支持多种语言,比如说,ruby, python, Js, C#。他们都有相应成熟的测试框架,由于我用的是用 Java,相应的测试框架就用了 Junit 。这点已被前端小哥和 Ruby 大神吐槽致死。前端小哥说,既然你要测页面为什么不用 JS 呢?因为前端就是用 JS 写的,同源的语言会更好。 Ruby 大神说,用 Ruby 你会少写很多行代码。 其实,我那时就对 Java 熟悉一点,最后用 Java 写了。 这里,虽然本人没有亲自尝试过,但我还是想推荐下用 JS。 现在的网站,页面上会有着大量的 ajax 请求,页面的测试必须等待某些页面元素的更新。在这方面 JS 会比 Java 方便点。

UI 测试工具 Selenium 简介

selenium 是一个操纵浏览器来进行测试的框架。分为 Selenium 1 ( RC ), Selenium 2 ( WebDriver ), 江湖传言今年圣诞节会发布 selenium 3,主要是增强对移动端浏览器的测试。还有就是 Selenium IDESelenium Grid。 这里不介绍,可以看文档.

Selenium 1 ( RC ), Selenium 2 ( WebDriver ) 的区别就是对浏览器操纵的方式。 RC 的原理就是通过对原始的页面元素中注入一段特定的 JS 代码来实现的。 学过 JS 的人都知道, JS 可以操控 DOM 元素,点击,删除,获取元素属性和文本。你可以把这些操作看成一个个 JS 函数。 只是浏览器对非同源的 JS 有限制, 举个简单的例子, 百度首页上的 JS 代码不能与淘宝首页进行交互 (不能访问它的 cookie 等)。 因此,就需要RC(Remote Control), 将特定的 JS 代码加到服务器放回的数据中,再发送给浏览器,这样就避开了同源的问题。 然后浏览器运行这些 JS 函数,进行测试。

WebDriver 用的方式更为直接,它本身就是浏览器的 API,所以是直接对浏览器进行操作。无需通过 JS 代理操作。
个人建议用 WebDriver。 因为,据“路边社”可靠消息 selenium 3 会逐步抛弃 RC。

这4个多月了,一直在用 selenium 写自动化测试,由小白到现在稍微熟悉。填了不少坑。 也算是有些心得,接下来如果有时间,我会在 coding 开个 selenium-study 的公有项目来具体讲解一些实战心得。 关于selenium的学习, 最好的教材是 selenium 官方文档。 如果你的英文不太好,那么百度一下“虫师 博客园”,里面有很多不错的学习材料。 要是开发中遇到 bug 最好用英文在 google 里搜。 至于百度搜出来的那坨*,诶,,往事不堪回首。

UI 测试用例设计

上文提到的自动化测试属于功能测试范畴。所谓功能测试,简单的说测试网站的功能点是否正常,比如能否注册和登录,能否在 coding 发冒泡,push 代码等等。这是面向用户的最终测试。

既然是功能测试,自然是围绕功能来进行用例设计。用例大致分为两个部分, 操作和表现。就“登录 coding 网站”这一功能来说, 操作有,输入个性后缀或邮箱以及密码,点击“登录”按钮。相应的 表现 为,登录成功则跳转到个人中心,同时输出提示“欢迎***!”。若失败,则弹出相应的失败提示。

在编写程序的时候, 调用selenium的接口来进行操作,用断言 (assertX) 来判断表现是否正确,例如登录:

loginPage.clearAndSendKeys("#email",email);

loginPage.clearAndSendKeys("#password",password);

loginPage.clickElement(".large.button ", "#project-list");

assertEquals("登录不成功",baseUrl + "user", loginPage.getDriver().getCurrentUrl());

这里的 loginPage 是我写的一个 Page 类的实例。这个类包括 selenium 部分常用接口的封装(如清除输入框并输入值:clearAndSendKeys(String cssSector, String inputContent)),以及一些常用的小测试用例,如验证页面提示是否正确, loginPage.verifyHint("用户名或个性后缀不能为空");

因为有很多操作其实是一系列操作的组合操作,比如,测试讨论评论的通知,创建讨论,评论,验证通知。多用点面向对象设计好点(方便添加新用例),但也不必全用。如:

createTopic(zombiePage, topic);
commentTopic(ciwangPage, topic, "@" + zombieUser.getUserName());
Notification atSomeoneNotification = new Notification(notificationFileReader.getEmailIconClass(), ciwangUser, ciwangUser.getUserName()+ " 在 "+ topic.getTopicTitle() + " 的评论中提到了你。", zombieUser, topicFileReader.getTopicTitleInDetailPage() ,topic.getTopicTitle() );
notificationTest.verifyForTwoLinkFormat(atSomeoneNotification, "讨论@某人",notificationFileReader.getAtSomeoneItemIcon());

UI 定位 – cssSelector

如果想要对元素进行操作,必须先定位到那个元素。 selenium 有很多种定位的方法:

图片

其中,功能最强大的是 xpath 和 cssSelector,已覆盖其他接口的功能。 cssSelector 写起来比 xpath 要简洁而且易于封装。推荐使用 cssSelector 定位。

cssSelector 教程就不写了。有 W3Cschool 在,我就不班门弄斧。讲下一些自己的“最佳实践”吧。

1.尽量写的短,如果元素有 id, 千万别客气

2.选用有含义的类名

图片

如上图的任务,就该用 “.project-task”。之所以说上述 2 点,是因为前端常有改动。因此,选择短且有含义的类名, 可以规避很大一部分改动的风险。 但也不是全部, 上个月有一天,前端小哥突然心血来潮。把冒泡的类名由 “tweet” 改成了 “bubbling”,改了我两个小时,才让程序又跑起来。 因此,还需要第三点。

3.把选择器写到配置文件里,然后用一个 fileReader 类去读。如

public void sendComment(Page zombiePage, String commentContent){
    zombiePage.sendKeys(topicFileReader.getCommentInput(),commentContent);
    zombiePage.clickElement(topicFileReader.getCommentButton());
    assertTrue("评论没有发送成功", zombiePage.waitElementDisappear(topicFileReader.getEmptyTopicComments()));
}

这个月有一天, 讨论的评论框被改掉了。我只需该两行配置文件,代码就可以跑了。

commentInput = #comment-form textarea
commentButton = #comment-form .clockwise

写选择器还有一个好处就是,代码的可读性,让别人知道选择器的意义。

今天写到这里。这篇水文能看到最后的,,我想,应该是真爱吧。如果有问题和讲得不实的地方欢迎登录 coding 私信我 (ciwang)。 Anyway, 欢迎大家拍砖

ciwang23635

5条评论

学习到了,但是你说的 selenium 在GitHub的地址是什么呢

KonishiLee2 年前回复
非常专业!
匿名5 年前回复
这。。。。因为评论框换了一个组件 ,然后选择器就不一样了,所以 把配置文件里的评论框的选择器改对就行了。。。
匿名5 年前回复
有用js写的测试用例吗?
匿名5 年前回复
为什么不用多说评论框
匿名5 年前回复