verdict 0.6.3 → 0.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a92b885958acdb2076598cf696dcd91c8a2247a9
4
- data.tar.gz: 942c8fca6745450639522b541f703d01ef3dab3f
3
+ metadata.gz: a1929eb3266514c557ec595e7fa7f80065a1b600
4
+ data.tar.gz: 1f34b0ad26c876f348649ad04d96a9f0c077ea48
5
5
  SHA512:
6
- metadata.gz: 6d7a2547e02b9e07864a0c26d74d244033d21e5ad8eaabf4aed09b92e1d356cc34aea7a70a4fd16271d740ff5393a3d1c13ebe940ceb7e56ea544ef3316b90bb
7
- data.tar.gz: f3d02419590bd341634b7946282aab584daf19db6d6fa7718425b8565d239b227906c3ef0354c17a253cb2f956f2a25c63b6bb4150a93323865f8b8ebcbbcf91
6
+ metadata.gz: 63801e6ec63ae74dcb33c418090fec977a4598e23da4ff6bc642e2041025915f5ea8eda536ff7c5415dfd18106d1dc1c1fe339b6901b26663b70bfcad4d8803f
7
+ data.tar.gz: 982e62386331ba13174d3e758a9624ba76b80e45e30ba59f788c65a239585a74abd6386f79622e0dd7314328c0e7843852a01bb6a4b4f7597f6b1d3618f99644
@@ -1,3 +1,10 @@
1
+ ## v0.7.0
2
+ **This version has breaking changes**
3
+
4
+ * Experiment can now specify multiple qualify blocks
5
+ * `Verdict::Experiment#qualifier` has been removed in favor for `Verdict::Experiment#qualifiers`, which returns an array of procs
6
+ * Allow pass of an argument to qualify with a method name as a symbol, instead of a block
7
+
1
8
  ## v0.6.3
2
9
 
3
10
  * Fix bug were Verdict.directory is overwritten
@@ -2,7 +2,7 @@ class Verdict::Experiment
2
2
 
3
3
  include Verdict::Metadata
4
4
 
5
- attr_reader :handle, :qualifier, :storage, :event_logger
5
+ attr_reader :handle, :qualifiers, :storage, :event_logger
6
6
 
7
7
  def self.define(handle, *args, &block)
8
8
  experiment = self.new(handle, *args, &block)
@@ -14,7 +14,7 @@ class Verdict::Experiment
14
14
  @handle = handle.to_s
15
15
 
16
16
  options = default_options.merge(options)
17
- @qualifier = options[:qualifier]
17
+ @qualifiers = Array(options[:qualifier] || options[:qualifiers])
18
18
  @event_logger = options[:event_logger] || Verdict::EventLogger.new(Verdict.default_logger)
19
19
  @storage = storage(options[:storage] || :memory)
20
20
  @store_unqualified = options[:store_unqualified]
@@ -58,8 +58,16 @@ class Verdict::Experiment
58
58
  end
59
59
  end
60
60
 
61
- def qualify(&block)
62
- @qualifier = block
61
+ def qualify(method_name = nil, &block)
62
+ if block_given?
63
+ @qualifiers << block
64
+ elsif method_name.nil?
65
+ raise ArgumentError, "no method nor blocked passed!"
66
+ elsif respond_to?(method_name, true)
67
+ @qualifiers << method(method_name).to_proc
68
+ else
69
+ raise ArgumentError, "No helper for #{method_name.inspect}"
70
+ end
63
71
  end
64
72
 
65
73
  def storage(storage = nil, options = {})
@@ -169,7 +177,7 @@ class Verdict::Experiment
169
177
  end
170
178
 
171
179
  def has_qualifier?
172
- !@qualifier.nil?
180
+ @qualifiers.any?
173
181
  end
174
182
 
175
183
  def everybody_qualifies?
@@ -204,7 +212,7 @@ class Verdict::Experiment
204
212
 
205
213
  def subject_qualifies?(subject, context = nil)
206
214
  ensure_experiment_has_started
207
- everybody_qualifies? || @qualifier.call(subject, context)
215
+ everybody_qualifies? || @qualifiers.all? { |qualifier| qualifier.call(subject, context) }
208
216
  end
