lib/tryouts/drill.rb
class Tryouts # = Drill # # This class represents a drill. A drill is single test. # class Drill require 'tryouts/drill/context' require 'tryouts/drill/response' require 'tryouts/drill/sergeant/cli' require 'tryouts/drill/sergeant/api' require 'tryouts/drill/sergeant/benchmark' require 'tryouts/drill/sergeant/rbenchmark' class NoSergeant < Tryouts::Exception; end class UnknownFormat < Tryouts::Exception; end # A symbol specifying the drill type. One of: :cli, :api attr_reader :dtype # The name of the drill. This should match the name used in the dreams file. attr_reader :name # A Proc object which contains the drill logic. attr_reader :drill # A Sergeant object which executes the drill attr_reader :sergeant # An Array of Dream objects (the expected output of the test) attr_reader :dreams # A Reality object (the actual output of the test) attr_reader :reality @@valid_dtypes = [:cli, :api, :benchmark] def initialize(name, dtype, *args, &drill) @name, @dtype, @drill, @skip = name, dtype, drill, false @dreams = [] case @dtype when :cli @sergeant = Tryouts::Drill::Sergeant::CLI.new *args when :api default_output = drill.nil? ? args.shift : nil @sergeant = Tryouts::Drill::Sergeant::API.new default_output @dreams << Tryouts::Drill::Dream.new(*args) unless args.empty? when :benchmark default_output, format, reps = *args @sergeant = Tryouts::Drill::Sergeant::Benchmark.new reps || 1 @dreams << Tryouts::Drill::Dream.new(Tryouts::Stats, :class) unless default_output.nil? @dreams << Tryouts::Drill::Dream.new(default_output, format) end when :skip @skip = true else raise NoSergeant, "Weird drill sergeant: #{@dtype}" end @clr = :red # For CLI drills, a block takes precedence over inline args. # A block will contain multiple shell commands (see Rye::Box#batch) drill_args = [] if dtype == :cli && drill.is_a?(Proc) @reality = Tryouts::Drill::Reality.new end def self.valid_dtype?(t); @@valid_dtypes.member?(t); end def skip?; @skip; end def run(context=nil) begin @reality = @sergeant.run @drill, context # Store the stash from the drill block @reality.stash = context.stash if context.respond_to? :stash # If the drill block returned true we assume success if there's no dream if @dreams.empty? && @reality.output == true @dreams << Tryouts::Drill::Dream.new @dreams.first.output = true end rescue => ex @reality.ecode, @reality.etype = -2, ex.class @reality.error, @reality.trace = ex.message, ex.backtrace end self.success? end def flag if skip? "SKIP" elsif success? "PASS".color(@clr).bright else note = @dreams.empty? ? '[nodream]' : '' "FAIL #{note}".color(@clr).bright end end def info out = StringIO.new if Tryouts.verbose > 1 if @dreams.empty? out.puts '%6s%s'.color(@clr) % ['', @reality.output.inspect] else @dreams.each do |dream| if dream != @reality out.puts '%6s%s'.color(:red) % ['', @reality.output.inspect] else out.puts '%6s%s'.color(:green) % ["", dream.test_to_string(@reality)] end end end elsif Tryouts.verbose > 0 out.puts '%6s%s'.color(@clr) % ['', @reality.output.inspect] unless @reality.stash.empty? @reality.stash.each_pair do |n,v| out.puts '%18s: %s'.color(@clr) % [n,v.inspect] end out.puts end end out.rewind out.read end def report return if skip? out = StringIO.new @dreams.each do |dream| next if dream == reality #? :normal : :red out.puts '%12s: %s'.color(@clr) % ["drill", dream.test_to_string(@reality)] out.puts '%12s: %s' % ["returned", @reality.comparison_value(dream).inspect] out.puts '%12s: %s' % ["expected", dream.comparison_value.inspect] out.puts end unless @reality.error.nil? out.puts '%14s: %s' % [@reality.etype, @reality.error.to_s.split($/).join($/ + ' '*16)] end unless @reality.trace.nil? trace = Tryouts.verbose > 1 ? @reality.trace : [@reality.trace.first] out.puts '%14s %s' % ['', trace.join($/ + ' '*16)] out.puts end out.rewind out.read end def success? return false if @dreams.empty? && @reality.output != true begin @dreams.each { |d| return false unless d == @reality } rescue => ex puts ex.message, ex.backtrace if Tryouts.debug? return false end @clr = :green true end def add_dream(d); @dreams << d; end def add_dreams(*d); @dreams += d; end private end; end