基础前端

Jest Parameterised Testing

2021-09-23  本文已影响0人  CondorHero
Jest Parameterised Testing.png

重复测试解决方案——参数化测试。

目录

前言

文章标题来源 jest-each

jest-each

自动化测试对我们项目健壮性是不言而喻的,因为测试是需要对代码覆盖场景各方面的测试,这会导致我们写出很多——只是简单输入输出,不同的测试实例,有没有一种方法能让测试代码显得更加精简凝练呢。

当然是有的,这就是我们要介绍的参数化测试。

重复测试

我们有一个简单的例子,加法计算器:

const add = (x, y) => x + y;

为了,验证程序的正确性,我们需要一个测试:

describe("addition calculator", () => {
    it("0 plus 0 equals 0", () => {
        expect(add(0, 0)).toBe(0);
    });

    it("-1 plus -2 equals -3", () => {
        expect(add(-1, -2)).toBe(-3);
    });

    it("1 plus 2 equals 3", () => {
        expect(add(1, 2)).toBe(3);
    });

    it("8 plus 2 equals 10", () => {
        expect(add(8, 2)).toBe(10);
    });
});

测试运行结果全部通过:

我们观察上面的代码,你就会发现虽然输入输出有所不同,但是逻辑类似,由此造成了测试代码重复,如果需要新增一个测试用例,需要重新复制一份代码。

参数化测试——数组语法

Jest 提供给我们处理这种情况一种方法,就是 Parameterized Tests

describe("addition calculator", () => {
    it.each([
        [0, 0, 0],
        [-1, -2, -3],
        [1, 2, 3],
        [8, 2, 10],
    ])(
        `%i plus %i equals %i`,
        (x, y, result) => {
            expect(add(x, y)).toBe(result);
        }
    );
});

上面的代码,你可能不明所以,但是心里肯定认同这种写法,因为如果你想更改删除测试输入输出,只需要维护一个二维数组就行了,更加直观。

顺带一提,我当时看 Jest 文档,愣是没明白 each 的用法,什么 The table contains rows 把我整的很懵圈。

我来简单讲下它大致执行逻辑,。

首先,看到 each 你肯定想到了循环,没错 Jest 首先会循环这个二维数组,拿到里面的数组之后,在进行断言,整个过程就类似下面这样:

// each 大致逻辑
const testArr = [
    [0, 0, 0],
    [-1, -2, -3],
    [1, 2, 3],
    [8, 2, 10],
];

testArr.forEach(([x, y, result]) => {
    test(`${x} plus ${y} equals ${result}`, () => {
        expect(add(x, y)).toBe(result);
    })
})



// 第一次循环

(0, 0, 0) => {
    expect(add(0, 0)).toBe(0);
}


// 第二次循环

(-1, -2, -3) => {
    expect(add(-1, -2)).toBe(-3);
}


// 第三次循环

(1, 2, 3) => {
    expect(add(1, 2)).toBe(3);
}


// 第四次循环

(2, 8, 10) => {
    expect(add(2, 8)).toBe(10);
}

除了,明白 each 的运行逻辑,我们应该还注意到,我们在 test 的 title 这里使用了 %i 这个占位符。如果你足够熟悉 NodeJs ,会发现这其实是一个 printf formatting,Jest 关于 test title 占位符的描述在 这里

二维数组还有一种变形就是数组包含对象(和接下来介绍的模板字符串语法很像):

describe("addition calculator", () => {
    it.each([
        { x: 0, y: 0, result: 0 },
        { x: -1, y: -2, result: -3 },
        { x: 1, y: 2, result: 3 },
        { x: 8, y: 2, result: 10 }
    ])(
        `$x plus $y equals $result`,
        ({ x, y, result }) => {
            expect(add(x, y)).toBe(result);
        }
    );
});

分析了二维数组,一维数组包对象相信你也能明白了,结合对象的特点你需要注意的有两点:

  1. test title 的占位符由 %i 的形式改成了 $x
  2. test fn 的参数使用的是解构。

参数化测试——模板字符串语法

each 除了支持数组还支持模板字符串的写法,写法如下:

describe("addition calculator", () => {
    it.each`
        x        | y        | result
        ${0}     | ${0}     | ${0}
        ${-1}    | ${-2}    | ${-3}
        ${1}     | ${2}     | ${3}
        ${2}     | ${8}     | ${10}
  `(
        `$x plus $y equals $result`,
        ({x, y, result}) => {
            expect(add(x, y)).toBe(result);
        }
    );
});

这个模板语法首先会翻译成对象,然后它的语法注意点以及使用和上面的数组包含对象完全相同。

参数化测试——支持的 API

Jest 的 it/test 是支持 each 的,更高一层的 describe 也是支持 each 的用法的。

你可以在 Jest API 查看所有的用法。

jest-each

Jest 对 .each 的语法支持仅在 Jest 23 及更高版本中支持,所以小于 23 版本的 Jest 无法使用参数化测试功能。

但是可以借助 jest-each 这个 npm 包,让小于 23 版本的 Jest 支持参数化测试功能。

大胆猜想,Jest 使用了jest-each 包,我们去 Jest 的 GitHub 链接验证下,点击此处——jest-jasmine2 阅读。

查验如下:

jest-each

概要

今天,我们学习了当遇到非常多的逻辑重复单元测试样板,我们可以使用 Jest 的参数化测试来减少样板书写,让测试变得更加直观易读和便于维护。

上一篇 下一篇

猜你喜欢

热点阅读