Merge branch 'add-gotcha-following-24341' into 'master'
Add a "gotcha" about FactoryGirl sequences to developer docs [ci skip] See merge request !7403
This commit is contained in:
commit
c69e3942e8
|
@ -32,6 +32,95 @@ spec/models/user_spec.rb|6 error| Failure/Error: u = described_class.new NoMeth
|
|||
Except for the top-level `describe` block, always provide a String argument to
|
||||
`describe`.
|
||||
|
||||
## Don't assert against the absolute value of a sequence-generated attribute
|
||||
|
||||
Consider the following factory:
|
||||
|
||||
```ruby
|
||||
FactoryGirl.define do
|
||||
factory :label do
|
||||
sequence(:title) { |n| "label#{n}" }
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Consider the following API spec:
|
||||
|
||||
```ruby
|
||||
require 'rails_helper'
|
||||
|
||||
describe API::Labels do
|
||||
it 'creates a first label' do
|
||||
create(:label)
|
||||
|
||||
get api("/projects/#{project.id}/labels", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.first['name']).to eq('label1')
|
||||
end
|
||||
|
||||
it 'creates a second label' do
|
||||
create(:label)
|
||||
|
||||
get api("/projects/#{project.id}/labels", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.first['name']).to eq('label1')
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
When run, this spec doesn't do what we might expect:
|
||||
|
||||
```sh
|
||||
1) API::API reproduce sequence issue creates a second label
|
||||
Failure/Error: expect(json_response.first['name']).to eq('label1')
|
||||
|
||||
expected: "label1"
|
||||
got: "label2"
|
||||
|
||||
(compared using ==)
|
||||
```
|
||||
|
||||
That's because FactoryGirl sequences are not reseted for each example.
|
||||
|
||||
Please remember that sequence-generated values exist only to avoid having to
|
||||
explicitly set attributes that have a uniqueness constraint when using a factory.
|
||||
|
||||
### Solution
|
||||
|
||||
If you assert against a sequence-generated attribute's value, you should set it
|
||||
explicitly. Also, the value you set shouldn't match the sequence pattern.
|
||||
|
||||
For instance, using our `:label` factory, writing `create(:label, title: 'foo')`
|
||||
is ok, but `create(:label, title: 'label1')` is not.
|
||||
|
||||
Following is the fixed API spec:
|
||||
|
||||
```ruby
|
||||
require 'rails_helper'
|
||||
|
||||
describe API::Labels do
|
||||
it 'creates a first label' do
|
||||
create(:label, title: 'foo')
|
||||
|
||||
get api("/projects/#{project.id}/labels", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.first['name']).to eq('foo')
|
||||
end
|
||||
|
||||
it 'creates a second label' do
|
||||
create(:label, title: 'bar')
|
||||
|
||||
get api("/projects/#{project.id}/labels", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.first['name']).to eq('bar')
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Don't `rescue Exception`
|
||||
|
||||
See ["Why is it bad style to `rescue Exception => e` in Ruby?"][Exception].
|
||||
|
|
|
@ -64,6 +64,7 @@ the command line via `bundle exec teaspoon`, or via a web browser at
|
|||
methods.
|
||||
- Use `context` to test branching logic.
|
||||
- Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)).
|
||||
- Don't assert against the absolute value of a sequence-generated attribute (see [Gotchas](gotchas.md#dont-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
|
||||
- Don't supply the `:each` argument to hooks since it's the default.
|
||||
- Prefer `not_to` to `to_not` (_this is enforced by Rubocop_).
|
||||
- Try to match the ordering of tests to the ordering within the class.
|
||||
|
|
Loading…
Reference in New Issue