• 测试
    • 概要
    • 开发一个测试套件
    • 运行测试套件
      • 运行交互式测试
      • 运行非交互式测试
    • 注意事项
    • 开发计划

    测试

    Revel提供了一个测试框架,可以很容易地编写和运行针对您的应用程序的功能测试。

    应用程序带有一个简单的测试骨架以便快速上手测试。

    概要

    测试代码保存在测试目录中:

    1. corp/myapp
    2. app/
    3. conf/
    4. public/
    5. tests/ <----

    一个简单的测试如下所示:

    1. type AppTest struct {
    2. revel.TestSuite
    3. }
    4.  
    5. func (t *AppTest) Before() {
    6. println("Set up")
    7. }
    8.  
    9. func (t *AppTest) TestThatIndexPageWorks() {
    10. t.Get("/")
    11. t.AssertOk()
    12. t.AssertContentType("text/html")
    13. }
    14.  
    15. func (t *AppTest) After() {
    16. println("Tear down")
    17. }

    上面的例子中展示了:

    • 测试套件是嵌入revel.TestSuite的一个struct
    • Before()After() 在每个测试方法之前和之后被调用,如果有的话。
    • revel.TestSuite 帮助发出请求到你的应用程序,和对响应的断言。
    • 如果一个断言失败,产生了恐慌,将被测试工具捕获。
      你可以用两种方式运行这个测试:

    • 交互方式,Web浏览器,开发过程中非常有用。

    • 非交互方式,命令行,对于持续构建整合有用。

    开发一个测试套件

    要创建自己的测试套件,需要定义一个嵌入了revel.TestSuite类型的struct, 它提供了一个HTTP客户端和一些辅助方法发出请求到应用程序。

    1. type TestSuite struct {
    2. Client *http.Client
    3. Response *http.Response
    4. ResponseBody []byte
    5. }
    6.  
    7. // 一些请求方法
    8. func (t *TestSuite) Get(path string)
    9. func (t *TestSuite) Post(path string, contentType string, reader io.Reader)
    10. func (t *TestSuite) PostForm(path string, data url.Values)
    11. func (t *TestSuite) MakeRequest(req *http.Request)
    12.  
    13. // 一些断言方法
    14. func (t *TestSuite) AssertOk()
    15. func (t *TestSuite) AssertContentType(contentType string)
    16. func (t *TestSuite) Assert(exp bool)
    17. func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{})

    参考godoc

    所有的请求方法类似:

    • 接受一个路径 (比如 /users/)
    • 向应用程序服务器发出一个请求
    • 存储 Response 中的成员
    • 读取完整的响应到ResponseBody 成员中
      如果开发人员希望使用一个定制的HTTP客户端,而不是默认的http.DefaultClient,应当在Before() 方法之前替换它。

    断言失败后,会抛出恐慌并被测试工具捕获,并将错误列出。

    运行测试套件

    为了运行测试,testrunner 模块必须被激活。需要在 app.conf文件中配置:

    1. module.testrunner = github.com/revel/revel/modules/testrunner

    您还必须导入测试模块的路由,在你的 routes 文件中加入下面的内容:

    1. module:testrunner

    配置完后,测试就可以交互或非交互方式运行。

    运行交互式测试

    要利用 Revel 的热编译功能,交互式测试运行提供了快速编辑刷新周期。

    例如,开发人员从浏览器中访问 /@tests:

    Test Runner interface

    然后,增加一个测试方法:

    1. func (t AppTest) TestSomethingImportant() {
    2. t.Get("/")
    3. t.AssertOk()
    4. t.AssertContentType("text/xml")
    5. }

    然后,刷新浏览器,看看新的测试:

    Test Runner interface

    运行测试:

    Test Runner interface

    嗯哼,,,行不通哦,,,修改代码使用“text/html” 替换 “text/xml”类型。

    1. t.AssertContentType("text/html")

    然后,重新运行测试:

    Test Runner interface

    成功啦!

    运行非交互式测试

    Revel 命令行工具 提供了一个 test 命令,允许在命令行中运行测试。

    下面是一个示例会话:

    1. $ revel test github.com/revel/revel/samples/booking dev
    2. ~
    3. ~ revel! http://revel.github.com/revel
    4. ~
    5. INFO 2012/11/09 19:21:02 revel.go:237: Loaded module testrunner
    6. Open DB
    7. Listening on port 9000...
    8. INFO 2012/11/09 19:21:06 test.go:95: Testing Booking example (github.com/revel/revel/samples/booking) in dev mode
    9. Go to /@tests to run the tests.
    10. 1 test suite to run.
    11. AppTest PASSED 0s
    12. All Tests Passed.

    您还可以运行单个测试套件,或套件内的方法,用句点分隔参数:

    1. $ revel test github.com/revel/revel/samples/booking dev ApplicationTest
    2. $ revel test github.com/revel/revel/samples/booking dev ApplicationTest.TestThatIndexPageWorks

    在控制台测试套件只有一个简单的合格/不合格显示。更详细的结果写入到文件系统:

    1. $ cd src/github.com/revel/revel/samples/booking
    2. $ find test-results
    3. test-results
    4. test-results/app.log
    5. test-results/AppTest.passed.html
    6. test-results/result.passed

    它写三点不同:

    • 应用程序的标准输出和标准错误重定向到 app.log
    • 每个测试套件有一个HTML文件被写入,说明测试通过或失败。
    • 无论 result.passedresult.failed 被写入, 这取决于整体的成功。
      对于整合持续构建测试,有两点建议:

    • 检查返回码,0代表测试成功,否则为非0值。

    • 测试运行后要求存在 result.success, 或禁止 result.failed存在。

    注意事项

    Revel 做了什么:

    • 扫描嵌入TestSuite类型 (transitively) 的源代码
    • 在生成的 main.go 文件中,为 revel.TestSuites 类型的变量设置一个列表
    • 按要求,使用反射来查找所有以“Test”开头的TestSuite类型的方法,并调用它们来运行测试。
    • 从错误或失败的断言捕获恐慌,显示错误。
      testrunner 模块激活后,测试代码才会被构建。

    开发计划

    改进测试框架:

    • 固定存储测试数据。
    • 日志写入到一个文件中(而不是 stderr / stdout)也应该被重定向到 test-results/app.log