基于 fis 的前端自动化单元测试方案

jopen 9年前

在上一片文章中,我介绍了如何在 fis 项目中使用 jasmine 进项单元测试,这个方案,可以解决 fis 中模块的引用的问题, 整个单元测试可以 run 起来,但是,还是有很多不足:

  1. 人工成本较高,需要手动配置 runner 页面,并在浏览器中查看结果。
  2. 难以统计单元测试的覆盖率。
  3. 无法生成测试报告。
  4. 无法部署到 ci 系统中。

为了解决以上问题,故采用了全新方案,实现全自动单测。新方案主要包含以下改进:

  1. 采用 karmar 代替手动配置的 runner 页面,测试 case 在 PhantomJS 跑。
  2. 采用 karmar-coverage 统计单测覆盖率,并生成 统计结果页面。
  3. 采用 karma-junit-report 生成测试报告。

karma.conf.js

我们知道,如果要引入 karma, 就需要通过 karma.conf.js 来配置相关的被测模块和 case,fis 的代码在编译前和编译后,会产生不同的 url,如何准确定位到单测的 case 和被测模块文件呢?

值得庆幸的是,fis 的编译会产出 map.json,所有资源的依赖关系都会记录在其中。我们可以把所有的 js 文件和 map.json 都添加到 karma server 且不自动加载,然后通过 require.async 的方式异步加载所需资源。

module.exports = function (config) {      config.set({          ……          frameworks: ['jasmine'],          reporters: ['progress', 'coverage', 'junit'],          browsers: ['PhantomJS'],            preprocessors: {              '**/*.js': 'coverage';          },            coverageReporter: {              type: 'html',              dir: './coverage/'          },            junitReporter: {              outputDir: './report/',              outputFile: 'report.xml'          },            files: [              // 优先加载mod.js              '**/*/common/mod*.js',                // 当前模块相关文件添加到Karma server上,设置included为false,不自动加载,通过modjs控制              {pattern: '**/*.js', included: false},                // 将map.json添加到 Karma server,后续读取文件内容,用以确定资源依赖关系              {pattern: 'config/**/*-map.json', included: false},                // 加载测试入口文件              './test/' + project + '/' + namespace + '/test-main.js'          ],          ……       });  };

test-main.js

测试入口文件,这里会读取 map.json,重写资源表中资源的路径为 karma server 上的真实地址,同时重写了 karma. start 方法,异步调用找出的 case 文件 (spec.js 结尾的文件 )。

(function () {        var tests = [];        if (window.XMLHttpRequest) // Firefox, Opera 8.0+, Safari,chrome,phantomjs          xhr = new XMLHttpRequest();      else // IE          xhr = new ActiveXObject("Microsoft.XMLHTTP");        // 遍历在karma.conf.js的files中配置的相关文件,这些文件已经在karma server上      for (var _file in window.__karma__.files) {            // 找到本模块和被依赖模块的map.json文件          if (window.__karma__.files.hasOwnProperty(_file) &&              _file.indexOf('map.json') > -1) {              xhr.open('get', _file, false);              xhr.send();                // 读取map.json文件内容,定义为resourceMap              var resourceMap = JSON.parse(xhr.responseText);                for (var file in resourceMap.res) {                    // 找出本模块所有单测文件                  if (/\.spec\.js$/.test(file)) {                      console.log('add spec: ' + file);                      tests.push(file);                  }                  // 从karma server上保存的文件路径中,获取到resourceMap中所需文件的真实url                  for (var _file in window.__karma__.files) {                      if (window.__karma__.files.hasOwnProperty(_file) &&                          _file.indexOf(resourceMap.res[file]['uri']) > -1) {                          resourceMap.res[file]['url'] = _file;                      }                  }              }                // 调用mod.js提供的require.resourceMap接口,将resourceMap打出来,以此确定资源的依赖关系和url              require.resourceMap(resourceMap);          }      }        // 由于使用自定义资源加载控制,因此需要重写触发 karma的方法      // 使用 jasmine 只需要在资源加载完毕之后触发 start 方法即可      // 主动加载测试文件,后续mod.js根据resourceMap自动加载测试文件所需的被测文件以及被依赖的文件      var _fn = window.__karma__.start;      window.__karma__.start = function () {          require.async(tests, function () {              _fn.call();          });      }    })();

fis-conf.js

添加单测相关的输出配置:

fis.config.set('roadmap.path', [{      reg: /^\/test\/(.*\.spec\.js)$/i,      isMod: true,      useHash: false,      release: '/test/middlepage/yunying/${namespace}/$1'  }, {      reg: /^\/test\/(.*)/i,      isMod: false,      useHash: false,      release: '/test/middlepage/yunying/${namespace}/$1'  }, {      reg: 'karma.conf.js',      useHash: false,      release: '/test/middlepage/yunying/${namespace}/$&'  }].concat(fis.config.get('roadmap.path', [])));

目录结构

整个 fis 项目的目录类似如下:

编译前

基于 fis 的前端自动化单元测试方案

编译后

基于 fis 的前端自动化单元测试方案

运行测试

首先编译指定 fis 模块

fis release -r common -d output   fis release module1 -d output 

进入产出目录,执行 karma start

cd output  karma start test/module1/karma.conf.js

命令行可看到如下测试结果:

基于 fis 的前端自动化单元测试方案

覆盖率和统计报告

分别位于 output 目录的 coverage 和 report 子目录中(如 karma.conf.js 配置)。

部署CI

以 jenkins 为例:

  1. 在execute shell中填写脚本:

    cd /home/work/repos/fis2-karma

    rm -rf ./output

    fis release -r common -d ./output -mp

    cd ./output

    karma start test/common/karma.conf.js

    </li>
  2. 设置 覆盖率报告位置

  3. </ol>

    基于 fis 的前端自动化单元测试方案

    1. 设置测试结果报告位置

    基于 fis 的前端自动化单元测试方案

    至此,整个 fis 单测方案部署完毕。

    </div>

    来自: http://annn.me/fis-unittest/