前面三个测量检验初探

作者:分分快三计划

三. 测试报告

一般跑完单元测试,都需要输出一份指定格式的报告,用于过后自查或问题追溯,此处需要注意的是当与webpack4.0结合使用时,karma的一些默认行为会失效(例如在控制台输出单元测试用例和结果汇总,以及karma独立运行时用来生成代码覆盖率报告插件karma-coverage也无法正常工作),在此均需要重新配置。

  • 单元测试报告

    单元测试信息无法输出的问题,可以显式引用插件karma-spec-reporterkarma-mocha-reporter并进行基本的配置即可。

  • 代码覆盖率报告

    代码覆盖率报告的自动生成配置较为复杂,需要依赖前端代码覆盖率工具istanbul并结合若干插件才能实现。低版本的webpack可以参考karma-webpack-example这个开源项目的示例进行配置。webpack4.0以上版本可以参考下文推荐的示例。

    单元测试结果:

图片 1

覆盖率报告:

图片 2

前端单测工具栈

一直知道前端也是有测试的,但理解很肤浅,今天下定决心摸索一遍到底什么是前端自动化测试...
本例子通过vue-cli生成的unite2e来探讨...

webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。本系列是笔者自己的学习记录,比较基础,希望通过问题 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法。(本篇中的参数配置及使用方式均基于webpack4.0版本

测试脚本的写法

通常,测试脚本与所要测试的源码脚本同名,但是后缀名为.test.js(表示测试)或者.spec.js(表示规格)。

// add.test.js
var add = require('./add.js');
var expect = require('chai').expect;

describe('加法函数的测试', function() {
  it('1 加 1 应该等于 2', function() {
    expect(add(1, 1)).to.be.equal(2);
  });
});

上面这段代码,就是测试脚本,它可以独立执行。测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。

describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。

describe干的事情就是给测试用例分组。为了尽可能多的覆盖各种情况,测试用例往往会有很多。这时候通过分组就可以比较方便的管理(这里提一句,describe是可以嵌套的,也就是说外层分组了之后,内部还可以分子组)。另外还有一个非常重要的特性,就是每个分组都可以进行预处理(before、beforeEach)和后处理(after, afterEach)。

it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。

大型项目有很多测试用例。有时,我们希望只运行其中的几个,这时可以用only方法。describe块和it块都允许调用only方法,表示只运行某个测试套件或测试用例。此外,还有skip方法,表示跳过指定的测试套件或测试用例。

describe.only('something', function() {
  // 只会跑包在里面的测试
})

it.only('do do', () => {
  // 只会跑这一个测试
})

Jest

哦,是不是这一大堆东西看晕了,用个karma还要集成一大堆各种插件配置,这一点上真是跟webpack一样了
就像有人受不了webpack这一大堆配置所以有了前端构建集成工具Parcel
而Jest就是这样一个前端测试集成工具
Jest的官方文档支持中文,这里就不详细说明了,有兴趣可以去官网查看
相比于karma最大特点就是快和方便,缺点就是没有karma测试环境真实和自由
具体抉择,仁者见仁智者见智啦~~

二. karma-webpack

插件地址:

react 单测示例二

react 单元测试框架 demo2

该框架只采用了Jest,是比较简洁的方案,同样也使用了 enzyme。

Jest 是Facebook开发的一个测试框架,它集成了测试执行器、断言库、spy、mock、snapshot和测试覆盖率报告等功能。React项目本身也是使用Jest进行单测的,因此它们俩的契合度相当高。
之前仅在其内部使用,后开源,并且是在Jasmine测试框架上演变开发而来,使用了熟知的expect(value).toBe(other)这种断言格式。

PS: 目前 enzyme 使用时需要加入设置如下:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

上面两个框架方案中都有加入该配置的方法,详见示例。

相关配置

unit目录结构,主要测试单元是一个个函数、方法

└── unit
    ├── coverage  代码覆盖率报告,src下面的index.html可以直接用浏览器打开
    │   ├── lcov-report
    │   │   ├── base.css
    │   │   ├── index.html
    │   │   ├── prettify.css
    │   │   ├── prettify.js
    │   │   ├── sort-arrow-sprite.png
    │   │   ├── sorter.js
    │   │   └── src
    │   │       ├── App.vue.html
    │   │       ├── components
    │   │       │   ├── Hello.vue.html
    │   │       │   └── index.html
    │   │       └── index.html
    │   └── lcov.info
    ├── index.js 运行测试用例前先加载的文件,方便统计代码覆盖率
    ├── karma.conf.js karma的配置文件
    └── specs 所有的测试用例都放在这里
        └── Hello.spec.js

karma.conf.js内容

module.exports = function (config) {
    config.set({
        // 要启动的测试浏览器
        browsers: [ 'Chrome'],
        // 测试框架
        frameworks: ['mocha', 'sinon-chai'],
        // 测试报告处理
        reporters: ['spec', 'coverage'],
        // 要测试的目标文件
        files: ['./index.js'],
        // 忽略的文件
        exclude: [],
        // 预处理文件
        preprocessors: {
            './index.js': ['webpack', 'sourcemap']
        },
        // webpack
        webpack: webpackConfig,
        webpackMiddleware: {
            noInfo: true
        },
        // Coverage options
        coverageReporter: {
            dir: './coverage',
            reporters: [
                { type: 'lcov', subdir: '.' },
                { type: 'text-summary' }
            ]
        },
        // true: 自动运行测试并退出
        // false: 监控文件持续测试
        singleRun: true,
        // 以下是 vue-cli 没有生成的一些配置
        // 文件匹配的起始路径
        // basePath: '',
        // 服务器端口
        // port: 9876,
        // 输出着色
        // colors: true,
        // 日志级别
        // LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
        // logLevel: config.LOG_INFO,
        // 监控文件更改
        // autoWatch: true,
        // 超时处理,6s内没有捕获浏览器将终止进程
        // captureTimeout: 6000
    })
}

index.js入口文件

// 加载所有的测试用例、 testsContext.keys().forEach(testsContext)这种写法是webpack中的加载目录下所有文件的写法

// 匹配的是specs目录,里面是存放的是测试用例
const testsContext = require.context('./specs', true, /.spec$/)
testsContext.keys().forEach(testsContext)

// 加载所有代码文件,方便统计代码覆盖率
// 匹配的是src目录,除了main.js以外的所有文件。
const srcContext = require.context('../../src', true, /^./(?!main(.js)?$)/)
srcContext.keys().forEach(srcContext)

e2e目录结构,测试的单元是一个个预期的行为表现,打开游览器,模拟测试

├── e2e
│   ├── custom-assertions
│   │   └── elementCount.js 自定义的断言方法
│   ├── nightwatch.conf.js nightwatch的配置文件
│   ├── reports 
│   │   ├── CHROME_60.0.3112.101_Mac OS X_test.xml
│   │   └── CHROME_60.0.3112.113_Mac OS X_test.xml
│   ├── runner.js  bootstrap文件,起我们的页面server和nightwatch文件
│   └── specs
│       └── test.js 测试用例

nightwatch.conf.js内容

  src_folders: ['test/e2e/specs'],
  output_folder: 'test/e2e/reports',
  custom_assertions_path: ['test/e2e/custom-assertions'],
    // 对selenium的配置
  selenium: {
    start_process: true,
    server_path: require('selenium-server').path,
    host: '127.0.0.1',
    port: 4444,
    cli_args: {
      'webdriver.chrome.driver': require('chromedriver').path
    }
  },
    // 测试环境的配置
  test_settings: {
    default: {
      selenium_port: 4444,
      selenium_host: 'localhost',
      silent: true,
      globals: {
        devServerURL: 'http://localhost:'   (process.env.PORT || config.dev.port)
      }
    },

    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    },

    firefox: {
      desiredCapabilities: {
        browserName: 'firefox',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    }
  }

runner.js入口文件内容,先起一个我们的网页服务然后再起nightWatch服务

var server = require('../../build/dev-server.js')

server.ready.then(() => {
  // 2. run the nightwatch test suite against it
  // to run in additional browsers:
  //    1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
  //    2. add it to the --env flag below
  // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
  // For more information on Nightwatch's config file, see
  // http://nightwatchjs.org/guide#settings-file
  var opts = process.argv.slice(2)
    console.log(opts);
  if (opts.indexOf('--config') === -1) {
    opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
  }
  if (opts.indexOf('--env') === -1) {
    opts = opts.concat(['--env', 'chrome,firefox'])
  }

  var spawn = require('cross-spawn')
  var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })

  runner.on('exit', function (code) {
    server.close()
    process.exit(code)
  })

  runner.on('error', function (err) {
    server.close()
    throw err
  })
})

