$LOAD_PATH.delete_if { |path| path[/gems\/vanity-\d/] } $LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__)) RAILS_ROOT = File.expand_path("..") require "test/unit" require "mocha" require "action_controller" require "action_controller/test_case" require "action_view/test_case" require "active_record" require "initializer" Rails.configuration = Rails::Configuration.new require "phusion_passenger/events" require "lib/vanity" require "timecop" require "webmock/test_unit" if $VERBOSE $logger = Logger.new(STDOUT) $logger.level = Logger::DEBUG end class Test::Unit::TestCase include WebMock::API def setup FileUtils.mkpath "tmp/experiments/metrics" new_playground end # Call this on teardown. It wipes put the playground and any state held in it # (mostly experiments), resets vanity ID, and clears database of all experiments. def nuke_playground Vanity.playground.connection.flushdb new_playground end # Call this if you need a new playground, e.g. to re-define the same experiment, # or reload an experiment (saved by the previous playground). def new_playground adapter = ENV["ADAPTER"] || "redis" # We go destructive on the database at the end of each run, so make sure we # don't use databases you care about. For Redis, we pick database 15 # (default is 0). spec = { "redis"=>"redis://localhost/15", "mongodb"=>"mongodb://localhost/vanity-test", "mock"=>"mock:/" }[adapter] raise "No support yet for #{adapter}" unless spec Vanity.playground = Vanity::Playground.new(:logger=>$logger, :load_path=>"tmp/experiments") Vanity.playground.establish_connection spec end # Defines the specified metrics (one or more names). Returns metric, or array # of metric (if more than one argument). def metric(*names) metrics = names.map do |name| id = name.to_s.downcase.gsub(/\W+/, '_').to_sym Vanity.playground.metrics[id] ||= Vanity::Metric.new(Vanity.playground, name) end names.size == 1 ? metrics.first : metrics end # Defines an A/B experiment. def new_ab_test(name, &block) id = name.to_s.downcase.gsub(/\W/, "_").to_sym experiment = Vanity::Experiment::AbTest.new(Vanity.playground, id, name) experiment.instance_eval &block experiment.save Vanity.playground.experiments[id] = experiment end # Returns named experiment. def experiment(name) Vanity.playground.experiment(name) end def today @today ||= Date.today end def not_collecting! Vanity.playground.collecting = false Vanity.playground.stubs(:connection).returns(stub(:flushdb=>nil)) end def teardown Vanity.context = nil FileUtils.rm_rf "tmp" Vanity.playground.connection.flushdb if Vanity.playground.connected? WebMock.reset! end end ActionController::Routing::Routes.draw do |map| map.connect ':controller/:action/:id' end ActiveRecord::Base.logger = $logger ActiveRecord::Base.establish_connection :adapter=>"mysql", :database=>"vanity_test" class Array # Not in Ruby 1.8.6. unless method_defined?(:shuffle) def shuffle copy = clone Array.new(size) { copy.delete_at(Kernel.rand(copy.size)) } end end end # Source: http://gist.github.com/25455 def context(*args, &block) return super unless (name = args.first) && block parent = Class === self ? self : (defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) klass = Class.new(parent) do def self.test(name, &block) define_method("test_#{name.gsub(/\W/,'_')}", &block) if block end def self.xtest(*args) end def self.setup(&block) define_method(:setup) { super() ; instance_eval &block } end def self.teardown(&block) define_method(:teardown) { super() ; instance_eval &block } end end parent.const_set name.split(/\W+/).map(&:capitalize).join, klass klass.class_eval &block end