前端单元测试---孤勇者级教程,2024年最新腾讯软件测试面试题社招

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
img

正文

It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!

官方的介绍就是上面2段话,就是说jest是一个让人愉悦的js测试框架,专注于简单性。可以配合babel、ts、node、react、angular、vue等其他库 一起使用。

我们前文提及的什么describe、test、expect方法等等在Jest中都有相应的api。

一、基础教程

安装

可以使用yarn或者npm进行安装

yarn add jest -D | npm i jest -D

源码开发

这里举了一个简单的例子,实际组件开发需要使用ts以及其他UI测试框架。

例如开发一个基础方法,返回2个参数的和。文件名为sum.ts

// sum.js
function sum(a, b) {
return a + b;
}
export default sum;

测试用例编写

首先我们根据上面的目标文件(sum.js)创建一个测试用例文件-- sum.test.js, 测试用例文件名称统一为*.test.js(后缀根据实际场景区分为.js或者.ts或者.tsx)

// sum.test.js
import sum from ‘./sum’;

test(‘adds 1 + 2 to equal 3’, () => {
expect(sum(1, 2)).toBe(3);
});

开始测试

添加下面的部分到你的package.json中

{
“scripts”: {
“test”: “jest”
}
}

最后,执行yarn testornpm run test命令,Jest将会打印如下信息:

PASS ./sum.test.js
✓ adds 1 + 2 to equal 3 (5ms)

就这样,基于jest的一个基础单元测试流程走好了,Jest的单元测试核心就是在test方法的第二个参数里面,expect方法返回一个期望对象,通过匹配器(例如toBe)进行断言,期望是否和你预期的一致,和预期一致则单元测试通过,不一致则测试无法通过,需要排除问题然后继续进行单元测试。

更多的配置以及命令行参数请参考官方文档下面开始讲解一些核心API。

二、核心API

全局方法

在你的测试文件中,Jest将下面这些方法和对象放置全局环境,所以你无需再显式的去require或者import。当然,如果你更喜欢显式的import,也可以使用例如import { describe, expect, it } from '@jest/globals’的方式。

1、test(name, fn, timeout)

test有别名it,两个方法是一样的。

第一个参数是你想要描述的测试用例名称; 第二个参数是包含测试期望的函数,也是测试用例的核心。第三个参数(可选)是超时时间,也就是超过多久将会取消测试(默认是5秒钟)

Note: 如果fn返回的是个promise,Jest在完成测试前将会等待Promise达到resolved状态。具体情况本文下面也会讲到如何对异步代码进行测试。

匹配器

Jest使用匹配器可以让你使用各种方式测试你的代码,Jest中的匹配器实际就是expect方法返回的期望对象中包含的相关方法。官方提供了非常多的匹配器,完善的学习请查看官方文档。

下面摘选了几个最常见的匹配器方法。

1、.toBe(value)

toBe是最简单最基础的匹配器,就是判定是否精确匹配,toBe方法使用了Object.is方法来测试精确相等。

Object.is方法的判定准则可以参考这里

test(‘two plus two is four’, () => {
expect(2 + 2).toBe(4);
});

在测试中,你有时需要区分 undefined、 null,和 false,但有时你又不需要区分。 Jest 让你明确你想要什么。

  • toBeNull 只匹配 null
  • toBeUndefined 只匹配 undefined
  • toBeDefined 与 toBeUndefined 相反
  • toBeTruthy 匹配任何 if 语句为真
  • toBeFalsy 匹配任何 if 语句为假

2、.not

非常容易理解,一般就是反向测试

test(‘two plus two is four’, () => {
expect(2 + 2).not.toBe(4);
});

3、.toEqual

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

和上面的toBe进行对比,toBe对比俩对象对比的是内存地址,toEqual比的是属性值。

