开发者

Setting up a test in rspec with multiple "it" blocks

Say I have an instance method that does many different things that I need to test, something like store#process_order. I'd like to test that it sends an email to the customer, adds an entry in the orders table, charges a credit card, etc. What's the best way to set this up in rspec? Currently, I'm using rspec and factory girl I do somethin开发者_开发知识库g like this:

describe Store do
  describe "#process_order" do
    before do
      @store = Factory(:store)
      @order = Factory(:order)
      # call the process method
      @store.process_order(@order)
    end

    it 'sends customer an email' do
      ...
    end
    it 'inserts order to db' do
      ...
    end
    it 'charges credit card' do
      ...
    end
  end
end

But it feels really tedious. Is this really the right way to write a spec for a method that I need to make sure does several different things?

Note: I'm not interested in answers about whether or not this is good design. It's just an example I made up to help w/ my question - how to write these types of specs.


This is a good method because you can identify which element is broken if something breaks in the future. I am all for testing things individually. I tend not to check things get inserted into the database as you are then rails functionality. I simply check the validity of the object instead.

This is the method that is used in the RSpec book too. I would certainly recommend reading it if you are unsure about anything related to RSpec.


I think what you are doing is fine and I think it's the way rspec is intended to be used. Every statement (specification) about your app gets its own block.

You might consider using before (:all) do so that the order only has to get processed once but this can introduce dependencies on the order the specs are run.

You could combine all the code inside describe "#process_order" into one big it block if you wanted to, but then it would be less readable and rspec would give you less useful error messages when a spec fails. Go head and add raise to one of your tests and see what a nice error message you can get from rspec if you do it the way you are currently doing it.


If you want to test the entire process then we're talking about an integration test, not a unit test. If you want to test #process_order method which does several things, then I'd expect those things mean calling other methods. So, I would add #should_receive expectations and make sure that all paths are covered. Then I would spec all those methods separately so I have a nice unit spec suite for everything. In the end I would definitely write an integration/acceptance spec which checks if all those pieces are working together.

Also, I would use #let to setup test objects which removes dependencies between spec examples (it blocks). Otherwise a failure of one of the examples may cause a failure in other example giving you an incorrect feedback.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