最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手摸手带你走入前端单元测试

    正文概述 掘金(涂鸦鸭)   2021-03-18   639

    背景

    测试是为了保证研发产品交付物质量的重要手段,也是软件生命周期的一部分 研发同学在此周期也是重要的参与者,毕竟 bug 都是同学们写的? 那么研发同学该如何理解测试呢?

    测试简介

    我们大致可以从两方面对测试分类,测试种类和测试阶段

    测试种类

    1. 功能测试:主要验证功能是否符合需求,是否遗漏
    2. 性能测试:主要关注系统提供能力,比如后端服务关注的 QPS, TPS,前端关注的 FCP,FMP 等指标
    3. 健壮性测试:主要关注系统的边界数据情况,非法数据会不会引起系统崩溃等
    4. 安全测试:主要是验证产品是否符合安全需求定义和产品质量标准的测试

    测试阶段

    1. 单元测试:本阶段主要是研发人员对当前最小可用功能的检查与验证
    2. 集成测试:单元测试通过后,对由几个子功能组成的子系统的测试
    3. 回归测试:检查已有功能的正确性检查
    4. 系统测试:在产品发布前做的最后一轮测试,对整个系统进行测试

    测试种类与测试阶段的关系

    测试阶段测试类型参与人员
    单元测试功能测试、健壮性测试研发同学集成测试功能测试、健壮性测试研发同学回归测试功能测试、健壮性测试、安全测试研发&测试同学系统测试功能测试、性能测试、健壮性测试、安全测试测试同学

    举个栗子

    假设我们现在有一部电梯

    功能测试:开门、关门、报警电话、轿厢上升、轿厢下降、不同楼层停留、不同楼层呼叫 健壮性测试:同时按上下呼叫按钮、不选楼层,选择全部楼层、载重量测试、停电测试 安全测试:超载报警测试,轿厢门阻塞报警测试 性能测试:1层到最高层空载耗时,1层到最高层满载耗时

    市场情况

    回归正题,测试在前端领域该怎么做,有哪些工具来帮助我们完成测试 对前端同学来说,前端测试分为两种,UT 和 E2E UT 测试就是我们常说的单元测试,我们围绕着功能 module 以及 function 来编写 test case,组合这些 test case 形成 test suits,来完成我们的单元测试 目前主流测试框架:jest, mocha, jasmine

    E2E 测试,是 End-to-End 测试,在此阶段,我们更关注整个操作链路的正确性 目前主流测试框架:playwright, pupeteer, nightwatch, phantomjs, selenium

    选型

    简便、通用、易学、高可扩展是框架选择的原则 结合市场情况,选择目前市场认可度最高的jest框架 jest 是由 Facebook 出品,集成了 expect, chalk, jsdom, jasmine, sinon 等测试库,同时通过一些插件,可以打通 E2E 测试,实现 UT 与 E2E 的全覆盖测试

    jest 简介

    jest 是一个驱动框架,负责运行测试用例,展示测试结果。我们是以 module 为单位书写具体的测试用例,每个 module 为一个独立的测试环境,jest 测试套件生命周期有 beforeAll, beforeEach, afterAll, afterEach 基本 api 有 describe, test, expect

    详细api地址:jestjs.io/zh-Hans/doc…

    来个栗子?:

    • GitHub:github.com/willchou/ut…
    • CodeSandBox:codesandbox.io/s/agitated-…
    import {initConfig, login, resetPassword, getChildrenAssetsByAssetId, addAsset} from '../src/utils';
    
    // 此module所有测试用例运行前执行
    beforeAll(() => {
      initConfig();
    })
    
    describe('account test', function () {
      describe('#login()', function() {
        test('should return true', function () {
          return login('test', 'test').then((res) => {
            expect(res).toBeTruthy();
          });
        })
      })
    
      // describe可以嵌套
      describe('#resetPassword()', function () {
        test('should return true', function() {
          return resetPassword('test', 'test', 'test1').then((res) => {
            expect(res).toBeTruthy();
          })
        });
    
        // describe中可以包含多个test case
        test('should return assets array', function () {
          return getChildrenAssetsByAssetId('1').then((res) => {
            return expect(res).toEqual([{
              assetId: '11',
              assetName: '11',
            }]);
          })
        })
      })
    })
    
    // test case可以脱离describe运行
    test('should return true', function () {
      return login('test', 'test').then((res) => {
        expect(res).toBeTruthy();
      });
    })
    
    test('should return full resp', function() {
      return addAsset('1', '1', {
        responseRaw: true,
      }).then((res) => {
        return expect(res).toMatchObject({
          data: {
            success: true,
            code: 200,
            msg: '',
            result: true,
          },
          status: 200,
          statusText: 'OK',
        })
      })
    })
    
    • 通过 expect 断言检测结果,参考上例
    • 支持异步处理,参考上例
    • 通过 Mock 方法,让测试更集中在待测试 function 本身, 参考例子2
    • 使用 snapshot,测试 ui 渲染的一致性,参考例子2
    • 测试覆盖率报告,jest --coverage

    功能代码:

    // example 2
    // mock function + snapshot
    // src/Clock.jsx
    import React, {useEffect, useState} from 'react';
    
    const Clock = () => {
      const [now, setNow] = useState(Date.now());
    
      useEffect(() => {
        const timer = setTimeout(() => {
          setNow(Date.now());
        }, 1000);
    
        return () => {
          clearTimeout(timer);
        }
      }, [])
    
      return (
        <div>
          timestamp is {now}
        </div>
      );
    }
    
    export default Clock;
    
    

    测试代码:

    // test/Clock.test.js
    import React from 'react';
    import render from 'react-test-renderer';
    import Clock from '../src/Clock';
    
    jest.useFakeTimers();
    Date.now = jest.fn(() => 1615972229101);
    
    beforeEach(() => {
      jest.clearAllTimers();
    })
    
    test('clock snapshot', () => {
      const tree = render.create(<Clock />).toJSON();
    
      expect(tree).toMatchSnapshot();
    })
    
    test('setTimeout tests', () => {
      const tree = render.create(<Clock />).toJSON();
      expect(setTimeout).toHaveBeenCalledTimes(2);
      expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1800);
    })
    
    

    测试结果:

    手摸手带你走入前端单元测试

    接下来,我们更新 Clock.jsx,line 18 文本有更新。这时 snapshot 结果发生变化,我们需要手动更新一下 snapshot 结果,否则测试用例还是会使用老版本的 snapshot 作为参照,导致测试结果不符合预期:

    import React, {useEffect, useState} from 'react';
    
    const Clock = () => {
      const [now, setNow] = useState(Date.now());
    
      useEffect(() => {
        const timer = setTimeout(() => {
          setNow(Date.now());
        }, 1800);
    
        return () => {
          clearTimeout(timer);
        }
      }, [])
    
      return (
        <div>
          the timestamp is {now}
        </div>
      );
    }
    
    export default Clock;
    

    没有更新 snapshot 时:

    手摸手带你走入前端单元测试

    更新 snapshot,并测试:

    手摸手带你走入前端单元测试

    总结

    测试需要投入大量资源开发维护,短期收益并不大,但从长远来看,可以帮忙开发和测试同学节省大量回归测试时间。同时,UT 测试还应该是研发同学自信的来源。UT 测试不一定适应每个项目和团队,短周期一次性项目和团队研发资源不足的场景就不太适合在 UT 测试投入资源。所以,还需结合项目实际情况和团队资源综合评估判断


    起源地下载网 » 手摸手带你走入前端单元测试

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元