209
217
 
210
218
  protected
@@ -1,3 +1,3 @@
1
1
  module Verdict
2
- VERSION = "0.6.3"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -5,7 +5,7 @@ class ExperimentTest < Minitest::Test
5
5
 
6
6
  def test_no_qualifier
7
7
  e = Verdict::Experiment.new('test')
8
- assert !e.has_qualifier?
8
+ refute e.has_qualifier?
9
9
  assert e.everybody_qualifies?
10
10
  end
11
11
 
@@ -18,14 +18,14 @@ class ExperimentTest < Minitest::Test
18
18
  end
19
19
 
20
20
  assert e.has_qualifier?
21
- assert !e.everybody_qualifies?
21
+ refute e.everybody_qualifies?
22
22
 
23
23
  subject_stub = Struct.new(:id, :country)
24
24
  ca_subject = subject_stub.new(1, 'CA')
25
25
  us_subject = subject_stub.new(1, 'US')
26
26
 
27
- assert e.qualifier.call(ca_subject)
28
- assert !e.qualifier.call(us_subject)
27
+ assert e.qualifiers.all? { |q| q.call(ca_subject) }
28
+ refute e.qualifiers.all? { |q| q.call(us_subject) }
29
29
 
30
30
  qualified = e.assign(ca_subject)
31
31
  assert_kind_of Verdict::Assignment, qualified
@@ -33,7 +33,74 @@ class ExperimentTest < Minitest::Test
33
33
 
34
34
  non_qualified = e.assign(us_subject)
35
35
  assert_kind_of Verdict::Assignment, non_qualified
36
- assert !non_qualified.qualified?
36
+ refute non_qualified.qualified?
37
+ assert_equal nil, non_qualified.group
38
+ end
39
+
40
+ def test_multiple_qualifier
41
+ e = Verdict::Experiment.new('test') do |experiment|
42
+ qualify { |subject| subject.language == 'fr' }
43
+ qualify { |subject| subject.country == 'CA' }
44
+
45
+ groups do
46
+ group :all, 100
47
+ end
48
+ end
49
+
50
+ assert e.has_qualifier?
51
+ refute e.everybody_qualifies?
52
+
53
+ subject_stub = Struct.new(:id, :country, :language)
54
+ fr_subject = subject_stub.new(1, 'CA', 'fr')
55
+ en_subject = subject_stub.new(2, 'CA', 'en')
56
+
57
+ assert e.qualifiers.all? { |q| q.call(fr_subject) }
58
+ refute e.qualifiers.all? { |q| q.call(en_subject) }
59
+
60
+ qualified = e.assign(fr_subject)
61
+ assert_kind_of Verdict::Assignment, qualified
62
+ assert_equal e.group(:all), qualified.group
63
+
64
+ non_qualified = e.assign(en_subject)
65
+ assert_kind_of Verdict::Assignment, non_qualified
66
+ refute non_qualified.qualified?
67
+ assert_equal nil, non_qualified.group
68
+ end
69
+
70
+ module CountryIsCanadaHelper
71
+ def country_is_canada(subject, _context)
72
+ subject.country == 'CA'
73
+ end
74
+ end
75
+ def test_method_qualifier
76
+
77
+ e = Verdict::Experiment.new('test') do |experiment|
78
+ extend CountryIsCanadaHelper
79
+
80
+ qualify :country_is_canada
81
+
82
+ groups do
83
+ group :all, 100
84
+ end
85
+ end
86
+
87
+ assert e.has_qualifier?
88
+ refute e.everybody_qualifies?
89
+
90
+ subject_stub = Struct.new(:id, :country)
91
+ ca_subject = subject_stub.new(1, 'CA')
92
+ us_subject = subject_stub.new(1, 'US')
93
+
94
+ assert e.qualifiers.all? { |q| q.call(ca_subject, nil) }
95
+ refute e.qualifiers.all? { |q| q.call(us_subject, nil) }
96
+
97
+ qualified = e.assign(ca_subject)
98
+ assert_kind_of Verdict::Assignment, qualified
99
+ assert_equal e.group(:all), qualified.group
100
+
101
+ non_qualified = e.assign(us_subject)
102
+ assert_kind_of Verdict::Assignment, non_qualified
103
+ refute non_qualified.qualified?
37
104
  assert_equal nil, non_qualified.group
