# 3 mistakes to avoid in your rspec tests

`rspec` is an amazing testing tool for Ruby and Rails apps. I have used it in most of the projects I’ve worked on for a long time. Despite this, I am still prone to make mistakes, so I’ll keep a log of some of them here for future reference

### Failing to use hooks correctly

Can you spot the error in the following code?

```ruby
context 'some setup code here' do
    call_some_setup_function(x, y)

	it 'validates some conditions' do
		expect(sum(1, 2)).to eq 3
	end
end
```

To help you along, this is the error message produced. Any luck?

```plaintext
NoMethodError:
  undefined method `call_some_setup_function' for #<Class:0x000040229933d0>
```

I don’t know about you but it took me quite some time to catch the source of the error. The mistake here is that the setup function should be called in a `before` block

```ruby
context 'some setup code here' do
	before { call_some_setup_function(x, y) }

	it 'validates some conditions' do
		expect(sum(1, 2)).to eq 3
	end
end
```

### Not using the full range of matchers

I wouldn’t be able to list all the possible matchers available by default in `rspec` here. For that, take a look at the [Built-in matchers documentation](https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/)

Here are some of them that I’ve found to be useful:

```ruby
expect(result).to be_success      # passes if result.success?
expect(result).to be_failure      # passes if result.failure?
expect(result).to be_processing   # passes if result.processing?

# arrays
expect(actual).to include(expected)
expect(array).to match_array(expected_array) # exact array match

# strings
expect('gato').not_to include('ef')
expect('hola').to include('h')

# changes to object count in DB from some external function
# e.g. HTTP Request
expect { good_post_request }.to change { Account.count }.by(1)
expect { bad_post_request }.not_to change { Account.count }
```

### Repeating specs

If you have a set of specs that you seem to keep repeating in many different tests, put them in a `shared_examples` block

```ruby
shared_examples 'account creation' do
  it 'succeeds' do
    expect { post :create, data: data }.to change { Account.count }
    expect(response).to be_success
    # ... and any other expectations for the new account
  end
end

# ...and to use it in other places without repeating the examples
include_examples 'account creation'
```

You can also share and re-use common test setup steps with `shared_context` and `include_context`

> Pro tip: Under the hood `shared_examples` , `shared_examples_for` and `shared_context` are all the same thing
> 
> [rspec-core/lib/rspec/core/shared\_example\_group.rb at 8caecca0b9b299ccbaa5c7ea5dd885ab42cd57d3 · rspec/rspec-core · GitHub](https://github.com/rspec/rspec-core/blob/8caecca0b9b299ccbaa5c7ea5dd885ab42cd57d3/lib/rspec/core/shared_example_group.rb#L100)

I still need to understand this better and you can find more information in the [shared examples documentation](https://rspec.info/features/3-12/rspec-core/example-groups/shared-examples/)

Happy testing!

---

Cover Photo by [Sarah Pflug](https://burst.shopify.com/@sarahpflugphoto?utm_campaign=photo_credit&utm_content=Free+Brewery+Beer+Tanks+Image%3A+Browse+1000s+of+Pics&utm_medium=referral&utm_source=credit) from [Burst](https://burst.shopify.com/beer?utm_campaign=photo_credit&utm_content=Free+Brewery+Beer+Tanks+Image%3A+Browse+1000s+of+Pics&utm_medium=referral&utm_source=credit)
