聊一聊前端自动化测试

发表于:2017-8-09 10:30

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:lingyucoder    来源:博客

  React组件测试
  去年React旋风一般席卷全球,当然天猫也在技术上紧跟时代脚步。天猫商家端业务已经全面切入React,形成了React组件体系,几乎所有新业务都采用React开发,而老业务也在不断向React迁移。React大红大紫,这里单独拉出来讲一讲React+webpack的打包方案如何进行测试
  这里只聊React Web,不聊React Native
  事实上天猫目前并未采用webpack打包,而是Gulp+Babel编译React CommonJS代码成AMD模块使用,这是为了能够在新老业务使用上更加灵活,当然也有部分业务采用webpack打包并上线
  叕一个煎蛋的栗子
  这里创建一个React组件,目录结构大致这样(这里略过CSS相关部分,只要跑通了,集成CSS像PostCSS、Less都没啥问题):
  .
  ├── demo
  ├── karma.conf.js
  ├── package.json
  ├── src
  │   └── index.jsx
  ├── test
  │   └── index_spec.jsx
  ├── webpack.dev.js
  └── webpack.pub.js
  React组件源码src/index.jsx大概是这个样子:
  import React from 'react';
  class Welcome extends React.Component {
    constructor() {
      super();
    }
    render() {
      return <div>{this.props.content}</div>;
    }
  }
  Welcome.displayName = 'Welcome';
  Welcome.propTypes = {
    /**
     * content of element
     */
    content: React.PropTypes.string
  };
  Welcome.defaultProps = {
    content: 'Hello Tmall'
  };
  module.exports = Welcome;
  那么对应的test/index_spec.jsx则大概是这个样子:
  import 'should';
  import Welcome from '../src/index.jsx';
  import ReactDOM from 'react-dom';
  import React from 'react';
  import TestUtils from 'react-addons-test-utils';
  describe('test', function() {
    const container = document.createElement('div');
    document.body.appendChild(container);
    afterEach(() => {
      ReactDOM.unmountComponentAtNode(container);
    });
    it('Hello Tmall', function() {
      let cp = ReactDOM.render(<Welcome/>, container);
      let welcome = TestUtils.findRenderedComponentWithType(cp, Welcome);
      ReactDOM.findDOMNode(welcome).textContent.should.be.eql('Hello Tmall');
    });
  });
  由于是测试React,自然要使用React的TestUtils,这个工具库提供了不少方便查找节点和组件的方法,最重要的是它提供了模拟事件的API,这可以说是UI测试最重要的一个功能。更多关于TestUtils的使用请参考React官网,这里就不扯了...
  代码有了,测试用例也有了,接下就差跑起来了。karma.conf.js肯定就和上面不一样了,首先它要多一个插件karma-webpack,因为我们的React组件是需要webpack打包的,不打包的代码压根就没法运行。另外还需要注意代码覆盖率测试也出现了变化。因为现在多了一层Babel编译,Babel编译ES6、ES7源码生成ES5代码后会产生很多polyfill代码,因此如果对build完成之后的代码做覆盖率测试会包含这些polyfill代码,这样测出来的覆盖率显然是不可靠的,这个问题可以通过isparta-loader来解决。React组件的karma.conf.js大概是这个样子:
  'use strict';
  const path = require('path');
  module.exports = function(config) {
    config.set({
      frameworks: ['mocha'],
      files: [
        './node_modules/phantomjs-polyfill/bind-polyfill.js',
        'test/**/*_spec.jsx'
      ],
      plugins: ['karma-webpack', 'karma-mocha',, 'karma-chrome-launcher', 'karma-firefox-launcher', 'karma-phantomjs-launcher', 'karma-coverage', 'karma-spec-reporter'],
      browsers: ['PhantomJS', 'Firefox', 'Chrome'],
      preprocessors: {
        'test/**/*_spec.jsx': ['webpack']
      },
      reporters: ['spec', 'coverage'],
      coverageReporter: {
        dir: 'coverage',
        reporters: [{
          type: 'json',
          subdir: '.',
          file: 'coverage.json',
        }, {
          type: 'lcov',
          subdir: '.'
        }, {
          type: 'text-summary'
        }]
      },
      webpack: {
        module: {
          loaders: [{
            test: /\.jsx?/,
            loaders: ['babel']
          }],
          preLoaders: [{
            test: /\.jsx?$/,
            include: [path.resolve('src/')],
            loader: 'isparta'
          }]
        }
      },
      webpackMiddleware: {
        noInfo: true
      }
    });
  };
  这里相对于之前的karma.conf.js,主要有以下几点区别:
  由于webpack的打包功能,我们在测试代码里直接import组件代码,因此不再需要在files里手动引入组件代码
  预处理里面需要对每个测试文件都做webpack打包
  添加webpack编译相关配置,在编译源码时,需要定义preLoaders,并使用isparta-loader做代码覆盖率打点
  添加webpackMiddleware配置,这里noInfo作用是不需要输出webpack编译时那一大串信息
  这样配置基本上就完成了,跑一把./node_modules/karma/bin/karma start --single-run:
  很好,结果符合预期。open coverage/lcov-report/index.html打开覆盖率页面:
  鹅妹子音!!!直接对jsx代码做的覆盖率测试!这样React组件的测试大体上就完工了
  小结
  前端的代码测试主要难度是如何模拟各种各样的浏览器环境,Karma给我们提供了很好地方式,对于本地有的浏览器能自动打开并测试,本地没有的浏览器则提供直接访问的页面。前端尤其是移动端浏览器种类繁多,很难做到完美,但我们可以通过这种方式实现主流浏览器的覆盖,保证每次上线大多数用户没有问题。
  持续集成
  测试结果有了,接下来就是把这些测试结果接入到持续集成之中。持续集成是一种非常优秀的多人开发实践,通过代码push触发钩子,实现自动运行编译、测试等工作。接入持续集成后,我们的每一次push代码,每个Merge Request都会生成对应的测试结果,项目的其他成员可以很清楚地了解到新代码是否影响了现有的功能,在接入自动告警后,可以在代码提交阶段就快速发现错误,提升开发迭代效率。
  持续集成会在每次集成时提供一个几乎空白的虚拟机器,并拷贝用户提交的代码到机器本地,通过读取用户项目下的持续集成配置,自动化的安装环境和依赖,编译和测试完成后生成报告,在一段时间之后释放虚拟机器资源。
  开源的持续集成
  开源比较出名的持续集成服务当属Travis,而代码覆盖率则通过Coveralls,只要有GitHub账户,就可以很轻松的接入Travis和Coveralls,在网站上勾选了需要持续集成的项目以后,每次代码push就会触发自动化测试。这两个网站在跑完测试以后,会自动生成测试结果的小图片
  Travis会读取项目下的travis.yml文件,一个简单的例子:
  language: node_js
  node_js:
    - "stable"
    - "4.0.0"
    - "5.0.0"
  script: "npm run test"
  after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"
  language定义了运行环境的语言,而对应的node_js可以定义需要在哪几个Node.js版本做测试,比如这里的定义,代表着会分别在最新稳定版、4.0.0、5.0.0版本的Node.js环境下做测试
  而script则是测试利用的命令,一般情况下,都应该把自己这个项目开发所需要的命令都写在package.json的scripts里面,比如我们的测试方法./node_modules/karma/bin/karma start --single-run就应当这样写到scripts里:
  {
    "scripts": {
      "test": "./node_modules/karma/bin/karma start --single-run"
    }
  }
  而after_script则是在测试完成之后运行的命令,这里需要上传覆盖率结果到coveralls,只需要安装coveralls库,然后获取lcov.info上传给Coveralls即可
  更多配置请参照Travis官网介绍
  这样配置后,每次push的结果都可以上Travis和Coveralls看构建和代码覆盖率结果了
  小结
  项目接入持续集成在多人开发同一个仓库时候能起到很大的用途,每次push都能自动触发测试,测试没过会发生告警。如果需求采用Issues+Merge Request来管理,每个需求一个Issue+一个分支,开发完成后提交Merge Request,由项目Owner负责合并,项目质量将更有保障
  总结
  这里只是前端测试相关知识的一小部分,还有非常多的内容可以深入挖掘,而测试也仅仅是前端流程自动化的一部分。在前端技术快速发展的今天,前端项目不再像当年的刀耕火种一般,越来越多的软件工程经验被集成到前端项目中,前端项目正向工程化、流程化、自动化方向高速奔跑。还有更多优秀的提升开发效率、保证开发质量的自动化方案亟待我们挖掘。
一篇看不够?你需要的是这门系统专业课程:
Node.js入门实战教程
33/3<123
《2023软件测试行业现状调查报告》独家发布~

精彩评论

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号