Skip to content

Commit 6f5b579

Browse files
Zeger-Jan van de Wegrymai
Zeger-Jan van de Weg
authored andcommitted
Use rspec-set to speed up examples
1 parent c7df977 commit 6f5b579

File tree

6 files changed

+58
-34
lines changed

6 files changed

+58
-34
lines changed

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ group :development, :test do
293293
gem 'spinach-rails', '~> 0.2.1'
294294
gem 'spinach-rerun-reporter', '~> 0.0.2'
295295
gem 'rspec_profiling', '~> 0.0.5'
296+
gem 'rspec-set', '~> 0.1.3'
296297

297298
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
298299
gem 'minitest', '~> 5.7.0'

Gemfile.lock

+2
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ GEM
659659
rspec-support (~> 3.5.0)
660660
rspec-retry (0.4.5)
661661
rspec-core
662+
rspec-set (0.1.3)
662663
rspec-support (3.5.0)
663664
rspec_profiling (0.0.5)
664665
activerecord
@@ -989,6 +990,7 @@ DEPENDENCIES
989990
rqrcode-rails3 (~> 0.1.7)
990991
rspec-rails (~> 3.5.0)
991992
rspec-retry (~> 0.4.5)
993+
rspec-set (~> 0.1.3)
992994
rspec_profiling (~> 0.0.5)
993995
rubocop (~> 0.47.1)
994996
rubocop-rspec (~> 1.15.0)

doc/development/testing.md

+15
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ Please consult the [dedicated "Frontend testing" guide](./fe_guide/testing.md).
202202
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
203203
to separate phases.
204204
- Try to use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
205+
- On `before` and `after` hooks, prefer it scoped to `:context` over `:all`
205206

206207
[four-phase-test]: https://robots.thoughtbot.com/four-phase-test
207208

@@ -225,6 +226,20 @@ so we need to set some guidelines for their use going forward:
225226

226227
[lets-not]: https://robots.thoughtbot.com/lets-not
227228

229+
#### `set` variables
230+
231+
In some cases there is no need to recreate the same object for tests again for
232+
each example. For example, a project is needed to test issues on the same
233+
project, one project will do for the entire file. This can be achieved by using
234+
`set` in the same way you would use `let`.
235+
236+
`rspec-set` only works on ActiveRecord objects, and before new examples it
237+
reloads or recreates the model, _only_ if needed. That is, when you changed
238+
properties or destroyed the object.
239+
240+
There is one gotcha; you can't reference a model defined in a `let` block in a
241+
`set` block.
242+
228243
### Time-sensitive tests
229244

230245
[Timecop](https://github.com/travisjeffery/timecop) is available in our

spec/finders/issues_finder_spec.rb

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
require 'spec_helper'
22

33
describe IssuesFinder do
4-
let(:user) { create(:user) }
5-
let(:user2) { create(:user) }
6-
let(:project1) { create(:empty_project) }
7-
let(:project2) { create(:empty_project) }
8-
let(:milestone) { create(:milestone, project: project1) }
9-
let(:label) { create(:label, project: project2) }
10-
let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone, title: 'gitlab') }
11-
let(:issue2) { create(:issue, author: user, assignee: user, project: project2, description: 'gitlab') }
12-
let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2, title: 'tanuki', description: 'tanuki') }
4+
set(:user) { create(:user) }
5+
set(:user2) { create(:user) }
6+
set(:project1) { create(:empty_project) }
7+
set(:project2) { create(:empty_project) }
8+
set(:milestone) { create(:milestone, project: project1) }
9+
set(:label) { create(:label, project: project2) }
10+
set(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone, title: 'gitlab') }
11+
set(:issue2) { create(:issue, author: user, assignee: user, project: project2, description: 'gitlab') }
12+
set(:issue3) { create(:issue, author: user2, assignee: user2, project: project2, title: 'tanuki', description: 'tanuki') }
1313

1414
describe '#execute' do
15-
let(:closed_issue) { create(:issue, author: user2, assignee: user2, project: project2, state: 'closed') }
16-
let!(:label_link) { create(:label_link, label: label, target: issue2) }
15+
set(:closed_issue) { create(:issue, author: user2, assignee: user2, project: project2, state: 'closed') }
16+
set(:label_link) { create(:label_link, label: label, target: issue2) }
1717
let(:search_user) { user }
1818
let(:params) { {} }
1919
let(:issues) { IssuesFinder.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute }
2020

21-
before do
21+
before(:context) do
2222
project1.team << [user, :master]
2323
project2.team << [user, :developer]
2424
project2.team << [user2, :developer]

spec/requests/api/issues_spec.rb

+27-22
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
describe API::Issues do
44
include EmailHelpers
55