test(‘object assignment’, () => {
const data1 = { one: 1, two: 2 };
const data2 = { one: 1, two: 2 };
expect(data1).toBe(data2); // 测试失败
expect(data1).toEqual(data2);// 测试通过
});

4、expect.assertions

expect.assertions(number) 验证一定数量的断言在某个测试用例中被调用。通常在异步代码测试中非常有用,目的就是为了确保所有的断言被真实的调用了。

比如下面这个例子,如果去掉了expect.assertions(2), 那么测试用例会通过测试,但实际的需求应该是失败的,因为我们最初的期望是catch中的断言也会被调用。而有了expect.assertions(2),Jest会判断断言实际调用的数量和我们预期是否一致,如果不一致则说明测试失败。

test(‘doAsync calls both callbacks’, () => {
expect.assertions(2);
return Promise.resolve(123).then((data: number) => {
expect(data).toBe(123);
return; // 例如手抖写了return
// 因为某些原因下面的代码没有执行
throw new Error(‘报错了’);
}).catch(err => {
expect(err).toBe(‘报错了’);
});
});

异步代码测试

在JavaScript中执行异步代码是很常见的。 当你有以异步方式运行的代码时,Jest 需要知道当前它测试的代码是否已执行完成,然后它可以转移到另一个测试。 Jest有若干方法处理这种情况。

回调

最常见的异步模式就是回调函数,例如下面的setTimeout方法,下面的测试用例无法通过,原因是Jest无法知道callback具体的调用时间,所以会造成测试已经结束,但是setTimeout的callback还没有执行。

test(‘the data is peanut butter’, () => {
function callback(data: string) {
expect(data).toBe(‘peanut butter’);
}
setTimeout(() => {
callback(‘peanut butter’);
}, 2000);
});

想要解决上面的问题,非常简单,很容易就会联想到消息通知机制,也就是在callback调用的时候通知Jest,表示当前测试用例通过,可以跑下一个测试。

test方法的第二个参数fn,可以添加一个done参数,done是一个方法,调用了done,就是通知Jest测试完成,当然如果你的测试用例中的done方法始终没有执行,那么你的测试也会失败(超时),所以最好的方式就是加上try catch。

test(‘the data is peanut butter’, done => {
function callback(data: string) {
try {
expect(data).toBe(‘peanut butter’);
done();
} catch (err) {
done(err);
}
}
setTimeout(() => {
callback(‘peanut butter’);
}, 2000);
});

Promise

如果你的代码使用了Promise, Jest提供了一种更加直接的方式去处理异步测试。在test第二个参数fn中直接返回一个promise,Jest就会等待这个promise达到resolved状态,如果达到了fulfilled状态,测试将会自动失败。

例如这个案例,此测试用例能够正常的通过

test(‘promise resolved’, () => {
return new Promise(resolve => {
setTimeout(() => {
resolve(‘resolved’);
}, 2000);
}).then((data: string) => {
expect(data).toBe(‘resolved’);
});
});

如果promise fulfilled如下,则测试用例会跑失败

test(‘promise fulfilled’, () => {
return Promise.reject(‘fulfilled’).then((data: string) => {
expect(data).toBe(‘fulfilled’);
})
});

当然我们也可以使用catch方法,例如下面这个例子,测试用例就能够正常的通过。

test(‘promise fulfilled’, () => {
expect.assertions(1);
return Promise.reject(‘fulfilled’).catch(err => {
expect(err).toMatch(‘fulfilled’);
});
});

promise代码可以配合匹配器.resolves和rejects一起使用,使用案例如下:

test(‘promise resolved’, () => {
return expect(Promise.resolve(‘resolved’)).resolves.toBe(‘resolved’);
});
test(‘promise fulfilled’, () => {
return expect(Promise.reject(‘fulfilled’)).rejects.toMatch(‘fulfilled’);
});

Async/Await

如果你的代码使用了Promise, Jest提供了一种更加直接的方式去处理异步测试。在test第二个参数fn中直接返回一个promise,Jest就会等待这个promise达到resolved状态,如果达到了fulfilled状态,测试将会自动失败。

