[ Jest ] 自动化测试 Jest 的使用总结基础篇

2021-08-23 14:31:53 浏览数 (2)

使用 jest 的原因

随着前端的发展,web的交互越来越复杂,自动化测试是非常有必要融入到开发的流程中,而目前界内普遍通用且比较火的就是有 facebook开发的 Jest 这套工具。他可以创建测试用例,执行测试,自身还有驱动和mock,且用起来也是很方便,正如 jest 的官网这样描述 jest,Jest is a delightful JavaScript Testing Framework with a focus on simplicity.

验证参数是否正确

jest 提供了多种匹配器可以对不同的数据类型做匹配,比如:array,string,object 等等,而它们的匹配器分别是 toContain ,toMatch,toEqual。同时, jest 也支持做不匹配的校验,也就是反向的校验。下面就是一些不同的匹配器。

简单类型的校验;

使用 tobe() 匹配器做简单类型的校验,校验结果是否正确。

代码语言:txt复制
// index.js
const sum = (a, b) => {
    return a   b;
}

// index.test.js
test('adds 1   2 to equal 3', ()=>{
    expect(sum(1,2)).toBe(3)
});

数组或者对象的校验

代码语言:txt复制
// index.js
const objectTest = () => {
    const data = {name: 'jest'};
    data['age'] = 20;
    return data;
}  

// index.test.js
test('object test', ()=>{
    const obj = sum.objectTest();
    expect(obj).toEqual({name: "jest",age: 20})
});

toEqual 会进行递归检查对象或者是数组。

判断数据是否为空的情况

官方文档把这一类的校验命名为 Truthiness ,也就是有效性。这里是以我自己的理解,我一般就把这样的情况称为 “空”,这里不仅可以判断 null 的情况也可以判断 undefine 等等的情况。

代码语言:txt复制
// index.js
const nullTest = () =>{
    return null;
};

// index.test.js
test('null test', ()=>{
    const params = sum.nullTest();
    expect(params).toBeNull()
});

条件判断的情况

像 number 这个类型,他也可以判断是否大于某一个值。

代码语言:txt复制
// index.js
const sum = (a, b) => {
    return a   b;
}

// index.test.js
test('adds 1   2 to equal 3', ()=>{
    expect(sum(1,2)).toBeGreaterThan(2)
});

判断字符类型

字符类型是通过增则匹配的方法去进行校验。

代码语言:txt复制
// index.js
const textTest = () =>{
    return 'there is no I in team';
};

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

验证异步情况下参数是否正确

callback 函数校验

使用 jest 做回调操作测试需要注意,函数的回掉情况。如下面的代码:

代码语言:txt复制
test('success', () => {
  function callback(data) {
    expect(data).toBe('success');
  }
  fetchData(callback);
});

官网上特别标记了这样的情况,这样是拿不到他的异步状态的,他的同步代码执行完毕之后,才能拿到异步的数据,而这里他是执行完,test 就停止了。

应该改为的写法是:

代码语言:txt复制
test('test ajax', done => {
    function callback(data) {
        try {
            expect(data).toBe('fight');
            done();
        } catch (error) {
            done(error);
        }
    }
    sum.fetchData(callback);
});  

当 done 这个参数函数一直没有执行的话,这个 test 用例就会报错。在 ecpect 执行失败之后,不会执行 done(). 同时,他会触发 catch 输出 error 日志。

promises 异步校验

使用 promises 那么会有更简单的方法进行校验操作,只需要返回一个 promises ,再监听这个 promises 的 resolve 状态。

代码如下:

代码语言:txt复制
// index.js
const promiseFetchData = async () =>{
    return new Promise((resolve,reject)=>{
        resolve('fight');
    })
}
// index.test.js
test('test ajax', () => {
    return promiseFetchData().then((data)=>{
        expect(data).toBe('fight')
    });
});  

resolve 传递返回值,再交给 expect 接收校验。

async / await

使用 async / await 标记,进行异步校验,本质上和 promise 的异步校验没有什么区别,只是使用 async / await 是可以获取结果之后在下一步校验,现在的话,这样的方法可能会更加的常见。

代码语言:txt复制
// index.js
const asyncFetchData = () =>{
    return new Promise((resolve,reject)=>{
        resolve('fight');
    });
};
// index.test.js
test('test ajax', async () => {
    const data = await sum.asyncFetchData();
    expect(data).toBe('fight');
}); 

如果期望是异常状态的情况可以使用 catch 进行捕获,异常情况的测试一般是在一些兜底逻辑的情况下,获取异常情况再执行特定的逻辑。

代码语言:txt复制
// index.js
const asyncErrorFetchData = ()=>{
    return new Promise((resolve,reject)=>{
        reject('error');
    });
}
// index.test.js
test('test ajax error', async () => {
    expect.assertions(1);
    try {
        const data = await sum.asyncErrorFetchData();
      } catch (e) {
        expect(e).toMatch('error');
    }
});  

其中,在进行异常测试的时候需要加上 expect.assertions(1) 断言次数,否则测试不会通过,这个是jset 文档上特别标记的。但是我在本地上测试的时候,把这个东东给去掉之后,测试还是可以通过。

可能是在某一些场景下。

钩子函数的使用

钩子执行

再执行测试文件的时候,如果有需要对函数进行特殊处理的可以在执行前和执行后使用钩子函数,beforeEach and afterEach。

使用的方法如下:

代码语言:txt复制
beforeEach(() => {
    console.log('beforeEach')
});
afterEach(() => {
    console.log('afterEach')
});
test('adds 1   2 to equal 3', ()=>{
    expect(sum.sum(1,2)).toBeGreaterThan(2);
});

每执行一个 test 函数就会执行一次的 beforeEach and afterEach,如果在一些特定的情况下所有函数只需要只需要执行一次的话,可以使用 beforeAll and afterAll。那么,在执行所有的 test 之后,也只是会执行一次的 beforeAll and afterAll。

条件执行钩子

顾名思义,就是选在什么情况下才触发钩子函数,按需使用。

代码语言:txt复制
beforeAll(() => {
    console.log('beforeAll')
});
afterAll(() => {
    console.log('afterAll')
});
test('adds 1   2 to equal 3', ()=>{
    // expect(sum.sum(1,2)).toBe(3);
    expect(sum.sum(1,2)).toBeGreaterThan(2);
});
describe('child component', () => {
    // Applies only to tests in this describe block
    beforeEach(() => {
      console.log('child beforeEach')
    });
    test('adds 1   2 to equal 3', ()=>{
        // expect(sum.sum(1,2)).toBe(3);
        expect(sum.sum(1,2)).toBeGreaterThan(2);
    });
  });

这里他的输出顺序是:先是执行 beforeAll ,下一步执行 child beforeEach ,在执行 afterAll。

还有一个是按顺序加载,顺序加载就是按照现有的匹配顺序进行匹配,这里使用官网 demo 说明。

代码语言:txt复制
describe('outer', () => {
  console.log('describe outer-a');

  describe('describe inner 1', () => {
    console.log('describe inner 1');
    test('test 1', () => {
      console.log('test for describe inner 1');
      expect(true).toEqual(true);
    });
  });

  console.log('describe outer-b');

  test('test 1', () => {
    console.log('test for describe outer');
    expect(true).toEqual(true);
  });

  describe('describe inner 2', () => {
    console.log('describe inner 2');
    test('test for describe inner 2', () => {
      console.log('test for describe inner 2');
      expect(false).toEqual(false);
    });
  });

  console.log('describe outer-c');
});

// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test for describe inner 1
// test for describe outer
// test for describe inner 2

以上就是 jest 的基础用法,下一篇文章将会总结 jest 的高级用法。

0 人点赞