38
105
  end
39
106
 
@@ -45,7 +112,7 @@ class ExperimentTest < Minitest::Test
45
112
  end
46
113
  end
47
114
 
48
- assert !e.assign(nil).qualified?
115
+ refute e.assign(nil).qualified?
49
116
  assert_equal nil, e.convert('', :mygoal)
50
117
  end
51
118
 
@@ -63,12 +130,12 @@ class ExperimentTest < Minitest::Test
63
130
  assignment = e.assign(1)
64
131
  assert_kind_of Verdict::Assignment, assignment
65
132
  assert assignment.qualified?
66
- assert !assignment.returning?
133
+ refute assignment.returning?
67
134
  assert_equal assignment.group, e.group(:a)
68
135
 
69
136
  assignment = e.assign(3)
70
137
  assert_kind_of Verdict::Assignment, assignment
71
- assert !assignment.qualified?
138
+ refute assignment.qualified?
72
139
 
73
140
  assert_equal :a, e.switch(1)
74
141
  assert_equal :b, e.switch(2)
@@ -175,7 +242,7 @@ class ExperimentTest < Minitest::Test
175
242
  original_assignment = e.assign(subject)
176
243
  assert original_assignment.qualified?
177
244
  new_assignment = e.disqualify_manually(subject)
178
- assert !new_assignment.qualified?
245
+ refute new_assignment.qualified?
179
246
  end
180
247
 
181
248
  def test_disqualify_manually_fails_with_store_unqualified_disabled
@@ -212,7 +279,7 @@ class ExperimentTest < Minitest::Test
212
279
  mock_store.expects(:store_assignment).never
213
280
 
214
281
  assignment = e.assign(mock('subject'))
215
- assert !assignment.qualified?
282
+ refute assignment.qualified?
216
283
  end
217
284
 
218
285
  def test_assignment_event_logging
@@ -273,7 +340,7 @@ class ExperimentTest < Minitest::Test
273
340
 
274
341
  storage_mock.stubs(:retrieve_assignment).raises(Verdict::StorageError, 'storage read issues')
275
342
  rescued_assignment = e.assign(stub(id: 123))
276
- assert !rescued_assignment.qualified?
343
+ refute rescued_assignment.qualified?
277
344
  end
278
345
 
279
346
  def test_storage_write_failure
@@ -286,7 +353,7 @@ class ExperimentTest < Minitest::Test
286
353
  storage_mock.expects(:retrieve_assignment).returns(e.subject_assignment(mock('subject_identifier'), e.group(:all), nil))
287
354
  storage_mock.expects(:store_assignment).raises(Verdict::StorageError, 'storage write issues')
288
355
  rescued_assignment = e.assign(stub(id: 456))
289
- assert !rescued_assignment.qualified?
356
+ refute rescued_assignment.qualified?
290
357
  end
291
358
 
292
359
  def test_initial_started_at
@@ -328,7 +395,7 @@ class ExperimentTest < Minitest::Test
328
395
  end
329
396
 
330
397
  subject = stub(id: 'old', created_at: Time.new(2011))
331
- assert !e.assign(subject).qualified?
398
+ refute e.assign(subject).qualified?
332
399
 
333
400
  subject = stub(id: 'new', created_at: Time.new(2013))
334
401
  assert e.assign(subject).qualified?
@@ -340,7 +407,7 @@ class ExperimentTest < Minitest::Test
340
407
  groups { group :all, 100 }
341
408
  end
342
409
 
343
- assert !e.started?, "The experiment should not have started yet"
410
+ refute e.started?, "The experiment should not have started yet"
344
411
 
345
412
  e.assign(stub(id: '123'))
346
413
  assert e.started?, "The experiment should have started after the first assignment"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verdict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-19 00:00:00.000000000 Z
11
+ date: 2017-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest