开始之前
自动化测试这个话题,相信很多人已经有了些许的了解,虽然叫自动化测试,当然也不是鼠标click一下就出一份报告,需要详尽的逻辑步骤配置,也就是写好脚本代码,模拟浏览器环境和操作,测出可能出现的问题;所以一开始有一个阻碍在这里,一个项目要写好一套测试脚本要花很多功夫,干嘛不让测试人员去手动测试?后面逐渐接触到一些测试场景和测试工具,觉得做这些工作还是很有必要的,理由就不累述了;如标题所述,把casperJS的坑先开好,扶好坐稳;
CasperJS是一个开源的导航脚本处理和测试工具,基于PhantomJS(前端自动化测试工具)编写。CasperJS简化了完整的导航场景的过程定义,提供了用于完成常见任务的实用的高级函数、方法和语法;具体说明/安装/功能可参考官网;
而这里测试主要用的就是CasperJS的测试功能,通过下面的test API和其他功能来完成诸如表单提交/文档检查/数据对比/Dom检查/条件匹配和数据抓取等一系列的测试功能;
具体测试实例就是使用CasperJS API 编写测试脚本,然后在命令行运行 casperjs test your_file.js,就会执行测试,这里casperjs test是固定格式(非测试脚本只要casperjs就行),your_file.js是测试实例,以官网为例(记得科学上网):
casper.test.begin('assertTitle() tests', 1, function(test) { casper.start('https://www.google.com.hk/', function() { test.assertTitle('Google', 'google.fr has the correct title'); //判定google.com.hk页面的title=='Google' }).run(function() { test.done(); }); });
取名google.js,然后运行 casperjs test google.js,然后:
最后一行就是测试结果,然后根据测试结果做相应的项目调整;
好了,下面是具体API:
assert()
语法:assert(Boolean condition[, String message])
判定所提供的条件严格地解析为布尔值true
casper.test.assert(true, "true's true"); casper.test.assert(!false, "truth is out");
assertNot()
语法:casper.test.assertNot(false, “Universe is still operational”);
判定传递的对象解析为一些错误的值
assertDoesntExist()
语法:assertDoesntExist(String selector[, String message])
判定在远程DOM环境中不存在与提供的选择器表达式匹配的元素
casper.test.begin('assertDoesntExist() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven"></div>'); test.assertDoesntExist('.taxes'); }).run(function() { test.done(); }); });
assertExists()
语法:assertExists(String selector[, String message])
判定在远程DOM环境中存在与提供的选择器表达式匹配的元素
casper.test.begin('assertExists() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven">beer</div>'); test.assertExists('.heaven'); }).run(function() { test.done(); }); });
assertEquals()
语法:assertEquals(mixed testValue, mixed expected[, String message])
判定两个值严格相等
casper.test.begin('assertEquals() tests', 3, function(test) { test.assertEquals(1 + 1, 2); test.assertEquals([1, 2, 3], [1, 2, 3]); test.assertEquals({a: 1, b: 2}, {a: 1, b: 2}); test.done(); });
assertEval()
语法:assertEval(Function fn[, String message, Mixed arguments])
判定远程DOM中的代码评估严格地解析为布尔值true
casper.test.begin('assertEval() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven">beer</div>'); test.assertEval(function() { return __utils__.findOne('.heaven').textContent === 'beer'; }); }).run(function() { test.done(); }); });
assertEvalEquals()
语法:assertEvalEquals(Function fn, mixed expected[, String message, Mixed arguments])
判定远程DOM中代码评估的结果严格等于预期值
casper.test.begin('assertEvalEquals() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven">beer</div>'); test.assertEvalEquals(function() { return __utils__.findOne('.heaven').textContent; }, 'beer'); }).run(function() { test.done(); }); });
assertElementCount()
语法:assertElementCount(String selector, Number count[, String message])
判定选择器表达式与给定数量的元素匹配
casper.test.begin('assertElementCount() tests', 3, function(test) { casper.start().then(function() { this.page.content = '<ul><li>1</li><li>2</li><li>3</li></ul>'; test.assertElementCount('ul', 1); test.assertElementCount('li', 3); test.assertElementCount('address', 0); }).run(function() { test.done(); }); });
assertExists()
语法:assertExists(String selector[, String message])
判定在远程DOM环境中存在与提供的选择器表达式匹配的元素
casper.test.begin('assertExists() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven">beer</div>'); test.assertExists('.heaven'); }).run(function() { test.done(); }); });
assertDoesntExist()
语法:assertDoesntExist(String selector[, String message])
判定在远程DOM环境中不存在与提供的选择器表达式匹配的元素
casper.test.begin('assertDoesntExist() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="heaven"></div>'); test.assertDoesntExist('.taxes'); }).run(function() { test.done(); }); });
assertFalsy()
语法:assertFalsy(Mixed subject[, String message])
判定所给的对象是false;
assertTruthy()
语法:assertTruthy(Mixed subject[, String message])
判定所给的对象是true
assertField()
语法:assertField(String|Object input, String expected[, String message, Object options])
判定给的表单域具有提供的输入名称或选择器表达式的值,除了表单,也可以检验select textarea:
casper.test.begin('assertField() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { this.fill('form[name="gs"]', { q: 'plop' }, false); test.assertField('q', 'plop'); }).run(function() { test.done(); }); }); // Path usage with type 'css' casper.test.begin('assertField() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { this.fill('form[name="gs"]', { q: 'plop' }, false); test.assertField({type: 'css', path: '.q.foo'}, 'plop'); }).run(function() { test.done(); }); });
assertFieldName()
语法: assertFieldName(String inputName, String expected[, String message, Object options])
判定给的表单字段具有预设的值
casper.test.begin('assertFieldName() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { this.fill('form[name="gs"]', { q: 'plop' }, false); test.assertFieldName('q', 'plop', 'did not plop', {formSelector: 'plopper'}); }).run(function() { test.done(); }); });
assertFieldCSS()
语法: assertFieldCSS(String cssSelector, String expected, String message)
判定给的表单字段具有预设CSS选择器的提供的值
casper.test.begin('assertFieldCSS() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { this.fill('form[name="gs"]', { q: 'plop' }, false); test.assertFieldCSS('q', 'plop', 'did not plop', 'input.plop'); }).run(function() { test.done(); }); });
assertFieldXPath()
语法:assertFieldXPath(String xpathSelector, String expected, String message)
判定给的表单域具有给定的XPath选择器的值
casper.test.begin('assertFieldXPath() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { this.fill('form[name="gs"]', { q: 'plop' }, false); test.assertFieldXPath('q', 'plop', 'did not plop', '/html/body/form[0]/input[1]'); }).run(function() { test.done(); }); });
assertHttpStatus()
语法:assertHttpStatus(Number status[, String message])
判定当前的HTTP状态代码与作为参数传递的代码相同
casper.test.begin('casperjs.org is up and running', 1, function(test) { casper.start('http://casperjs.org/', function() { test.assertHttpStatus(200); }).run(function() { test.done(); }); });
assertMatch()
语法:assertMatch(mixed subject, RegExp pattern[, String message])
判定所提供的字符串与提供的JavaScript RegExp模式相匹配
casper.test.assertMatch('Chuck Norris', /^chuck/i, 'Chuck Norris\' first name is Chuck');
assertTitle()
语法:assertTitle(String expected[, String message])
判定远程页面的标题等于预期的标题
casper.test.begin('assertTitle() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertTitle('Google', 'google.fr has the correct title'); }).run(function() { test.done(); }); });
assertTitleMatch()
语法:assertTitleMatch(RegExp pattern[, String message])
判定远程页面的标题与提供的RegExp模式匹配
casper.test.begin('assertTitleMatch() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertTitleMatch(/Google/, 'google.fr has a quite predictable title'); }).run(function() { test.done(); }); });
assertType()
语法:assertType(mixed input, String type[, String message])
判定提供的参数值类型是否跟设定的相同
casper.test.begin('assertType() tests', 1, function suite(test) { test.assertType(42, "number", "Okay, 42 is a number"); test.assertType([1, 2, 3], "array", "We can test for arrays too!"); test.done(); });
assertInstanceOf()
语法:assertInstanceOf(mixed input, Function constructor[, String message])
判定提供的参数是给定的构造函数
function Cow() { this.moo = function moo() { return 'moo!'; }; } casper.test.begin('assertInstanceOf() tests', 2, function suite(test) { var daisy = new Cow(); test.assertInstanceOf(daisy, Cow, "Ok, daisy is a cow."); test.assertInstanceOf(["moo", "boo"], Array, "We can test for arrays too!"); test.done(); });
assertUrlMatch()
语法:assertUrlMatch(Regexp pattern[, String message])
判定当前页面的URL与提供的RegExp模式相匹配
casper.test.begin('assertUrlMatch() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertUrlMatch(/^http:\/\//, 'google.fr is served in http://'); }).run(function() { test.done(); }); });
assertVisible()
语法:assertVisible(String selector[, String message])
判定至少一个与提供的选择器表达式匹配的元素是可见的
casper.test.begin('assertVisible() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertVisible('h1'); }).run(function() { test.done(); }); });
assertNotEquals()
语法: assertNotEquals(mixed testValue, mixed expected[, String message])
判定两个值不是严格相等的
casper.test.assertNotEquals(true, "true");
assertRaises()
语法:assertRaises(Function fn, Array args[, String message])
判定使用给定参数调用的函数会引发一个JavaScript错误
casper.test.assertRaises(function(throwIt) { if (throwIt) { throw new Error('thrown'); } }, [true], 'Error has been raised.'); casper.test.assertRaises(function(throwIt) { if (throwIt) { throw new Error('thrown'); } }, [false], 'Error has been raised.'); // fails
assertSelectorDoesntHaveText()
语法:assertSelectorDoesntHaveText(String selector, String text[, String message])
判定所给的文本在所有的元素匹配中都不存在
casper.test.begin('assertSelectorDoesntHaveText() tests', 1, function(test) { casper.start('http://google.com/', function() { test.assertSelectorDoesntHaveText('title', 'Yahoo!'); }).run(function() { test.done(); }); });
assertSelectorHasText()
语法:assertSelectorHasText(String selector, String text[, String message])
判定给定文本存在于与提供的选择器表达式匹配的元素中
casper.test.begin('assertSelectorHasText() tests', 1, function(test) { casper.start('http://google.com/', function() { test.assertSelectorHasText('title', 'Google'); }).run(function() { test.done(); }); });
assertResourceExists()
语法:assertResourceExists(Function testFx[, String message])
对所有加载的资源执行testFx函数,并至少有一个匹配时,测试通过
casper.test.begin('assertResourceExists() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertResourceExists(function(resource) { return resource.url.match('logo3w.png'); }); }).run(function() { test.done(); }); }); //简写: casper.test.begin('assertResourceExists() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertResourceExists('logo3w.png'); }).run(function() { test.done(); }); });
assertTextExists()
语法:assertTextExists(String expected[, String message])
判定body中纯文本内容包含给定的字符串
casper.test.begin('assertTextExists() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertTextExists('google', 'page body contains "google"'); }).run(function() { test.done(); }); });
assertTextDoesntExist()
语法: assertTextDoesntExist(String unexpected[, String message])
判定body中纯文本内容不包含给定的字符串
casper.test.begin('assertTextDoesntExist() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertTextDoesntExist('bing', 'page body does not contain "bing"'); }).run(function() { test.done(); }); });
assertAllVisible()
语法:assertAllVisible(String selector[, String message])
判定所有与提供的选择器表达式匹配的元素都是可见的
casper.test.begin('assertAllVisible() tests', 1, function(test) { casper.start('http://www.google.fr/', function() { test.assertAllVisible('input[type="submit"]'); }).run(function() { test.done(); }); });
assertNotVisible()
语法:assertNotVisible(String selector[, String message])
判定与提供的选择器表达式匹配的元素不可见
casper.test.begin('assertNotVisible() tests', 1, function(test) { casper.start().then(function() { this.setContent('<div class="foo" style="display:none>boo</div>'); test.assertNotVisible('.foo'); }).run(function() { test.done(); }); });
begin()
语法:
begin(String description, Number planned, Function suite)
begin(String description, Function suite)
begin(String description, Number planned, Object config)
begin(String description, Object config)
开始一套<planned>测试(如果已定义)。套件回调将获取当前的Tester实例作为其第一个参数
function Cow() { this.mowed = false; this.moo = function moo() { this.mowed = true; // mootable state: don't do that return 'moo!'; }; } // unit style synchronous test case casper.test.begin('Cow can moo', 2, function suite(test) { var cow = new Cow(); test.assertEquals(cow.moo(), 'moo!'); test.assert(cow.mowed); test.done(); });
一个更异步的例子:
casper.test.begin('Casperjs.org is navigable', 2, function suite(test) { casper.start('http://casperjs.org/', function() { test.assertTitleMatches(/casperjs/i); this.clickLabel('Testing'); }); casper.then(function() { test.assertUrlMatches(/testing\.html$/); }); casper.run(function() { test.done(); }); });
begin()也可接受测试配置对象,可以加上set()和tearDown()方法:
casper.test.begin('Cow can moo', 2, { setUp: function(test) { this.cow = new Cow(); }, tearDown: function(test) { this.cow.destroy(); }, test: function(test) { test.assertEquals(this.cow.moo(), 'moo!'); test.assert(this.cow.mowed); test.done(); } });
done()
语法:done()
标记完结一个以begin()开头处理的测试用例
casper.test.begin('my test suite', 2, function(test) { test.assert(true); test.assertNot(false); test.done(); });
异步用法:
casper.test.begin('Casperjs.org is navigable', 2, function suite(test) { casper.start('http://casperjs.org/', function() { test.assertTitleMatches(/casperjs/i); this.clickLabel('Testing'); }); casper.then(function() { test.assertUrlMatches(/testing\.html$/); }); casper.run(function() { test.done(); }); });
colorize()
语法:colorize(String message, String style)
渲染彩色输出,基本是对Casper.Colorizer方法的替代;
comment()
语法:comment(String message)
在控制台输出一个评论格式的提示信息
casper.test.comment("Hi, I'm a comment");
error()
语法:error(String message)
在控制台输出一个错误格式的提示信息
casper.test.error("Hi, I'm an error");
fail()
语法:fail(String message [, Object option])
将失败的测试条目添加到堆栈
casper.test.fail("Georges W. Bush"); casper.test.fail("Here goes a really long and expressive message", {name:'shortfacts'});
pass()
语法:pass(String message)
将成功的测试条目添加到堆栈
casper.test.pass("Barrack Obama");
formatMessage()
语法:formatMessage(String message, String style)
格式化一个消息,高亮某些部分。仅由测试仪内部使用
getFailures()
语法:getFailures()
检索当前测试用例的故障(1.1版本后已弃用)
casper.test.assertEquals(true, false); require('utils').dump(casper.test.getFailures()); casper.test.done();
会给出以下提示:
$ casperjs test test-getFailures.js Test file: test-getFailures.js FAIL Subject equals the expected value # type: assertEquals # subject: true # expected: false { "length": 1, "cases": [ { "success": false, "type": "assertEquals", "standard": "Subject equals the expected value", "file": "test-getFailures.js", "values": { "subject": true, "expected": false } } ] } FAIL 1 tests executed, 0 passed, 1 failed. Details for the 1 failed test: In c.js:0 assertEquals: Subject equals the expected value
var failures = []; casper.test.on("fail", function(failure) { failures.push(failure); });
getPasses()
语法:getPasses()
在当前测试套件中检索成功测试用例的报告(1.1版本后已弃用)
casper.test.assertEquals(true, true); require('utils').dump(casper.test.getPasses()); casper.test.done();
1.1版本可以这样使用:
var successes = []; casper.test.on("success", function(success) { successes.push(success); });
info()
语法:info(String message)
在控制台输出一个信息格式的提示
casper.test.info("Hi, I'm an informative message.");
renderResults()
语法:renderResults(Boolean exit, Number status, String save)
渲染测试结果,将结果保存在XUnit格式的文件中,并可选择退出phantomjs
casper.test.renderResults(true, 0, 'test-results.xml')
setUp()
语法:setUp([Function fn])
在每次使用begin()定义的测试之前执行的函数
casper.test.setUp(function() { casper.start().userAgent('Mosaic 0.1'); });
要执行异步操作,要使用done参数:
casper.test.setUp(function(done) { casper.start('http://foo').then(function() { // ... }).run(done); });
skip()
语法:skip(Number nb, String message)
跳过一定数量的计划测试
casper.test.begin('Skip tests', 4, function(test) { test.assert(true, 'First test executed'); test.assert(true, 'Second test executed'); test.skip(2, 'Two tests skipped'); test.done(); });
tearDown()
语法:tearDown([Function fn])
定义一个函数,将在使用begin()的每个测试后执行
casper.test.tearDown(function() { casper.echo('See ya'); });
要执行异步操作,请使用done参数:
casper.test.tearDown(function(done) { casper.start('http://foo/goodbye').then(function() { // ... }).run(done); });
以上是CasperJS中的tester module部分,实际操作还要配合其他的module API如getCurrentUrl()等等;
PS:如有纰漏,请联系我;
Reference:
http://docs.casperjs.org/en/latest/modules/tester.html