`

如何为Rails的views写测试。

阅读更多
原文链接:http://weblog.jamisbuck.org/2007/1/29/testing-your-views

简单的说,就是别用断言来测试你的页面结构。
也就是说,别这么做:

#输入框必须在一个table的单元格里
assert_select "table td input[type=text]"
#person.name必须在h2标签里
assert_select "h2", person.name


为什么呢?因为你会希望页面(的结构)非常的容易改变(be very fluid)。你会希望改动页面的成本很低以便于你可以毫不犹豫地投入到页面的重新布局,从而使页面变得更干净。如果你在测试代码里使用的是明确的标签名,那你的页面结构将会变得十分僵硬。因为你的测试代码暗示着使用table以外的标签来排版你的表单是错误的。想用h1或者div来包装person.name吗?你不敢,这样会使测试失败。

一个更好的方式是:思考一下你真正想要测试的是什么。

首先,别测试静态的内容,比如table的结构、表单域(form fields)的顺序。相反的,要测试的是页面上动态的部分,特别是受条件支配渲染的部分(especially those parts that are subject to conditional rendering. )。

第二,测试语义,而不是测试语法(test semantically, not syntactically. )。也就是说,别基于标签的类型写测试,而是基于你要展现的内容。用CSS的class属性或者DOM的id来代替明确的标签名。

这里有个实例,假设有个这样的页面:
<% if @user.administrator? %>
  Hi <%= @user.name %>! You appear to be an administrator.
  <%= link_to "Click here", admin_url, :id => "admin_link" %>
  to see the admin stuff!
<% end %>

这里唯一真正有必要测试的是:admin的链接只能让管理员(administrators)看见。也许你会想测试链接是否指向你期望的地方,但那是次要的。

def test_admin_sees_link
  # 为管理员set up一个session,然后:
  get "index"
  assert_select "#admin_link"
end

def test_non_admin_does_not_see_link
  # 先为非管理员用户set up一个session,然后:
  get "index"
  assert_select "#admin_link", false
end


像这样安排你的测试会让测试代码更少的干扰到你为页面的美化而进行的调整。而且这会增强你对测试的信心,同时你也会很乐意去调整界面。

相关链接:Spec your views
分享到:
评论
8 楼 ywencn 2010-04-07  
yuan同学对测试非常有研究啊。。。

7 楼 yuan 2010-03-13  
我觉得给页面写测试是必要的,而且是一开始要做的第一件事(也可能是从route测试开始)。
需求细化之后,可能最终会变成这样:

引用
访问 GET /admin/articles/new链接
我希望能返回一个页面,这个页面上要有一个表单,里面有一个textfield和一个textarea,根据Rails的约定,这个textfield的name必须是article[title],textarea的name必须是article[body]。表单的action值必须是'/admin/articles',method值必须是post


再进一步(写伪代码吧):

example1:
向/admin/articles/new发送GET请求
我希望rails会去调用Admin::ArticlesController#new方法


然后开始写路由,我觉得没有必要像TDD那本书上那样傻傻的写一个直接让测试通过的傻瓜实现。没有必要先写一个map.connect,回头再写测试,说POST请求不允许过,然后再给map.connect写个condition,等测试通过后,最后再回来重构,写成map.resources。这样真的太麻烦了,我记得那书上曾经说过,这么小步的走只是告诉咱们,当有难以找到根源的bug发生时,可以通过这种方式来慢慢排除bug。我可以直接写上map.resources,反正测试==需求文档,所以测试能通过==产品符合需求。

然后如果我们不希望post请求这个url能够通过,就把这个需求也写上:
example2:
向/admin/articles/new发送POST请求
我希望rails会抛出一个routing error


OK,路由的测试足够了,其它的情况我觉得可以等bug来驱动你写测试。(至少目前我不觉得这样的路由规则会有bug。另外我认为bug==需求,bug是在它发生之前没有被考虑到的需求。)

写好路由并通过测试同时代码看起来很干净之后,接着
example3:
渲染模板/admin/articles/new
我希望渲染的结果中包括一个表单 do |表单|
  表单的action值是'/admin/articles'
  表单的method值是post
  表单.包含一个名为article[title]的textfield
  表单.包含一个名为article[body]的textarea
end


ok,现在这个页面的测试写好了。当然,还有细节上的东西要处理,比如该mock的mock,该stub的stub,让我们把注意力只集中在views上。等view写好了,测试通过了,可以开始接下来的controller测试。驱动咱们给controller写测试的原因应该是集成测试工具Cucumber告诉咱们:Red alert,任务还没有完成。(我觉得mock1234同学说“凡是考虑测试驱动必从突出集成测试这个概念入手”挺有道理的。)



我认为给页面写测试的一个原则就是:至少保证页面可以正常工作(这个也是给页面写测试的理由),不用多考虑页面的外观、结构。

最后我觉得这样自顶向下的过程是完全从需求出发,很自然。我不是很明白为什么有人说TDD/BDD必须是自底向上的(不是在本帖中说的)。如果真的是我理解的不对,我希望坚持必须自底向上的同学可以说明一下自底向上的理由。

呃,写些自己的想法,不知道看起来乱不乱。
=====================2010年9月25==================
回头再看主帖跟这个回复,似乎挺矛盾的。
6 楼 rainchen 2009-10-11  
测试view里元素是否存在,在Cucumber时代很简单很常见的场景,一句:
I should see "Click here"

很自然很语义

甚至可以顺便测试连接可访问性(如权限限制)

When I follow "Click here"
Then I should be on the admin page

这几句都是Cucumber默认生成的steps
5 楼 不是流氓 2009-10-10  
我喜欢TA的头像
4 楼 贫嘴男孩 2009-10-10  
圆圆英文不错啊!
3 楼 kaka2008 2009-10-08  
呵呵,好文啊
最近也在学习写测试代码呢。

ps:yuan同学,你很勤奋嘛,假期里还学习,发文章
2 楼 amonlei 2009-10-06  
页面上的测试,就只能考人工测试了,机器没法取代的
1 楼 yangzhihuan 2009-10-06  
我个人以为写这种views的测试实在是得不偿失.
做的功夫多,但是用处不大.一次都没写过.

相关推荐

    rails2-sample

    从给定的文件信息来看,我们正在探讨的是一本关于Ruby on Rails的书籍,书名为《Simply Rails2》,作者是Patrick Lenz。本书旨在为初学者提供深入理解Ruby on Rails框架的指南,从基础概念到高级主题均有涵盖,是...

    使用Aptana+Rails开发Rails Web应用(中文)

    为了运行和测试应用,你需要在命令行中使用Rails服务器。在Aptana中,可以使用内置的终端工具。打开“Terminal”视图,输入`rails server`启动服务器,然后在浏览器中访问`http://localhost:3000`查看你的应用。 在...

    好用的rails 2.0 Api 文档

    Rails 2.0 API 文档是一个非常宝贵的资源,它为开发者提供了全面的指南,以便于在使用Ruby on Rails 2.0版本时更好地理解和利用其框架功能。Ruby on Rails(简称Rails)是一个开源的Web应用框架,它遵循MVC(模型-...

    ruby on rails 开发环境包(ruby1.8.7,rails2.2.3)

    8. **测试**:Rails内置了测试框架Test::Unit和Functional测试,用于编写和运行应用的测试用例。 在Rails 2.2.3时代,社区已经发展出很多插件和 gems(Ruby的扩展库),如Devise用于身份验证,CanCanCan进行授权...

    Ruby on Rails源代码

    通过分析测试代码,你可以学习Rails的最佳实践和测试策略。 7. **Gemfile和Gemfile.lock**:Rails应用使用Gemfile来管理依赖,而Gemfile.lock记录了确切的gem版本。了解如何配置和管理gem可以帮助你优化应用性能和...

    rails 项目起步示例

    Rails是Ruby语言的一个著名Web开发框架,全称为Ruby on Rails,它遵循MVC(Model-View-Controller)架构模式,旨在提高开发效率和代码可读性。本示例"rails项目起步示例"是一个购物系统,非常适合初学者入门学习。 ...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    ### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助...随着对Rails的深入了解,你将会发现更多高级特性和应用场景,为实际项目开发提供更多可能性。

    Ruby on Rails Tutorial Learn Rails by Example 的源代码

    9. **测试**:Rails鼓励TDD(测试驱动开发),`spec`目录包含了RSpec测试用例,它们验证应用程序的正确性。通过`rails spec`命令,你可以运行这些测试。 10. **Scaffolding**:在`sample_app`中,你可能会看到一些...

    ruby on rails 3 tutorial.pdf

    此外,你还将接触到Rails的测试驱动开发(TDD)理念,学习如何编写测试用例,确保代码的质量和稳定性。 随着学习的深入,你将探索更高级的主题,如AJAX集成、Caching技术以提升应用性能,以及如何利用gem(Ruby的库...

    ruby on rails 教程源码

    8. **test**目录:包含测试用例,Rails支持多种测试框架,如RSpec和Test::Unit,用于确保代码质量。 9. **log**目录:存放应用的日志文件。 通过分析这个`sample_app-master`,你可以跟随教程逐步了解Rails的每个...

    Apress - Practical Rails Projects (Oct 2007)

    接着,书中会讲解Rails的基本组件,如路由(Routes)、控制器(Controllers)、模型(Models)和视图(Views),以及ActiveRecord ORM(对象关系映射)的工作原理。 在模型部分,你将学习如何定义数据库模型,使用...

    Rails入门教程一(翻译).pdf

    在开发过程中,Rails还提供了TDD(测试驱动开发)的支持,其内建的测试框架Rspec和MiniTest允许开发者编写单元测试、集成测试和功能测试,确保代码的质量和稳定性。 总之,Rails入门教程一将涵盖Rails的基础知识,...

    基于ruby on rails开发示例源码

    6. **bin/**:包含Rails的可执行脚本,如启动服务器(rails server)和运行测试(rails test)。 7. **public/**:存放静态资源,如HTML、CSS、JavaScript文件和图片。 8. **lib/**:用于存放自定义库和扩展代码。...

    Ruby on Rails入门经典-例子

    Ruby on Rails,简称RoR,是由David Heinemeier Hansson基于Ruby语言开发的一款开源Web应用程序框架,它遵循MVC(模型...学习过程中,你可以逐步理解Rails的优雅设计和强大功能,为成为一个熟练的Rails开发者奠定基础。

    inspinia_admin_v2.5_Rails_Full_Version

    Inspinia Admin是一款广受欢迎的后台管理界面模板,特别为Rails框架打造的全版本版本更是受到了开发者们的热烈追捧。此模板以其优雅的设计、丰富的功能以及对Rails框架的深度集成,为构建高效、美观的Web应用后台...

    Ruby on Rails中文指南

    11. **测试(Testing)**:Rails鼓励TDD(Test-Driven Development),提供了丰富的测试工具,如RSpec、Cucumber和MiniTest,确保代码的质量和可靠性。 12. **生成器(Generators)**:Rails的生成器可以帮助快速...

    Rails 4 in Action, Second Edition.pdf

    - **测试驱动开发(TDD)**:介绍如何使用RSpec和Capybara等工具进行单元测试和集成测试。 - **部署策略**:探讨如何将Rails应用部署到Heroku或AWS等云平台上,并确保其稳定运行。 - **安全性最佳实践**:包括如何防止...

Global site tag (gtag.js) - Google Analytics