图片 3

BDD

所谓的BDD行为驱动开发,即Behaviour Driven Development,是一种新的敏捷开发方法。它更趋向于需求,需要共同利益者的参与,强调用户故事(User Story)和行为。2009年,在伦敦发表的“敏捷规格,BDD和极限测试交流”中,Dan North对BDD给出了如下定义:

BDD是第二代的、由外及内的、基于拉(pull)的、多方利益相关者的(stakeholder)、多种可扩展的、高自动化的敏捷方法。它描述了一个交互循环,可以具有带有良好定义的输出(即工作中交付的结果):已测试过的软件。

它对TDD的理念进行了扩展,在TDD中侧重点偏向开发,通过测试用例来规范约束开发者编写出质量更高、bug更少的代码。而BDD更加侧重设计,其要求在设计测试用例的时候对系统进行定义,倡导使用通用的语言将系统的行为描述出来,将系统设计和测试用例结合起来,从而以此为驱动进行开发工作。

大致过程:

  1. 从业务的角度定义具体的,以及可衡量的目标

  2. 找到一种可以达到设定目标的、对业务最重要的那些功能的方法

  3. 然后像故事一样描述出一个个具体可执行的行为。其描述方法基于一些通用词汇,这些词汇具有准确无误的表达能力和一致的含义。例如,expect, should, assert

  4. 寻找合适语言及方法,对行为进行实现

  5. 测试人员检验产品运行结果是否符合预期行为。最大程度的交付出符合用户期望的产品,避免表达不一致带来的问题

Puppeteer

Puppeteer是类似于Nightwatch的一个Chrome专用版,有更友好的api,是用来测试游览器环境的一个工具
也可用于爬虫,比如这个demo演示了爬取百度图片,相较于cheerio,它的爬虫更模拟真实环境,不易反爬虫

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();

一. webpack与自动化测试

webpack对应的关键词是模块化,它的主要任务就是打包和管理模块,所以首先需要明确的概念就是webpack之所以关联自动化测试,是因为它能够为测试脚本提供模块管理的能力,本质上来讲,是将webpack的打包功能嵌入了自动化测试框架,而不是将自动化测试框架作为插件集成进了webpack,理解这个区别是非常关键的。

对于Karma Mocha Chai及其他自动化测试相关工具的话题将在《大前端的自动化工厂》系列博文中讲述,本篇主要介绍karma-webpack连接件,它从工具实现层面上将自动化测试与自动化构建联系在了一起。

参考

  • 聊一聊前端自动化测试
  • 前端自动化单元测试初探
  • Javascript的Unit Test
  • 单元测试all in one
  • Sinon指南: 使用Mocks, Spies 和 Stubs编写JavaScript测试
  • 测试框架 Mocha 实例教程

Mocha

Mocha的作用是运行测试脚本,首先必须学会写测试脚本。所谓"测试脚本",就是用来测试源码的脚本
Mocha默认运行test子目录里面的测试脚本 添加--recursive参数可以运行test目录下所有层数用例
基本用法:

describe('#math', () => {
    describe('add', () => {
        it('should return 5 when 2   3', () => {
            assert(add(2, 3), 5)
        })
    })
    describe('mul', () => {
        it('should return 6 when 2 * 3', () => {
            assert(mul(2, 3), 6)
        })
        // 只执行此条
       it.only('should return 6 when 2 * 3', () => {
            assert(mul(2, 3), 6)
        })
       // 忽略此条
       it.skip('should return 6 when 2 * 3', () => {
            assert(mul(2, 3), 6)
        })
    })
    describe('mul', () => {
        it('should return -1 when 2 < 3', () => {
            assert(cover(2, 3), -1)
        })
        it('should return 1 when 3 > 2', () => {
            assert(cover(3, 2), 1)
        })
        it('should return 4 when 2 = 2', () => {
            assert(cover(2, 2), 4)
        })
    })
})

