随着每一个工程的复杂化、代码的高复用性要求和前端代码模块之间的高内聚低耦合的需求,前端工程中的单元测试流程就显得颇有其必要。html
首先咱们要明确测试是什么:前端
为检测特定的目标是否符合标准而采用专用的工具或者方法进行验证,并最终得出特定的结果。node
对于前端开发过程来讲,这里的特定目标就是指咱们写的代码,而工具就是咱们须要用到的测试框架(库)、测试用例等。检测处的结果就是展现测试是否经过或者给出测试报告,这样才能方便问题的排查和后期的修正。git
基于测试“是什么”的说法,为便于刚从事前端开发的同行的进阶理解,那咱们就列出单元测试它“不是什么”:github
须要访问数据库的测试不是单元测试面试
须要访问网络的测试不是单元测试chrome
须要访问文件系统的测试不是单元测试数据库
--- 修改代码的艺术npm
对于单元测试“不是什么”的引用解释,至此点到为止。鉴于篇幅限制,对于引用内容,我想前端开发的同行们看到后会初步有一个属于本身的理解。api
对于如今的前端工程,一个标准完整的项目,测试是很是有必要的。不少时候咱们只是完成了项目而忽略了项目测试的部分,测试的意义主要在于下面几点:
在单元测试中,经常使用的方法论有两个:TDD(测试驱动开发)&BDD(行为驱动开发)
TDD(Test-driven development):
其基本思路是经过测试来推进整个开发的进行。
单元测试的首要目的不是为了可以编写出大覆盖率的所有经过的测试代码,而是须要从使用者(调用者)的角度出发,尝试函数逻辑的各类可能性,进而辅助性加强代码质量
测试是手段而不是目的。测试的主要目的不是证实代码正确,而是帮助发现错误,包括低级的错误
测试要快。快速运行、快速编写
测试代码保持简洁
不会忽略失败的测试。一旦团队开始接受1个测试的构建失败,那么他们渐渐地适应二、三、4或者更多的失败。在这种状况下,测试集就再也不起做用
须要注意的是:
必定不能误解了TDD的核心目的!
测试不是为了覆盖率和正确率
而是做为实例,告诉开发人员要编写什么代码
红灯(代码还不完善,测试挂)-> 绿灯(编写代码,测试经过)-> 重构(优化代码并保证测试经过)
TDD的过程是:
需求分析,思考实现。考虑如何“使用”产品代码,是一个实例方法仍是一个类方法,是从构造函数传参仍是从方法调用传参,方法的命名,返回值等。这时其实就是在作设计,并且设计以代码来体现。此时测试为红
实现代码让测试为”绿灯“
重构,而后重复测试
最终符合全部要求即:
每一个概念都被清晰的表达
代码中无自我重复
没有多余的东西
经过测试
行为驱动开发(BDD),重点是经过与利益相关者(简单说就是客户)的讨论,取得对预期的软件行为的认识,其重点在于沟通
BDD过程是:
从业务的角度定义具体的,以及可衡量的目标
找到一种能够达到设定目标的、对业务最重要的那些功能的方法
而后像故事同样描述出一个个具体可执行的行为。其描述方法基于一些通用词汇,这些词汇具备准确无误的表达能力和一致的含义。例如,expect
, should
, assert
寻找合适语言及方法,对行为进行实现
测试人员检验产品运行结果是否符合预期行为。最大程度的交付出符合用户指望的产品,避免表达不一致带来的问题
以上内容从什么是单元测试谈到单元测试的方法论。那么怎样用经常使用框架进行单元测试?单元测试的工具环境是什么?单元测试的实际示例是怎样的?
首先应该简单介绍一下Mocha、Karma和Travis.CI
Mocha:mocha 是一个功能丰富的前端测试框架。所谓"测试框架",就是运行测试的工具。经过它,能够为JavaScript应用添加测试,从而保证代码的质量。mocha 既能够基于 Node.js 环境运行 也能够在浏览器环境运行。
Karma:一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试全部主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其余代码编辑器一块儿使用。这个测试工具的一个强大特性就是,它能够监控文件的变化,而后自行执行,经过console.log显示测试结果。Karma的一个强大特性就是,它能够监控一套文件的变换,并当即开始测试已保存的文件,用户无需离开文本编辑器。测试结果一般显示在命令行中,而非代码编辑器。这也就让 Karma 基本能够和任何 JS 编辑器一块儿使用。
Travis.CI:提供的是持续集成服务(Continuous Integration,简称 CI)。它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。而后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。
持续集成指的是只要代码有变动,就自动运行构建和测试,反馈运行结果。确保符合预期之后,再将新代码"集成"到主干。
持续集成的好处在于,每次代码的小幅变动,就能看到运行结果,从而不断累积小的变动,而不是在开发周期结束时,一会儿合并一大块代码。
断言库
基本工具框架介绍完毕后,相信稍微了解点测试的同行都知道,作单元测试是须要写测试脚本的,那么测试脚本就须要用到断言库。”断言“,我的理解即为”用彼代码判定测试此代码的正确性,检验并暴露此代码的错误。“那么对于前端单元测试来讲,有如下经常使用断言库:
看一段代码示例:
expect(add(1, 1)).to.be.equal(2);
这是一句断言代码。
所谓"断言",就是判断源码的实际执行结果与预期结果是否一致,若是不一致就抛出一个错误。上面这句断言的意思是,调用 add(1, 1),结果应该等于 2。全部的测试用例(it 块)都应该含有一句或多句的断言。它是编写测试用例的关键。断言功能由断言库来实现,Mocha 自己不带断言库,因此必须先引入断言库。
引入断言库代码示例:
var expect = require('chai').expect;
断言库有不少种,Mocha 并不限制使用哪种,它容许你使用你想要的任何断言库。上面代码引入的断言库是 chai,而且指定使用它的 expect 断言风格。下面这些常见的断言库:
此处主要介绍一下node assert中经常使用的API
断言 value 的值是否为true,这里的等于判断使用的是 == 而不是 ===。message 是断言描述,为可选参数。
const assert = require('assert'); assert(true);
使用方法同 assert(value[, message])
。
预期 actual 与 expect值相等。equal用于比较的 actual 和 expect 是基础类型(string, number, boolearn, null, undefined)的数据。其中的比较使用的是 == 而不是 ===。
it('assert.equal', () => { assert.equal(null, false, 'null compare with false'); // 报错 assert.equal(null, true, 'null compare with true'); // 报错 assert.equal(undefined, false, 'undefined compare with false'); // 报错 assert.equal(undefined, true, 'undefined compare with true'); // 报错 assert.equal('', false, '"" compare with false'); // 正常 })
用法同 assert.equal(actual, expect[, message])
只是对预期结果取反(即不等于)。
用法同 assert.equal(actual, expect[, message])
可是内部比较是使用的是 === 而不是 ==。
用法同 assert.strictEqual(actual, expect[, message])
只是对预期结果取反(即不严格等于)。
it('assert.strictEqual', () => { assert.strictEqual('', false); // 报错 })
deepEqual 方法用于比较两个对象。比较的过程是比较两个对象的 key 和 value 值是否相同, 比较时用的是 == 而不是 ===。
it('assert.deepEqual', () => { const a = { v: 'value' }; const b = { v: 'value' }; assert.deepEqual(a, b); })
用法同 assert.deepEqual(actual, expect[, message])
只是对预期结果取反(即不严格深等于)。
用法同 assert.deepEqual(actual, expect[, message])
可是内部比较是使用的是 === 而不是 ==。
用法同 assert.deepStrictEqual(actual, expect[, message])
只是对结果取反(即不严格深等于)。
错误断言与捕获, 断言指定代码块运行必定会报错或抛出错误。若代码运行未出现错误则会断言失败,断言异常。
it('throws', () => { var fun = function() { xxx }; assert.throws(fun, 'fun error'); })
错误断言与捕获, 用法同 throws 相似,只是和 throws 预期结果相反。断言指定代码块运行必定不会报错或抛出错误。若代码运行出现错误则会断言失败,断言异常。
it('throws', () => { var fun = function() { xxx }; assert.doesNotThrow(fun, 'fun error'); })
npm install mocha -g
固然也能够在不在全局安装,只安局部安装在项目中
npm install mocha --save
test.js
var assert = require('assert') describe('Array', function() { describe('#indexOf()', function() { it('should return -1 when the value is not present', function() { assert.equal(-1, [1, 2, 3].indexOf(-1)) }) }) })
这段文件和简单就是测试 Array
的一个 indexOf()
方法。这里我是用的断言库是 Node 所提供的 Assert
模块里的API。这里断言 -1 等于 数组 [1, 2, 3]
执行 indexOf(-1)
后返回的值,若是测试经过则不会报错,若是有误就会报出错误。
下面咱们使用全局安装的 mocha
来运行一下这个文件 mocha test.js
。
下面是返回结果
基础测试用例实例
const assert = require('assert'); describe('测试套件描述', function() { it('测试用例描述: 1 + 2 = 3', function() { // 测试代码 const result = 1 + 2; // 测试断言 assert.equal(result, 3); }); });
Mocha 测试用例主要包含下面几部分:
说明:每一个测试文件中能够有多个测试套件和测试用例。mocha不只能够在node环境运行, 也能够在浏览器环境运行;在node中运行也能够经过npm i mocha -g
全局安装mocha而后以命令行的方式运行测试用例也是可行的。
这里略微详细介绍下测试脚本写法
Mocha 的做用是运行测试脚本,首先必须学会写测试脚本。所谓"测试脚本",就是用来测试源码的脚本。下面是一个加法模块 add.js 的代码。
// add.js function add(x, y) { return x + y; } module.exports = add;
要测试这个加法模块是否正确,就要写测试脚本。一般,测试脚本与所要测试的源码脚本同名,可是后缀名为.test.js(表示测试)或者.spec.js(表示规格)。好比,add.js 的测试脚本名字就是 add.test.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),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。
it 块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。
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 断言不成立,就会抛出一个错误。事实上,只要不抛出错误,测试用例就算经过。
it('1 加 1 应该等于 2', function() {});
上面的这个测试用例,内部没有任何代码,因为没有抛出了错误,因此仍是会经过。
基于 karma 测试经常使用的一些模块
# 基础测试库 npm install karma-cli -g npm install karma mocha karma-mocha --save-dev # 断言库 npm install should --save-dev npm install karma-chai --save-dev # 浏览器相关 npm install karma-firefox-launcher --save-dev npm install karma-chrome-launcher --save-dev
若是对软件测试、接口测试、自动化测试、面试经验交流。感兴趣能够加软件测试交流:1085991341,还会有同行一块儿技术交流。
这里的配置主要关注的是karma.conf.js
的相关配置。若是要使用 karma 和 mocha 最好经过npm install karma-cli -g
全局安装karma-cli
。
须要注意的两个字段:
NODE_ENV
变量。--no-sandbox
模式。{ "browsers": ["Chrome", "ChromeHeadless", "ChromeHeadlessNoSandbox"], "customLaunchers": { "ChromeHeadlessNoSandbox": { "base": "ChromeHeadless", "flags": ["--no-sandbox"] } } }
或者
{ "browsers": ["Chrome_travis_ci"], "customLaunchers": { "Chrome_travis_ci": { "base": "Chrome", "flags": ["--no-sandbox"] } } }
mocha
来测试完成的求和方法。下面是项目结构,项目建立完成后经过 npm i mocha -D
安装 mocha
模块。而后在本地运行 npm test
看是否可以测试经过。若是可以测试经过则说明咱们的能够继续下一步了。
建立 travis-ci 配置文件 .travis.yml
, 文件内容。
language: node_js node_js: - "node" - "8.9.4"
至此基本完成了项目开发和测试代码编写的过程,下一步就能够接入 travis-ci 测试了。
经过GitHub登陆 travis-ci 的官网
找到GitHub上刚才建立的须要测试的项目,并开启测试
查看测试过程,及时发现问题。
查看测试状态是否经过测试,若是未经过及时排查问题反复修改;若是经过能够在项目文档中添加一个测试经过的标识。
以上内容就是本篇的所有内容,以上内容但愿对你有帮助,有被帮助到的朋友欢迎点赞,评论。