Learn To FE AutoTest

前言

前端自动测试在强调快速完成速度的环境常常不能获得足够支持,以至大家在这个领域实践较少.但随着业务环境的变化和技术的发展,这种情况会发生变化. 以下是我又一次实践前端自动测试的总结,希望能对大家进行尝试时有所帮助.

TDD/BDD

受BDD的影响,出现了越来越接近自然语言的断言库 ,我们可以称他们BDD风格的断言库。虽然是BDD风格,但不妨碍我们用这样的断言库写TDD流程的测试.

前端测试框架的分类和选型参考

基于浏览器的框架

在浏览器里把测试框架和其他JavaScript脚本一并引入。测试结果直接显示在浏览器里。 这种方式比较直观,但不易于接入更为完整的工作流内。jasmine是当前这种类型测试框架里不错的选择.

基于Node环境的框架

在Node环境运行,并以Node模块的方式加载测试用例,测试结果在终端显示. 如果是Node项目或者以Node模块组织代码的前端项目( 通过 browserify 提供给浏览器使用),这种类型的测试框架能最好的为你服务. 该类别中 Mocha 目前较为流行.

基于Server / Client 结构的测试框架

这种方式通过让浏览器接入一个Server,再由这个Server向接入的浏览器下发测试用例,让其同时兼备上面提到的两种类型的特点 (代码运行于浏览器,同时在终端获取测试结果)。这种方式在需要测试不同浏览器的JavaScript执行环境的情景特别适合,但部署比较麻烦。 Google系较旧的jsTestDriver 和伴随Angularjs发展起来的 Karma和支付宝的totorojs 都是以这种思路实现的.

我自己先后学习过jsTestDriver , jasmine 和 mocha.

如果一个项目能从底层就开始以TDD思想作为指导编写测试,根据场景特点,以上提到的框架都是不错的选择。但如果是想通过编写测试对一个已成型项目进行质量保障,我们就要借鉴BDD思想做出新的选择。

基于浏览器行为的测试框架

除了以TDD的思路从每一个模块,每一个函数这样从内及外的去测试我们的代码。我们也能从外到内的去测试我们的项目, 比如给定时间内你的页面是否如预期的渲染出来 ; 比如点击特定元素时,浏览器是否切换到了预期的URL ; 比如加载一份特定mock数据时,页面上是否渲染出了预期的内容.

这时我们就可以利用基于浏览器行为的框架来对项目进行测试.

selenium是一套控制浏览器的强大工具, 我们可以利用它来进行浏览器行为测试。但selenium的设计意图是一套提供给专业测试人员的可视化IDE , 而不仅仅是能方便集成于开发工作流的测试框架,所以用起来会有一些不便。

幸好有更好的选择 , PhantomJSCasperJS

PhantomJS是剥离了显示部分的Webkit(headless webkit ), 和其他基于WebKit的浏览器不同, PhantomJS没有提供哪怕最简单的UI界面,但提供了一套控制WebKit的 API . 我们可以利用它的API加载任意URL,然后像在Chrome控制台中一样对页面进行探知或执行代码获取结果.

CasperJS是在PhantomJS之上的抽象层,它包裹了PhantomJS的底层方法,以更高级,更方便开发者使用的API暴露出来. 通过CasperJS我们可以更直观的编写浏览器控制代码,触发事件,探测页面DOM结构。

好上加好的是, 我们还能结合CasperJS 和 Mocha 。利用mocha-casperjs 我们可以用Mocha作为框架,定义我们项目在特定行为发生时应该具备的表现. 然后在用例里以CasperJS来重现特定行为,并判断表现是否符合预期。

例如以下这个例子

 it('Test Demo From H5 Detail', function() {
      casper.start(TEST_TARGET_URL);    //打开特定URL
      return casper.waitFor(function() {  //直到传入函数返回True
        return this.exists('#J_detail_main');
      }, function() {
        var itemTitle;
        itemTitle = this.fetchText('.dtif-h');
        return expect(itemTitle).to.be.a('string');
      }, function() {
        return this.echo('页面未能加载出商品信息', 'ERROR');
      }, 1000); // 1s 超时阈值
    });

这是一个mocha测试用例,其中测试了在访问TEST_TARGET_URL时,页面在1秒之内是否已经渲染出了”#J_detail_main”元素,同时”.dtif-h”元素是否存在并包含文本内容。

另一个例子

it('Another Test Demo From H5 Detail', function() {
      casper.start(TEST_TARGET_URL);
    return casper.waitFor(function() {  
        return this.exists('#J_detail_main');
      }, function() {      
        this.mouseEvent('click', '.dt-sku'); //模拟点击
        return casper.wait(700, function() {
          var targetClass;
          expect(this.visible('.dt-sku')).to.be["false"];
          expect(this.visible('#J_detail_skum')).to.be["true"];
          targetClass = this.getElementAttribute('.dgsc-pc i:nth-child(1)', 'class');
          expect(targetClass).to.eql('sel');
        });
 });

这个例子中,我们测试了点击页面元素”.dt-sku”后,页面在700毫秒内是否已经符合我们一系列的判断。

得益于Mocha在Node环境中非常好的可集成性, 我们可以把Mocha和现有的 Grunt / Gulp 构建流程整合在一起,在每一次构建,准备发布时为我们的项目增加一重或许能避免重大事故的保障。