异步例子:
it块执行的时候,传入一个done参数,当测试结束的时候,必须显式调用这个函数,告诉Mocha测试结束了
需要用-t--timeout参数,改变默认的(2000)超时设置。

// $ mocha -t 5000 timeout.test.js

it('测试应该5000毫秒后结束', done => {
  var x = true;
  var f = function() {
    x = false;
    expect(x).to.be.not.ok;
    done(); // 通知Mocha测试结束
  };
  setTimeout(f, 4000);
});

测试用例的钩子:
Mochadescribe块之中,提供测试用例的四个钩子:before()、after()、beforeEach()和afterEach()

describe('hooks', function() {

  before(function() {
    // 在本区块的所有测试用例之前执行
  });

  after(function() {
    // 在本区块的所有测试用例之后执行
  });

  beforeEach(function() {
    // 在本区块的每个测试用例之前执行
  });

  afterEach(function() {
    // 在本区块的每个测试用例之后执行
  });

  // test cases
});

四. 配置参考

笔者提供了针对webpack4.0 karma的自动化测试配置示例,放在了Webpack4-Karma-Mocha-Chai-Demo,有需要的小伙伴可以自行查看,如果对你有帮助,不要忘记给个Star哦~

什么是单元测试

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。——百度百科

chai

定义几个函数

const math = {
    add: (...args) => args.reduce((num, value) => num   value),
    mul: (...args) => args.reduce((num, value) => num * value),
    cover: (a, b) => {
        if (a > b) {
            return a - b
        } else if (a == b) {
            return a   b
        } else {
            return -1
        }
    }
}

node自带的断言测试

const assert = require('assert')
const {add, mul} = require('./math')
assert.equal(add(2, 3), 5)

引入chai库测试,3个方法作用一样,断言分格不同而已

