编写RSpec测试/示例的最佳实践是什么?写一些例子来测试肯定/肯定,否定或两者?

时间:2011-08-11 05:30:30

标签: ruby-on-rails-3 bdd rspec2 rspec-rails

BDD和RSpec相当新,我真的很好奇人们在编写RSpec测试/示例时通常会做些什么,特别是因为它与同一事物的正面和负面测试有关。

例如验证用户名和有效用户名仅包含字母数字字符的规则。

肯定/肯定的测试将是这样的:

it "should be valid if it contains alphanumeric characters"
  username = 'abc123'
  username.should be_valid
end

虽然否定测试将是这样的:

it "should be invalid if it contains non-alphanumeric characters"
  username = '%as.12-'
  username.should_not be_valid
end

你会写一个测试,但不会写另一个吗?你会写两个吗?你会把它们放在同一个测试中吗?我已经看过人们做上述任何事情的例子,所以我想知道是否有最好的做法,如果是,那是什么?

写正面和负面测试的例子:

it "should be invalid if it contains non-alphanumeric characters"
  username = '%as.12-'
  username.should_not be_valid

  username = 'abc123'
  username.should be_valid
end

我已经看过人们这样做的例子,但老实说,我并不喜欢这种做法。我倾向于在保持事物干净和明确的方面有一个目的,就像我们应该如何编写方法一样,所以我更有可能编写两个单独的测试,而不是将它们合二为一。那么有一种最佳做法可以说明这种情况吗?这些示例应该从一个角度而不是所有角度测试单个特征/行为。

3 个答案:

答案 0 :(得分:2)

在那种特殊情况下,我会为正面和负面编写它们。这是因为您确实希望确保拥有有效用户名的人员拥有这些用户名,并且尝试拥有无效用户名的人不能这样做。

这样一来,如果一个应该/不应该有效的用户名与它应该是相反的,那么你就已经有了这些测试,这只是一个简单的问题,即将失败的测试添加到正确的类别中你的测试,确认测试确实失败,修复它然后确认测试然后通过。

所以是的,在这种情况下测试两者。不只是一个或另一个。

答案 1 :(得分:2)

我发现在任何这种情况下,它都可以帮助你意识到你正在做的事情并不是真正的测试。您将提供有关如何/为何使用该类及其行为的一些描述的示例。如果您需要多个示例来锚定有价值的行为,我认为可以同时包含这两种行为。

所以,例如,如果我正在描述列表的行为,我会有两个例子来描述“列表应该告诉我它是否为空”。无论是空的例子还是完整的例子都不是有价值的。

另一方面,如果您有某些事情有效的默认情况,然后是一些例外情况,那么“有效”情况是独立有价值的。您可能会在以后发现其他情况,例如:

  • 对于非字母数字
  • 应该无效
  • 对于已经采取的名称
  • 应该无效
  • 仅对数字无效
  • 应对重音字母有效

在这种情况下,你的行为有两个巧合的例子,而不是因为它们构成了一个有价值的行为方面的两个方面。有效的行为本身就很有价值。所以我在这个案例中每个测试都有一个例子,但每个测试的行为的一个方面一般。

这也适用于其他非布尔行为。例如,如果我正在编写ATM软件,我想要提供现金和借记帐户。没有另一种行为,这两种行为都没有价值。

“每次测试一个断言”是一个很好的经验法则。我发现它可能被过度使用,有时会出现“每次测试行为的一个方面”的情况。这不是其中之一,但无论如何我认为值得一提。

答案 2 :(得分:1)

此模式通常称为“每次测试一次断言”: