通常来讲对一个网站作测试,最直接的方法就是用手点,眼睛看。用手点和眼睛看把网站的功能点都过一遍,好比在百度首页的搜索框里输入 “coding”,点击“百度一下”,用眼睛看会不会弹出有关 “coding” 的搜索页面。不过,你点了2天以后就会发现,这些点击和“眼睛确认”是一个机械式重复的过程。css
当你遇到重复操做的事情,你就要想一想如何让机器去作这些事。用人脑去从事这种低等人工智能的活动绝对是种浪费。前端
设想下,若是有段程序,自动把你打开浏览器,而后跳转到百度首页。再输入框里填充 “coding”,点击搜索,套转到搜索结果页面以后,自动确认这个页面上是否有 “coding” 的字样。如有,输出“测试经过”。若无,输出“测试失败”。你只须要点开程序,而后去吃个晚饭,而后回来看测试结果就行了(我就是这么干的),一切都如此简单和美妙。python
那么,须要什么工具来实现这个美妙的过程呢?首先你须要一双“手”来点击和一对“眼”来获取信息 —— Selenium。 还须要一个脑子来操纵“手和眼”判断测试对错 —— Junit。 其实,Selenium 支持多种语言,好比说,ruby, python, Js, C#。他们都有相应成熟的测试框架,因为我用的是用 Java,相应的测试框架就用了 Junit 。这点已被前端小哥和 Ruby 大神吐槽致死。前端小哥说,既然你要测页面为何不用 JS 呢?由于前端就是用 JS 写的,同源的语言会更好。 Ruby 大神说,用 Ruby 你会少写不少行代码。 其实,我那时就对 Java 熟悉一点,最后用 Java 写了。 这里,虽然本人没有亲自尝试过,但我仍是想推荐下用 JS。 如今的网站,页面上会有着大量的 ajax 请求,页面的测试必须等待某些页面元素的更新。在这方面 JS 会比 Java 方便点。ajax
selenium 是一个操纵浏览器来进行测试的框架。分为 Selenium 1 ( RC ), Selenium 2 ( WebDriver ), 江湖传言今年圣诞节会发布 selenium 3,主要是加强对移动端浏览器的测试。还有就是 Selenium IDE 和 Selenium Grid。 这里不介绍,能够看文档.浏览器
Selenium 1 ( RC ), Selenium 2 ( WebDriver ) 的区别就是对浏览器操纵的方式。 RC 的原理就是经过对原始的页面元素中注入一段特定的 JS 代码来实现的。 学过 JS 的人都知道, JS 能够操控 DOM 元素,点击,删除,获取元素属性和文本。你能够把这些操做当作一个个 JS 函数。 只是浏览器对非同源的 JS 有限制, 举个简单的例子, 百度首页上的 JS 代码不能与淘宝首页进行交互 (不能访问它的 cookie 等)。 所以,就须要RC(Remote Control), 将特定的 JS 代码加到服务器放回的数据中,再发送给浏览器,这样就避开了同源的问题。 而后浏览器运行这些 JS 函数,进行测试。ruby
WebDriver 用的方式更为直接,它自己就是浏览器的 API,因此是直接对浏览器进行操做。无需经过 JS 代理操做。
我的建议用 WebDriver。 由于,据“路边社”可靠消息 selenium 3 会逐步抛弃 RC。服务器
这4个多月了,一直在用 selenium 写自动化测试,由小白到如今稍微熟悉。填了很多坑。 也算是有些心得,接下来若是有时间,我会在 coding 开个 selenium-study 的公有项目来具体讲解一些实战心得。 关于selenium的学习, 最好的教材是 selenium 官方文档。 若是你的英文不太好,那么百度一下“虫师 博客园”,里面有不少不错的学习材料。 要是开发中遇到 bug 最好用英文在 google 里搜。 至于百度搜出来的那坨*,诶,,往事不堪回首。cookie
上文提到的自动化测试属于功能测试范畴。所谓功能测试,简单的说测试网站的功能点是否正常,好比可否注册和登陆,可否在 coding 发冒泡,push 代码等等。这是面向用户的最终测试。app
既然是功能测试,天然是围绕功能来进行用例设计。用例大体分为两个部分, 操做和表现。就“登陆 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());
若是想要对元素进行操做,必须先定位到那个元素。 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, 欢迎你们拍砖
Coding 官方技术博客: http://blog.coding.net/
Coding 官网 : https://coding.net