Terminology

Let's wrangle this RSpec jargon!

Test structure

describe

describe blocks are used to create example groups. You can nest describe blocks.

The official definition:

Thedescribemethod creates an example group. Within the block passed to
describeyou can declare nested groups using thedescribeorcontext
methods, or you can declare examples using theitorspecifymethods.

Under the hood, an example group is a class in which the block passed to
describeorcontextis evaluated. The blocks passed toitare evaluated
in the context of an _instance _of that class.

https://relishapp.com/rspec/rspec-core/v/3-4/docs/example-groups/basic-structure-describe-it

RSpec.describe MyClass do
  # prepend instance methods with #
  describe "#my_instance_method" do
  end

  # prepend class methods with a .
  describe ".my_class_method" do
  end
end

context

context blocks function like describe blocks, but semantically, they're used to flesh out the various logical branches you're trying to test.

describe "GET #my_page_under_auth" do
  subject { get :my_page_under_auth }

  context "When a user is not logged in" do
    it "does not access the page but redirects to sign in" do
      ...
    end
  end

  context "When the user is logged in" do
    before { login_the_user }

    it "successfully gets page" do
      expect(subject).to be_success
    end
  end
end

let

How to define variables in your RSpec tests

let(:sir_george) { Cat.create }
let!(:sweet_pea) { Cat.create }

# let does not create your variable immediately but waits for it to be called
# let! creates your variable immediately
# Cat.count => 1 right meow

Great read about why you should use let to define your test variables (tldr -- they're faster!) https://www.ombulabs.com/blog/rails/rspec/ruby/let-vs-instance.html

before

Use a before block to do any necessary test set up. By default, this block runs before each expectation. You can use before(:all) to only execute the before block once before all expectations. More on that here.

describe "GET #my_page_under_auth" do
  context "When the user is logged in" do
    before { login_the_user }

    it "successfully gets page" do
      expect(subject).to be_success
    end
  end
end

after

Opposite of before block; it runs after all expectations. Use after blocks to tear down any test setup.

after { User.destroy_all }

it

it "is active" do
  expect(subject.active?).to be true
  expect(subject).to be_active
end

# where subject is defined
it { is_expected.to be_active }

expectations

# expect to be a type of thing
expect(User.new).to be_an_instance_of(User)

# expect to include a module
expect(instance).to be_a_kind_of(MyModuleName)

#expect an instance or class to receive a method
expect(object).to receive(:some_wild_n_crazy_method)

# expect an action to have side effects
expect{ MyAction.call }.to change{ my_array.count }.from(1).to(2)

eq vs eql and matchers

Note the difference between eq and eql ... one checks for string type equivalence, the other does not.

expect(1).to eq(1.0)  # passes
expect(1).to eql(1.0) # fails

Read more here: https://relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers

Testing Data/Dependencies

double

Test object that mimics your objects and dependencies

stubs and mocks

I'm guilty of using these terms interchangeably, but essentially you mock out an interface and stub a canned response.

A stub...

Returns canned responses, avoiding any meaningful computation or I/O example: allow(some_object).to receive(some_method).and_return(some_value)

While mocks...

Expects specific messages; will raise an error if it doesn’t receive them by the end of the example example: expect(some_object).to receive(some_method).and_return(some_value)

Hat tip to rubyblog.pro for the definitions! Helped me to understand :)

factory

Generator for your test data! The Bot formerly known as FactoryGirl is the gem we'll be using for factory data.

fixture

File or static asset you test against

results matching ""

    No results matching ""