企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
Revel提供了一个测试框架,可以很容易地编写和运行针对您的应用程序的功能测试。 应用程序带有一个简单的测试骨架以便快速上手测试。 ## 概要 测试代码保存在测试目录中: ~~~ 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") } ~~~ 上面的例子中展示了: * 测试套件是嵌入`revel.TestSuite`的一个struct * `Before()` 、 `After()` 在每个测试方法之前和之后被调用,如果有的话。 * `revel.TestSuite` 帮助发出请求到你的应用程序,和对响应的断言。 * 如果一个断言失败,产生了恐慌,将被测试工具捕获。 你可以用两种方式运行这个测试: * 交互方式,Web浏览器,开发过程中非常有用。 * 非交互方式,命令行,对于持续构建整合有用。 ## 开发一个测试套件 要创建自己的测试套件,需要定义一个嵌入了`revel.TestSuite`类型的struct, 它提供了一个HTTP客户端和一些辅助方法发出请求到应用程序。 ~~~ type TestSuite struct { Client *http.Client Response *http.Response ResponseBody []byte } // 一些请求方法 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{}) ~~~ [参考godoc](http://gorevel.cn/docs/docs/godoc/tests.html) 所有的请求方法类似: 1. 接受一个路径 (比如 `/users/`) 2. 向应用程序服务器发出一个请求 3. 存储 `Response` 中的成员 4. 读取完整的响应到`ResponseBody` 成员中 如果开发人员希望使用一个定制的HTTP客户端,而不是默认的[http.DefaultClient](http://golang.org/pkg/net/http/#pkg-variables),应当在`Before()` 方法之前替换它。 断言失败后,会抛出恐慌并被测试工具捕获,并将错误列出。 ## 运行测试套件 为了运行测试,`testrunner` 模块必须被激活。需要在 `app.conf`文件中配置: ~~~ module.testrunner = github.com/revel/revel/modules/testrunner ~~~ 您还必须导入测试模块的路由,在你的 `routes` 文件中加入下面的内容: ~~~ module:testrunner ~~~ 配置完后,测试就可以交互或非交互方式运行。 ### 运行交互式测试 要利用 Revel 的热编译功能,交互式测试运行提供了快速编辑刷新周期。 例如,开发人员从浏览器中访问 `/@tests`: ![](https://box.kancloud.cn/2015-10-20_5625fc0008afb.png) 然后,增加一个测试方法: ~~~ func (t AppTest) TestSomethingImportant() { t.Get("/") t.AssertOk() t.AssertContentType("text/xml") } ~~~ 然后,刷新浏览器,看看新的测试: ![](https://box.kancloud.cn/2015-10-20_5625fc0022c0a.png) 运行测试: ![](https://box.kancloud.cn/2015-10-20_5625fc0035a1c.png) 嗯哼,,,行不通哦,,,修改代码使用“text/html” 替换 “text/xml”类型。 ~~~ t.AssertContentType("text/html") ~~~ 然后,重新运行测试: ![](https://box.kancloud.cn/2015-10-20_5625fc005745a.png) 成功啦! ### 运行非交互式测试 Revel [命令行工具](http://gorevel.cn/docs/manual/tool.html) 提供了一个 `test` 命令,允许在命令行中运行测试。 下面是一个示例会话: ~~~ $ revel test github.com/revel/revel/samples/booking dev ~ ~ revel! http://revel.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/revel/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/revel/revel/samples/booking dev ApplicationTest $ revel test github.com/revel/revel/samples/booking dev ApplicationTest.TestThatIndexPageWorks ~~~ 在控制台测试套件只有一个简单的合格/不合格显示。更详细的结果写入到文件系统: ~~~ $ cd src/github.com/revel/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代表测试成功,否则为非0值。 2. 测试运行后要求存在 `result.success`, 或禁止 `result.failed`存在。 ## 注意事项 Revel 做了什么: * 扫描嵌入TestSuite类型 (transitively) 的源代码 * 在生成的 main.go 文件中,为 `revel.TestSuites` 类型的变量设置一个列表 * 按要求,使用反射来查找所有以“Test”开头的TestSuite类型的方法,并调用它们来运行测试。 * 从错误或失败的断言捕获恐慌,显示错误。 当 `testrunner` 模块激活后,测试代码才会被构建。 ## 开发计划 改进测试框架: * 固定存储测试数据。 * 日志写入到一个文件中(而不是 stderr / stdout)也应该被重定向到 `test-results/app.log`