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