【问题标题】:How to test a method that filters on several conditions?如何测试在多个条件下过滤的方法?
【发布时间】:2016-10-05 11:04:45
【问题描述】:

我想改进一种便捷方法的规范,该方法返回一组用户,这些用户的购买将于明天到期,并将使用某种支付方式(忽略其他支付方式)进行支付。

规格大致如下:

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. 设置(几乎)所有记录组合,并有一个单一的期望。这不会产生重叠,但也会让开发人员对为什么这个方法返回这个特定的数组一无所知。

所有方法都有其缺点,我想知道是否有最佳实践来测试这些方法?

【问题讨论】:

  • 您也可以发布您正在测试的方法吗?乍一看您的规范,我建议您将原始方法分解成更小的部分并进行测试。

标签: ruby-on-rails ruby testing rspec


【解决方案1】:

在选项 1 和 2 之间做出决定可能很棘手,但选项 3 无疑是最糟糕的选项。单元测试有两个目的* - 它们推动干净的代码设计,并记录代码对未来开发人员的作用。正如您正确指出的那样,拥有“一个巨大的测试”会使开发人员不知道该方法为何如此行事,因此破坏了测试的一半好处。此外,这些类型的测试并不是那种驱动干净代码设计的测试,所以你可能也失去了这种好处。

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

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

指导原则是,不要对同一事物进行两次测试。如果通过在每个测试中断言每个元素,您觉得您在测试同一事物两次,那么这可能不是正确的方法。

* 好吧,有时他们也会发现错误,但他们自己并不会告诉您您的系统工作正常并且没有错误。这就是测试整个系统的其他形式的测试的目的。绿色单元测试不会让您有足够的信心将其发布到生产环境中。

【讨论】:

  • “弱”断言允许您拥有共享设置并有选择地使用它。如果您添加更多用户,则断言不会失败,因为它仍会“包含该特定用户”。
  • 选择性设置是一个坏主意,因为它隐藏了与哪个测试相关的设置。任何共享设置代码都应该是所有使用它的测试的必要设置。您不应该添加到共享设置代码来服务一个额外的测试,因为随着时间的推移,每个测试的目的变得模糊不清。这就是在测试中重复自己的美妙之处 - 每个测试都易于阅读,并且随着时间的推移保持不变。
猜你喜欢
  • 1970-01-01
  • 2021-11-01
  • 2015-07-18
  • 2014-01-28
  • 2020-07-07
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多