前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单元测试初体验

单元测试初体验

作者头像
零式的天空
发布2022-03-25 15:13:40
1.6K0
发布2022-03-25 15:13:40
举报
文章被收录于专栏:零域Blog

博客背景:单元测试作为今年的全组通用任务,要求在所有项目中实施,每个人都需要会写单元测试。所以我在上周进行了一下单元测试的调研,这次调研的方向是主要使用 Mocha 基于 Karma 进行包括 UI 层的单元测试。

下面我主要描述一下搭建这套单元测试环境和开发的所用技术,和具体的 demo。

使用的工具介绍

  1. 使用 JavaScript 测试执行过程管理工具 Karma Karma是一个基于 Node.js 的 JavaScript 测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器。这个测试工具的一个强大特性就是,它可以监控(Watch)文件的变化,然后自行执行,通过 console.log 显示测试结果。
  2. 单元测试框架 Mocha Mocha 是 JavaScript 的一种单元测试框架,既可以在浏览器环境下运行,也可以在 Node.js 环境下运行。
  3. 断言库 Chai Chai 是一个针对 Node.js 和浏览器的行为驱动测试和测试驱动测试的断言库,可与任何 JavaScript 测试框架集成。
  4. 测试辅助工具 Sinon Sinon 是一个独立的 JavaScript 测试 spy, stub, mock库,没有依赖任何单元测试框架工程。

Karma 的部分 API

代码语言:javascript
复制
// karma.conf.js
module.exports = function(config) {
  config.set({

    // Type: String。默认为""。将用于解析files和exclude中定义的所有相对路径的根路径位置。如果basePath的配置是一个相对路径,那么它将被解析到__dirname的配置文件中。
    basePath: '',

    // Type: Array。默认为[]。你要使用的测试框架列表。通常情况下,你会设置该值为['jasmine'], ['mocha'] 或 ['qunit']…
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    // frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
    frameworks: ['mocha', 'sinon-chai', 'source-map-support'],

    // Type: Array。默认为[]。在浏览器中加载的文件/模式列表。
    files: [
      // {pattern: 'test/**/*.js', included: false}
      'src/**/*.test.js'
    ],

    // Type: Array。默认为[]。从加载文件中排除的文件/模式的列表
    exclude: [
    ],

    // Type: Object。默认为{'**/*.coffee': 'coffee'}。要是用的预处理器的映射。预处理器可以通过插件加载。
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'src/**/*.test.js': ['webpack', 'sourcemap']
    },

    // Type: Array。默认为 ['progress']。 
    // 可能的值:
    //  · dots
    //  · progress。
    // 使用的报告者(reporter)列表。
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['spec', 'coverage'],

    // Type: Number。默认值为9876。设置将被web服务器监听的端口。
    port: 9876,

    // Type: Boolean。默认为true。启用或禁用输出(报告和日志)的颜色
    colors: true,

    // Type: Constant。默认为config.LOG_INFO。
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_ERROR,

    // Type:Boolean。默认为true。启用或禁用监视文件,当这些文件被改变时,执行测试。
    autoWatch: true,

    // 该值是要启动和捕获的浏览器列表。当Karma启动时,它也会启动放置在这个设置中的每个浏览器。一旦Karma关闭,它也会关闭这些浏览器。您可以通过打开浏览器并访问Karma Web服务器正在侦听的URL来手动捕获任何浏览器(默认情况下为http://localhost:9876/)。
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    // browsers: ['PhantomJS'],
    browsers: ['Chrome'],

    // Type: Boolean。默认为false。持续集成模式。
    // 如果该值为true,karma将会启动和捕获配置的浏览器,运行测试然后退出,退出使用的代码0或1取决于测试是成功还是失败。
    singleRun: false,

    // Type: Number。默认为"Infinity"。karma并行启动多少个浏览器。使用该配置,你可以指定在同一时间点上,一次运行多少个浏览器。
    concurrency: Infinity,

    // coverage 配置项
    coverageReporter: {
      reporters:[
        {type: 'html', dir: 'coverage/'},
        {type: 'text-summary'}
      ]
    }
  }
}

Mocha 的部分 API

代码语言:javascript
复制
describe('标题', function() {
  it('断言内容', function() {
    // 断言部分
  });
});

Chai 的部分 API

Chai 支持 BDD 风格的 expect/should API 和 TDD 风格的 Assert API。

expect 和 should是 BDD 风格的,二者使用相同的链式语言来组织断言,但不同在于他们初始化断言的方式:expect 使用构造函数来创建断言对象实例,而 should 通过为 Object.prototype 新增方法来实现断言(所以 should 不支持 IE);expect 直接指向chai.expect,而 should 则是 chai.should()。

语言链

下面的接口是单纯作为语言链提供以期提高断言的可读性。除非被插件改写否则它们一般不提供测试功能。

to be been is that which and has have with at of same

.not

对之后的断言取反

