有效的单元测试
好的单元测试会有一些原则,说起来比较容易,但是书写起来就有一些抽象,不太好实践。换一个思路,只要你的单元测试不要出现一些错误,这样对于书写者来说是更容易接受和实践的。在这罗列些单元测试中不要出现的情况:
人格分裂
好的单元测试不能出现“人格分裂”的情况,单元测试是个单纯的小家伙,没有什么胃口,他只能处理一种情况并妥善执行。如果单元测试中测试了多个功能,那就属于人格分裂。
示例
func TestNum(t *testing.T) {
testNum := 1
evenRes := IsEven(testNum)
primeRes := IsPrime(testNum)
expectEven := false
expectPrime := false
assert.Equal(t, expectEven, evenRes)
assert.Equal(t, expectPrime, primeRes)
}
该对他做点什么
拆成两个单元测试
func TestIsEven(t *testing.T) {
testNum := 1
evenRes := IsEven(testNum)
expectEven := false
assert.Equal(t, expectEven, evenRes)
}
func TestIsPrime(t *testing.T) {
testNum := 1
primeRes := IsPrime(testNum)
expectPrime := false
assert.Equal(t, expectPrime, primeRes)
}
魔法数字
在程序的任意位置,魔法数字都是不好的并且应该避免。在写单元测试时,需要构造一些假的参数,这些假的参数我们可能会给赋值为1,事后阅读时你可能就会忘记这个1表示什么含义,带来不必要的麻烦,并且一个魔法值的出现基本不会只有一次,两次中1是不是表示同一个含义就有待商榷。
示例
func TestIsEven(t *testing.T) {
evenRes := IsEven(1)
assert.Equal(t, false, evenRes)
}
该对他做点什么
1这个数字表示要测试的数字,false是预期的结果。这个都可以通过变量的方式让其更容易理解
func TestIsEven(t *testing.T) {
testNum := 1
evenRes := IsEven(testNum)
expectEven := false
assert.Equal(t, expectEven, evenRes)
}
条件逻辑
在单元测试中出现了条件逻辑,此时是非常不好的,会给阅读带来很大的麻烦。
示例
func Test(t *testing.T) {
tests := []int{1,2}
for i := range tests {
realRes := IsEven(i)
if i == 1 {
assert.Equal(t, false, realRes)
}else if i == 2 {
assert.Equal(t, true, realRes)
}
}
}
该对他做点什么
上述条件逻辑中,判断如果数是1则给一个期望值。这种直接改为组测试。按照顺序先后赋予预期结果。
func Test(t *testing.T) {
tests := []int{1,2}
expectRes := []bool{false,true}
for i := 0; i < len(tests); i++ {
realRes := IsEven(tests[i])
assert.Equal(t, expectRes[i], realRes)
}
}
注释掉的测试
注释是帮助程序员去理解源代码,但是往往会适得其反,迷惑或者误导我们。关于测试中的注释经常出现整个测试方法被注释掉,这种就会非常的误导人。要猜测书写时的用意。
示例
//func Test(t *testing.T) {
// tests := []int{1,2}
//
// expectRes := []bool{false,true}
// for i := 0; i < len(tests); i++ {
// realRes := IsEven(tests[i])
// assert.Equal(t, expectRes[i], realRes)
// }
//}
该对他做点什么
问下身边有没有对这个了解的人,了解后按照正确的方式完善这个注释的测试方法。如果没有直接删掉。
永不失败的测试
不能失败的测试不具有价值,出了事情不警告你。
示例
func TestIsEven(t *testing.T) {
testNum := 1
evenRes := IsEven(testNum)
fmt.Println(evenRes)
}
该对他做点什么
此代码永远不会失败,都不会给出一个明确的结果。没有意义。类似的情况还有try catch掉异常和错误,代码不会报错。也是同样的道理。
func TestIsEven(t *testing.T) {
testNum := 1
expectEven := false
evenRes := IsEven(testNum)
assert.Equal(t, expectEven, evenRes)
}