大前端测试

引子

在之前分享的编辑器相关文章里,讲到了语雀是全栈js开发的,并且号称团队没有测试工程师,参考文章里面有放关于全栈 JavaScript 测试的相关总结分享,今天我们就聊一聊前端的测试。

单元测试

  1. 定义:

在计算机编程中,单元测试(Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。
程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

  1. 意义
  • 提升能力
  • 提升效率:及早发现问题
  • 追求卓越:有助于开发人员去思考代码结构的设计,让代码更加有利于测试
  • 覆盖全面:能够覆盖到QA测试覆盖不到的情况
  • 大型项目,协同开发,公共抽离组件会出现一些问题,有了单测后,更强壮,更易读,升级时,回归测试任务少,提升公共组件的质量。
  1. 测试方法论 TDD&BDD
  • TDD:Test-driven development 测试驱动开发
    TDD 从测试的角度来检验整个项目。大概的流程是先针对每个功能点抽象出接口代码,然后编写单元测试代码,接下来实现接口,运行单元测试代码,循环此过程,直到整个单元测试都通过。
  • BDD:Behavior Driven Development 行为驱动开发
    是通过编写行为和规范来驱动软件开发。更注重功能本身。
  1. 原则:FIRST
  • F fast 快速 过程快
  • I Isolate 隔离 测试用例应当独立执行,避免一个测试结果依赖于另外一个。需要把测试分解成尽可能小的单元,这将帮我们确定在错误发生时的确切代码位置。
  • R Repeatable 可重复:多次运行测试应该产生相同的结果,如果不确定,就不知道哪些结果是有效的,哪些又是无效的。另外,反复性可以确保我们的测试不依赖于外部因素(诸如网络或 CPU 负载)。
  • S Self-validating 自我验证无需人工
  • T Timely 及时,上线前
  1. 测什么
    结果正确
    边界条件检查
    反向关联(加密解密 读写操作)
    强制错误条件

  2. 测试的核心
    断言(assert)即表达程序设计人员对于系统应达到状态的一种预期。

前端测试框架:

帮助我们把测试代码抽离出来,作为一个整体结构化地去设计测试用例,放置到专门测试文件,然后也可以实现自动运行以及显示测试结果。
介绍:
Mocha,Jest,Jasmine 可以说都是测试框架,可以达到之前说的,抽离,结构化,自动运行等等,其中 Jest 是一个相当全面的框架,且零配置,同时需要注意的是 Jest 也是基于 Jasmine 的,所以 Jest 的一些语法和 Jasmine 一模一样,连报错有时都会相同。
Chai,Should 都属于断言库,它们的 API 相对测试框架自带的断言 API 更加语义化,更好用,可以和上面的测试框架结合着用。
Karma 是一个 Test-Runner,可以说是凌驾测试框架之上,可以让给你的浏览器自动跑所有的测试用例。
Enzyme是由airbnb开发的React单元测试工具。它扩展了React的TestUtils并通过支持类似jQuery的find语法可以很方便的对render出来的结果做各种断言。

Jest

https://github.com/facebook/jest star 36.2k
Jest是Facebook开发的一个测试框架,它集成了测试执行器、断言库、spy、mock、snapshot和测试覆盖率报告等功能。React项目本身也是使用Jest进行单测的,因此契合度相当高。

  • 自带断言函数
exspect(运行结果).toBe(期望的结果);
//常见断言方法
expect({a:1}).toBe({a:1})//判断两个对象是否相等
expect(1).not.toBe(2)//判断不等
expect({ a: 1, foo: { b: 2 } }).toEqual({ a: 1, foo: { b: 2 } })//判断相等
expect(n).toBeNull(); //判断是否为null
expect(n).toBeUndefined(); //判断是否为undefined
expect(n).toBeDefined(); //判断结果与toBeUndefined相反
expect(n).toBeTruthy(); //判断结果为true
expect(n).toBeFalsy(); //判断结果为false
expect(value).toBeGreaterThan(3); //大于3
expect(value).toBeGreaterThanOrEqual(3.5); //大于等于3.5
expect(value).toBeLessThan(5); //小于5
expect(value).toBeLessThanOrEqual(4.5); //小于等于4.5
expect(value).toBeCloseTo(0.3); // 浮点数判断相等
expect('Christoph').toMatch(/stop/); //正则表达式判断
expect(['one','two']).toContain('one'); //包含
  • 支持异步测试
  • 支持Dom测试
  • Mock Functions

一个简单的示例:

  1. 安装 npm install --save-dev jest
  2. 新建测试文件 unit.test.js
import {dealData} from "./src/util/Util";

describe("dealData测试",()=>{
  test('dealData 1 GB to equal 1 GB', () => {
    expect(dealData(1, 'GB')).toEqual({
      value:1,
            unit:'GB'
    });
  });
  //输入数据大于1024GB则转换为TB
  test('dealData 2048 GB to equal 2 TB', () => {
    expect(dealData(2048, 'GB')).toEqual({
      value:2,
            unit:'TB'
    });
  });
  //输入数据大于1024*1024*10GB则转换为PB
  test('dealData 20971520 GB to equal 20 PB', () => {
    expect(dealData(20971520, 'GB')).toEqual({
      value:20,
            unit:'PB'
    });
  });
  //PB为最大单位,不进行进一步处理
  test('dealData 419430400 GB to equal 20 PB', () => {
    expect(dealData(41943040000, 'GB')).toEqual({
      value:40000,
            unit:'PB'
    });
  });
  //其他单位不进行转换
  test('dealData 1 KB to equal 1 KB', () => {
    expect(dealData(1, 'KB')).toEqual({
      value:1,
            unit:'KB'
    });
  });
  //接口异常时数据不进行转换
  test('dealData --  to equal --', () => {
    expect(dealData('--', '')).toEqual({
      value:'--',
            unit:''
    });
  });
})

注:dealData 是一个抽离出来的工具函数,帮助动态处理业务数据单位

  1. package.json中增加代码
{
  "scripts": {
    "test": "jest"
  }
}
  1. 运行npm run test
    image.png

Enzyme

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

项目实战时,结合jest和enzyme。

Enzyme为我们提供来三种渲染组件的方法shallow、render、mount。
shallow 方法就是官方的shallow rendering的封装。
render 方法将React组件渲染成静态的HTML字符串,然后分析这段HTML代码的结构,返回一个对象。它跟shallow方法非常像,主要的不同是采用了第三方HTML解析库Cheerio,它返回的是一个Cheerio实例对象。
mount方法用于将React组件加载为真实DOM节点。

测试登录交互例子:

import Login from 'pages/Login';
import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { mount } from 'enzyme';
configure({ adapter: new Adapter() });

const wrapper = mount(<Login />);
describe('', () => {
 it('标题显示', () => {
   const title = wrapper.find('.title').text();
   expect(title).toBe('登录');
 })
 const accountInput = wrapper.find('.account').find('input');
 const accountTitle = wrapper.find('.account .name').find('span');
 it('输入不合法账号', () => {
     const event = {
         target: {
           value: 'abc123'
       }
     }
   accountInput.simulate('change', event);
   expect(accountTitle.text()).toBe('账户输入错误,请重新输入');
 })
})

uirecorder

https://github.com/alibaba/uirecorder star 1.8k
UI Recorder 是一款面向多端的 UI 自动化录制工具,类似于Selenium IDE 但比Selenium IDE 更加强大!
UI Recorder 非常简单易用,零成本解决测试回归问题。

功能:

  1. 支持所有用户行为: 键盘事件, 鼠标事件, alert, 文件上传, 拖放, svg, shadow dom
  2. 全平台支持,移动端 Android, iOS 录制, 基于 Macaca 实现
  3. 无干扰录制: 和正常测试无任何区别,无需任何交互
  4. 录制用例存储在本地
  5. 支持丰富的断言类型: val,text,displayed,enabled,selected,attr,css,url,title,cookie,localStorage,sessionStorage
  6. 支持图片对比
  7. 支持强大的变量字符串
  8. 支持公共测试用例: 允许用例中动态调用另外一个
  9. 支持并发测试
  10. 支持多国语言: 英文, 简体中文, 繁体中文
  11. 支持单步截图
  12. 支持HTML报告和JUnit报告
  13. 全系统支持: Windows, Mac, Linux
  14. 基于Nodejs的测试用例: jWebDriver

官方教程:https://www.yuque.com/artist/uirecorder/yd7ztf

  • 初始化工程
  • 开始录制,进行界面操作,可以添加断言,悬停等等
  • 结束录制,自动生成脚本文件
  • 利用已有脚本文件进行回归测试
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容