CasperJS 开源的导航脚本处理和测试工具 - 文章教程

CasperJS 开源的导航脚本处理和测试工具

发布于 2019-12-12 字数 7181 浏览 1131 评论 0

CasperJS 是一个开源的导航脚本和测试工具,使用 JavaScript 基于 PhantomJS 编写,用于测试 Web 应用功能,Phantom JS是一个服务器端的 JavaScript API 的 WebKit。其支持各种Web标准: DOM 处理、CSS 选择器、JSON、Canvas 和SVG。

CasperJS 开源的导航脚本处理和测试工具

开发背景

一段时间之前,我发表过一篇关于 PhantomJS 的文章,PhantomJS 是一个无界面的,包含了 WebKit 浏览器引擎和 JavaScript API 的脚本解释器,于此同时,我开始编写一个用来简化 PhantomJS 脚本编写尤其是导航操作脚本的轻量级库。

六个月过去了,这个库有了更多的功能,现在已经是一个独立的项目了,CasperJS 就这样诞生了,目前在 GitHub上,该代码库已经有超过180个关注者和32个分支。

Ariya Hidayat — PhantomJS 的作者 — 甚至说:

如果你还不知道 CasperJS 快去看一看吧,它是一个非常有用的 PhantomJS 伴侣

特点

CasperJS 是一个开源的,用 JavaScript 编写的,基于 PhantomJS 的导航脚本和测试工具,它简化了定义一个完成的导航操作所需的步骤,还提供了很有用的函数封装、方法和语法糖,它可以完成下面这些常见任务:

  • 定义 & 排序浏览器导航步骤
  • 填充 & 提交表单
  • 点击 & 跟踪链接
  • 捕获网页截图 (还可以截取某一区域)
  • 在远程DOM上进行断言测试
  • 记录事件
  • 下载资源,包括二进制文件
  • 编写功能测试套件,结果保存为JUnit XML文件
  • 抓取网页内容

进行导航操作

如果你在 PhantomJS 脚本中使用链式回调来进行导航操作,那是相当痛苦的。这种代码无论写起来,读起来,理解起来还是维护起来,都是噩梦:

var page = require('webpage').create();             //新建一个页面page.open(url1, function(status) {                  //导航到第一个URL
    if (status == "fail") phantom.exit();           //如果发生错误,退出程序
    page.open(url2, function(status) {              //否则在页面加载完成的回调函数中继续导航到第二个URL,依次类推
        if (status == "fail") phantom.exit();
        page.open(url3, function(status) {
            if (status == "fail") phantom.exit();
            page.open(url4, function(status) {
                if (status == "fail") phantom.exit();
                // 我可以停下来了吗?
            });
        });
    });
});

CasperJS 使用更方便的 API 解决了这种异步操作的问题:

var casper = require('casper').create();           //新建一个页面
casper.start(url1);                                //添加第一个URL
casper.thenOpen(url2);                             //添加第二个URL,依次类推
casper.thenOpen(url3);
casper.thenOpen(url4);
casper.run();                                      //开始导航

想要模拟用户通过点击链接来进行导航操作吗?没问题:

var casper = require("casper").create()
//新建一个页面
casper.start('http://my.blog.tld/');
//添加第一个URL
casper.thenClick('nav#menu a.blog');
//在页面加载完成后,点击选择器指定的链接,进入一个新页面
casper.thenClick('.posts li a');
//在新页面加载完成后,再次点击一个选择器指定的链接
casper.then(function() {
    //在第二个新页面加载完成后,输出一些信息到控制台中
    this.echo('Page url is ' + this.getCurrentUrl());
    this.echo('Page title is ' + this.getTitle());
});

casper.run();
//开始导航

你还可以使用 coffeescript 来编写如上功能的脚本:

var casper = require("casper").create()
casper.start "http://my.blog.tld/"
casper.thenClick "nav#menu a.blog"
casper.thenClick ".posts li a"
casper.then ->
    @echo "Page url is #{@getCurrentUrl()}"
    @echo "Page title is #{@getTitle()}"
casper.run()

填充和处理表单

填充和提交表单也并不难:

casper.start('http://admin.domain.tld/login/', function() {
    //打开页面,并指定一个回调函数
    this.fill('form[id="login-form"]', {
    //定位到一个form中
        'username': 'chuck',
        //给name为username的表单控件填充值'chuck'
        'password': 'n0rr1s'
        //给name为password的表单控件填充值'n0rr1s'
    }, true);
    //参数true,表示填充完毕后,立刻提交表单
});

casper.then(function() {
    this.echo(this.getTitle());
    //新页面加载完成后,在控制台输出页面标题
});

casper.run();
//开始导航

页面截图

给页面上指定的区域截图非常简单:

casper.start('http://domain.tld/page.html', function() {
    this.captureSelector('capture.png', '.article-content');
    //给页面中'.article-content'选择器匹配的元素截图
    //输出图片文件名为cpature.png,目录为当前目录
});

casper.run();

异步渲染页面

有时(好吧,其实是经常),很多页面内容是通过Ajax或者其他的手段异步加载的.你可以等到某个元素出现时再执行想要的操作:

casper.start('https://twitter.com/casperjs_org', function() {
    this.waitForSelector('.tweet-row', function() {
    //等到'.tweet-row'选择器匹配的元素出现时再执行回调函数
        this.captureSelector('twitter.png', 'html');
        //成功时调用的函数,给整个页面截图
    }, function() {
        this.die('Timeout reached. Fail whale?').exit();
        //失败时调用的函数,输出一个消息,并退出
    }, 2000);
    //超时时间,两秒钟后指定的选择器还没出现,就算失败 
});

测试

除了上面讲的这些功能之外,CasperJS真正的威力是它提供了功能测试的能力.例如,测试谷歌的搜索操作可以这样完成:

casper.start('http://www.google.fr/', function() {
    //打开谷歌主页,添加页面加载完成时的回调函数
    this.test.assertTitle('Google', 'google homepage title is the one expected');
    //检测页面标题是否是'Google',如果是,输出第二个参数指定的字符串
    this.test.assertExists('form[action="/search"]', 'main form is found');
    //检测页面中是否存在选择器指定的元素,如果存在输出第二个参数指定的字符串
    this.fill('form[action="/search"]', {
        //填充表单并提交,执行搜索操作
        q: 'foo'
    }, true);
});

casper.then(function() {
    this.test.assertTitle('foo - Recherche Google', 'google title is ok');
    //检测搜索结果页的页面标题是否正确    
    this.test.assertUrlMatch(/q=foo/, 'search term has been submitted');
    //检测搜索结果页的网址是否匹配指定的正则表达式
    this.test.assertEval(function() {
        return __utils__.findAll('h3.r').length >= 10;
        //自定义一个检测函数
    }, 'google search for "foo" retrieves 10 or more results');
});

casper.run(function() {
    this.test.renderResults(true);
    //输出检测结果
});

输出结果还能导出为 XUnit XML 文件,可以用在持续集成服务器中,比如 Jenkins,对于记录来说,整个 CasperJS 测试套件使用自己的 API 写成,结果在 visible on Travis-CI

相关链接

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

2583 文章
29 评论
84935 人气
更多

推荐作者

猫性小仙女

文章 1 评论 0

qq_VO6LhT

文章 0 评论 0

猿舌电影

文章 0 评论 0

7556275422

文章 0 评论 0

YYQ_139

文章 0 评论 0