summaryrefslogtreecommitdiff
path: root/doc/development/gotchas.md
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2016-11-10 15:24:23 +0100
committerRémy Coutable <remy@rymai.me>2016-11-16 17:55:11 +0100
commit600282799606ed260a1149d8312494a2f6a83290 (patch)
tree5afc3e9d5bcdf4ed2e6bc66faf4743e70df05e6b /doc/development/gotchas.md
parenta65f83c6de7286fa0505742946a3629848b260c3 (diff)
downloadgitlab-ce-600282799606ed260a1149d8312494a2f6a83290.tar.gz
Add a gotcha about FactoryGirl sequencesadd-gotcha-following-24341
Related to https://gitlab.com/gitlab-org/gitlab-ce/issues/24341 Signed-off-by: Rémy Coutable <remy@rymai.me>
Diffstat (limited to 'doc/development/gotchas.md')
-rw-r--r--doc/development/gotchas.md89
1 files changed, 89 insertions, 0 deletions
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index b25ce79e89f..7bfc9cb361f 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -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].