Typescript 测试驱动开发 TDD (11)

发布时间 2023-09-22 10:50:01作者: 天涯上过客

数据驱动测试 (Data-driven tests)


很多时候,我们需要运行相同的测试多次,只是输入值不同。作为这个的一个例子,请考虑以下测试:

[1, 2, 3, 4, 5]
    .forEach((value: number) => {
       it(`${value} should be less than 5`, () => {
            expect(value).toBeLessThan(5);
       }) 
});

在这里,我们定义了一个包含数字1到5的数组。然后,我们调用forEach函数,该函数接受一个函数作为参数,并且将对数组中的每个值执行一次该函数。请注意,在此forEach函数内部,我们定义了一个测试,并且该测试期望传入的值应小于5。还要注意,在实际测试名称中使用了模板字符串,以便通过值来区分这些测试。以下是此测试失败的情况:

 

在这里,我们可以看到失败的测试被命名为“5应该小于5”,而Jest告诉我们值5实际上不小于5。
以这种方式使用forEach给了我们一种快速设置一系列带有各种数据的测试的方法。现在让我们来看看如何为验证函数编写一些数据驱动的测试,其代码如下:

1 function hasValueNoWhiteSpace(value: string): boolean {
2     if (
3        value &&
4        value.length > 0 &&
5        value.trim().length > 0 ) {
6        return true;  
7      }
8      return false;
9 }

这里,我们有一个名为hasValueNoWhiteSpace的函数,它接受一个字符串参数,并返回一个布尔值。此代码正在检查输入值是否为空字符串,或者在修剪后是否为空字符串。要测试此函数,我们期望值" "将返回false,但值"a"将返回true。
然后我们的测试用例类似于以下内容:

1 [
2     [undefined, false],
3     [null, false],
4     [" ", false],
5     ["   ", false],
6     [" a ", true]
7 ]

在这里,我们定义了一个元组数组,每个元组有两个值。第一个值是我们想要测试的值,第二个值是hasValueNoWhiteSpace函数的预期结果。为了使用这种输入创建数据驱动测试,让我们编写一个小型实用函数如下:

1 function testUsing<T>(values: T[], func: Function) {
2     for (let value of values) {
3         func.apply(Object, [value]);
4     }
5 }

这里,我们有一个名为testUsing的函数,它可以与任何类型T一起使用。该函数有两个参数,分别是values和func。values参数是一个类型为T的数组,而func参数是一个回调函数。在testUsing函数内部,我们正在循环遍历数组的每个元素,并使用apply函数调用当前数组元素来调用func函数。现在我们可以按照以下方式使用这个testUsing函数:

 1 testUsing(
 2    [
 3       [undefined, false],
 4       [null , false],
 5       [" ", false],
 6       ["  ", false],
 7       [" a ", true] 
 8    ]
 9    , ([value, isValid]: [string, boolean]) => {
10       
11        it(`"${value}" hasValueNoWhiteSpace ? ${isValid}`,
12             () => {
13                 isValid ? 
14                     expect(hasValueNoWhiteSpace(value)).toBeTruthy() :
15                     expect(hasValueNoWhiteSpace(value)).toBeFalsy();
16             }
17        );
18 });

在这里,我们使用两个参数调用testUsing函数。第一个参数是我们想要运行测试的值数组。第二个参数是一个函数,它将数组中的每个元组解构为名为value和isValid的变量。然后,我们调用it函数来创建一个包含数组中每个值的测试。这个数据驱动测试序列的输出如下:

在这里,我们可以看到testUsing函数正在对我们的数据数组中的每个值运行一个测试。根据每个元组的第二个值,该测试将确定hasValueNoWhiteSpace函数是否返回正确的布尔值。

 

数据驱动测试是一种方便的编写单元测试的方式,其中一系列测试唯一真正变化的是输入或结果值,但测试本身保持不变。