1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::Ml::ExperimentsController, feature_category: :mlops do
let_it_be(:project_with_feature) { create(:project, :repository) }
let_it_be(:user) { project_with_feature.first_owner }
let_it_be(:project_without_feature) do
create(:project, :repository).tap { |p| p.add_developer(user) }
end
let_it_be(:experiment) do
create(:ml_experiments, project: project_with_feature, user: user).tap do |e|
create(:ml_candidates, experiment: e, user: user)
end
end
let(:params) { basic_params }
let(:ff_value) { true }
let(:project) { project_with_feature }
let(:basic_params) { { namespace_id: project.namespace.to_param, project_id: project } }
before do
stub_feature_flags(ml_experiment_tracking: false)
stub_feature_flags(ml_experiment_tracking: project_with_feature) if ff_value
sign_in(user)
end
shared_examples '404 if feature flag disabled' do
context 'when :ml_experiment_tracking disabled' do
let(:ff_value) { false }
it 'is 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'GET index' do
before do
list_experiments
end
it 'renders the template' do
expect(response).to render_template('projects/ml/experiments/index')
end
it 'does not perform N+1 sql queries' do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_experiments }
create_list(:ml_experiments, 2, project: project, user: user)
expect { list_experiments }.not_to exceed_all_query_limit(control_count)
end
context 'when :ml_experiment_tracking is disabled for the project' do
let(:project) { project_without_feature }
it 'responds with a 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
it_behaves_like '404 if feature flag disabled'
end
describe 'GET show' do
let(:params) { basic_params.merge(id: experiment.iid) }
it 'renders the template' do
show_experiment
expect(response).to render_template('projects/ml/experiments/show')
end
describe 'pagination' do
let_it_be(:candidates) { create_list(:ml_candidates, 5, experiment: experiment) }
before do
stub_const("Projects::Ml::ExperimentsController::MAX_CANDIDATES_PER_PAGE", 2)
candidates
show_experiment
end
context 'when out of bounds' do
let(:params) { basic_params.merge(id: experiment.iid, page: 10000) }
it 'redirects to last page' do
last_page = (experiment.candidates.size + 1) / 2
expect(response).to redirect_to(project_ml_experiment_path(project, experiment.iid, page: last_page))
end
end
context 'when bad page' do
let(:params) { basic_params.merge(id: experiment.iid, page: 's') }
it 'uses first page' do
expect(assigns(:pagination)).to include(
page: 1,
is_last_page: false,
per_page: 2,
total_items: experiment.candidates&.size
)
end
end
end
it 'does not perform N+1 sql queries' do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { show_experiment }
create_list(:ml_candidates, 2, :with_metrics_and_params, experiment: experiment)
expect { show_experiment }.not_to exceed_all_query_limit(control_count)
end
it_behaves_like '404 if feature flag disabled' do
before do
show_experiment
end
end
end
private
def show_experiment
get project_ml_experiment_path(project, experiment.iid), params: params
end
def list_experiments
get project_ml_experiments_path(project), params: params
end
end
|