rails笔记: 测试
rails 测试
- model的测试 => unit test
- controller的测试 => functional
unit test
默认所有的Model都产生在 test/unit/xxxx_test.rb
rake clone_structure_to_test #可以把dev中的数据结果自动同步到test的数据中
fixture
数据库不好测试,因为数据是长时间有效的,很难重现,所有得采用类似csv导入的技术(我目前用的),而fixture 就是类似csv文件的东西,但是和rails内部结合更紧密,在Conveniences的作用下能自动控制数据初始状态,这也是rails的一次成功尝试(在java中未看到这样的设施, 倒是有蹩脚的dbunit...xml啊xml)
fixture的结构是一个yaml格式的文件
version_control_book:
id: 1
title: Pragmatic Version Control
description: How to use version control
image_url: http://.../sk_svn_small.jpg
price: 29.95
date_available: 2005-01-26 00:00:00
entity_name:
id: 2
title: Pragmatic Project Automation
description: How to automate your project
image_url: http://.../sk_auto_small.jpg
price: 29.95
date_available: <%=some_method%>
抬头的标记version_control_book标明了该记录的名字, 缩进的部分一共组成了一个hash做为一条记录, fixture支持使用erb指令<%%>来进行一些动态生成
在所有的的testcase中 都可以直接使用fixture :fixnames指令来导入数据到对象中, 十分方便,访问方式为fixname(:entityname),
这里的对应关系是Product.rb => products(db teable) => products.yml=>fixture :products
test_helper.rb
test_helper负责test环境中的初始化, 在这里进行的修改所有test都可以看到, 比如添加新的assert方法
rails (升级的问题)
1 fixture升级
- 老rails中 fixture中的记录会自动创建@var 实例变量到对象中,可以直接用@version_control_book访问
- 新的采用products(:ersion_control_book),不自动创建实例变量
2 事务管理升级
- 老rails默认没有事务, 每个testcase都会重新生成数据,速度较慢
- 新的采用事务,每个testcase从新开始事务,结束以后ROLLBACK,避免删除数据以及重新导入(对于mysql需要使用支持事务的表类型,如innodb)
至于如何让新rails采用旧方式测试, 目前还没有这个的需求,觉得随着rails1.0流行,可能今后也不会用到
functional test (controller)
controller的测试能力
- 检查rails内部对象: session, flash, cookies等
- 模仿浏览器作操作: get post put delete head
- 检查服务端响应: assert_redirected_to assert_response
- 检查view: assert_template
- 解析view: assert_tag
功能虽然强大,但是使用的时候应采取KISS原则写测试,有必要的才测
Mock Object
在ruby下,mock很简单, 如下步骤即可
require 'models/some_model'
class SomeModel
def mockedmethod(arg)
....
end
end
这样自动覆盖了原来的方法, 起到mock的效果
测试驱动
- 一定要先写测试
- 有bug的时候,先写测试,能测试出bug以后再修改
- 如果一个类难测试,那么说明设计有问题, 测试驱动设计
rake的工具支持
..见rails工具
性能测试
首先通过 fixture 的动态功能批量生成数据
<% for i in 1..100 %>
order_<%= i %>:
id: <%= i %>
name: Fred
email: fred@flintstones.com
address: 123 Rockpile Circle
pay_type: check
<% end %>
在test方法中,使用 Benchmark::realltime do xxx end来跑测试即可