31

我不明白如何在以下代码中不遵守TDD FIRST 原则。

这些是我对 FIRST 原则的注释:

  • 快速:快速运行(子集)测试(因为您将一直运行它们)
  • 独立:没有测试依赖于其他测试,因此可以以任何顺序运行任何子集
  • 可重复:运行 N 次,得到相同的结果(帮助隔离错误并启用自动化)
  • 自检:测试可以自动检测是否通过(无需人工检查输出)
  • 及时:与被测代码几乎同时编写(使用 TDD,先编写!)

测验问题:

Sally 希望她的网站在每个月的第一个星期二有一个特殊的布局。她有以下控制器和测试代码:

# HomeController
 def index
   if Time.now.tuesday?
     render 'special_index'
   else
     render 'index'
   end
 end

 # HomeControllerSpec
 it "should render special template on Tuesdays" do
   get 'index'
   if Time.now.tuesday?
     response.should render_template('special_index')
   else
     response.should render_template('index')
   end
 end

没有遵循什么 FIRST 原则?

  1. 快速地
  2. 独立的
  3. 可重复
  4. 自检
  5. 及时

我不确定哪个 FIRST 原则没有得到遵守:

  • 快速:代码似乎很快,因为它的测试并不复杂。
  • 独立:测试不依赖于其他测试。
  • 可重复:每次测试都会得到相同的结果。'special_index'如果是星期二,'index'如果不是星期二。
  • 自检:测试可以自动检测是否通过。
  • 及时:代码和测试代码同时呈现在这里。

我在测验中选择了Timely,因为测试代码出现在控制器代码之后。但我问错了问题,回想起来,这不是一个好的选择。我不确定这里没有遵循哪个 FIRST 原则。

4

3 回答 3

45

It's not Repeatable as not everyday is Tuesday :) If you run this test on Monday you will get one result, if you run it on Tuesday, a different one.

于 2013-08-02T19:33:35.000 回答
2

第一,第一FASRCS

是的,混淆的部分原因在于,FIRST 原则对于“我”来说不够完整或不够简洁。在我参加的课程中,该原则被称为FIIRST

第二个“I”代表“孤立”。上面的测试独立于其他测试,但不是隔离在单独的类或项目中。

[更新]:

隔离可能意味着:

  • 单元测试将功能与 SUT(被测系统)隔离开来。您甚至可以从一个功能中分离出功能。这在单元测试或它们的相关组件测试和集成测试之间划定了界限,当然还有系统测试。

  • “测试隔离失败。开发人员永远不必对测试或被测试的代码进行逆向工程才能知道出了什么问题。每个测试类名称和测试方法名称以及断言文本都应该准确说明哪里出了问题。” 参考:FIRST 原则的历史

  • 单元测试可以与它在不同的开发人员工件(类、包、开发项目)和/或交付工件(Dll、包、程序集)中测试的 SUT 隔离。

  • 单元测试,测试同一个 SUT,尤其是它们包含的 Asserts,应该在不同的测试功能中相互隔离,但这只是一个建议。理想情况下,每个单元测试只包含一个断言。

  • 单元测试,测试不同的 SUT,应该相互隔离,或者与其他类型的测试隔离,当然更多的是在不同的类或其他提到的工件中。

独立可能意味着:

  • 单元测试不应该相互依赖(显式独立),除了特殊的“setup”和“teardown”函数,但即使这也是讨论的主题。

  • 特别是单元测试应该是顺序无关的(隐式独立性)。结果不应依赖于之前执行的单元测试。虽然这听起来微不足道,但事实并非如此。有些测试无法避免进行初始化和/或启动运行时。如果之前启动了一个共享(例如类)变量,SUT 可能会做出不同的反应。你给操作系统打外线电话?第一次会加载一些dll?您已经有潜在的依赖关系,至少在操作系统级别 - 有时只是轻微的,有时对于不发现错误至关重要。可能需要添加清理代码以达到最佳的测试独立性。

  • 单元测试应尽可能独立于运行时环境,而不依赖于特定的测试环境或设置。这也部分属于“可重复”。之前无需填写 20 个用户对话框。无需启动服务器。无需使数据库可用。不需要其他组件。无需网络。为了做到这一点,经常使用测试替身(存根,模拟,假货,假人,间谍......)。

Gerard Meszaros 的经典著作:xUnit 模式,在这里创造了“测试替身”这个名称并定义了不同的类型

测试双动物园赶紧解释

跟随 Martin Fowler 2007,思考存根、模拟等经典

  • 虽然单元测试永远不会完全独立于它的 SUT,但理想情况下它应该尽可能地独立于当前的实现,并且只依赖于被测试的函数或类 (SUT) 的公共接口。

结论:在这种解释中,“隔离”一词更多地强调物理位置,这通常在某种程度上暗示逻辑独立(例如类级别的隔离)。

没有关于可能更多的强调和所声称的含义的完整性。

另请参阅此处的评论。

但是(好的)单元测试还有更多的属性: Roy Osherove 在他的书“单元测试的艺术”中发现了更多的属性,我在 FIIRST 原则(链接到他的书网站)中找不到这些属性,它们是在这里用我自己的话(和首字母缩写词)引用:

  • 完全控制SUT:单元测试应该完全控制 SUT。我认为这实际上等同于独立于测试和运行时环境(例如使用模拟等)。但是由于独立性是如此的模棱两可,所以单独花一个字母是有道理的。

  • 自动化(与可重复和自检相关,但不相同)相同)。这需要一个测试(运行器)基础设施。

  • S mall,简单或用他的话来说:“易于实施”(再次,相关,但不完全相同)。常与“快”有关

  • 相关:明天的测试应该是相关的。这是最难达到的要求之一,根据“学校”的不同,在 TDD 期间也可能需要进行临时单元测试。当测试仅测试合约时,这是可以实现的,但这可能不足以满足高代码覆盖率要求。

  • 一致的结果:实际上是“足够”独立的结果。一致性是某些人在“可重复”中包含的内容。有一个基本的重叠,但它们并不相同。

  • 自我解释:就整个测试的命名、结构,特别是作为关键行的断言的语法而言,应该清楚测试了什么,如果测试失败可能会出现什么问题。与“测试隔离故障”相关,见上文。

鉴于所有这些具体点,应该比以前更清楚,编写(好的)单元测试几乎是简单的。

于 2017-03-30T23:17:25.177 回答
0

独立且可重复

它不独立于日期,然后它可以重复运行,但从技术上讲,你会得到相同的结果,因为你选择

就 FIRST 概念对 HomeController 进行测试的正确方法是更改​​评估阶段之前的时间

于 2014-11-25T07:34:39.600 回答