PhantomJS是什么?
PhantomJS 是一个无界面的,包含了WebKit浏览器引擎和JavaScript API的脚本解释器. 速度快并且支持各种web标准: DOM 操作, CSS 选择器, JSON, Canvas 和SVG.
PhantomJS 的创建者是 Ariya Hidayat. 它是一个非常棒的技术,但是通过网站上的了解和所有的APIs文档, 我遇到了 CasperJS.
CasperJS是什么?
Casper 是一个用JavaScript编写的基于PhantomJS的导航脚本和测试工具.它充许我们像PHPUnit或 JUnit一样测试我们的网站,测试我们的代码.
它是一个非常棒的工具 – 一是它是非常简单的,用JavaScript编写,满足各种各样的测试需求,一是它可以方便的和我们的开发环境集成. 完美的组合前端和后端.
在本篇文章中,我将浏览一下CasperJS的基础用法。我将扮演一个典型的用户访问New Relic(新的遗址)网站的一页,特别是‘真实用户监控’部分。
我之所以选择这一页是因为它有大量方面对一个标准网站或应用极为常见,如图像,表单,按钮,链接和文本。它内容丰富并且有许多东西可供我们处理与测试。现在,我确信New Relic的勤快的伙计已经做过这些,但我也非常相信他们不会介意我为这个网站建立一个简单的测试集和断言。
特征CasperJS具有一系列特征。 本文中,我会聚焦于 测试人员 API。它具有一些列功能与断言,都是你期望一个好的测试API所具有的,包括:
* assertTextExists (文本存在断言)
* assertTitle (标题断言)
* assertHttpStatus (HTTP状态断言)
* assertDoesntExist (不存在断言)
* assertUrlMatch (Url匹配断言)
如果你点击了这个表单里的任何元素,它其余的部分就会显露出来,看起来就是下图这样。
测试将着眼于表单,但我们也要看看title标签,表单左边的图片,及其上的文字。
代码:
首先,为节省时间,我初始化了两个变量:一个用来存储URL,一个用来存储网站名称,因为我要在测试中的‘success’信息里显示它们。
var url = 'http://newrelic.com/product/real-user-monitoring'; var siteName = 'NewRelic';
Casper带有4个内建记录级别:
* debug
* info
* warning
* error
var casper = require('casper').create({ verbose: false, logLevel: 'debug' });
你可以在Casper API页面上发现其它配置选项。comment函数,如下面演示的,使我们能记录输出——在这种情况下是输出到控制台。我在这里使用一个简单的消息说明测试开始了:
casper.test.comment('Starting Testing');
函数‘casper.start’开始运行测试:
casper.start(url, function() { this.test.assert( this.getCurrentUrl() === url, 'url is the one expected' ); this.test.assertHttpStatus(200, siteName + ' is up');
这是我所做的:我加载在‘url’中指定的URL,并假定我们可以载入想要的网址。在成功加载页面之后,开始调用一些断言来确认所载入的页面上的内容是我们所期望的。
在这种情况下,我对返回的状态码进行了一个快速检查,它应该是200,我得到的也是200。让我们进行另一个断言:
this.test.assertTitle( 'Real User Monitoring, End User Experience Monitoring : New Relic', siteName + ' has the correct title' );
上面这个测试非常简单。它断言载入的页面的标题应该是什么,并输出一个含有该信息的消息。
在下面的代码里,我首先检查确认存在一个ID为‘nr-signup-form’的表单。如果这个表单不存在,那对表单内的元素进行检查就没有意义了,对吧?
this.test.assertExists( 'form[id="nr-signup-form"]', siteName + ' has a form with name "nr-signup-form"' );
现在,在我继续之前,我要提到的是,当我断言元素存在或不存在于加载的页面上时,我可以用两种不同的方法:
如果你想要更多XPath的信息,请检阅后面‘延伸阅读’部分中的一些相关链接,或阅读 我写并发到maltblue的文章。CSS选择器应该有很好的自我解释性。但为以防万一,我在“延伸阅读”部分中同样包含了关于它的链接。
现在让我们用断言来搜索输入域控件:
this.test.assertExists( {type: 'xpath', path: '//input[@id="FullName"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//input[@id="Company"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//input[@id="Email"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//input[@id="Password"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//input[@id="PromoCode"]' }, 'the element exists' );
在上面的五个断言中,我查找了五个输入域控件,它们的ID分别是‘FullName’, ‘Company’, ‘Email’, ‘Password’ 和‘PromoCode’。用XPath查找选择列表控件元素同样容易。
在下面的测试中,我假定有四个选择列表控件,它们的ID分别是:‘country’, ‘group’, ‘company_size’ 和‘HostEstimate’。
this.test.assertExists( {type: 'xpath', path: '//select[@id="country"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//select[@id="group"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//select[@id="company_size"]' }, 'the element exists' ); this.test.assertExists( {type: 'xpath', path: '//select[@id="HostEstimate"]' }, 'the element exists' );
现在,这些测试还非常简单。那么,让我们来把它们变得复杂点。
this.test.assertExists( { type: 'xpath', path: '//button[@id="sign-up-button" and @class="small-button" and @type="submit"]' }, 'the element exists' );
我在查询中使用了一些条件运算符。我们要寻找一个具有下列条件的按钮:
* ID 为 ‘sign-up-button’
* class 为‘small-button’
* type 为‘submit’
虽然看起来似乎我关注XPath比CasperJS更多,但为了更多的功能和配置,请耐心忍受我多说一点吧。
var x = require('casper').selectXPath; var checkboxXpath = "//input[@type='checkbox' and @id='checkbox1']/parent::*/a/label[ contains(., 'Java') or contains(., 'Python') or contains(., 'Ruby') or contains(., 'PHP') or contains(., '.NET') or contains(., 'Node.js') ]"; this.test.assertExists(x(checkboxXpath), 'the element exists');
我在上面的测试中所做的,是通过把'x'初始化为‘selectXPath’助手来使XPath测试变得简化一点。我要查找那一页上所有选择应用程序类型的复选框,所以XPath查询查找复选框时用一个伴随的label标签来匹配所提供的应用程序语言的名称。
为专门显示我并非只会使用XPath(虽然它极其强大而且简单),下面的两个测试也使用CSS选择器来检查一个输入域控件和列表项目也存在。
this.test.assertVisible('input#Company'); this.test.assertExists('li.nav-enterprise', 'the element exists');
搜索表单元素和列表项目很简单,但若你的页面有很多资源,对于图片或Flash的载入又怎么检测呢?这有一个例子:
this.test.assertResourceExists( '/images/tshirt-dude-form.png', 'T-shirt Image exists' );
对于上面的测试,我断言穿着所展示T恤的男人的照片已载入。 最后一个测试断言某些文本存在,在本情况中就是在穿着T恤的男人镜头上方的‘Sign up for free!’文本:
this.test.assertTextExists( 'Sign up for free!', 'page body contains "Sign up for free!"' ); });
然后我们这样结束‘start’函数:
casper.test.comment('Ending Testing');
测试基本完成了,所以我输出另一个日志记录来让用户知道这一点:
casper.run(function() { this.test.done(16); this.echo('So the whole suite ended.'); require('utils').dump(casper.test.getFailures()); require('utils').dump(casper.test.getPasses()); this.exit(); });
我可以写出我想要的所有测试,但若不调用“run”则什么都不会发生。所以“run”是揭开上述工作的序幕。我所做的是检查脚本是否已经运行了16个测试,并且在最后用‘this.echo()’输出最后一行文字表示整个测试已结束。
评论删除后,数据将无法恢复
评论(9)
引用来自“daxiaoming”的评论
看来翻译的大牛都隐身了啊,机器翻译大行其道。