const chai = require('chai')
// should
chai.should()
add(2, 3).should.equal(5)
// expect
consr expect = chai.expect
expect(add(2, 3).to.be(5)
// assert
consr assert = chai.assert
assert.equal(add(2, 3), 5)

expect断言的优点是很接近自然语言,下面是一些例子

// 相等或不相等
expect(4   5).to.be.equal(9);
expect(4   5).to.be.not.equal(10);
expect(foo).to.be.deep.equal({ bar: 'baz' });

// 布尔值为true
expect('everthing').to.be.ok;
expect(false).to.not.be.ok;

// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(foo).to.be.an.instanceof(Foo);

// include
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');

// empty
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;

// match
expect('foobar').to.match(/^foo/);

基本上,expect断言的写法都是一样的。头部是expect方法,尾部是断言方法,比如equal、a/an、ok、match等。两者之间使用to或to.be连接

如果expect断言不成立,就会抛出一个错误。只要不抛出错误,测试用例就算通过

2.2 基本使用

使用yarn add karma-webpack -D进行安装,karma.conf.js配置文件如下:

module.exports = (config) => {
  config.set({

    files: [
      // 针对test目录下所有符合命名规范的测试文件
      { pattern: 'test/*_test.js', watched: false },
      { pattern: 'test/**/*_test.js', watched: false }
    ],

    preprocessors: {
      // 为选定脚本指定前处理器,这里配置所有的测试脚本需要经过webpack处理
      'test/*_test.js': [ 'webpack' ],
      'test/**/*_test.js': [ 'webpack' ]
    },

    webpack: {
      // webpack配置,针对测试脚本打包的compilation配置,与项目文件打包不相关
      // 也可以引入独立的配置文件
    },

    webpackMiddleware: {
      //如果使用了webpack-dev-server则可以传入一些参数
      stats: 'errors-only'
    }
  })
}

这种配置中webpack会将每一个命中的文件当做是一个entry,也就是说它只会处理局部的依赖管理,这样做的优点是可以针对部分测试脚本单独跑单元测试,但劣势也很明显,就是当测试脚本数量很大且需要默认跑所有的测试用例的场景下(例如自动化流水线上自动触发的LLT测试中)效率相对较低。

react 单测示例一

react 单元测试框架 demo1

该框架采用 karma mocha chai sinon 的组合, 是一种采用工具较多,同时自由度较高的解决方案。虽然工具库使用的较多,但有助于理解各个工具库的作用和使用,也有助于加深对前端单元测试的理解。

其中React的测试库使用 enzyme,React测试必须使用官方的测试工具库,但是它用起来不够方便,所以有人做了封装,推出了一些第三方库,其中Airbnb公司的Enzyme最容易上手。

关于该库的 api 使用可参考:

官方文档

阮老师React测试入门

benchmark

benchmark是一个测试函数性能的库

var suite = new Benchmark.Suite;
// add tests
suite.add('RegExp#test', function() {
  /o/.test('Hello World!');
})
.add('String#indexOf', function() {
  'Hello World!'.indexOf('o') > -1;
})
.add('String#match', function() {
  !!'Hello World!'.match(/o/);
})
// add listeners 
.on('cycle', function(event) {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log('Fastest is '   this.filter('fastest').map('name'));
})
// run async
.run({ 'async': true });

2.3 默认跑完全部测试用例的场景

针对上面的问题,webpak提供了另一种可选的处理测试脚本集的方法,很容易想象,其实就是自己新建一个entryPoint,将要跑的测试脚本全部引入,打包成一个bundle.js文件,它的优势和劣势和基本场景正好是相反的。

这种场景下,karma.conf.js的配置只需要针对入口文件即可:

files: [
  // only specify one entry point
  // and require all tests in there
  'test/index_test.js'
],

preprocessors: {
  // add webpack as preprocessor
  'test/index_test.js': [ 'webpack' ]
},

然后在测试文件的根目录下新建一个入口脚本index_test.js:

// 这个配置针对的是test/**/?_test.js格式的脚本文件
const testsContext = require.context(".", true, /_test$/);
testsContext.keys().forEach(testsContext)

相关概念

基础名词

一些前端测试的名词解释:

  • karma是一个基于Node.jsJavaScript测试执行过程管理工具,其在测试中的作用相当于开发构建中使用的webpack

  • karma-webpack连接karmawebpack的桥梁。不经过webpack编译命令是文件是无法独立运行的,karma需要了解你的webpack配置,决定如何处理你的测试文件。

  • karma-phantomjs-launcher是phantomjskarma中的启动器,由此引出了PhantomJS,一个基于webkit内核的无头浏览器,即没有UI界面,即它就是一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。在查找相关资料时,也发现了其他的常规浏览器launcher,比如:Chrome、Firefox、Safari、IE 等,以应对不同浏览器或多浏览器的测试需求。见Browsers

  • karma-sourcemap-loader一个Karma插件,生成文件的sourcemap

  • karma-mocha让你在karma中使用Mocha一款功能丰富的javascript单元测试框架,它既可以运行在nodejs环境中,也可以运行在浏览器环境中

  • karma-sinon-chai让你在karma中使用sinon-chai断言库的插件, 提供丰富的断言方法,前置依赖有sinon-chaisinonchai

  • karma-spec-reporter用于将测试结果显示到控制台。

  • karma-coverage用来生成代码覆盖率。

  • Nightwatch是一套基于Node.js的测试框架,使用Selenium WebDriver API以将Web应用测试自动化。它提供了简单的语法,支持使用JavaScript和CSS选择器,来编写运行在Selenium服务器上的端到端测试。

图片 4

mock库

  • sinon.js:使用Sinon,我们可以把任何JavaScript函数替换成一个测试替身。通过配置,测试替身可以完成各种各样的任务来让测试复杂代码变得简单。支持 spies, stub, fake XMLHttpRequest, Fake server, Fake time,很强大

工具详解

2.1 自动化单元测试库简介

先对基本的单元测试工具做一个简要说明:

  • Karma 测试框架,提供多浏览器环境跑单元测试的能力,包括headless浏览器。
  • Mocha 测试框架,提供兼容浏览器和Node环境的单元测试能力,可使用karma-mocha集成进Karma中。
  • Chai 断言库,支持should,expect,assert不同类型的断言测试函数,可使用karma-chai集成进Karma中。

大部分单元测试都是基于上述三个库联合使用而展开的。Karma-webpack主要提供的能力,是为Karma中加载的测试脚本提供模块化加载的能力。

测试集成管理工具

  • karma:Google Angular 团队写的,功能很强大,有很多插件。可以连接真实的浏览器跑测试。能够用一些测试覆盖率统计的工具统计一下覆盖率;或是能够加入持续集成,提交代码后自动跑测试用例。

TDD

前面三个测量检验初探。TDD是Test Driven Development 的缩写,也就是测试驱动开发。

通常传统软件工程将测试描述为软件生命周期的一个环节,并且是在编码之后。但敏捷开发大师Kent Beck在2003年出版了 Test Driven Development By Example 一书,从而确立了测试驱动开发这个领域。

TDD需要遵循如下规则:

  • 写一个单元测试去描述程序的一个方面。
  • 运行它应该会失败,因为程序还缺少这个特性。
  • 为这个程序添加一些尽可能简单的代码保证测试通过。
  • 重构这部分代码,直到代码没有重复、代码责任清晰并且结构简单。
  • 持续重复这样做,积累代码。

TDD具有很强的目的性,在直接结果的指导下开发生产代码,然后不断围绕这个目标去改进代码,其优势是高效和去冗余的。所以其特点应该是由需求得出测试,由测试代码得出生产代码。打个比方就像是自行车的两个轮子,虽然都是在向同一个方向转动,但是后轮是施力的,带动车子向前,而前轮是受力的,被向前的车子带动而转。

为何要测试

以前没有编写和维护测试用例的习惯,在项目的紧张开发周期中也没时间去做这个工作,相信有不少开发人员都不会重视单元测试这项工作。在真正写了一段时间基础组件后,才发现自动化测试有很多好处:

  1. 提升代码质量。虽不能说百分百无bug,但至少说明测试用例覆盖到的场景是没有问题的。
  2. 能快速反馈,能确定UI组件工作情况是否符合自己预期。
  3. 开发者会更加信任自己的代码,也不会惧怕将代码交给别人维护。后人接手一段有测试用例的代码,修改起来也会更加从容。测试用例里非常清楚的阐释了开发者和使用者对于这段代码的期望和要求,也非常有利于代码的传承。

当然由于维护测试用例也是一大笔开销,还是要基于投入产出比来做单元测试。对于像基础组件、基础模型之类的不常变更且复用较多的部分,可以考虑写测试用例来保证质量,但对于迭代较快的业务逻辑及生存时间不长的部分就没必要浪费时间了。

因此github上看到的star较多的牛逼开源前端项目基本上都是有测试代码的,看来业界大牛们都是比较重视单元测试这块的。

前言

随着Web业务的日益复杂化和多元化,前端开发也有了前端工程化的概念,前端工程化成为目前前端架构中重要的一环,本质上也是软件工程的一种,因此我们需要从软件工程的角度来研究前端工程,而自动化测试则是软件工程中重要的一环。本文就研究一下前端领域中的自动化测试,以及如何实践。

断言库

断言库提供了很多语义化的方法来对值做各种各样的判断。

  • chai: 目前比较流行的断言库,支持 TDD(assert),BDD(expect、should)两种风格
  • should.js:也是tj大神所写

覆盖率

如何衡量测试脚本的质量呢?其中一个参考指标就是代码覆盖率(coverage)。

什么是代码覆盖率?简而言之就是测试中运行到的代码占所有代码的比率。其中又可以分为行数覆盖率,分支覆盖率等。具体的含义不再细说,有兴趣的可以自行查阅资料。

虽然并不是说代码覆盖率越高,测试的脚本写得越好,但是代码覆盖率对撰写测试脚本还是有一定的指导意义的。

测试框架

主要提供了清晰简明的语法来描述测试用例,以及对测试用例分组,测试框架会抓取到代码抛出的AssertionError,并增加一大堆附加信息,比如那个用例挂了,为什么挂等等。目前比较流行的测试框架有:

  • Jasmine: 自带断言(assert),mock功能
  • Mocha: 框架不带断言和mock功能,需要结合其他工具,由tj大神开发
  • Jest: 由Facebook出品的测试框架,在Jasmine测试框架上演变开发而来

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 前端技术 前端学