mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-14 10:32:12 +00:00
回到简体
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
### 11.2.4. 擴展測試包
|
||||
### 11.2.4. 扩展测试包
|
||||
|
||||
考慮下這兩個包:net/url包,提供了URL解析的功能;net/http包,提供了web服務和HTTP客戶端的功能。如我們所料,上層的net/http包依賴下層的net/url包。然後,net/url包中的一個測試是演示不同URL和HTTP客戶端的交互行爲。也就是説,一個下層包的測試代碼導入了上層的包。
|
||||
考虑下这两个包:net/url包,提供了URL解析的功能;net/http包,提供了web服务和HTTP客户端的功能。如我们所料,上层的net/http包依赖下层的net/url包。然后,net/url包中的一个测试是演示不同URL和HTTP客户端的交互行为。也就是说,一个下层包的测试代码导入了上层的包。
|
||||
|
||||

|
||||
|
||||
這樣的行爲在net/url包的測試代碼中會導致包的循環依賴,正如圖11.1中向上箭頭所示,同時正如我們在10.1節所講的,Go語言規范是禁止包的循環依賴的。
|
||||
这样的行为在net/url包的测试代码中会导致包的循环依赖,正如图11.1中向上箭头所示,同时正如我们在10.1节所讲的,Go语言规范是禁止包的循环依赖的。
|
||||
|
||||
不過我們可以通過測試擴展包的方式解決循環依賴的問題,也就是在net/url包所在的目録聲明一個獨立的url_test測試擴展包。其中測試擴展包名的`_test`後綴告訴go test工具它應該建立一個額外的包來運行測試。我們將這個擴展測試包的導入路徑視作是net/url_test會更容易理解,但實際上它併不能被其他任何包導入。
|
||||
不过我们可以通过测试扩展包的方式解决循环依赖的问题,也就是在net/url包所在的目录声明一个独立的url_test测试扩展包。其中测试扩展包名的`_test`后缀告诉go test工具它应该建立一个额外的包来运行测试。我们将这个扩展测试包的导入路径视作是net/url_test会更容易理解,但实际上它并不能被其他任何包导入。
|
||||
|
||||
因爲測試擴展包是一個獨立的包,所以可以導入測試代碼依賴的其他的輔助包;包內的測試代碼可能無法做到。在設計層面,測試擴展包是在所以它依賴的包的上層,正如圖11.2所示。
|
||||
因为测试扩展包是一个独立的包,所以可以导入测试代码依赖的其他的辅助包;包内的测试代码可能无法做到。在设计层面,测试扩展包是在所以它依赖的包的上层,正如图11.2所示。
|
||||
|
||||

|
||||
|
||||
通過迴避循環導入依賴,擴展測試包可以更靈活的編寫測試,特别是集成測試(需要測試多個組件之間的交互),可以像普通應用程序那樣自由地導入其他包。
|
||||
通过回避循环导入依赖,扩展测试包可以更灵活的编写测试,特别是集成测试(需要测试多个组件之间的交互),可以像普通应用程序那样自由地导入其他包。
|
||||
|
||||
我們可以用go list命令査看包對應目録中哪些Go源文件是産品代碼,哪些是包內測試,還哪些測試擴展包。我們以fmt包作爲一個例子:GoFiles表示産品代碼對應的Go源文件列表;也就是go build命令要編譯的部分。
|
||||
我们可以用go list命令查看包对应目录中哪些Go源文件是产品代码,哪些是包内测试,还哪些测试扩展包。我们以fmt包作为一个例子:GoFiles表示产品代码对应的Go源文件列表;也就是go build命令要编译的部分。
|
||||
|
||||
{% raw %}
|
||||
|
||||
@@ -25,7 +25,7 @@ $ go list -f={{.GoFiles}} fmt
|
||||
|
||||
{% endraw %}
|
||||
|
||||
TestGoFiles表示的是fmt包內部測試測試代碼,以_test.go爲後綴文件名,不過隻在測試時被構建:
|
||||
TestGoFiles表示的是fmt包内部测试测试代码,以_test.go为后缀文件名,不过只在测试时被构建:
|
||||
|
||||
{% raw %}
|
||||
|
||||
@@ -36,9 +36,9 @@ $ go list -f={{.TestGoFiles}} fmt
|
||||
|
||||
{% endraw %}
|
||||
|
||||
包的測試代碼通常都在這些文件中,不過fmt包併非如此;稍後我們再解釋export_test.go文件的作用。
|
||||
包的测试代码通常都在这些文件中,不过fmt包并非如此;稍后我们再解释export_test.go文件的作用。
|
||||
|
||||
XTestGoFiles表示的是屬於測試擴展包的測試代碼,也就是fmt_test包,因此它們必須先導入fmt包。同樣,這些文件也隻是在測試時被構建運行:
|
||||
XTestGoFiles表示的是属于测试扩展包的测试代码,也就是fmt_test包,因此它们必须先导入fmt包。同样,这些文件也只是在测试时被构建运行:
|
||||
|
||||
{% raw %}
|
||||
|
||||
@@ -49,11 +49,11 @@ $ go list -f={{.XTestGoFiles}} fmt
|
||||
|
||||
{% endraw %}
|
||||
|
||||
有時候測試擴展包也需要訪問被測試包內部的代碼,例如在一個爲了避免循環導入而被獨立到外部測試擴展包的白盒測試。在這種情況下,我們可以通過一些技巧解決:我們在包內的一個_test.go文件中導出一個內部的實現給測試擴展包。因爲這些代碼隻有在測試時才需要,因此一般會放在export_test.go文件中。
|
||||
有时候测试扩展包也需要访问被测试包内部的代码,例如在一个为了避免循环导入而被独立到外部测试扩展包的白盒测试。在这种情况下,我们可以通过一些技巧解决:我们在包内的一个_test.go文件中导出一个内部的实现给测试扩展包。因为这些代码只有在测试时才需要,因此一般会放在export_test.go文件中。
|
||||
|
||||
例如,fmt包的fmt.Scanf函數需要unicode.IsSpace函數提供的功能。但是爲了避免太多的依賴,fmt包併沒有導入包含鉅大表格數據的unicode包;相反fmt包有一個叫isSpace內部的簡易實現。
|
||||
例如,fmt包的fmt.Scanf函数需要unicode.IsSpace函数提供的功能。但是为了避免太多的依赖,fmt包并没有导入包含巨大表格数据的unicode包;相反fmt包有一个叫isSpace内部的简易实现。
|
||||
|
||||
爲了確保fmt.isSpace和unicode.IsSpace函數的行爲一致,fmt包謹慎地包含了一個測試。是一個在測試擴展包內的白盒測試,是無法直接訪問到isSpace內部函數的,因此fmt通過一個祕密出口導出了isSpace函數。export_test.go文件就是專門用於測試擴展包的祕密出口。
|
||||
为了确保fmt.isSpace和unicode.IsSpace函数的行为一致,fmt包谨慎地包含了一个测试。是一个在测试扩展包内的白盒测试,是无法直接访问到isSpace内部函数的,因此fmt通过一个秘密出口导出了isSpace函数。export_test.go文件就是专门用于测试扩展包的秘密出口。
|
||||
|
||||
```Go
|
||||
package fmt
|
||||
@@ -61,5 +61,5 @@ package fmt
|
||||
var IsSpace = isSpace
|
||||
```
|
||||
|
||||
這個測試文件併沒有定義測試代碼;它隻是通過fmt.IsSpace簡單導出了內部的isSpace函數,提供給測試擴展包使用。這個技巧可以廣泛用於位於測試擴展包的白盒測試。
|
||||
这个测试文件并没有定义测试代码;它只是通过fmt.IsSpace简单导出了内部的isSpace函数,提供给测试扩展包使用。这个技巧可以广泛用于位于测试扩展包的白盒测试。
|
||||
|
||||
|
Reference in New Issue
Block a user