6-
let(:user) { create(:user) }
6+
set(:user) { create(:user) }
7+
set(:project) do
8+
create(:empty_project, :public, creator_id: user.id, namespace: user.namespace)
9+
end
10+
711
let(:user2) { create(:user) }
812
let(:non_member) { create(:user) }
9-
let(:guest) { create(:user) }
10-
let(:author) { create(:author) }
11-
let(:assignee) { create(:assignee) }
13+
set(:guest) { create(:user) }
14+
set(:author) { create(:author) }
15+
set(:assignee) { create(:assignee) }
1216
let(:admin) { create(:user, :admin) }
13-
let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: user.namespace ) }
1417
let(:issue_title) { 'foo' }
1518
let(:issue_description) { 'closed' }
1619
let!(:closed_issue) do
@@ -43,19 +46,19 @@
4346
title: issue_title,
4447
description: issue_description
4548
end
46-
let!(:label) do
49+
set(:label) do
4750
create(:label, title: 'label', color: '#FFAABB', project: project)
4851
end
4952
let!(:label_link) { create(:label_link, label: label, target: issue) }
50-
let!(:milestone) { create(:milestone, title: '1.0.0', project: project) }
51-
let!(:empty_milestone) do
53+
set(:milestone) { create(:milestone, title: '1.0.0', project: project) }
54+
set(:empty_milestone) do
5255
create(:milestone, title: '2.0.0', project: project)
5356
end
5457
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
5558

5659
let(:no_milestone_title) { URI.escape(Milestone::None.title) }
5760

58-
before do
61+
before(:all) do
5962
project.team << [user, :reporter]
6063
project.team << [guest, :guest]
6164
end
@@ -70,6 +73,8 @@
7073
end
7174

7275
context "when authenticated" do
76+
let(:first_issue) { json_response.first }
77+
7378
it "returns an array of issues" do
7479
get api("/issues", user)
7580

@@ -79,46 +84,46 @@
7984
end
8085

8186
it 'returns an array of closed issues' do
82-
get api('/issues?state=closed', user)
87+
get api('/issues', user), state: :closed
8388

8489
expect_paginated_array_response(size: 1)
85-
expect(json_response.first['id']).to eq(closed_issue.id)
90+
expect(first_issue['id']).to eq(closed_issue.id)
8691
end
8792

8893
it 'returns an array of opened issues' do
89-
get api('/issues?state=opened', user)
94+
get api('/issues', user), state: :opened
9095

9196
expect_paginated_array_response(size: 1)
92-
expect(json_response.first['id']).to eq(issue.id)
97+
expect(first_issue['id']).to eq(issue.id)
9398
end
9499

95100
it 'returns an array of all issues' do
96-
get api('/issues?state=all', user)
101+
get api('/issues', user), state: :all
97102

98103
expect_paginated_array_response(size: 2)
99-
expect(json_response.first['id']).to eq(issue.id)
104+
expect(first_issue['id']).to eq(issue.id)
100105
expect(json_response.second['id']).to eq(closed_issue.id)
101106
end
102107

103108
it 'returns issues matching given search string for title' do
104-
get api("/issues?search=#{issue.title}", user)
109+
get api("/issues", user), search: issue.title
105110

106111
expect_paginated_array_response(size: 1)
107112
expect(json_response.first['id']).to eq(issue.id)
108113
end
109114

110115
it 'returns issues matching given search string for description' do
111-
get api("/issues?search=#{issue.description}", user)
116+
get api("/issues", user), search: issue.description
112117

113118
expect_paginated_array_response(size: 1)
114-
expect(json_response.first['id']).to eq(issue.id)
119+
expect(first_issue['id']).to eq(issue.id)
115120
end
116121

117122
it 'returns an array of labeled issues' do
118-
get api("/issues?labels=#{label.title}", user)
123+
get api("/issues", user), labels: label.title
119124

120125
expect_paginated_array_response(size: 1)
121-
expect(json_response.first['labels']).to eq([label.title])
126+
expect(first_issue['labels']).to eq([label.title])
122127
end
123128

124129
it 'returns an array of labeled issues when all labels matches' do
@@ -135,13 +140,13 @@
135140
end
136141

137142
it 'returns an empty array if no issue matches labels' do
138-
get api('/issues?labels=foo,bar', user)
143+
get api('/issues', user), labels: 'foo,bar'
139144

140145
expect_paginated_array_response(size: 0)
141146
end
142147

143148
it 'returns an array of labeled issues matching given state' do
144-
get api("/issues?labels=#{label.title}&state=opened", user)
149+
get api("/issues", user), labels: label.title, state: :opened
145150

146151
expect_paginated_array_response(size: 1)
147152
expect(json_response.first['labels']).to eq([label.title])

spec/requests/api/merge_requests_spec.rb

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
context "when unauthenticated" do
2727
it "returns authentication error" do
2828
get api("/projects/#{project.id}/merge_requests")
29+
2930
expect(response).to have_http_status(401)
3031
end
3132
end

0 commit comments

Comments
 (0)