测试记忆

发布于 2024-12-04 03:22:21 字数 1051 浏览 0 评论 0原文

我有一个名为 calculate_total 的昂贵方法。我需要一个名为 total 的方法,它将返回 calculate_total 的结果。对 total 的后续调用应返回 calculate_total 的先前结果。

我想以测试驱动的方式做到这一点。这是我的测试(我正在使用 RSpec):

describe Item do
  describe "total" do
    before do
      @item = Item.new
      @item.stub!(:calculate_total => 123)
    end

    it "returns the calculated total" do
      @item.total.should == 123
    end

    it "subsequent calls return the original result" do
      previous_total = @item.total
      @item.total.should equal(previous_total)
    end
  end
end

这不是一个好的测试,因为以下方法使测试通过,但我预计第二个测试会失败:

def total
  calculate_total
end

原因是 calculate_total 返回一个Fixnum 因此 ruby​​ 不会将结果视为 2 个不同的对象。我预计第二次测试会失败,所以我可以执行以下操作以使其通过:

def total
  @total ||= calculate_total
end

有人知道更好的测试方法吗?

我不认为这是测试它的最佳/正确方法,但我已经决定了:https://gist.github。 com/1207270

I have an expensive method called calculate_total. I need a method called total that will return the result of calculate_total. Subsequent calls to total should return the previous result of calculate_total.

I want to do this in a test driven way. Here are my tests (I'm using RSpec):

describe Item do
  describe "total" do
    before do
      @item = Item.new
      @item.stub!(:calculate_total => 123)
    end

    it "returns the calculated total" do
      @item.total.should == 123
    end

    it "subsequent calls return the original result" do
      previous_total = @item.total
      @item.total.should equal(previous_total)
    end
  end
end

This is not a good test because the following method makes the tests pass, but I was expecting the second test to fail:

def total
  calculate_total
end

The reason is calculate_total returns a Fixnum so ruby doesn't see the result as 2 different objects. I was expecting the second test to fail, so then I could do the following to make it pass:

def total
  @total ||= calculate_total
end

Anyone know a better way to test this?

I don't think this is the best/correct way to test it, but I've settled on this: https://gist.github.com/1207270

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

昇り龍 2024-12-11 03:22:22

我认为你的要点很好:你想要测试的是calculate_total是否被多次调用,而这正是你正在做的事情。我可能建议的唯一区别是稍微更明确的测试:

it "subsequent calls don't calculate the total, but still return the original result" do
  @item.should_receive(:calculate_total).once
  2.times do 
    @item.total.should == 123
  end
end

I think your gist is fine: what you want to test is whether or not calculate_total is called more than once, and that's exactly what you're doing. The only difference I might suggest is a slightly more explicit test:

it "subsequent calls don't calculate the total, but still return the original result" do
  @item.should_receive(:calculate_total).once
  2.times do 
    @item.total.should == 123
  end
end
勿忘初心 2024-12-11 03:22:22

您可以在同一规范中调用它两次并比较返回的对象以确保它们相等:

it "should memoize it" do
  total = Item.total
  # second call will yield a different object if not memoized
  Item.total.should == total
end

You could call it twice in the same spec and compare the returned objects to make sure they are equal:

it "should memoize it" do
  total = Item.total
  # second call will yield a different object if not memoized
  Item.total.should == total
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文