总结自动化测试

185 阅读5分钟

前端自动化测试

(内容有的来自其他帖子,自己做了整合)

一个需要多人合作、开发周期长的大规模前端项目 会出现

代码风格各不相同 、代码过度耦合 、组件职责不够单一 、新同学上手慢,因为项目大、杂、乱,

我们是否能够保证项目的稳定?如果在后续的维护中,一不小心影响到了之前的功能怎么办?类似这种通用库,发布一个有严重 Bug 的版本,可能就会造成成百上千的项目一起崩溃

我们需要自动化测试。

对核心组件覆盖自动化测试,可以有效地保证组件功能的单一,起到警醒工程师的作用,而不至于让不同的业务代码相互耦合;新同学可以通过单测快速 get 到这个组件打算做什么、有什么能力,不论是后续的维护还是重构都会更有底气

技术选型上使用 Jest + React Testing Library + Cypress + Storybook。

vue项目推荐用vitest

单元测试 or 端对端测试

单元测试是更细粒度的、从代码组件层次进行的功能测试

端对端测试是从用户视角,从项目整体展开的测试

仅通过 Jest 没办法完成前端的所有单元测试,因为与常规的接口逻辑测试不同,前端的单元测试涉及到 Dom 和事件的模拟,我们还需要选用一个辅助库来协助我们模拟相关的场景。

Jest 是基础的测试库,是安装 Enzyme 和 React Testing Library 的前置条件

安装jest

ts 版本

npm install --save-dev jest @types/jest @jest/types

初始化配置

npx jest --init

  • 前两个配置选项是字面意思,不赘述了。
  • 单测环境(jsdom):因为我们会涉及到 dom 的单测,不仅仅是纯逻辑,如果是纯逻辑的选 node。
  • 是否需要覆盖率报告(no):暂时用不上,后面覆盖率章节会着重介绍。
  • 编译代码(babel): 可以转 ES5,避免一些兼容性问题。
  • 每次测试完是否清理 mock、实例等结果(yes): 每次测试完成后会清理 mock 等上次测试的结果,可以避免用例之间的互相影响

运行

yarn jest

匹配器

Jest使用“匹配器”的机制让你可以使用各种方法进行测试

精确匹配

// 我希望执行这个函数》 传入的值 ,tobe 期望得到的值
test("adds 1 + 2 to equal 3" //name
     , () => {
  expect(add(1, 2)).toBe(3);
});

比如

test('获取最大值',()=>{
  expect(FindMax([1,3,46,7])).toBe(46); //期望得到46
})

toEqual

递归检查对象或数组的每个字段

test("对象赋值", () => {
  const data = { one: 1, two: 51 };

  expect(data).toEqual({ one: 1, two: 2 });
});

image-20230112150745866

//会标注期望的值的地方哪里有问题

使用 toStrictEqual 优于使用 toEqualtoEqual 只是简单地忽略 undefined 值,而 toStrictEqual 则考虑它们。

匹配相反的 not

真值

  • toBeNull 只匹配 null
  • toBeUndefined 只匹配 undefined
  • toBeDefinedtoBeUndefined 相反
  • toBeTruthy 匹配任何 if 语句为真
  • toBeFalsy 匹配任何 if 语句为假
test("真值", () => {
  const n = null;
  expect(n).toBeNull(); //为空通过
  expect(n).toBeDefined(); //undifend 取反
  expect(n).not.toBeUndefined();///undifend 取反
  expect(n).not.toBeTruthy(); //为假 加了 not
  expect(n).toBeFalsy(); //取的假
});

数字

大多数的比较数字有等价的匹配器。

对于比较浮点数相等,使用 toBeCloseTo 而不是 toEqual,因为你不希望测试取决于一个小小的舍入误差。 精度问题

字符串

您可以检查对具有 toMatch 正则表达式的字符串︰

test('there is no I in team', () => {
  expect('team').not.toMatch(/I/);
});

数组和可迭代对象

数组foreach的迭代寻找

你可以通过 toContain来检查一个数组或可迭代对象是否包含某个特定项:

const shoppingList = [  'diapers',  'kleenex',  'trash bags',  'paper towels',  'milk',];

test('shoppingList数组中包含milk', () => {
  expect(shoppingList).toContain('milk');
  expect(new Set(shoppingList)).toContain('milk');
});

例外

若你想测试某函数在调用时是否抛出了错误,你需要使用 toThrow

测试异步代码

异步请求的代码测试

Promise

test('the data is peanut butter', () => {
  return fetchData().then(data => {
  //期望的data 匹配器‘peanut butter’返回
    expect(data).toBe('peanut butter');
  });
});

哪里需要匹配在哪里添加

Async/Await

test('the data is peanut butter', async () => {
  const data = await fetchData();
  expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  try {
    await fetchData();
  } catch (e) {
    expect(e).toMatch('error');
  }
});

使用单个参数调用 done Jest会等done回调函数被调用执行结束后,再结束测试。

test('the data is peanut butter', done => {
  function callback(error, data) {
    if (error) {
      done(error); //最后执行
      return;
    }
    try {
      expect(data).toBe('peanut butter');
      done();
    } catch (error) {
      done(error);
    }
  }

  fetchData(callback);
});

分组测试

t给了我们更优雅的写法---分组,我们使用describe函数分组,如下

describe('分别测试Count的4个方法', () => {
    test('测试increase', () => {
        //1
    })
    test('测试decrease', () => {
        //2
    })
    test('测试double', () => {
        //3
    })
    test('测试half', () => {
        //4
    })
})

作者:catboy
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

beforeEach是在每一个test函数执行之前,会被调用;afterEach则是在每一个test函数执行之后调用;beforeAll是在所有test函数执行之前调用;afterAll则是在所有test函数执行之后调用。

可以自定义这4个周期的函数执行路径

describe("分别测试Count的4个方法", () => {
//所有
  beforeAll(() => {
    console.log("before all tests!");
  });
// 之前
  beforeEach(() => {
    console.log("before each test!");
    // count = new Count()
  });
// 后面说有
  afterAll(() => {
    console.log("after all tests!");
  });
  //每一个函数后面
  afterEach(() => {
    console.log("after each test!");
  });

  test("测试increase", () => {
    // count.increase()
    console.log(1);
  });
  test("测试decrease", () => {
    // count.decrease()
    console.log(2);
  });
  test("测试double", () => {
 
    console.log(3);
  });
  test("测试half", () => {
    // count.half()
    console.log(4);
  });
});

jest监听文件变化

"scripts": {
    "test": "jest",
    "test-watch": "jest --watch"
},

改变文件

会出现

image-20230112154324908

  1. a键运行所有测试代码
  2. f键只运行所有失败的测试代码
  3. p键按照文件名筛选测试代码(支持正则)
  4. t键按照测试名筛选测试代码(支持正则)
  5. q键盘推出watch模式
  6. enter键触发一次测试运行

生成测试覆盖率文件

"scripts": {
    "test": "jest",
    "test-watch": "jest --watch",
    "coverage": "jest --coverage"
},

检查我们测试代码占用整个项目的覆盖率是多少