| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 开发测试 -> 前端代码接入单元测试一 -> 正文阅读 |
|
[开发测试]前端代码接入单元测试一 |
一、单元测试发展
二、
|
类型 | 说明 |
---|---|
line coverage | 行覆盖率 |
function coverage | 函数覆盖率 |
branch coverage | 分支覆盖率 |
statement coverage | 语句覆盖率 |
7、常见的匹配器
8、全部的匹配器
babel
和typescript
来做单元测试1、安装依赖包,参考文档
yarn add jest ts-node babel-jest @types/jest @babel/core @babel/preset-env @babel/preset-typescript typescript -D
2、生成tscconfig.json
文件
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "src"
},
"exclude": ["node_modules"],
"include": ["./src/**/*.ts", "__tests__/**/*.ts"]
}
3、根目录下创建一个babel.config.js
的文件
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
'@babel/preset-typescript',
],
};
4、初始化jest
文件
npx jest --init
// jest.config.ts文件内容
export default {
// 用来检测测试文件的glob模式,
// 单元测试文件可以是在__tests__文件夹下以js、ts、jsx、tsx结尾的文件,也可以是spec.ts和test.ts结尾的文件
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[tj]s?(x)',
],
// 在每一次测试时自动清除mock调用和实例
clearMocks: true,
collectCoverage: true,
// 输出代码覆盖率的目录
coverageDirectory: 'coverage',
// 使用的模块的文件扩展名数组
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
// 用来跑测试的测试环境,可以选择jsdom或node
testEnvironment: 'jsdom',
};
5、在src
目录下创建match.ts
和match.spec.ts
文件
// match.ts文件代码
export const add = (a: number, b: number): number => {
return a + b;
};
export const minus = (a: number, b: number): number => {
return a - b;
};
// match.spec.ts文件代码
import { add, minus } from './match';
describe('测试add', function () {
test('测试1+1', function () {
expect(add(1, 1)).toBe(2);
});
test('测试2+2', function () {
expect(add(2, 2)).toBe(4);
});
});
describe('测试minus', function () {
test('测试1-1', function () {
expect(minus(1, 1)).toBe(0);
});
test('测试2-2', function () {
expect(minus(2, 2)).toBe(0);
});
});
6、也可以将测试代码放到__tests__
目录下,文件名与src
里面的文件名保持一致
jsdom
的使用在jest
初始化的时候会默认生成jsdom
的,如果没有的话,可以在jest.config.ts
中配置上testEnvironment: "jsdom"
,jsdom
官方地址
1、创建待测试的文件
/** 定义删除node节点 */
export const remove = (node: HTMLElement) => {
node.parentNode?.removeChild(node);
};
/**定义绑定事件 */
export const addEventListener = (
node: HTMLElement,
type: any,
listener: (this: HTMLElement, ev: MouseEvent) => any
) => {
node.addEventListener(type, listener);
};
2、单元测试文件
import { remove, addEventListener } from './../src/dom';
describe('dom节点测试', function () {
test('测试remove方法', () => {
document.body.innerHTML = `
<div id="parent">
<div id="children">子节点</div>
</div>
`;
const parentDom = document.getElementById('parent');
// 期望这个节点是div
expect(parentDom?.nodeName.toLocaleLowerCase()).toBe('div');
const childDom = document.getElementById('children');
expect(childDom?.nodeName.toLocaleLowerCase()).toBe('div');
remove(childDom!);
// 删除后期望是空节点
expect(document.getElementById('children')).toBeNull();
});
test('测试addEventListener方法', () => {
document.body.innerHTML = `
<div id="parent">
<button id="children">子节点</button>
</div>
`;
const childDom = document.getElementById('children');
expect(childDom).not.toBeNull();
addEventListener(childDom!, 'click', () => {
childDom!.innerHTML = '点击后的内容';
});
// 模拟点击
childDom?.click();
expect(childDom?.innerHTML).toBe('点击后的内容');
});
});
1、官方地址
2、定义待测试的异步函数
export const callBack = (fn: Function) => {
setTimeout(() => {
fn({ code: 0 });
}, 3000);
};
3、测试代码
import { callBack } from './../src/callback';
describe('测试异步方法', () => {
test('测试异步', (done: Function) => {
// 调用callBack方法
callBack((response: Record<string, any>) => {
expect(response).toEqual({ code: 0 });
done();
});
});
});
promise
1、待测试的方法
export const callPromise = (): Promise<Record<string, any>> => {
return new Promise((resolve: Function) => {
setTimeout(() => resolve({ code: 0 }), 3000);
});
};
2、测试方法一
describe('测试promise', () => {
test('方法一', (done: Function) => {
callPromise().then((response: Record<string, any>) => {
expect(response).toEqual({ code: 0 });
done();
});
});
});
3、方式二
describe('测试promise', () => {
test('方法二', async () => {
const result: Record<string, number> = await callPromise();
expect(result).toEqual({ code: 0 });
});
});
Mock
的使用1、关于介绍可以参考官方地址
2、官方的测试案例
export const forEachFn = (items: number[], callback: Function) => {
for (let index = 0; index < items.length; index++) {
callback(items[index]);
}
};
import { forEachFn } from './../src/mock1';
describe('mock的测试', () => {
test('测试forEach函数', () => {
// mock一个函数
const mockFn = jest.fn((x: number) => 42 + x);
// 调用定义的方法
forEachFn([0, 1, 2], mockFn);
// 测试调用了几次
expect(mockFn.mock.calls.length).toBe(3);
// 调用函数传递的参数
expect(mockFn.mock.calls[0][0]).toBe(0);
expect(mockFn.mock.calls[1][0]).toBe(1);
expect(mockFn.mock.calls[2][0]).toBe(2);
// 调用函数的返回值
expect(mockFn.mock.results[0].value).toBe(42);
expect(mockFn.mock.results[1].value).toBe(43);
expect(mockFn.mock.results[2].value).toBe(44);
});
});
3、测试函数的返回值
/**测试函数 */
export const exec = (callback: (name: string) => string) => {
return callback('张三');
};
describe('测试函数', () => {
test('测试exec函数', () => {
// 模拟一个函数并且执行这个函数
const fn = jest.fn();
exec(fn);
// 测试是否调用
expect(fn).toBeCalled();
expect(fn).toHaveBeenCalled();
// 测试调用次数
expect(fn).toBeCalledTimes(1);
expect(fn).toBeCalledWith('张三');
// 测试返回值
fn.mockReturnValueOnce('张三');
expect(fn()).toBe('张三');
});
});
4、测试模拟接口请求,官方地址
import axios from 'axios';
/** 请求后端接口的方法 */
export const getUserList = async (): Promise<any> => {
return await axios.get('/user');
};
import axios from 'axios';
import { getUserList } from './../src/mock2';
jest.mock('axios');
describe('测试模拟接口', () => {
test('调用后端用户接口', async () => {
// 模拟数据
(axios.get as any).mockResolvedValue({
code: 0,
message: '成功请求',
result: {},
});
const result = await getUserList();
expect(result.code).toBe(0);
});
});
1、钩子函数对不同测试执行阶段提供了对应的回调接口
2、beforeAll
在所有测试用例执行之前执行
3、beforeEach
每个测试用例执行前执行
4、afterEach
每个测试用例执行结束时
5、afterAll
等所有测试用例都执行之后执行
6、only的意思是只调用特定的测试用例
let count: number = 0;
describe('测试钩子函数', () => {
beforeAll(() => {
count++;
console.log('beforeAll钩子函数', count); // 1
});
afterAll(() => {
count++;
console.log('afterAll在全部的钩子之后执行', count); // 8
});
beforeEach(() => {
count++;
console.log('在每一个测试单元的时候执行', count); //2,4
});
afterEach(() => {
count++;
console.log('在每一个测试单元之后执行', count); // 5,7
});
describe('测试单元', () => {
test('测试单元1', () => {
count++;
console.log('测试单元1', count); // 3
});
test('测试单元2', () => {
count++;
console.log('测试单元2', count); //6
});
});
});
|
开发测试 最新文章 |
pytest系列——allure之生成测试报告(Wind |
某大厂软件测试岗一面笔试题+二面问答题面试 |
iperf 学习笔记 |
关于Python中使用selenium八大定位方法 |
【软件测试】为什么提升不了?8年测试总结再 |
软件测试复习 |
PHP笔记-Smarty模板引擎的使用 |
C++Test使用入门 |
【Java】单元测试 |
Net core 3.x 获取客户端地址 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/17 20:44:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |