Go Revel - Testing(測試模塊)
revel提供了一個測試框架來方便的為自己的程序編寫功能測試用例。
默認創建的應用骨架附帶一個簡單的測試用例,這里將它作為起點
##概覽
測試保存在`tests`目錄:
corp/myapp
app/
conf/
public/
tests/ <----
一個簡單的測試用例如下:
type AppTest struct {
revel.TestSuite
}
func (t *AppTest) Before() {
println("Set up")
}
func (t *AppTest) TestThatIndexPageWorks() {
t.Get("/")
t.AssertOk()
t.AssertContentType("text/html")
}
func (t *AppTest) After() {
println("Tear down")
}
這個示例做了如下事情:
1、一個測試用例可以是任意一個嵌入了`revel.TestSuite`的struct
2、如果存在`Before()`與`After()`方法,那么它將在每個測試用例的前后被調用。
3、`revel.TestSuite`為請求和響應的斷言提供了輔助工具。
4、一個失敗的斷言講拋出一個`panic`,會由測試工具進行捕獲
可以在這兩個地方使用測試工具:
1、交互模式,在瀏覽器中使用,開發階段下非常有用
2、非交換模式,在命令行中使用,對于集成持續構建非常有用
##開發一個測試用例
自己創建一個測試用例,只需要將`revel.TestSuite`嵌入struct即可,它會提供一個HTTP客戶端和一些用于請求的輔助性工具。
// 一些請求方法
func (t *TestSuite) Get(path string)
func (t *TestSuite) Post(path string, contentType string, reader io.Reader)
func (t *TestSuite) PostForm(path string, data url.Values)
func (t *TestSuite) MakeRequest(req *http.Request)
// 一些斷言方法
func (t *TestSuite) AssertOk()
func (t *TestSuite) AssertContentType(contentType string)
func (t *TestSuite) Assert(exp bool)
func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{})
所有的請求都有類似的功能:
1、它們接收一個路徑(如/users)
2、它們想服務器發送一個請求
3、它們在`Response`中存儲一個響應
4、他們在`ResponseBody`中讀取全部的響應體
如果開發者想使用一個自定義的HTTP客戶端,而不想用默認的`http.DefaultClient`,那么只需要在`Before()`方法中替換。
所有不通過的斷言都將拋出一個`panic`,所有被測試工具捕獲的`panic`都被當作錯誤。
##運行一個測試用例
如果要運行測試用力,那么`testrunner`模塊必須被激活。編輯`app.conf`激活測試框架:
module.testrunner = github.com/robfig/revel/modules/testrunner
并且還得在`routes`路由文件添加測試的路由:
module:testrunner
這樣,測試用例才能在交互模式與非交互模式下運行。
**交互模式下運行測試用例**
利用revel的代碼熱編譯功能,測試框架提供了一個快速的 更改-刷新 周期
例如在開發階段,在瀏覽器中加載`/@tests`頁面

然后,添加一個測試方法:
func (t AppTest) TestSomethingImportant() {
t.Get("/")
t.AssertOk()
t.AssertContentType("text/xml")
}
接著刷新瀏覽器頁面就會看到新增加的測試方法:

運行測試用例:

額。。它沒有運行,這里所期望的內容類型是`text/html`而不是`text/xml`,修改它:
t.AssertContentType("text/html")
然后重新運行:

成功!
**非交互模式下運行測試用例**
revel工具提供了`test`選項在命令行下運行測試用例,例如:
$ revel test github.com/robfig/revel/samples/booking dev
~
~ revel! http://robfig.github.com/revel
~
INFO 2012/11/09 19:21:02 revel.go:237: Loaded module testrunner
Open DB
Listening on port 9000...
INFO 2012/11/09 19:21:06 test.go:95: Testing Booking example (github.com/robfig/revel/samples/booking) in dev mode
Go to /@tests to run the tests.
1 test suite to run.
AppTest PASSED 0s
All Tests Passed.
也可以用`,`逗號分割的形式來運行個別測試用例:
$ revel test github.com/robfig/revel/samples/booking dev ApplicationTest
$ revel test github.com/robfig/revel/samples/booking dev ApplicationTest.TestThatIndexPageWorks
命令行下,測試用例只會簡單的顯示`PASSED/FAILED`來表示測試是否通過,但測試工具會在文件系統生成詳細的測試報告:
$ cd src/github.com/robfig/revel/samples/booking
$ find test-results
test-results
test-results/app.log
test-results/AppTest.passed.html
test-results/result.passed
它會生成三種不同的內容:
1、程序的標準輸出與標準錯誤寫在`app.log`文件
2、一個HTML被測試用例寫入通過還是不通過的描述信息
3、`result.passed`或`result.failed`的生成,取決于整個測試否通過
對于連續構建,這里有兩點建議:
1、檢查返回碼,0表示成功,其它則表示失敗
2、檢查文件,如果`result.passed`文件存在,則表示測試通過,反之則不通過
##實現說明
revel做了哪些事:
1、掃描測試源碼用來傳遞給嵌入的測試用例
2、將`revel.TestSuites`變量的那些類型的列表設置進生成的`main.go`文件中
3、根據反射來獲取所有以`Test`開頭`TestSuite`類型的方法,然后運行測試代碼
4、捕獲所有的錯誤,并顯示出來
測試代碼只有在`testrunner`模塊啟用的情況下才會被建立。
##開發相關
測試框架可以有下面的改進:
1、用于將測試數據存入存儲區域的裝置
2、`Loggers`輸出文件(代替stderr/stdout)也應該重定向至`test-results/app.log`
浙公網安備 33010602011771號