# File lib/camping-abingo.rb, line 295
  def self.test(test_name, alternatives, options = {})
        ABingoCampingPlugin.logger.debug "test #{test_name} alternatives: #{alternatives.inspect} options:#{options.inspect} for #{Abingo.identity}"
    short_circuit = Abingo.cache.read("Abingo::Experiment::short_circuit(#{test_name})".gsub(" ", "_"))
    unless short_circuit.nil?
      return short_circuit  #Test has been stopped, pick canonical alternative.
    end
    
    unless ABingoCampingPlugin::Models::Experiment.exists?(test_name) # Camping-specific
      lock_key = "Abingo::lock_for_creation(#{test_name.gsub(" ", "_")})"
      creation_required = true

      #this prevents (most) repeated creations of experiments in high concurrency environments.
      if Abingo.cache.exist?(lock_key)
        creation_required = false
        while Abingo.cache.exist?(lock_key)
          sleep(0.1)
        end
        creation_required = ABingoCampingPlugin::Models::Experiment.exists?(test_name)  # Camping-specific
      end

      if creation_required
        Abingo.cache.write(lock_key, 1, :expires_in => 5.seconds)
        conversion_name = options[:conversion] || options[:conversion_name]
        ABingoCampingPlugin::Models::Experiment.start_experiment!(test_name, self.parse_alternatives(alternatives), conversion_name) # Camping-specific
        Abingo.cache.delete(lock_key)
      end
    end

    choice = self.find_alternative_for_user(test_name, alternatives)
    participating_tests = Abingo.cache.read("Abingo::participating_tests::#{Abingo.identity}") || []
    
    #Set this user to participate in this experiment, and increment participants count.
    if options[:multiple_participation] || !(participating_tests.include?(test_name))
      unless participating_tests.include?(test_name)
        participating_tests = participating_tests + [test_name]
        expires_in = Abingo.expires_in
        if expires_in
          Abingo.cache.write("Abingo::participating_tests::#{Abingo.identity}", participating_tests, {:expires_in => expires_in})
        else
          Abingo.cache.write("Abingo::participating_tests::#{Abingo.identity}", participating_tests)
        end
      end
      #If we're only counting known humans, then postpone scoring participation until after we know the user is human.
      if (!@@options[:count_humans_only] || Abingo.is_human?)
        ABingoCampingPlugin::Models::Alternative.score_participation(test_name) # Camping-specific
      end
    end

    if block_given?
      yield(choice)
    else
      choice
    end
  end