Web development blog

Objects behaviour inheritance with RSpec

Oct.27, 2009

About half of a year ago I was writing about object interface and Liskov Substitution Princeple. In short: Any class instance that extends the base class should pass all unit tests behaviour tests written for base class instance. It was a surprise for me that this concept has already been implemented in RSpec.

My previous article was primary inspired by Java programming language and it’s interface concept. Unlike Java, Ruby does not have interfaces, but behaviour inheritance is still actual for both languages. RSpec seems the first testing framework that provide the ability to validate LSP and behavior inheritance with ‘it_should_behave_like’.
With Ruby modules(mixins) feature we can build reusable code and include it in different classes(read more). With RSpec we can bundle the tests as well.

Let’s review the following module that uses one of the Rails callback and adds some logging:
module LoggedModel def after_save super handle_logging end end
and the some tests group for this module:
describe LoggableModel it "should be loggable" do LoggableModel.should ... end end
Now, we have a tested code that is going to be used in many cases like this:
class MyModel include LoggableModel def after_save do_some_other_thing end end
OK, let’s see what we have: after_save in MyModel overwrites after_save in LoggableModel and breaks the logging. This is simplest example when the behavior inheritance may be broken. Rspec shared examples groups allows you to ensure that the code in LoggableModel is used correctly from any inherited class. Let’s change the definithin of LoggableModel tests.
shared_examples_for "logged model" do it "should be loggable" do subject.should... end end
‘Subject’ is the ultimate RSpec magic that let us make a simple abstraction with the tested class and reuse these shared examples in MyModel spec:
describe MyModel do it_should_behave_like 'loggable model' end
In this way we will rerun the LoggableModel examples for MyModel and make sure that it’s behavior wasn’t broken.
:, , , ,

Web Developer Howto


3 comments to “Objects behaviour inheritance with RSpec”

  1. Ryan Davis

    I’ve been doing this for years and years through simple test class inheritance.
  2. Mark Wilden

    Yes, RSpec’s text classes are (AFAIK) somewhat opaque, so inheritance isn’t as useful.
  3. Dmitry

    Shoulda allows similar stuff via merge_block method.

Leave a Reply

The Content of this blog can be published anywhere with the link to original source.