什么不在Rails中测试?

Cor*_*res 13 testing rspec ruby-on-rails

我已经写了一段时间的测试,我开始掌握一切.但是我有一些关于测试覆盖率真正需要的问题.共识似乎很清楚:更多的报道总是更好.但是,至少从初学者的角度来看,我想知道这是否真的如此.

以这个完全香草控制器动作为例:

def create
  @event = Event.new(params[:event])
  if @event.save
    flash[:notice] = "Event successfully created."
    redirect_to events_path
  else
    render :action => 'new'
  end
end
Run Code Online (Sandbox Code Playgroud)

只是生成的脚手架.我们这里没有做任何不寻常的事情.为什么为此操作编写控制器测试很重要?毕竟,我们甚至没有编写代码 - 生成器为我们完成了工作.除非rails中存在错误,否则此代码应该没问题.看起来测试这个动作与测试,例如collection_select并没有太大的不同 - 我们不会这样做.此外,假设我们使用黄瓜,我们应该已经涵盖了基础知识(例如重定向的地方).

对于简单的模型方法,甚至可以说同样的情况.例如:

def full_name
  "#{first_name} #{last_name}"
end
Run Code Online (Sandbox Code Playgroud)

我们真的需要为这些简单的方法编写测试吗?如果出现语法错误,您将在页面刷新时捕获它.同样,只要你的功能点击任何调用full_name方法的页面,黄瓜就会捕获这个.显然,我们不应该依赖黄瓜来做任何过于复杂的事情.但是full_name真的需要单元测试吗?

您可能会说,因为代码很简单,测试也很简单.所以你不妨写一个测试,因为它只需要一分钟.但似乎写作基本上毫无价值的测试可能弊大于利.例如,它们使您的规格变得混乱,使得更难以专注于实际上重要的复杂测试.此外,他们需要时间来运行(虽然可能不多).

但是,就像我说的那样,我几乎不是专家测试员.我不一定主张减少测试覆盖率.相反,我正在寻找一些专家建议.是否真的有理由写这么简单的测试?

Mia*_*rke 9

我在这方面的经验是,你不应该浪费你的时间来编写一些微不足道的代码测试,除非你有很多复杂的东西依赖于那些无关紧要的正确性.我认为测试吸气剂和制定者这样的东西完全是浪费时间,但我确信那里会有不止一个报道的瘾君子愿意反对我.

对我来说,测试有三个方面:

  1. 它们可以保证不间断的旧功能如果我可以通过运行测试检查我放入的任何新东西都破坏了我的旧东西,这是一件好事.

  2. 当我重写旧东西时,它们让我感到安全我重构的代码很少是微不足道的.但是,如果我想重构非常重要的代码,那么必须进行测试以确保我的重构没有破坏任何行为.

  3. 它们是我工作的文档.需要记录大量的代码.但是,如果您同意我的观点,那么代码中的注释就是魔鬼的工作,通过简明扼要的单元测试可以让您理解某些东西的正确行为,这是必须的.

任何我确定我不会破坏的东西,或者我觉得无法记录,我只是不浪费时间测试.您生成的控制器和模型方法,即使没有单元测试,我也会说都很好.


ejo*_*aud 7

唯一的绝对规则是测试应该具有成本效益.

任何实现这一目标的实用指南都会引起争议,但这里有一些建议可以避免通常会浪费的测试,或者弊大于利.

单元

  • 不要直接测试私有方法,只能通过调用它们的公共方法间接评估它们的影响.
  • 不要测试内部状态
  • 只测试非平凡的方法,其中不同的上下文可能会得到不同的结果(计算,连接,正则表达式,分支......)
  • 不要评估你不关心的事情,例如对API返回的某些消息的完整拷贝或复杂数据结构的无用部分......
  • 在单元测试中存储所有内容,它们被称为单元测试,因为您只测试一个类,而不是它的协作者.使用存根/间谍,您可以测试发送它们的消息,而无需测试其内部逻辑.
  • 将私有嵌套类视为私有方法

