3

对于 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

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

4

3 回答 3

2

在那种特殊情况下,我会将它们同时写为positive 和negative。这是因为您确实想确保拥有有效用户名的人被允许拥有它们,而试图拥有无效用户名的人则不能这样做。

同样,如果一个应该/不应该有效的用户名与它应该是相反的用户名出现,那么您将已经进行了这些测试,并且只需在测试中将失败的测试添加到正确的类别中即可,确认测试确实失败,修复它,然后确认测试通过。

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

于 2011-08-11T06:22:06.867 回答
2

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

因此,例如,如果我在描述列表的行为,我将有两个示例来描述“列表应该告诉我它是否为空”。空的例子和完整的例子本身都没有价值。

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

  • 对于非字母数字应该是无效的
  • 对于已经使用的名字应该是无效的
  • 应该只对数字无效
  • 应该对重音字母有效

等等

在这种情况下,您的行为有两个巧合的例子,而不是因为它们形成了行为的有价值方面的两个方面。有效的行为本身就是有价值的。因此,在这种情况下,我会为每个测试提供一个示例,但通常是每个测试的行为的一个方面。

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

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

于 2011-08-12T23:11:38.190 回答
1

这种模式通常被称为“每个测试一个断言”:

于 2011-08-11T22:16:13.140 回答