diff options
Diffstat (limited to 'spec/experiments/application_experiment_spec.rb')
-rw-r--r-- | spec/experiments/application_experiment_spec.rb | 144 |
1 files changed, 58 insertions, 86 deletions
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb index 501d344e920..2481ee5a806 100644 --- a/spec/experiments/application_experiment_spec.rb +++ b/spec/experiments/application_experiment_spec.rb @@ -58,30 +58,38 @@ RSpec.describe ApplicationExperiment, :experiment do end describe "publishing results" do + it "doesn't track or push data to the client if we shouldn't track", :snowplow do + allow(subject).to receive(:should_track?).and_return(false) + expect(Gon).not_to receive(:push) + + subject.publish(:action) + + expect_no_snowplow_event + end + it "tracks the assignment" do expect(subject).to receive(:track).with(:assignment) - subject.publish(nil) + subject.publish end - it "pushes the experiment knowledge into the client using Gon.global" do - expect(Gon.global).to receive(:push).with( - { - experiment: { - 'namespaced/stub' => { # string key because it can be namespaced - experiment: 'namespaced/stub', - key: '86208ac54ca798e11f127e8b23ec396a', - variant: 'control' - } - } - }, - true - ) + it "pushes the experiment knowledge into the client using Gon" do + expect(Gon).to receive(:push).with({ experiment: { 'namespaced/stub' => subject.signature } }, true) + + subject.publish + end - subject.publish(nil) + it "handles when Gon raises exceptions (like when it can't be pushed into)" do + expect(Gon).to receive(:push).and_raise(NoMethodError) + + expect { subject.publish }.not_to raise_error end end + it "can exclude from within the block" do + expect(described_class.new('namespaced/stub') { |e| e.exclude! }).to be_excluded + end + describe "tracking events", :snowplow do it "doesn't track if we shouldn't track" do allow(subject).to receive(:should_track?).and_return(false) @@ -115,91 +123,36 @@ RSpec.describe ApplicationExperiment, :experiment do end describe "variant resolution" do - context "when using the default feature flag percentage rollout" do - it "uses the default value as specified in the yaml" do - expect(Feature).to receive(:enabled?).with('namespaced_stub', subject, type: :experiment, default_enabled: :yaml) - - expect(subject.variant.name).to eq('control') - end + it "uses the default value as specified in the yaml" do + expect(Feature).to receive(:enabled?).with('namespaced_stub', subject, type: :experiment, default_enabled: :yaml) - it "returns nil when not rolled out" do - stub_feature_flags(namespaced_stub: false) - - expect(subject.variant.name).to eq('control') - end - - context "when rolled out to 100%" do - it "returns the first variant name" do - subject.try(:variant1) {} - subject.try(:variant2) {} - - expect(subject.variant.name).to eq('variant1') - end - end + expect(subject.variant.name).to eq('control') end - context "when using the round_robin strategy", :clean_gitlab_redis_shared_state do - context "when variants aren't supplied" do - subject :inheriting_class do - Class.new(described_class) do - def rollout_strategy - :round_robin - end - end.new('namespaced/stub') - end - - it "raises an error" do - expect { inheriting_class.variants }.to raise_error(NotImplementedError) - end + context "when rolled out to 100%" do + before do + stub_feature_flags(namespaced_stub: true) end - context "when variants are supplied" do - let(:inheriting_class) do - Class.new(described_class) do - def rollout_strategy - :round_robin - end - - def variants - %i[variant1 variant2 control] - end - end - end - - it "proves out round robin in variant selection", :aggregate_failures do - instance_1 = inheriting_class.new('namespaced/stub') - allow(instance_1).to receive(:enabled?).and_return(true) - instance_2 = inheriting_class.new('namespaced/stub') - allow(instance_2).to receive(:enabled?).and_return(true) - instance_3 = inheriting_class.new('namespaced/stub') - allow(instance_3).to receive(:enabled?).and_return(true) - - instance_1.try {} - - expect(instance_1.variant.name).to eq('variant2') + it "returns the first variant name" do + subject.try(:variant1) {} + subject.try(:variant2) {} - instance_2.try {} - - expect(instance_2.variant.name).to eq('control') - - instance_3.try {} - - expect(instance_3.variant.name).to eq('variant1') - end + expect(subject.variant.name).to eq('variant1') end end end context "when caching" do - let(:cache) { ApplicationExperiment::Cache.new } + let(:cache) { Gitlab::Experiment::Configuration.cache } before do + allow(Gitlab::Experiment::Configuration).to receive(:cache).and_call_original + cache.clear(key: subject.name) subject.use { } # setup the control subject.try { } # setup the candidate - - allow(Gitlab::Experiment::Configuration).to receive(:cache).and_return(cache) end it "caches the variant determined by the variant resolver" do @@ -207,7 +160,7 @@ RSpec.describe ApplicationExperiment, :experiment do subject.run - expect(cache.read(subject.cache_key)).to eq('candidate') + expect(subject.cache.read).to eq('candidate') end it "doesn't cache a variant if we don't explicitly provide one" do @@ -222,7 +175,7 @@ RSpec.describe ApplicationExperiment, :experiment do subject.run - expect(cache.read(subject.cache_key)).to be_nil + expect(subject.cache.read).to be_nil end it "caches a control variant if we assign it specifically" do @@ -232,7 +185,26 @@ RSpec.describe ApplicationExperiment, :experiment do # write code that would specify a different variant. subject.run(:control) - expect(cache.read(subject.cache_key)).to eq('control') + expect(subject.cache.read).to eq('control') + end + + context "arbitrary attributes" do + before do + subject.cache.store.clear(key: subject.name + '_attrs') + end + + it "sets and gets attributes about an experiment" do + subject.cache.attr_set(:foo, :bar) + + expect(subject.cache.attr_get(:foo)).to eq('bar') + end + + it "increments a value for an experiment" do + expect(subject.cache.attr_get(:foo)).to be_nil + + expect(subject.cache.attr_inc(:foo)).to eq(1) + expect(subject.cache.attr_inc(:foo)).to eq(2) + end end end end |