积分

  • 不要尝试在集成测试中测试所有组合.这就是单元测试的用途.只需测试快乐路径或最常见的情况.
  • 除非你真的是BDD,否则不要使用黄瓜
  • 集成测试并不总是需要在浏览器中运行.要测试更多性能较低的情况,可以让一些集成测试直接与模型类交互.
  • 不要测试你不拥有的东西.集成测试应该期望第三方依赖项能够完成它们的工作,但不能替代它们自己的测试套件.

调节器

  • 在控制器测试中,仅测试控制器逻辑:重定向,身份验证,权限,HTTP状态.存根业务逻辑.考虑过滤器等,如单元测试中的私有方法,仅通过公共控制器操作进行测试.

其他

  • 除了编写API之外,不要为集成测试尚未涵盖的端点编写路由测试.
  • 不要编写视图测试.您应该能够在不破坏测试的情况下更改副本或HTML类.只需评估关键视图元素作为浏览器内集成测试的一部分.
  • 测试你的客户端JS,特别是如果它拥有一些应用程序逻辑.所有这些规则也适用于JS测试.

忽略任何关于关键业务的东西的规则,或者当某些东西真正中断时(没有人想要解释他们的老板/用户为什么同样的错误发生两次,这就是为什么你应该在修复bug时至少编写回归测试).

查看该帖子的更多详情.


Bri*_*zan 6

更多的覆盖范围更适合代码质量 - 但成本更高.这里有一个滑动刻度,如果你编写一个人造心脏,你需要更多的测试.您预先支付的金额越少,您支付的可能性就越大,也许很痛苦.

在示例中,full_name,为什么要在它们之间放置一个空格,并按first_name排序,然后是last_name-这有关系吗?如果稍后要求您按姓氏排序,是否可以交换订单并添加逗号?如果姓氏是两个字会怎么样 - 额外的空间会影响事物吗?也许你还有一个别人正在解析的xml feed?如果您不确定要测试什么,对于一个简单的未记录的函数,可以考虑方法名称隐含的功能.

我认为贵公司的文化也很重要.如果你做的比别人多,那你就是在浪费时间.如果主要内容是错误的话,没有一个经过良好测试的页脚是没有帮助的.导致主要构建或其他开发人员的构建中断,会更糟糕.找到平衡很难 - 除非有人是决策者,花点时间阅读其他团队成员编写的测试代码.

有些人采用测试边缘情况的方法,并假设主要功能将通过使用得到解决.考虑到getter/setter,我想要一个模型类,对这些方法进行一些测试,可能会测试数据库列类型范围.这至少告诉我网络没问题,可以建立数据库连接,我可以访问写入存在的表等.页面来去匆匆,所以不要认为页面加载是实际的替代单元测试.(测试效率方面的注意事项 - 如果基于文件更新时间戳(自动测试)进行自动测试,该测试将无法运行,并且您想知道asap)

我宁愿进行更好的质量测试,而不是全面覆盖.但我还想要一个自动化工具来指出未经测试的内容.如果它没有经过测试,我认为它已经坏了.当你发现失败时,添加测试,即使它是简单的代码.

如果要自动化测试,运行所需的时间并不重要.每次运行测试代码时都会受益 - 此时,您知道代码的最低功能正在运行,并且您可以了解测试功能在一段时间内的可靠性.

100%的覆盖率不应该是您的目标 - 良好的测试应该是.认为正则表达式的单个测试完成任何事情都会产生误导.我宁愿没有测试而不是一个,因为我的自动覆盖报告提醒我RE是不可靠的.


And*_*hop 5

对于此方法编写一个或两个单元测试所获得的主要好处是回归测试.如果在将来的某个时候,某些事情发生了变化,会对此方法产生负面影响,那么您将能够抓住它.

是否值得付出努力最终取决于你.

通过查看它可以看到的第二个好处是测试边缘情况,比如,如果last_name""或者应该做什么nil.这可以揭示出意外的行为.

(即如果last_namenil,并且first_name"John",你得到full_name=> "John ")

同样,成本与收益最终取决于您.