Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for reusing code in Rspec?

I'm writing integration tests using Rspec and Capybara. I've noticed that quite often I have to execute the same bits of code when it comes to testing the creation of activerecord options.

For instance:

it "should create a new instance" do
  # I create an instance here
end

it "should do something based on a new instance" do
  # I create an instance here
  # I click into the record and add a sub record, or something else
end

The problem seems to be that ActiveRecord objects aren't persisted across tests, however Capybara by default maintains the same session in a spec (weirdness).

I could mock these records, but since this is an integration test and some of these records are pretty complicated (they have image attachments and whatnot) it's much simpler to use Capybara and fill out the user-facing forms.

I've tried defining a function that creates a new record, but that doesn't feel right for some reason. What's the best practice for this?

like image 747
James Avatar asked Dec 01 '22 23:12

James


2 Answers

There are a couple different ways to go here. First of all, in both cases, you can group your example blocks under either a describe or context block, like this:

describe "your instance" do
  it "..." do
    # do stuff here
  end

  it "..." do
    # do other stuff here
  end
end

Then, within the describe or context block, you can set up state that can be used in all the examples, like this:

describe "your instance" do
  # run before each example block under the describe block
  before(:each) do
    # I create an instance here
  end

  it "creates a new instance" do
    # do stuff here
  end

  it "do something based on a new instance" do
    # do other stuff here
  end
end

As an alternative to the before(:each) block, you can also use let helper, which I find a little more readable. You can see more about it here.

like image 57
Adam Avatar answered Dec 06 '22 18:12

Adam


The very best practice for your requirements is to use Factory Girl for creating records from a blueprint which define common attributes and database_cleaner to clean database across different tests/specs.

And never keep state (such as created records) across different specs, it will lead to dependent specs. You could spot this kind of dependencies using the --order rand option of rspec. If your specs fails randomly you have this kind of issue.

like image 21
Fabio Avatar answered Dec 06 '22 18:12

Fabio