gitlab-experiment 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/gitlab/experiment.rb +4 -0
- data/lib/gitlab/experiment/rspec.rb +99 -17
- data/lib/gitlab/experiment/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf6802aee233e6124ae21b95a164a92be868f5c5eda19e9560a813ac9f0ade0a
|
4
|
+
data.tar.gz: e8691d32ae73422e172176477c54966edc187ec72a43030070b3412e9f15d346
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a9eded639610b17e6b0cccbd17a232d187fd9bddc68047cfa14a01500e17f0f6ba78e93e7cd08d87a0cdce6e15e31198d00b0976bb72ff7de5115be15c50859
|
7
|
+
data.tar.gz: a6cdae13a053ab7c2e0ae8cdb6934db927a856263a8759499f072c9364be6f6ca6ac8bc5e279f4512e04fc930d2491fe09a72909a949ce57ff64c4971ab43a65
|
data/lib/gitlab/experiment.rb
CHANGED
@@ -66,6 +66,10 @@ module Gitlab
|
|
66
66
|
yield self if block_given?
|
67
67
|
end
|
68
68
|
|
69
|
+
def inspect
|
70
|
+
"#<#{self.class.name || 'AnonymousClass'}:#{format('0x%016X', __id__)} @name=#{name} @signature=#{signature}>"
|
71
|
+
end
|
72
|
+
|
69
73
|
def context(value = nil)
|
70
74
|
return @context if value.blank?
|
71
75
|
|
@@ -9,14 +9,32 @@ module Gitlab
|
|
9
9
|
raise ArgumentError, 'variant must be a symbol or false' unless variant.is_a?(Symbol)
|
10
10
|
|
11
11
|
klass = Gitlab::Experiment.send(:constantize, name) # rubocop:disable GitlabSecurity/PublicSend
|
12
|
-
allow(klass).to receive(:new).and_wrap_original do |new, *args, &block|
|
13
|
-
new.call(*args).tap do |instance|
|
14
|
-
allow(instance).to receive(:enabled?).and_return(true)
|
15
|
-
allow(instance).to receive(:resolve_variant_name).and_return(variant.to_s)
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
# We have to use this high level any_instance behavior as there's
|
14
|
+
# not an alternative that allows multiple wrappings of `new`.
|
15
|
+
allow_any_instance_of(klass).to receive(:enabled?).and_return(true)
|
16
|
+
allow_any_instance_of(klass).to receive(:resolve_variant_name).and_return(variant.to_s)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def wrapped_experiment(experiment, shallow: false, failure: nil, &block)
|
21
|
+
if shallow
|
22
|
+
yield experiment if block.present?
|
23
|
+
return experiment
|
24
|
+
end
|
25
|
+
|
26
|
+
receive_wrapped_new = receive(:new).and_wrap_original do |new, *new_args, &new_block|
|
27
|
+
instance = new.call(*new_args)
|
28
|
+
instance.tap(&block) if block.present?
|
29
|
+
instance.tap(&new_block) if new_block.present?
|
30
|
+
instance
|
31
|
+
end
|
32
|
+
|
33
|
+
klass = experiment.class == Class ? experiment : experiment.class
|
34
|
+
if failure
|
35
|
+
expect(klass).to receive_wrapped_new, failure
|
36
|
+
else
|
37
|
+
allow(klass).to receive_wrapped_new
|
20
38
|
end
|
21
39
|
end
|
22
40
|
end
|
@@ -24,10 +42,27 @@ module Gitlab
|
|
24
42
|
module RSpecMatchers
|
25
43
|
extend RSpec::Matchers::DSL
|
26
44
|
|
45
|
+
def require_experiment(experiment, matcher_name, classes: false)
|
46
|
+
klass = experiment.class == Class ? experiment : experiment.class
|
47
|
+
unless klass <= Gitlab::Experiment
|
48
|
+
raise(
|
49
|
+
ArgumentError,
|
50
|
+
"#{matcher_name} matcher is limited to experiment instances#{classes ? ' and classes' : ''}"
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
if experiment == klass && !classes
|
55
|
+
raise ArgumentError, "#{matcher_name} matcher requires an instance of an experiment"
|
56
|
+
end
|
57
|
+
|
58
|
+
experiment != klass
|
59
|
+
end
|
60
|
+
|
27
61
|
matcher :exclude do |context|
|
28
62
|
ivar = :'@excluded'
|
29
63
|
|
30
64
|
match do |experiment|
|
65
|
+
require_experiment(experiment, 'exclude')
|
31
66
|
experiment.context(context)
|
32
67
|
|
33
68
|
experiment.instance_variable_set(ivar, nil)
|
@@ -47,6 +82,7 @@ module Gitlab
|
|
47
82
|
ivar = :'@variant_name'
|
48
83
|
|
49
84
|
match do |experiment|
|
85
|
+
require_experiment(experiment, 'segment')
|
50
86
|
experiment.context(context)
|
51
87
|
|
52
88
|
experiment.instance_variable_set(ivar, nil)
|
@@ -72,29 +108,74 @@ module Gitlab
|
|
72
108
|
|
73
109
|
def message_details
|
74
110
|
message = ''
|
75
|
-
message += %(\n
|
76
|
-
message += %(\n
|
111
|
+
message += %( into variant\n expected variant: #{@expected}) if @expected
|
112
|
+
message += %(\n actual variant: #{@actual}) if @actual
|
77
113
|
message
|
78
114
|
end
|
79
115
|
end
|
80
116
|
|
81
117
|
matcher :track do |event, *event_args|
|
82
118
|
match do |experiment|
|
83
|
-
|
119
|
+
expect_tracking_on(experiment, event, *event_args)
|
84
120
|
end
|
85
121
|
|
86
122
|
match_when_negated do |experiment|
|
87
|
-
|
123
|
+
expect_tracking_on(experiment, event, *event_args, negated: true)
|
88
124
|
end
|
89
125
|
|
90
|
-
|
91
|
-
|
92
|
-
|
126
|
+
chain :for do |expected_variant|
|
127
|
+
raise ArgumentError, 'variant name must be provided' if expected.blank?
|
128
|
+
|
129
|
+
@expected_variant = expected_variant.to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
chain(:with_context) { |expected_context| @expected_context = expected_context }
|
133
|
+
chain(:on_any_instance) { @on_self = false }
|
134
|
+
|
135
|
+
def expect_tracking_on(experiment, event, *event_args, negated: false)
|
136
|
+
@experiment = experiment
|
137
|
+
@on_self = true if require_experiment(experiment, 'track', classes: !@on_self) && @on_self.nil?
|
138
|
+
wrapped_experiment(experiment, shallow: @on_self, failure: failure_message(:no_new, event)) do |instance|
|
139
|
+
@experiment = instance
|
140
|
+
allow(@experiment).to receive(:track)
|
141
|
+
|
142
|
+
if negated
|
143
|
+
expect(@experiment).not_to receive_tracking_call_for(event, *event_args)
|
144
|
+
else
|
145
|
+
expect(@experiment).to receive_tracking_call_for(event, *event_args)
|
146
|
+
end
|
93
147
|
end
|
94
148
|
end
|
95
149
|
|
96
|
-
def
|
97
|
-
receive(:track).with(*
|
150
|
+
def receive_tracking_call_for(event, *event_args)
|
151
|
+
receive(:track).with(*[event, *event_args]) do # rubocop:disable CodeReuse/ActiveRecord
|
152
|
+
if @expected_variant
|
153
|
+
expect(@experiment.variant.name).to eq(@expected_variant), failure_message(:variant, event)
|
154
|
+
end
|
155
|
+
|
156
|
+
if @expected_context
|
157
|
+
expect(@experiment.context.value).to include(@expected_context), failure_message(:context, event)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def failure_message(failure_type, event)
|
163
|
+
case failure_type
|
164
|
+
when :variant
|
165
|
+
<<~MESSAGE.strip
|
166
|
+
expected #{@experiment.inspect} to have tracked #{event.inspect} for variant
|
167
|
+
expected variant: #{@expected_variant}
|
168
|
+
actual variant: #{@experiment.variant.name}
|
169
|
+
MESSAGE
|
170
|
+
when :context
|
171
|
+
<<~MESSAGE.strip
|
172
|
+
expected #{@experiment.inspect} to have tracked #{event.inspect} with context
|
173
|
+
expected context: #{@expected_context}
|
174
|
+
actual context: #{@experiment.context.value}
|
175
|
+
MESSAGE
|
176
|
+
when :no_new
|
177
|
+
%(expected #{@experiment.inspect} to have tracked #{event.inspect}, but no new instances were created)
|
178
|
+
end
|
98
179
|
end
|
99
180
|
end
|
100
181
|
end
|
@@ -103,9 +184,10 @@ end
|
|
103
184
|
|
104
185
|
RSpec.configure do |config|
|
105
186
|
config.include Gitlab::Experiment::RSpecHelpers
|
187
|
+
config.include Gitlab::Experiment::Dsl
|
106
188
|
|
107
189
|
config.include Gitlab::Experiment::RSpecMatchers, :experiment
|
108
|
-
config.define_derived_metadata(file_path:
|
190
|
+
config.define_derived_metadata(file_path: Regexp.new('/spec/experiments/')) do |metadata|
|
109
191
|
metadata[:type] = :experiment
|
110
192
|
end
|
111
193
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-experiment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitLab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|