设计测试用例

更新时间: 2023-03-19 18:01:24

之前完成了测试环境的搭建,现在继续完善单元测试。在编写代码之前需要先设计测试用例,测试用例要尽可能全面地覆盖各种情况,这样才能保证质量。在覆盖全面的同时,数量要尽可能少,这样能够提高测试效率。

# 设计思路

对于函数的测试,可以按照参数分组,每个参数一组,在对一个参数进行测试时,保证其他参数无影响。例如要测试以下的leftpad函数:

// 当字符串str的长度小于count时,在字符串的左侧填充指定字符
function leftpad(str, count, ch = '0') {
    return `${[...Array(count)].map((v) => '0')}${str}`.slice(-count)
}

leftpad('1', 2) // '01'
1
2
3
4
5
6

由于leftpad函数有3个参数,因此可以分为3组。在对每个参数进行测试时,测试用例可以分为正确的测试用例和错误的测试用例,并且对于存在边界值的情况的参数,还需要对边界值设计测试用例。需要注意的是,每个分组下面可以采用等价类划分方法,对于同一个类型的输入,只需要设计一个用例即可。

分组 正确的测试用例 错误的测试用例 边界值测试用例
str 任意字符串 非字符串 空字符串
count 1-N 非数字 0:负数
ch 任意字符串 非字符串 空字符串

接下来,用上述方法来给我们的深度拷贝库设计测试用例。
深拷贝库示例代码:

function type(data) {
    return Object.prototype.toString.call(data).slice(8, -1).toLowerCase()
}

function clone(source) {
    const t = type(source)
    if(t !== 'object' && t !== 'array') {
        return source
    }
    let target
    if(t === 'object') {
        target = {}
        for(let i in source) {
            if(source.hasOwnProperty(i)) {
                target[i] = clone(source[i])
            }
        }
    }else{
        target = []
        for(let i = 0;i < source.length; i++) {
            target[i] = clone(source[i])
        }
    }

    return target
}

export default clone
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

由于只有一个参数,因此只有一个分组,但是因为基本类型数据和引用类型数据的拷贝行为不一致,所以要分别测试。

分组 正确的测试用例 错误的测试用例 边界值测试用例
data 基本数据类型、对象、数组 空参数、undefined、null

# 编写代码

我们将在test.js文件中编写测试代码,因为测试代码是在Node.js中运行的,所以可以直接引用dist/index.js文件。

下面的代码会用到expect.js中一些新的断言接口,下面先进行简单介绍。

在断言中添加not即可对结果进行取非转换:

expect(1).to.equal(1)
expect(1).not.to.equal(2)
1
2

equal相当于全等,而eql则表示值相等,对于深拷贝后的引用类型数据,需要用eql来验证深拷贝结果的正确性。

例如,下面代码中arr和cloneArr的值都是[1,2,3],但两个变量并不相等

var arr = [1,2,3]
var cloneArr = [...arr]
expect(arr).to.equal(cloneArr)
expect(arr).to,eql(cloneArr)
1
2
3
4

完整的测试代码如下。外层的describe用来区分函数,这里只有一个函数。内层的describe用来区分不同的参数,这里只有一个参数data,内部有正确的测试用例和边界值测试用例。

var expect = require('expect.js')
var clone = require('../dist/index.js')

describe('function clone', function() {
    describe('param source', function() {
        it('正确的测试用例',function() {
            //基本数据类型
            expect(clone('abc')).to.equal('abc')

            //数组
            var arr = [1,[2]]
            var cloneArr = clone(arr)
            expect(cloneArr).not.to.equal(arr)
            expect(cloneArr).to.eql(arr)

            //对象
            var obj = {a: {b: 1}}
            var cloneObj = clone(obj)
            expect(cloneObj).not.to.equal(obj)
            expect(cloneObj).to.eql(obj)
        })

        it('边界值测试用例', function(){
            expect(clone()).to.equal(undefined)

            expect(clone(undefined)).to.equal(undefined)

            expect(clone(null)).to.equal(null)
        })
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

额案场测试代码的编写后,在控制台中输入npm test命令即可运行测试,验证结果如下: