如何测试在几种条件下过滤的方法?

时间:2016-10-05 11:04:45

标签: ruby-on-rails ruby testing rspec

我希望改进规格以获得便利方法,该方法会返回明天将要购买的一系列用户,并且将使用特定付款方式支付(忽略其他付款方式)。

规格如下:

it "doesn't return users without purchases being due tomorrow" do
  # create user and associated records that don't fit the time condition
  expect(subject).to eq([])
end

context "with users who have purchases due tomorrow" do

  it "returns users with $CERTAIN_PAYMENT_METHOD" do
    # create different users with different payment methods,
    # all matching the time condition.

    expect(subject).to eq([user_1, user_2])
  end


  it "doesn't return users without $CERTAIN_PAYMENT_METHOD" do
    # create user with credit card,
    # matching the time condition.

    expect(subject).to eq([])
  end

end

我在这里看到三种可能的方法:

  1. 上面使用的方法:设置记录的任意组合,并期望特定于单个条件的事物,始终断言整个数组。设置可能很长且重复。
  2. 设置任意组合,并期望在返回的数组中包含/排除事物。这些"软预期"非常好读,但可能非常容易出错。
  3. 设置(几乎)所有记录组合,并且只有一个期望。这不会产生任何重叠,但也会让开发人员处于黑暗状态,因为为什么此方法会返回此特定数组。
  4. 所有方法都有其缺点,我想知道如何测试这些方法是否是最佳实践?

1 个答案:

答案 0 :(得分:1)

选项1和2之间的决定可能很棘手,但选项3毫无疑问是最糟糕的选择。单元测试有两个目的* - 它们驱动干净的代码设计,并记录代码为未来开发人员所做的工作。正如你已经正确指出的那样,进行一次巨大的测试"让开发人员在黑暗中为什么该方法的行为与它一样,因此破坏了测试的一半好处。此外,这些类型的测试不是那种驱动干净代码设计的测试,因此您可能也会失去这种优势。

选项1或2是否更好取决于您的情况。重复设置代码不一定是一个问题(研究DAMP与DRY相关的TDD),如果是一个问题,可以通过提取常见的设置代码来改进,以便它可以在测试用例之间共享(尽管这可能是一种气味如果采取太远)。在任何情况下,我都不知道选项2如何解决重复设置代码的问题 - 这两个选项之间的唯一区别在于你如何进行断言。

" stock" vs"弱"断言是一个共同的主题(研究严格的模拟与松散的模拟),并且是选项1和2之间的主要区别。选项1的问题是对生产代码进行1次更改可能导致必须更改每个测试用例的断言。出于这个原因,我建议在整个阵列上进行几个测试(测试排序和完整性等),但大多数测试尽可能具体,只测试包含/排除。这允许测试清楚地记录哪些类型的设置导致哪些输出值,而不是每个测试都有一长串断言,其中只有一个对当前测试用例感兴趣。

指导原则是,不要两次测试同一件事。如果通过断言每个测试中的每个元素,你觉得你正在测试两次相同的东西,那么它可能不是正确的方法。

*好吧,有时候他们也会发现错误,但是他们自己并没有告诉你系统是否正常工作并且没有错误。这是测试整个系统的其他形式测试的目的。绿色单元测试没有给你足够的信心来释放到生产中。