Class: Tryouts::Drill

Inherits:
Object
  • Object
show all
Defined in:
lib/tryouts/drill.rb,
lib/tryouts/drill/dream.rb,
lib/tryouts/drill/reality.rb,
lib/tryouts/drill/response.rb,
lib/tryouts/drill/sergeant/api.rb,
lib/tryouts/drill/sergeant/cli.rb,
lib/tryouts/drill/sergeant/benchmark.rb,
lib/tryouts/drill/sergeant/rbenchmark.rb

Overview

Drill

This class represents a drill. A drill is single test.

Defined Under Namespace

Modules: Sergeant Classes: Dream, NoSergeant, Reality, Response, UnknownFormat

Constant Summary collapse

@@valid_dtypes =
[:api, :cli, :benchmark]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, dtype, *args, &drill) ⇒ Drill

  • name The display name of this drill

  • dtype A Symbol representing the drill type. One of: :api, :benchmark

  • args These are dependent on the drill type. See the Sergeant classes

  • &drill The body of the drill. The return value of this block is compared to the exepected output of the dreams.

The DSL syntax:

  • dream OUTPUT

  • dream FORMAT, OUTPUT

  • dream FORMAT, OUTPUT, REPS (benchmark only)



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/tryouts/drill.rb', line 49

def initialize(name, dtype, *args, &drill)
  @name, @dtype, @drill, @skip = name, dtype, drill, false
  @dreams = []
  
  # We create a default empty reality but if the drill runs correctly
  # this reality gets replaced with the return value from the drill.
  @reality = Tryouts::Drill::Reality.new
  
  case @dtype 
  when :cli
    # For CLI drills, a block takes precedence over inline args. 
    # A block will contain multiple shell commands (see Rye::Box#batch)
    args = [] if dtype == :cli && drill.is_a?(Proc)
    @sergeant = Tryouts::Drill::Sergeant::CLI.new *args
  when :api
    default_output = drill.nil? ? args.shift : nil
    @sergeant = Tryouts::Drill::Sergeant::API.new default_output
    unless args.empty?
      if args.size == 1
        dream_output, format = args.first, nil
      else
        dream_output, format = args[1], args[0]
      end
      @dreams << Tryouts::Drill::Dream.new(dream_output, format)
    end
  when :benchmark
    if args.size == 1
      reps = args.first
    else
      dream_output, format, reps = args[1], args[0], args[2]
    end
    @sergeant = Tryouts::Drill::Sergeant::Benchmark.new reps
    @dreams << Tryouts::Drill::Dream.new(Tryouts::Stats, :class)
    unless dream_output.nil?
      @dreams << Tryouts::Drill::Dream.new(dream_output, format)
    end
  when :skip
    @skip = true
  else
    raise NoSergeant, "Weird drill sergeant: #{@dtype}"
  end
  @clr = :red

  
end

Instance Attribute Details

#dreamsObject (readonly)

An Array of Dream objects (the expected output of the test)



32
33
34
# File 'lib/tryouts/drill.rb', line 32

def dreams
  @dreams
end

#drillObject (readonly)

A Proc object which contains the drill logic.



28
29
30
# File 'lib/tryouts/drill.rb', line 28

def drill
  @drill
end

#dtypeObject (readonly)

A symbol specifying the drill type. One of: :cli, :api



24
25
26
# File 'lib/tryouts/drill.rb', line 24

def dtype
  @dtype
end

#nameObject (readonly)

The name of the drill. This should match the name used in the dreams file.



26
27
28
# File 'lib/tryouts/drill.rb', line 26

def name
  @name
end

#realityObject (readonly)

A Reality object (the actual output of the test)



34
35
36
# File 'lib/tryouts/drill.rb', line 34

def reality
  @reality
end

#sergeantObject (readonly)

A Sergeant object which executes the drill



30
31
32
# File 'lib/tryouts/drill.rb', line 30

def sergeant
  @sergeant
end

Class Method Details

.valid_dtype?(t) ⇒ Boolean

Returns:

  • (Boolean)


96
# File 'lib/tryouts/drill.rb', line 96

def self.valid_dtype?(t); @@valid_dtypes.member?(t); end

.valid_dtypesObject



95
# File 'lib/tryouts/drill.rb', line 95

def self.valid_dtypes; @@valid_dtypes; end

Instance Method Details

#add_dream(d) ⇒ Object



213
# File 'lib/tryouts/drill.rb', line 213

def add_dream(d); @dreams << d; end

#add_dreams(*d) ⇒ Object



214
# File 'lib/tryouts/drill.rb', line 214

def add_dreams(*d); @dreams += d; end

#flagObject



120
121
122
123
124
125
126
127
128
129
# File 'lib/tryouts/drill.rb', line 120

def flag
  if skip?
    "SKIP"
  elsif success? 
    "PASS".color(@clr).bright 
  else
    note = @dreams.empty? ? '[nodream]' : ''
    "FAIL #{note}".color(@clr).bright
  end
end

#has_error?Boolean

Returns:

  • (Boolean)


196
197
198
# File 'lib/tryouts/drill.rb', line 196

def has_error?
  !@reality.error.nil?
end

#infoObject



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/tryouts/drill.rb', line 131

def info
  out = StringIO.new
  if Tryouts.verbose > 0
    if @dtype == :benchmark
      unless @reality.output.nil?
        mean, sdev, sum = @reality.output.mean, @reality.output.sdev, @reality.output.sum
        out.puts '%6s%.4f (sdev:%.4f sum:%.4f)'.color(@clr) % ['', mean, sdev, sum]
      end
    elsif @dtype == :cli
      out.puts '%6s%s'.color(@clr) % ['', @reality.command]
      output = @reality.output
      output = output.join($/ + ' '*6) if output.kind_of?(Array)
      out.puts '%6s%s'.color(@clr) % ['', output]
    else
      out.puts '%6s%s'.color(@clr) % ['', @reality.output.inspect]
    end
    unless @reality.stash.empty?
      @reality.stash.each_pair do |n,v|
        out.puts '%18s: %s'.color(@clr) % [n,v.inspect]
      end
    end
  end
  if Tryouts.verbose > 1

    @dreams.each do |dream|
      if dream != @reality
        out.puts '%6s%s'.color(:red) % ['', dream.test_to_string(@reality)]
      else
        out.puts '%6s%s'.color(:green) % ["", dream.test_to_string(@reality)]
      end
    end  
    out.puts
  
  end
  out.rewind
  out.read
end

#reportObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/tryouts/drill.rb', line 169

def report
  return if skip?
  out = StringIO.new
  
  out.puts '%12s'.color(:red) % '[nodream]' if @dreams.empty?
  
  @dreams.each do |dream|
    next if dream == reality #? :normal : :red 
    out.puts '%12s: %s'.color(@clr) % ["failed", dream.test_to_string(@reality)]
    out.puts '%12s: %s' % ["drill", @reality.comparison_value(dream).inspect]
    out.puts '%12s: %s' % ["dream", 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

#run(context = nil) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/tryouts/drill.rb', line 100

def run(context=nil)
  unless @dreams.empty?
    @dreams.each { |d| d.execute_output_block }
  end
  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

#skip?Boolean

Returns:

  • (Boolean)


98
# File 'lib/tryouts/drill.rb', line 98

def skip?; @skip; end

#success?Boolean

Returns:

  • (Boolean)


200
201
202
203
204
205
206
207
208
209
210
# File 'lib/tryouts/drill.rb', line 200

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