test/test_conductor.rb in conductor-0.0.0 vs test/test_conductor.rb in conductor-0.2.9

- old
+ new

@@ -1,7 +1,225 @@ require 'helper' class TestConductor < Test::Unit::TestCase - def test_something_for_real - flunk "hey buddy, you should probably rename this file and start testing for real" - end + #Wipes cache, D/B prior to doing a test run. + VectorSixteen.cache.clear + + test "will automatically assign an identity if none is specified" do + assert VectorSixteen.identity != nil + end + + test "will select one of the specified options randomly" do + selected = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) # => value must be unique + assert ["a", "b", "c"].include? selected + end + + test "will always select the same option using the cache" do + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + + selected = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) # => value must be unique + different = false + + (1..100).each do |x| + different = true if selected != VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) + end + + assert !different + end + + test "will select a lander and then successfully record a conversion" do + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + selected = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) # => value must be unique + + VectorSixteen::Experiment.track! + + experiments = V16::RawExperiment.find_all_by_identity_id(VectorSixteen.identity) + assert_equal 1, experiments.count + assert_equal 1, experiments.first.conversion_value + end + + test "will select a lander and then successfully record custom conversion value" do + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + selected = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) # => value must be unique + + VectorSixteen::Experiment.track!({:value => 12.34}) + + experiments = V16::RawExperiment.find_all_by_identity_id(VectorSixteen.identity) + assert_equal 1, experiments.count + assert_equal 12.34, experiments.first.conversion_value + end + + + + test "will record three different experiments with two goals but a single conversion for all goals for the same identity" do + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + first = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"], {:goal => 'goal_1'}) # => value must be unique + second = VectorSixteen::Experiment.pick('b_group', ["1", "2", "3"], {:goal => 'goal_2'}) # => value must be unique + third = VectorSixteen::Experiment.pick('c_group', ["zz", "xx", "yy"], {:goal => 'goal_1'}) # => value must be unique + + VectorSixteen::Experiment.track! + + experiments = V16::RawExperiment.find_all_by_identity_id(VectorSixteen.identity) + assert_equal 3, experiments.count + assert_equal 2, experiments.count {|x| x.goal == 'goal_1'} + assert_equal 3, experiments.sum_it(:conversion_value) + end + + test "will record three different experiments with two goals but only track a conversion for goal_1" do + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + first = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"], {:goal => 'goal_1'}) # => value must be unique + second = VectorSixteen::Experiment.pick('b_group', ["1", "2", "3"], {:goal => 'goal_2'}) # => value must be unique + third = VectorSixteen::Experiment.pick('c_group', ["zz", "xx", "yy"], {:goal => 'goal_1'}) # => value must be unique + + VectorSixteen::Experiment.track!({:goal => 'goal_1'}) + + experiments = V16::RawExperiment.find_all_by_identity_id(VectorSixteen.identity) + assert_equal 3, experiments.count + assert_equal 2, experiments.count {|x| x.goal == 'goal_1'} + assert_equal 2, experiments.sum_it(:conversion_value) + end + + + test "will almost equally select each option if no weights exist" do + a = 0 + b = 0 + c = 0 + (1..1000).each do |x| + selected_lander = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"]) # => value must be unique + case selected_lander + when 'a' then + a += 1 + when 'b' then + b += 1 + when 'c' then + c += 1 + end + end + + nums = [] << a << b << c + nums.sort! + range = nums.last - nums.first + + assert (nums.first * 0.20) >= range + end + + test "will correctly RollUp daily data" do + # seed + seed_raw_data(100) + + # rollup + VectorSixteen::RollUp.process + + # do some checks + assert V16::DailyExperiment.count > 2 + assert V16::DailyExperiment.all.detect {|x| x.conversions > 0} + assert V16::DailyExperiment.all.detect {|x| x.views > 0} + assert V16::DailyExperiment.all.detect {|x| x.conversion_value > 0} + end + + test "will correctly populate weighting table" do + # seed + seed_raw_data(100) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + end + + test "will populate the weighting table with equal weights if all new options are launched" do + wipe + seed_raw_data(100, 7) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + + # this makes the following assumptions: + # MINIMUM_LAUNCH_DAYS = 7 + # each weight will be equal to 0.18 + assert_equal 0.54, V16::WeightedExperiment.all.sum_it(:weight).to_f + end + + test "will populate the weighting table with different weights" do + wipe + seed_raw_data(100, 14) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + + # if this DOES NOT work then each weight will be equal to 0.18 + assert_not_equal 0.54, V16::WeightedExperiment.all.sum_it(:weight).to_f + end + + test "will record the new weights in the weight history table in database" do + wipe + seed_raw_data(100, 14) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + + assert V16::WeightHistory.count > 1 + end + + test "will correctly record the launch window in the weight histories table" do + wipe + seed_raw_data(10, 6) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + + # make sure that launch_window values can be detected + assert_not_nil V16::WeightHistory.find(:all, :conditions => 'launch_window > 0') + end + + test "will return a weight 1.25 times higher than the highest weight for a newly launched and non-recorded alernative" do + wipe + seed_raw_data(100, 14) + + # rollup + VectorSixteen::RollUp.process + + # compute weights + VectorSixteen::Weights.compute + + # get the highest weight + max_weight = V16::WeightedExperiment.maximum(:weight) + + # pick something + weights = VectorSixteen::Experiment.weights('a_group', ["a", "b", "c", "f"]) # => value must be unique + + assert_equal weights['f'], (max_weight * 1.25) + end + + private + + def wipe + V16::DailyExperiment.delete_all + V16::RawExperiment.delete_all + V16::WeightedExperiment.delete_all + V16::WeightHistory.delete_all + end + + def seed_raw_data(num, days_ago=14) + # seed the raw data + (1..num).each do |x| + VectorSixteen.identity = ActiveSupport::SecureRandom.hex(16) + + options = {:created_at => rand(days_ago).days.ago} + options.merge!({:conversion_value => rand(100)}) if rand() < 0.20 # => convert 20% of traffic + selected_lander = VectorSixteen::Experiment.pick('a_group', ["a", "b", "c"], options) # => value must be unique + end + end end