const TEN = 10;
const BASE = 5;
function fetchData () {
return new Promise((resolve, reject) => {
const random = Math.random() * TEN;
random > BASE ? resolve(random) : reject(random);
});
}

test(‘the random promise’, async () => {
expect.assertions(1);
try {
const random = await fetchData();
expect(random).toBeGreaterThan(BASE);
} catch (e) {
expect(e).toBeLessThanOrEqual(BASE);
}
});

Mock Functions

Mock 函数简单的说就是模拟一个函数,这个功能很强大,例如nodejs中没有DOM/BOM,及时是jsdom也会缺少一些api,那么我们可以使用mock函数来进行一些测试,具体暂不详细说明。

有两种方法可以模拟函数:要么在测试代码中创建一个 mock 函数,要么编写一个手动 mock来覆盖模块依赖。

Mock Functions Doc

使用 mock 函数

假设我们要测试函数 forEach 的内部实现,这个函数为传入的数组中的每个元素调用一次回调函数。

function forEach(items, callback) {
for (let index = 0; index < items.length; index++) {
callback(items[index]);
}
}

为了测试此函数,我们可以使用一个 mock 函数,然后检查 mock 函数的状态来确保回调函数如期调用。

const mockCallback = jest.fn(x => 42 + x);
forEach([0, 1], mockCallback);

// 此 mock 函数被调用了两次
expect(mockCallback.mock.calls.length).toBe(2);

// 第一次调用函数时的第一个参数是 0
expect(mockCallback.mock.calls[0][0]).toBe(0);

// 第二次调用函数时的第一个参数是 1
expect(mockCallback.mock.calls[1][0]).toBe(1);

// 第一次函数调用的返回值是 42
expect(mockCallback.mock.results[0].value).toBe(42);

.mock 属性

所有的 mock 函数都有这个特殊的 .mock属性,它保存了关于此函数如何被调用、调用时的返回值的信息。 .mock 属性还追踪每次调用时 this的值,所以我们同样可以也检视

Mock 的返回值

const filterTestFn = jest.fn();

// Make the mock return true for the first call,
// and false for the second call
filterTestFn.mockReturnValueOnce(true).mockReturnValueOnce(false);

const result = [11, 12].filter(num => filterTestFn(num));

console.log(result);
// > [11]
console.log(filterTestFn.mock.calls);
// > [ [11], [12] ]

Mocking Modules

在Jest单元测试的真实场景中,会有很多的数据来自接口,但是Jest并不推荐直接在测试代码中去调用真实的接口,因为这可能会让测试变得非常缓慢而且脆弱,所以jest.fn().mockResolvedValue提供了mock接口的方式,使用假数据进行测试。

test(‘async test’, async () => {
const asyncMock = jest.fn().mockResolvedValue(23);
const result = await asyncMock(); // 43
expect(result).toBe(23);
});

快照测试

每当你想要确保你的UI不会有意外的改变,快照测试是非常有用的工具。

一点典型的快照测试案例就是一个移动端的app渲染一个UI组件,拍下快照,然后将其与之前测试存储的参考快照文件进行对比,如果2个快照不匹配的话测试就会失败。简单的来说就是对比前后2次组件渲染的照片,这个测试方法非常适合React这类UI框架。

Jest快照测试第一次会生成一个快照文件,就像下面这样

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[component--Loading 单元测试start 1] = `

努力加载中...
`;

我们可以在Jest 命令中加入–updateSnapshot,这样快照有跟新的话会跟新快照文件而不是直接让整个快照测试失败了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ing 单元测试start 1] =

努力加载中...
`;

我们可以在Jest 命令中加入–updateSnapshot,这样快照有跟新的话会跟新快照文件而不是直接让整个快照测试失败了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-gtapWds1-1713468454460)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值