This commit is contained in:
chai2010
2015-12-11 17:19:15 +08:00
parent fd6262f241
commit 643409dd27
4 changed files with 44 additions and 44 deletions

View File

@@ -1,15 +1,15 @@
## 11.3. 測試覆蓋率
就其性而言, 测试不可能是完整的. 计算机科学家 Edsger Dijkstra 曾说过: "测试可以示存在缺陷, 但是不是说没有BUG." 再多的测试也不能明一个包没有BUG. 在最好的情下, 测试可以增强我们的信息, 包在我们测试的环境是可以正常工作的.
就其性而言, 測試不可能是完整的. 計算機科學傢 Edsger Dijkstra 曾説過: "測試可以示存在缺陷, 但是不是説沒有BUG." 再多的測試也不能明一個包沒有BUG. 在最好的情下, 測試可以增強我們的信息, 包在我們測試的環境是可以正常工作的.
测试驱动触发运行到的被测试函数的代码数目称为测试的覆率. 测试覆盖率并不能量化 — 甚至连最简单的动态程序也以精确测量 — 但是可以启发并帮助我们编写的有效的测试代码.
測試驅動觸發運行到的被測試函數的代碼數目稱爲測試的覆率. 測試覆蓋率併不能量化 — 甚至連最簡單的動態程序也以精確測量 — 但是可以啓發併幫助我們編寫的有效的測試代碼.
这些帮助信息中句的覆率是最简单和最广泛使用的. 句的覆率是指在测试中至少被行一次的代码占总代码数的比例. 在本中, 我使用 `go test` 中集成的测试覆盖率工具, 度量下面代码的测试覆盖率, 助我们识别测试和我期望的差距.
這些幫助信息中句的覆率是最簡單和最廣汎使用的. 句的覆率是指在測試中至少被行一次的代碼佔總代碼數的比例. 在本中, 我使用 `go test` 中集成的測試覆蓋率工具, 度量下麫代碼的測試覆蓋率, 助我們識彆測試和我期望的差距.
The code below is a table-driven test for the expression evaluator we built back in Chapter 7:
的代是一个表格驱动的测试, 用于测试第七章的表达式求值程序:
的代是一個錶格驅動的測試, 用於測試第七章的錶達式求值程序:
```Go
gopl.io/ch7/eval
@@ -49,7 +49,7 @@ func TestCoverage(t *testing.T) {
}
```
首先, 我们要确保所有的测试都正常通:
首先, 我們要確保所有的測試都正常通:
```
$ go test -v -run=Coverage gopl.io/ch7/eval
@@ -59,7 +59,7 @@ PASS
ok gopl.io/ch7/eval 0.011s
```
面这个命令可以显示测试覆盖率工具的用法信息:
麫這個命令可以顯示測試覆蓋率工具的用法信息:
```
$ go tool cover
@@ -72,20 +72,20 @@ Open a web browser displaying annotated source code:
...
```
`go tool` 命令行Go工具的底层可执行程序. 些底层可执行程序放在 $GOROOT/pkg/tool/${GOOS}_${GOARCH} 目. 因 `go build` 的原因, 我很小直接调用这些底工具.
`go tool` 命令行Go工具的底層可執行程序. 些底層可執行程序放在 $GOROOT/pkg/tool/${GOOS}_${GOARCH} 目. 因 `go build` 的原因, 我很小直接調用這些底工具.
在我可以用 `-coverprofile` 标志参数重新行:
在我可以用 `-coverprofile` 標誌蔘數重新行:
```
$ go test -run=Coverage -coverprofile=c.out gopl.io/ch7/eval
ok gopl.io/ch7/eval 0.032s coverage: 68.5% of statements
```
这个标志参数通过插入生成子代码来统计覆盖率数据. 也就是, 在行每个测试前, 它会修改要测试代码的副本, 在每个块都会设置一个布尔标志变量. 当被修改后的被测试代码运行退出时, 将统计日志数据写入 c.out 文件, 打印一部分行的句的一个总结. (如果你需要的是摘要,使用 `go test -cover`.)
這個標誌蔘數通過插入生成子代碼來統計覆蓋率數據. 也就是, 在行每個測試前, 它會脩改要測試代碼的副本, 在每個塊都會設置一個佈爾標誌變量. 噹被脩改後的被測試代碼運行退齣時, 將統計日誌數據寫入 c.out 文件, 打印一部分行的句的一個總結. (如果你需要的是摘要,使用 `go test -cover`.)
如果使用了 `-covermode=count` 标志参数, 那么将在每个代码块插入一个计数器而不是布尔标志量. 在统计结果中记录了每个块的执行次, 可以用衡量哪些是被频繁执行的热点代码.
如果使用了 `-covermode=count` 標誌蔘數, 那麽將在每個代碼塊插入一個計數器而不是佈爾標誌量. 在統計結果中記彔了每個塊的執行次, 可以用衡量哪些是被頻繁執行的熱點代碼.
了收集数据, 我们运行了测试覆盖率工具, 打印了测试日志, 生成一HTML告, 然后在浏览器中打开(图11.3).
了收集數據, 我們運行了測試覆蓋率工具, 打印了測試日誌, 生成一HTML告, 然後在瀏覽器中打開(圖11.3).
```
$ go tool cover -html=c.out
@@ -93,14 +93,14 @@ $ go tool cover -html=c.out
![](../images/ch11-03.png)
绿色的代码块被测试覆盖到了, 色的则表示没有被覆到. 了清晰起, 我们将的背景色文本的背景置成了影效果. 我可以马上发现 unary 操作的 Eval 方法并没有被行到. 如果我们针对这部分未被覆的代添加下面的测试, 然重新行上的命令, 那么我们将会看到那个红色部分的代码也变成绿色了:
色的代碼塊被測試覆蓋到了, 色的則錶示沒有被覆到. 了清晰起, 我們將的背景色文本的背景置成了影效果. 我可以馬上發現 unary 操作的 Eval 方法併沒有被行到. 如果我們針對這部分未被覆的代添加下麫的測試, 然重新行上的命令, 那麽我們將會看到那個紅色部分的代碼也變成綠色了:
```
{"-x * -x", eval.Env{"x": 2}, "4"}
```
过两个 panic 句依然是色的. 这是没有问题的, 因为这两个语句并不会被执行到.
過兩個 panic 句依然是色的. 這是沒有問題的, 因爲這兩個語句併不會被執行到.
实现 100% 的测试覆盖率听起来很好, 但是在具体实践中通常是不可行的, 也不是值得推的做法. 因为那只能说明代码被执行过而已, 不意味着代码是没有BUG的; 因为对于逻辑复杂的语句需要针对不同的输入执行多次. 有一些句, 例如上的 panic 语句则永远都不会被执行到. 另外, 有一些晦的错误在现实中很少遇到也很难编写对应的测试代码. 测试从本质上来说是一个比较务实的工作, 编写测试代码和编写应用代的成本比是需要考的. 测试覆盖率工具可以助我快速识别测试薄弱的地方, 但是设计好的测试用例和编写应用代码一样需要密的思考.
實現 100% 的測試覆蓋率聽起來很好, 但是在具體實踐中通常是不可行的, 也不是值得推的做法. 因爲那隻能説明代碼被執行過而已, 不意味着代碼是沒有BUG的; 因爲對於邏輯復雜的語句需要針對不衕的輸入執行多次. 有一些句, 例如上的 panic 語句則永遠都不會被執行到. 另外, 有一些晦的錯誤在現實中很少遇到也很難編寫對應的測試代碼. 測試從本質上來説是一個比較務實的工作, 編寫測試代碼和編寫應用代的成本比是需要考的. 測試覆蓋率工具可以助我快速識彆測試薄弱的地方, 但是設計好的測試用例和編寫應用代碼一樣需要密的思考.