代码语言:javascript
复制
expect(foo).to.not.equal('bar')
expect(goodFn).to.not.throw(Error)
expect({ foo: 'baz'}).to.have.property('foo')
  .and.not.equal('bar')

.deep

设置 deep 标记,然后使用 equal 和 property 断言。该标记可以让其后的断言不是比较对象本身,而是递归比较对象的键值对。

代码语言:javascript
复制
expect(foo).to.deep.equal({ bar: 'baz'})
expect({ foo: { bar: { baz: 'quux'}}})
  .to.have.deep.property('foo.bar.baz', 'quux')

.a(type) / .an(type)

type:String,被测试的值的类型 a 和 an 断言即可作为语言链又可作为断言使用

代码语言:javascript
复制
// 类型断言
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');

.include(value) / contains(value)

value:Object | String | Number

include() 和 contains() 即可作为属性类断言前缀语言链又可作为作为判断数组、字符串是否包含某值的断言使用。当作为语言链使用时,常用于 key() 断言之前

代码语言:javascript
复制
expect([1, 2, 3]).to.include(2)
expect('foobar').to.include('bar')
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo')

.ok

断言目标为真值。

代码语言:javascript
复制
expect('everything').to.be.ok
expect(1).to.be.ok
expect(false).to.not.be.ok
expect(null).to.not.be.ok

.true

断言目标为 true。注意,这里与 ok 的区别是不进行类型转换,只能为 true 才能通过断言

代码语言:javascript
复制
expect(true).to.be.true
expect(1)to.not.be.true

.false

断言目标为 false

代码语言:javascript
复制
expect(false).to.be.false
expect(0).to.not.be.false

.NaN

断言目标为非数字 NaN

代码语言:javascript
复制
expect('foo').to.be.null
expect(4)to.not.be.null

.exist

断言目标存在,即非 null 也非 undefined

代码语言:javascript
复制
var foo = 'hi',
  bar = null,
  baz

expect(foo).to.exist
expect(bar).to.not.exist
expect(baz).to.not.exist

.empty

断言目标的长度为 0。对于数组和字符串,它检查 length 属性,对于对象,它检查可枚举属性的数量

代码语言:javascript
复制
expect([]).to.be.empty
expect('').to.be.empty
expect({}).to.be.empty

Sinon API 介绍

辅助工具库 Sinon 主要有三个Api:spy, stub, mock

spy

翻译过来的意思是 “监视”。

sinon.js 中 spy 主要用来监视函数的调用情况,sinon 对待监视的函数进行 wrap 包装,因此可以通过它清楚的知道,该函数被调用过几次,传入什么参数返回什么结果,甚至是抛出的异常情况。

代码语言:javascript
复制
var spy = sinon.spy(orginObj, 'launch');
spy.restore();

当 spy 使用完成后,切记把它恢复成原始函数,就像上边例子中最后一步那样。如果不这样做,你的测试可能会出现不可预知的结果。

stub

使用 stub 来嵌入或者直接替换掉一些代码,来达到隔离的目的。stub 是代码的一部分。在运行时用 stub 替换真正代码,忽略调用代码的原有实现。目的是用一个简单一点的行为替换一个复杂的行为,从而独立地测试代码的某一部分。它拥有 spy 提供的所有功能,区别在于它会完全替换掉目标函数,而不只是记录函数的调用信息。换句话说,当使用 spy 时,原函数还会继续执行,但使用 stub 时就不会。

Mocks

Mocks 是使用 stub 的另一种途径。如果你曾经听过“mock 对象”这种说法,这其实是一码事 —— Sinon 的 mock 可以用来替换整个对象以改变其行为,就像函数 stub 一样。

单元测试 Demo

这里的一些 Demo,结合了公司内部的代码进行了实际单元测试的书写,因为涉及公司业务代码,暂不公开。请前往公司 gitlab 查看相关 Demo。

  1. 正常单元测试,git地址:https://git.ms.netease.com/changxiao/unitTest
  2. 基于 Vue 开发的组件进行 UI 层测试,主要测试 Dom 的改变,事件的触发。git 地址:https://git.ms.netease.com/guessing/fe/tree/f_unit

参考

https://mochajs.org/ https://cn.vuejs.org/v2/guide/unit-testing.html http://blog.csdn.net/maomaolaoshi/article/details/78542837 https://www.cnblogs.com/wyqlxy/p/7131079.html http://blog.csdn.net/hustzw07/article/details/74178051 http://www.zcfy.cc/article/sinon-tutorial-javascript-testing-with-mocks-spies-stubs-422.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用的工具介绍
  • Karma 的部分 API
  • Mocha 的部分 API
  • Chai 的部分 API
    • 语言链
      • .not
        • .deep
          • .a(type) / .an(type)
            • .include(value) / contains(value)
              • .ok
                • .true
                  • .false
                    • .NaN
                      • .exist
                        • .empty
                        • Sinon API 介绍
                          • spy
                            • stub
                              • Mocks
                              • 单元测试 Demo
                              • 参考
                              相关产品与服务
                              持续集成
                              CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档