delano-tryouts 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +15 -0
- data/README.rdoc +13 -56
- data/bin/sergeant +3 -3
- data/lib/tryouts.rb +15 -158
- data/lib/tryouts/cli/run.rb +12 -10
- data/lib/tryouts/drill.rb +17 -39
- data/lib/tryouts/drill/context.rb +32 -0
- data/lib/tryouts/drill/response.rb +24 -58
- data/lib/tryouts/drill/sergeant/api.rb +14 -14
- data/lib/tryouts/drill/sergeant/cli.rb +18 -9
- data/lib/tryouts/tryout.rb +43 -109
- data/tryouts.gemspec +75 -0
- metadata +4 -2
data/CHANGES.txt
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
TRYOUTS, CHANGES
|
2
2
|
|
3
|
+
|
4
|
+
#### 0.6.0 (2009-06-24) ###############################
|
5
|
+
|
6
|
+
NOTE: External dreams files are no longer supported.
|
7
|
+
NOTE: command testing (:cli) is disabled.
|
8
|
+
|
9
|
+
* CHANGE: Removed all mention of external dreams files.
|
10
|
+
* CHANGE: dream method is not available inside drill block.
|
11
|
+
* CHANGE: rcode, emsg, backtrace renamed to ecode, error, trace
|
12
|
+
* ADDED: dream is now available above drill blocks.
|
13
|
+
* ADDED: Better verbose and debugging output
|
14
|
+
* ADDED: Cleaner test output
|
15
|
+
* ADDED: drill success is now solely based on output.
|
16
|
+
|
17
|
+
|
3
18
|
#### 0.5.1 (2009-06-13) ###############################
|
4
19
|
|
5
20
|
* ADDED: dream method is now available inside drill block
|
data/README.rdoc
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
= Tryouts - v0.
|
1
|
+
= Tryouts - v0.6 BETA
|
2
2
|
|
3
3
|
Tryouts is a high-level testing library for your command-line applications and Ruby codes.
|
4
4
|
|
5
|
+
NOTE: The DSL syntax has changed significantly from 0.5 and command-line app tests are currently disabled.
|
5
6
|
|
6
7
|
== Terminology
|
7
8
|
|
@@ -11,41 +12,6 @@ Tryouts is a bit different than other testing libraries. Test definitions are or
|
|
11
12
|
* Drill: a test.
|
12
13
|
* Dream: the expected outcome of a drill.
|
13
14
|
|
14
|
-
|
15
|
-
== Testing a command-line application (a CLI)
|
16
|
-
|
17
|
-
Tryouts tests command-line applications by comparing expected output with the actual output. Let's say we have an executable called mockout and we want to test the following commands:
|
18
|
-
|
19
|
-
$ bin/executable
|
20
|
-
$ bin/executable -f yaml
|
21
|
-
|
22
|
-
The tryout definition would look like this:
|
23
|
-
|
24
|
-
command :executable, "path/2/executable"
|
25
|
-
|
26
|
-
tryout "Common Usage" do
|
27
|
-
drill "No Command"
|
28
|
-
drill "YAML Output", :f, 'yaml'
|
29
|
-
end
|
30
|
-
|
31
|
-
And the expected output would be defined like this:
|
32
|
-
|
33
|
-
dream "No Command" do
|
34
|
-
output inline(%Q{
|
35
|
-
Date: 2009-02-16
|
36
|
-
Players: d-bam, alberta, birds, condor man
|
37
|
-
Owners: greg, rupaul, telly, prince kinko
|
38
|
-
})
|
39
|
-
end
|
40
|
-
dream "YAML Output" do
|
41
|
-
format :yaml
|
42
|
-
output ({
|
43
|
-
"Date" => "2009-02-16",
|
44
|
-
"Players" => ["d-bam", "alberta", "birds", "condor man"],
|
45
|
-
"Owners" => ["greg", "rupaul", "telly", "prince kinko"]
|
46
|
-
})
|
47
|
-
end
|
48
|
-
|
49
15
|
== Testing Ruby codes (an API)
|
50
16
|
|
51
17
|
Tryouts employs the same approach for testing Ruby codes. The return value of the drill block is compared to the expectation defined by the dream. Here is an example of including dreams inside the tryout definition.
|
@@ -53,17 +19,22 @@ Tryouts employs the same approach for testing Ruby codes. The return value of th
|
|
53
19
|
library :caesars, LIBRARY_PATH
|
54
20
|
|
55
21
|
tryout "Common Usage" do
|
56
|
-
dream
|
57
|
-
drill "
|
22
|
+
dream 3
|
23
|
+
drill "Check the return value" do
|
58
24
|
12 / 4
|
59
25
|
end
|
60
26
|
|
61
|
-
dream
|
62
|
-
drill "
|
27
|
+
dream :class, :Proc
|
28
|
+
drill "Check the return value class" do
|
63
29
|
Proc.new do
|
64
30
|
:anything
|
65
31
|
end
|
66
32
|
end
|
33
|
+
|
34
|
+
dream :exception, NameError
|
35
|
+
drill "A test can pass based on the exception" do
|
36
|
+
raise NameError
|
37
|
+
end
|
67
38
|
end
|
68
39
|
|
69
40
|
|
@@ -75,23 +46,9 @@ This library is very new (est. 2009-05-19) and has not been vetted by the scruti
|
|
75
46
|
* Unexpected errors.
|
76
47
|
|
77
48
|
|
78
|
-
== 3 Ways to define tryouts
|
79
|
-
|
80
|
-
There are three ways to define an instance of this class:
|
81
|
-
* In +_tryouts.rb+ files using the DSL syntax. One file per Tryouts object.
|
82
|
-
* See: http://github.com/delano/tryouts/blob/master/tryouts/mockoutcli_tryouts.rb
|
83
|
-
* In standalone ruby files using a hybrid DSL/OO syntax. Supports multiple
|
84
|
-
Tryouts objects per file.
|
85
|
-
* See: http://github.com/delano/tryouts/blob/master/tryouts/standalone_test.rb
|
86
|
-
* With regular object-oriented syntax.
|
87
|
-
* See: http://tryouts.rubyforge.org/
|
88
|
-
|
89
49
|
== On Threads
|
90
50
|
|
91
|
-
Tryouts does some funky stuff to make it simple to write tests. This "funky
|
92
|
-
stuff" means that this library is *not thread-safe at definition-time*. However, once
|
93
|
-
all tryouts files are parsed (or in OO-syntax, once all objects are created), this
|
94
|
-
class should be *thread-safe at drill-time*.
|
51
|
+
Tryouts does some funky stuff to make it simple to write tests. This "funky stuff" means that this library is *not thread-safe at definition-time*. However, once all tryouts files are parsed (or in OO-syntax, once all objects are created), this class should be *thread-safe at drill-time*.
|
95
52
|
|
96
53
|
== More Info
|
97
54
|
|
@@ -101,7 +58,7 @@ class should be *thread-safe at drill-time*.
|
|
101
58
|
|
102
59
|
== Thanks
|
103
60
|
|
104
|
-
* Everyone at Utrecht.rb
|
61
|
+
* Everyone at Utrecht.rb and Amsterdam.rb
|
105
62
|
|
106
63
|
== Credits
|
107
64
|
|
data/bin/sergeant
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
TRYOUTS_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
4
4
|
|
5
|
-
local_libs = %w{tryouts net-scp amazon-ec2 aws-s3 caesars drydock rye storable sysinfo annoy}
|
6
|
-
local_libs.each { |dir| $:.unshift File.join(TRYOUTS_HOME, '..', dir, 'lib') }
|
5
|
+
#local_libs = %w{tryouts net-scp amazon-ec2 aws-s3 caesars drydock rye storable sysinfo annoy}
|
6
|
+
#local_libs.each { |dir| $:.unshift File.join(TRYOUTS_HOME, '..', dir, 'lib') }
|
7
7
|
|
8
8
|
require 'drydock'
|
9
9
|
require 'tryouts'
|
@@ -15,7 +15,7 @@ require 'tryouts/cli'
|
|
15
15
|
module TryoutsCLI
|
16
16
|
extend Drydock
|
17
17
|
|
18
|
-
debug :
|
18
|
+
debug :off
|
19
19
|
default :run, :with_args
|
20
20
|
|
21
21
|
global :q, :quiet, "Decrease output"
|
data/lib/tryouts.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rye'
|
|
4
4
|
require 'yaml'
|
5
5
|
begin; require 'json'; rescue LoadError; end # json may not be installed
|
6
6
|
|
7
|
-
GYMNASIUM_HOME = File.join(Dir.pwd, 'tryouts')
|
7
|
+
GYMNASIUM_HOME = File.join(Dir.pwd, 'tryouts') ## also check try (for rye)
|
8
8
|
GYMNASIUM_GLOB = File.join(GYMNASIUM_HOME, '**', '*_tryouts.rb')
|
9
9
|
|
10
10
|
|
@@ -29,7 +29,7 @@ class Tryouts
|
|
29
29
|
# Raised when there is a problem loading or parsing a Tryouts::Drill::Dream object
|
30
30
|
class BadDreams < Exception; end
|
31
31
|
|
32
|
-
VERSION = "0.
|
32
|
+
VERSION = "0.6.0"
|
33
33
|
|
34
34
|
require 'tryouts/mixins'
|
35
35
|
require 'tryouts/tryout'
|
@@ -49,6 +49,17 @@ class Tryouts
|
|
49
49
|
# An instance of SysInfo
|
50
50
|
@@sysinfo = SysInfo.new
|
51
51
|
|
52
|
+
@@debug = false
|
53
|
+
@@verbose = 0
|
54
|
+
|
55
|
+
def self.debug?; @@debug; end
|
56
|
+
def self.enable_debug; @@debug = true; end
|
57
|
+
def self.disable_debug; @@debug = false; end
|
58
|
+
|
59
|
+
def self.verbose; @@verbose; end
|
60
|
+
def self.verbose=(v); @@verbose = (v == true) ? 1 : v; end
|
61
|
+
|
62
|
+
|
52
63
|
# Returns +@@instances+
|
53
64
|
def self.instances; @@instances; end
|
54
65
|
# Returns +@@sysinfo+
|
@@ -60,26 +71,18 @@ class Tryouts
|
|
60
71
|
attr_accessor :dtype
|
61
72
|
# An Array of file paths which populated this instance of Tryouts
|
62
73
|
attr_accessor :paths
|
63
|
-
# A Hash of dreams for all tryouts in this class. The keys should
|
64
|
-
# match the names of each tryout. The values are hashes will drill
|
65
|
-
# names as keys and response
|
66
|
-
attr_accessor :dreams
|
67
74
|
# An Array of Tryout objects
|
68
75
|
attr_accessor :tryouts
|
69
76
|
# A Symbol representing the command taking part in the tryouts. For @dtype :cli only.
|
70
77
|
attr_accessor :command
|
71
78
|
# A Symbol representing the name of the library taking part in the tryouts. For @dtype :api only.
|
72
79
|
attr_accessor :library
|
73
|
-
# The name of the most recent dreams group (see self.dream)
|
74
|
-
attr_accessor :dream_pointer
|
75
80
|
|
76
81
|
def initialize(group=nil)
|
77
82
|
@group = group || "Default Group"
|
78
83
|
@tryouts = HASH_TYPE.new
|
79
84
|
@paths = []
|
80
85
|
@command = nil
|
81
|
-
@dreams = HASH_TYPE.new
|
82
|
-
@dream_pointer = nil
|
83
86
|
end
|
84
87
|
|
85
88
|
# Populate this Tryouts from a block. The block should contain calls to
|
@@ -101,6 +104,7 @@ class Tryouts
|
|
101
104
|
# Add a shell command to Rye::Cmd and save the command name
|
102
105
|
# in @@commands so it can be used as the default for drills
|
103
106
|
def command(name=nil, path=nil)
|
107
|
+
raise "command testing is temporarily disabled"
|
104
108
|
return @command if name.nil?
|
105
109
|
@command = name.to_sym
|
106
110
|
@dtype = :cli
|
@@ -139,9 +143,6 @@ class Tryouts
|
|
139
143
|
def group(name=nil)
|
140
144
|
return @group if name.nil?
|
141
145
|
@group = name unless name.nil?
|
142
|
-
# Preload dreams if possible
|
143
|
-
dfile = self.class.find_dreams_file(GYMNASIUM_HOME, @group)
|
144
|
-
self.load_dreams_file(dfile) if dfile
|
145
146
|
@group
|
146
147
|
end
|
147
148
|
# Raises a Tryouts::Exception. +group+ is not support in the standalone syntax
|
@@ -171,8 +172,7 @@ class Tryouts
|
|
171
172
|
to = Tryouts::Tryout.new(name, dtype, command)
|
172
173
|
@tryouts[name] = to
|
173
174
|
end
|
174
|
-
|
175
|
-
to.dreams = @dreams[name] if @dreams.has_key?(name)
|
175
|
+
|
176
176
|
# Process the rest of the DSL
|
177
177
|
to.from_block block if block
|
178
178
|
to
|
@@ -201,67 +201,6 @@ class Tryouts
|
|
201
201
|
# NOTE: this is a standalone DSL-syntax method.
|
202
202
|
def self.xtryout(*args, &block); end
|
203
203
|
|
204
|
-
# Load dreams from a file or directory or if a block is given
|
205
|
-
# it's processed
|
206
|
-
# Raises a Tryouts::BadDreams exception when something goes awry.
|
207
|
-
#
|
208
|
-
# This method is used in two ways:
|
209
|
-
# * In the dreams file DSL
|
210
|
-
# * As a getter method on a Tryouts object
|
211
|
-
def dreams(tryout_name=nil, &definition)
|
212
|
-
return @dreams unless tryout_name
|
213
|
-
|
214
|
-
#
|
215
|
-
# dreams "path/2/dreams"
|
216
|
-
# OR
|
217
|
-
# dreams "path/2/file_of_dreams.rb"
|
218
|
-
#
|
219
|
-
if File.exists?(tryout_name)
|
220
|
-
dfile = tryout_name
|
221
|
-
# If we're given a directory we'll build the filename using the class name
|
222
|
-
if File.directory?(tryout_name)
|
223
|
-
dfile = self.class.find_dreams_file(tryout_name, @group)
|
224
|
-
end
|
225
|
-
raise BadDreams, "Cannot find dreams file (#{tryout_name})" unless dfile
|
226
|
-
@dreams = load_dreams_file( dfile) || {}
|
227
|
-
|
228
|
-
#
|
229
|
-
# dreams "Tryout Name" do
|
230
|
-
# dream "drill name" ...
|
231
|
-
# end
|
232
|
-
#
|
233
|
-
elsif tryout_name.kind_of?(String) && definition
|
234
|
-
to = find_tryout(tryout_name, @dtype)
|
235
|
-
|
236
|
-
if to.nil?
|
237
|
-
@dream_pointer = tryout_name # Used in Tryouts.dream
|
238
|
-
@dreams[ @dream_pointer ] ||= {}
|
239
|
-
definition.call
|
240
|
-
else
|
241
|
-
to.from_block &definition
|
242
|
-
end
|
243
|
-
else
|
244
|
-
raise BadDreams, tryout_name
|
245
|
-
end
|
246
|
-
@dreams
|
247
|
-
end
|
248
|
-
# Without arguments, returns a Hash of all known dreams.
|
249
|
-
# With arguments, it calls Tryouts#dreams on the current instance of Tryouts.
|
250
|
-
#
|
251
|
-
# NOTE: this is a standalone DSL-syntax method.
|
252
|
-
def self.dreams(*args, &block)
|
253
|
-
if args.empty? && block.nil?
|
254
|
-
dreams = {}
|
255
|
-
@@instances.each_pair do |name,inst|
|
256
|
-
dreams[name] = inst.dreams
|
257
|
-
end
|
258
|
-
return dreams
|
259
|
-
else
|
260
|
-
# Call the Tryouts#dreams instance method
|
261
|
-
@@instances.last.dreams(*args, &block)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
204
|
# Returns +@tryouts+.
|
266
205
|
#
|
267
206
|
# Also acts as a stub for Tryouts#tryout in case someone
|
@@ -275,66 +214,6 @@ class Tryouts
|
|
275
214
|
tryout(args, &block)
|
276
215
|
end
|
277
216
|
|
278
|
-
# +name+ of the Drill associated to this Dream
|
279
|
-
# +output+ A String or Array of expected output. A Dream object will be created using this value (optional)
|
280
|
-
# +definition+ is a block which will be run on an instance of Dream
|
281
|
-
#
|
282
|
-
# This method is different than Tryout#dream because this one stores
|
283
|
-
# dreams inside an instance variable of the current Tryouts object.
|
284
|
-
# This allows for the situation where the dreams block appears before
|
285
|
-
# the tryout block. See Tryouts#tryout
|
286
|
-
#
|
287
|
-
# NOTE: This method is DSL-only. It's not intended to be used in OO syntax.
|
288
|
-
def dream(name, output=nil, format=nil, rcode=0, emsg=nil, &definition)
|
289
|
-
to = find_tryout(@dream_pointer, @dtype)
|
290
|
-
if to.nil?
|
291
|
-
if output.nil?
|
292
|
-
dobj = Tryouts::Drill::Dream.from_block definition
|
293
|
-
else
|
294
|
-
dobj = Tryouts::Drill::Dream.new(output)
|
295
|
-
dobj.format, dobj.rcode, dobj.emsg = format, rcode, emsg
|
296
|
-
end
|
297
|
-
@dreams[@dream_pointer][name] = dobj
|
298
|
-
else
|
299
|
-
# Let the Tryout object process the dream DSL.
|
300
|
-
# We'll get here if the dream is placed after
|
301
|
-
# the drill with the same name in the same block.
|
302
|
-
to.dream name, output, format, rcode, emsg, &definition
|
303
|
-
end
|
304
|
-
end
|
305
|
-
# Calls Tryouts#dream on the current instance of Tryouts
|
306
|
-
#
|
307
|
-
# NOTE: this is a standalone DSL-syntax method.
|
308
|
-
def self.dream(*args, &block)
|
309
|
-
@@instances.last.dream(*args, &block)
|
310
|
-
end
|
311
|
-
|
312
|
-
# This method does nothing. It provides a quick way to disable a dream.
|
313
|
-
#
|
314
|
-
# NOTE: This is a DSL-only method and is not intended for OO use.
|
315
|
-
def xdream(*args, &block); end
|
316
|
-
# This method does nothing. It provides a quick way to disable a dream.
|
317
|
-
#
|
318
|
-
# NOTE: this is a standalone DSL-syntax method.
|
319
|
-
def self.xdream(*args, &block); end
|
320
|
-
|
321
|
-
# Populate @@dreams with the content of the file +dpath+.
|
322
|
-
#
|
323
|
-
# NOTE: this is an OO syntax method
|
324
|
-
def load_dreams_file(dpath)
|
325
|
-
type = File.extname dpath
|
326
|
-
if type == ".yaml" || type == ".yml"
|
327
|
-
@dreams = YAML.load_file dpath
|
328
|
-
elsif type == ".json" || type == ".js"
|
329
|
-
@dreams = JSON.load_file dpath
|
330
|
-
elsif type == ".rb"
|
331
|
-
@dreams = instance_eval File.read(dpath)
|
332
|
-
else
|
333
|
-
raise BadDreams, "Unknown kind of dream: #{dpath}"
|
334
|
-
end
|
335
|
-
@dreams
|
336
|
-
end
|
337
|
-
|
338
217
|
# Parse a +_tryouts.rb+ file. See Tryouts::CLI::Run for an example.
|
339
218
|
#
|
340
219
|
# NOTE: this is an OO syntax method
|
@@ -387,27 +266,5 @@ class Tryouts
|
|
387
266
|
## end
|
388
267
|
##+++
|
389
268
|
|
390
|
-
# Find a dreams file in the directory +dir+ based on the current group name.
|
391
|
-
# The expected filename format is: groupname_dreams.ext where "groupname" is
|
392
|
-
# the lowercase name of the Tryouts group (spaces removed) and "ext" is one
|
393
|
-
# of: yaml, js, json, rb.
|
394
|
-
#
|
395
|
-
# e.g.
|
396
|
-
# Tryouts.find_dreams_file "dirpath" # => dirpath/tryouts_dreams.rb
|
397
|
-
#
|
398
|
-
def self.find_dreams_file(dir, group=nil)
|
399
|
-
dpath = nil
|
400
|
-
group ||= @@instances.last.group
|
401
|
-
group = group.to_s.downcase.tr(' ', '')
|
402
|
-
[:rb, :yaml].each do |ext|
|
403
|
-
tmp = File.join(dir, "#{group}_dreams.#{ext}")
|
404
|
-
if File.exists?(tmp)
|
405
|
-
dpath = tmp
|
406
|
-
break
|
407
|
-
end
|
408
|
-
end
|
409
|
-
dpath
|
410
|
-
end
|
411
|
-
|
412
269
|
|
413
270
|
end
|
data/lib/tryouts/cli/run.rb
CHANGED
@@ -14,7 +14,7 @@ class Run < Drydock::Command
|
|
14
14
|
# Display the dreams from all known tryouts
|
15
15
|
def dreams
|
16
16
|
load_available_tryouts_files
|
17
|
-
if
|
17
|
+
if Tryouts.verbose > 0
|
18
18
|
puts Tryouts.dreams.to_yaml
|
19
19
|
else
|
20
20
|
Tryouts.dreams.each_pair do |n,dreams|
|
@@ -32,16 +32,18 @@ class Run < Drydock::Command
|
|
32
32
|
# $ sergeant run [path/2/tryouts]
|
33
33
|
# Executes all tryouts that can be found from the current working directory.
|
34
34
|
def run
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
|
36
|
+
Tryouts.enable_debug if Drydock.debug?
|
37
|
+
Tryouts.verbose = @global.verbose
|
38
|
+
|
39
|
+
puts "#{Tryouts.sysinfo.to_s} (#{RUBY_VERSION})" if Tryouts.verbose > 0
|
38
40
|
|
39
41
|
load_available_tryouts_files
|
40
42
|
|
41
43
|
passed, failed = 0, 0
|
42
44
|
Tryouts.instances.each_pair do |group,tryouts_inst|
|
43
45
|
puts '', ' %-60s'.att(:reverse) % group
|
44
|
-
puts " #{tryouts_inst.paths.join("\n ")}" if
|
46
|
+
puts " #{tryouts_inst.paths.join("\n ")}" if Tryouts.verbose > 0
|
45
47
|
tryouts_inst.tryouts.each_pair do |name,to|
|
46
48
|
to.run
|
47
49
|
to.report
|
@@ -52,14 +54,14 @@ class Run < Drydock::Command
|
|
52
54
|
end
|
53
55
|
unless @global.quiet
|
54
56
|
if (passed == 0 && failed == 0)
|
55
|
-
puts DEV if
|
57
|
+
puts DEV if Tryouts.verbose > 4
|
56
58
|
msg = " You didn't even try to acheive your dreams :[ "
|
57
59
|
elsif failed == 0
|
58
|
-
puts PUG if
|
60
|
+
puts PUG if Tryouts.verbose > 4
|
59
61
|
msg = " All %s dreams came true ".color(:green)
|
60
62
|
msg = msg % [passed+failed]
|
61
63
|
else
|
62
|
-
puts BUG if
|
64
|
+
puts BUG if Tryouts.verbose > 4
|
63
65
|
score = (passed.to_f / (passed.to_f+failed.to_f)) * 100
|
64
66
|
msg = " %s of %s dreams came true (%d%%) ".color(:red)
|
65
67
|
msg = msg % [passed, passed+failed, score.to_i]
|
@@ -74,7 +76,7 @@ class Run < Drydock::Command
|
|
74
76
|
load_available_tryouts_files
|
75
77
|
Tryouts.instances.each_pair do |n,tryouts_inst|
|
76
78
|
puts n
|
77
|
-
if
|
79
|
+
if Tryouts.verbose > 0
|
78
80
|
puts " #{tryouts_inst.paths.join("\n ")}"
|
79
81
|
end
|
80
82
|
tryouts_inst.tryouts.each_pair do |t2,tryout|
|
@@ -104,7 +106,7 @@ private
|
|
104
106
|
end
|
105
107
|
end
|
106
108
|
@tryouts_files.uniq! # Don't load the same file twice
|
107
|
-
@tryouts_files.each { |f| puts "LOADING: #{f}"} if
|
109
|
+
@tryouts_files.each { |f| puts "LOADING: #{f}"} if Tryouts.verbose > 1
|
108
110
|
@tryouts_files.each { |file| Tryouts.parse_file file }
|
109
111
|
end
|
110
112
|
end
|
data/lib/tryouts/drill.rb
CHANGED
@@ -7,7 +7,8 @@ class Tryouts
|
|
7
7
|
# This class represents a drill. A drill is single test.
|
8
8
|
#
|
9
9
|
class Drill
|
10
|
-
|
10
|
+
|
11
|
+
require 'tryouts/drill/context'
|
11
12
|
require 'tryouts/drill/response'
|
12
13
|
require 'tryouts/drill/sergeant/cli'
|
13
14
|
require 'tryouts/drill/sergeant/api'
|
@@ -28,22 +29,22 @@ class Tryouts
|
|
28
29
|
# A Reality object (the actual output of the test)
|
29
30
|
attr_reader :reality
|
30
31
|
|
31
|
-
def initialize(name, dtype, *
|
32
|
+
def initialize(name, dtype, *opts, &drill)
|
32
33
|
@name, @dtype, @drill = name, dtype, drill
|
33
|
-
@sergeant = hire_sergeant
|
34
|
+
@sergeant = hire_sergeant opts
|
34
35
|
# For CLI drills, a block takes precedence over inline args.
|
35
36
|
# A block will contain multiple shell commands (see Rye::Box#batch)
|
36
37
|
drill_args = [] if dtype == :cli && drill.is_a?(Proc)
|
37
38
|
@reality = Tryouts::Drill::Reality.new
|
38
39
|
end
|
39
40
|
|
40
|
-
def hire_sergeant(
|
41
|
+
def hire_sergeant(opts={})
|
41
42
|
if @dtype == :cli
|
42
|
-
Tryouts::Drill::Sergeant::CLI.new(*
|
43
|
+
Tryouts::Drill::Sergeant::CLI.new(*opts)
|
43
44
|
elsif @dtype == :api
|
44
|
-
Tryouts::Drill::Sergeant::API.new(
|
45
|
+
Tryouts::Drill::Sergeant::API.new(opts.first) # should be a hash
|
45
46
|
else
|
46
|
-
raise NoSergeant, "
|
47
|
+
raise NoSergeant, "Weird drill sergeant: #{@dtype}"
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -53,15 +54,6 @@ class Tryouts
|
|
53
54
|
@reality = @sergeant.run @drill, context
|
54
55
|
# Store the stash from the drill block
|
55
56
|
@reality.stash = context.stash if context.respond_to? :stash
|
56
|
-
# Create or overwrite an existing dream if onw was defined in the block
|
57
|
-
if context.respond_to?(:dream) && context.has_dream?
|
58
|
-
@dream = Tryouts::Drill::Dream.new
|
59
|
-
@dream.output = context.dream
|
60
|
-
@dream.format = context.format unless context.format.nil?
|
61
|
-
@dream.rcode = context.rcode unless context.rcode.nil?
|
62
|
-
@dream.emsg = context.emsg unless context.emsg.nil?
|
63
|
-
end
|
64
|
-
|
65
57
|
# If the drill block returned true we assume success if there's no dream
|
66
58
|
if @dream.nil? && @reality.output == true
|
67
59
|
@dream = Tryouts::Drill::Dream.new
|
@@ -69,45 +61,31 @@ class Tryouts
|
|
69
61
|
end
|
70
62
|
process_reality
|
71
63
|
rescue => ex
|
72
|
-
@reality.
|
73
|
-
@reality.
|
64
|
+
@reality.ecode, @reality.etype = -2, ex.class
|
65
|
+
@reality.error, @reality.trace = ex.message, ex.backtrace
|
74
66
|
end
|
75
|
-
note = @dream ? discrepency.join(', ') : 'nodream'
|
76
|
-
puts self.success? ? "PASS".color(:green) : "FAIL (#{note})".color(:red)
|
77
67
|
self.success?
|
78
68
|
end
|
79
69
|
|
80
70
|
def success?
|
81
|
-
return false if @dream.nil? || @reality.nil?
|
82
71
|
@dream == @reality
|
83
72
|
end
|
84
73
|
|
85
|
-
def discrepency
|
86
|
-
diffs = []
|
87
|
-
if @dream
|
88
|
-
diffs << "rcode" if @dream.rcode != @reality.rcode
|
89
|
-
diffs << "output" if !@dream.compare_output(@reality)
|
90
|
-
diffs << "emsg" if @dream.emsg != @reality.emsg
|
91
|
-
end
|
92
|
-
diffs
|
93
|
-
end
|
94
74
|
|
95
75
|
def add_dream(d)
|
96
|
-
@dream = d
|
76
|
+
@dream = d
|
97
77
|
end
|
98
78
|
|
99
79
|
private
|
80
|
+
|
100
81
|
# Use the :format provided in the dream to convert the output from reality
|
101
82
|
def process_reality
|
102
|
-
@
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
@reality.output = JSON.load(@reality.output.join("\n"))
|
83
|
+
case @dream.format
|
84
|
+
when :class
|
85
|
+
@reality.output = @reality.output.class
|
86
|
+
when :exception
|
87
|
+
@reality.output = @reality.etype
|
108
88
|
end
|
109
|
-
|
110
|
-
#p [:process, @name, @dream.format, @reality.output]
|
111
89
|
end
|
112
90
|
|
113
91
|
end; end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
class Tryouts
|
3
|
+
class Tryout
|
4
|
+
|
5
|
+
# All :api Drills are run within this context (not used for :cli).
|
6
|
+
# Each Drill is executed in a new instance of this class. That means
|
7
|
+
# instance variables are not carried through, but class variables are.
|
8
|
+
# The before and after blocks are also run in this context.
|
9
|
+
class DrillContext
|
10
|
+
# An ordered Hash of stashed objects.
|
11
|
+
attr_writer :stash
|
12
|
+
|
13
|
+
def initialize; @stash = Tryouts::HASH_TYPE.new; @has_dream = false; end
|
14
|
+
|
15
|
+
# Set to to true by DrillContext#dream
|
16
|
+
def has_dream?; @has_dream; end
|
17
|
+
|
18
|
+
# If called with no arguments, returns +@stash+.
|
19
|
+
# If called with arguments, it will add a new value to the +@stash+
|
20
|
+
# and return the new value. e.g.
|
21
|
+
#
|
22
|
+
# stash :name, 'some value' # => 'some value'
|
23
|
+
#
|
24
|
+
def stash(*args)
|
25
|
+
return @stash if args.empty?
|
26
|
+
@stash[args[0]] = args[1]
|
27
|
+
args[1]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -5,66 +5,23 @@ class Tryouts::Drill
|
|
5
5
|
# A generic base class for Dream and Reality
|
6
6
|
#
|
7
7
|
class Response
|
8
|
-
attr_accessor :output, :format
|
9
|
-
def initialize(output=nil, format=nil
|
10
|
-
@output, @format
|
11
|
-
@output = nil if @output.nil?
|
12
|
-
normalize!
|
8
|
+
attr_accessor :output, :format
|
9
|
+
def initialize(output=nil, format=nil)
|
10
|
+
@output, @format = output, format
|
13
11
|
end
|
14
12
|
|
15
|
-
def
|
16
|
-
|
17
|
-
@rcode == other.rcode &&
|
18
|
-
@emsg == other.emsg &&
|
19
|
-
compare_output(other)
|
20
|
-
end
|
21
|
-
|
22
|
-
def rcode(val=nil); @rcode = val unless val.nil?; normalize!; @rcode; end
|
23
|
-
def output(val=nil); @output = val unless val.nil?; normalize!; @output; end
|
24
|
-
def emsg(val=nil); @emsg = val unless val.nil?; normalize!; @emsg; end
|
25
|
-
def format(val=nil); @format = val unless val.nil?; normalize!; @format; end
|
26
|
-
|
27
|
-
def output=(val); @output = val; normalize!; @output; end
|
28
|
-
def rcode=(val); @rcode = val; normalize!; @rcode; end
|
29
|
-
def format=(val); @format = val; normalize!; @format; end
|
30
|
-
def emsg=(val); @emsg = val; normalize!; @emsg; end
|
13
|
+
def format(val=nil); @format = val.to_sym unless val.nil?; @format; end
|
14
|
+
def format=(val); @format = val.to_sym; @format; end
|
31
15
|
|
32
|
-
|
33
|
-
|
34
|
-
# * +format+ is a Symbol
|
35
|
-
# This method is called automatically any time a field is updated.
|
36
|
-
def normalize!
|
37
|
-
@rcode = @rcode.to_i if @rcode.is_a?(String)
|
38
|
-
@format = @format.to_sym if @format.is_a?(String)
|
39
|
-
end
|
40
|
-
def compare_output(other)
|
41
|
-
#
|
42
|
-
# The dream is always on the left (Does your dream match reality?)
|
43
|
-
# This check is important so we can support both:
|
44
|
-
# @dream == @reality
|
45
|
-
# AND
|
46
|
-
# @reality == @dream
|
47
|
-
#
|
48
|
-
if self.is_a? Tryouts::Drill::Dream
|
49
|
-
dream, reality = self, other
|
50
|
-
elsif self.is_a? Tryouts::Drill::Reality
|
51
|
-
dream, reality = other, self
|
52
|
-
else
|
53
|
-
# If self isn't a Dream or a Reality, then we have a problem
|
54
|
-
return false
|
55
|
-
end
|
16
|
+
def Response.compare(dream, reality)
|
17
|
+
return false if reality.nil?
|
56
18
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
reality.output.send(dream.format) == dream.output
|
62
|
-
else
|
63
|
-
false
|
64
|
-
end
|
19
|
+
## I don't think this check is necessary or useful
|
20
|
+
##return false unless reality.error.nil? && reality.trace.nil?
|
21
|
+
return true if reality.output == true and dream.nil?
|
22
|
+
reality.output == dream.output
|
65
23
|
|
66
24
|
end
|
67
|
-
|
68
25
|
end
|
69
26
|
|
70
27
|
|
@@ -82,18 +39,20 @@ class Tryouts::Drill
|
|
82
39
|
|
83
40
|
def from_block(definition)
|
84
41
|
instance_eval &definition
|
85
|
-
self.normalize!
|
86
42
|
self
|
87
43
|
end
|
88
44
|
|
89
|
-
# Takes a String +val+ and splits the lines into an Array.
|
90
|
-
# has
|
45
|
+
# Takes a String +val+ and splits the lines into an Array.
|
91
46
|
def inline(val=nil)
|
92
47
|
lines = (val.split($/) || [])
|
93
48
|
lines.shift if lines.first.strip == ""
|
94
49
|
lines.pop if lines.last.strip == ""
|
95
50
|
lines
|
96
51
|
end
|
52
|
+
|
53
|
+
def ==(reality)
|
54
|
+
Response.compare(self, reality)
|
55
|
+
end
|
97
56
|
end
|
98
57
|
|
99
58
|
# = Reality
|
@@ -103,10 +62,17 @@ class Tryouts::Drill
|
|
103
62
|
class Reality < Tryouts::Drill::Response
|
104
63
|
# An ordered hash taken from the DrillContext that created this Reality.
|
105
64
|
attr_accessor :stash
|
65
|
+
attr_accessor :error
|
66
|
+
attr_accessor :trace
|
67
|
+
attr_accessor :ecode
|
68
|
+
attr_accessor :etype
|
106
69
|
def initialize
|
107
|
-
@rcode = 0
|
108
70
|
@stash = Tryouts::HASH_TYPE.new
|
109
71
|
end
|
72
|
+
|
73
|
+
def ==(dream)
|
74
|
+
Response.compare(dream, self)
|
75
|
+
end
|
110
76
|
end
|
111
77
|
|
112
78
|
end
|
@@ -9,30 +9,30 @@ class Tryouts; class Drill; module Sergeant
|
|
9
9
|
#
|
10
10
|
class API
|
11
11
|
|
12
|
-
|
12
|
+
attr_reader :opts
|
13
|
+
|
14
|
+
# +opts+ is a Hash with the following optional keys:
|
15
|
+
#
|
16
|
+
# * +:output+ specify a return value. This will be
|
13
17
|
# used if no block is specified for the drill.
|
14
|
-
def initialize(
|
15
|
-
@
|
18
|
+
def initialize(opts={})
|
19
|
+
@opts = opts
|
16
20
|
end
|
17
21
|
|
18
22
|
def run(block, context, &inline)
|
19
|
-
|
20
23
|
# A Proc object takes precedence over an inline block.
|
21
24
|
runtime = (block.nil? ? inline : block)
|
22
25
|
response = Tryouts::Drill::Reality.new
|
23
26
|
if runtime.nil?
|
24
|
-
response.output = @
|
27
|
+
response.output = @opts[:output]
|
25
28
|
else
|
26
29
|
begin
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
response.
|
33
|
-
response.output = ret
|
34
|
-
response.emsg = ex.message
|
35
|
-
response.backtrace = ex.backtrace
|
30
|
+
response.output = context.instance_eval &runtime
|
31
|
+
rescue => e
|
32
|
+
puts e.message, e.backtrace if Tryouts.debug? && Tryouts.verbose > 2
|
33
|
+
response.etype = e.class
|
34
|
+
response.error = e.message
|
35
|
+
response.trace = e.backtrace
|
36
36
|
end
|
37
37
|
end
|
38
38
|
response
|
@@ -25,21 +25,30 @@ class Tryouts; class Drill; module Sergeant
|
|
25
25
|
response = Tryouts::Drill::Reality.new
|
26
26
|
begin
|
27
27
|
if runtime.nil?
|
28
|
-
ret = @rbox.send
|
28
|
+
ret = @rbox.send *@rbox_args
|
29
29
|
else
|
30
30
|
ret = @rbox.instance_eval &runtime
|
31
31
|
end
|
32
|
-
response.
|
33
|
-
|
34
|
-
|
32
|
+
response.ecode = ret.exit_code
|
33
|
+
if ret.stdout.size == 1
|
34
|
+
response.output = ret.stdout.first
|
35
|
+
else
|
36
|
+
response.output = Array.new(ret.stdout) # Cast the Rye::Rap object
|
37
|
+
end
|
38
|
+
response.error = ret.stderr unless ret.stderr.empty?
|
35
39
|
rescue Rye::CommandNotFound => ex
|
36
|
-
|
37
|
-
response.
|
38
|
-
response.
|
40
|
+
puts ex.message, ex.backtrace if Tryouts.debug? && Tryouts.verbose > 2
|
41
|
+
response.etype = ex.class
|
42
|
+
response.ecode = ex.exit_code
|
43
|
+
response.error = "[#{@rbox.host}] Command not found: #{ex.message}"
|
44
|
+
response.trace = ex.backtrace
|
39
45
|
rescue Rye::CommandError => ex
|
40
|
-
|
46
|
+
puts ex.message, ex.backtrace if Tryouts.debug? && Tryouts.verbose > 2
|
47
|
+
response.etype = ex.class
|
48
|
+
response.ecode = ex.exit_code
|
41
49
|
response.output = ex.stdout
|
42
|
-
response.
|
50
|
+
response.error = ex.stderr.join $/
|
51
|
+
response.trace = ex.backtrace
|
43
52
|
end
|
44
53
|
response
|
45
54
|
end
|
data/lib/tryouts/tryout.rb
CHANGED
@@ -26,74 +26,15 @@ class Tryouts
|
|
26
26
|
# For drill type :api, this attribute is ignored.
|
27
27
|
attr_reader :command
|
28
28
|
# A Hash of Dream objects for this Tryout. The keys are drill names.
|
29
|
-
|
29
|
+
attr_reader :dream_catcher
|
30
30
|
|
31
31
|
@@valid_dtypes = [:cli, :api]
|
32
|
-
|
33
|
-
# All :api Drills are run within this context (not used for :cli).
|
34
|
-
# Each Drill is executed in a new instance of this class. That means
|
35
|
-
# instance variables are not carried through, but class variables are.
|
36
|
-
# The before and after blocks are also run in this context.
|
37
|
-
class DrillContext
|
38
|
-
# An ordered Hash of stashed objects.
|
39
|
-
attr_writer :stash
|
40
|
-
# A value used as the dream output that will overwrite a predefined dream
|
41
|
-
attr_writer :dream
|
42
|
-
attr_writer :format
|
43
|
-
attr_writer :rcode
|
44
|
-
attr_writer :emsg
|
45
|
-
attr_writer :output
|
46
|
-
|
47
|
-
def initialize; @stash = Tryouts::HASH_TYPE.new; @has_dream = false; end
|
48
|
-
|
49
|
-
# Set to to true by DrillContext#dream
|
50
|
-
def has_dream?; @has_dream; end
|
51
|
-
|
52
|
-
# If called with no arguments, returns +@stash+.
|
53
|
-
# If called with arguments, it will add a new value to the +@stash+
|
54
|
-
# and return the new value. e.g.
|
55
|
-
#
|
56
|
-
# stash :name, 'some value' # => 'some value'
|
57
|
-
#
|
58
|
-
def stash(*args)
|
59
|
-
return @stash if args.empty?
|
60
|
-
@stash[args[0]] = args[1]
|
61
|
-
args[1]
|
62
|
-
end
|
63
|
-
|
64
|
-
# If called with no arguments, returns +@dream+.
|
65
|
-
# If called with one argument, it will overwrite +@dream+ with the
|
66
|
-
# first element. If called with two arguments, it will check if
|
67
|
-
# the second argument is a Symbol or Fixnum. If it's a Symbol it
|
68
|
-
# will assume it's +@format+. If it's a Fixnum, it will assume
|
69
|
-
# it's +@rcode+. If there's a there's a third argument and it's a
|
70
|
-
# Fixnum, it's assumed to be +@rcode+. In all cases, this method
|
71
|
-
# returns the value of +@dream+. e.g.
|
72
|
-
#
|
73
|
-
# dream 'some value' # => 'some value'
|
74
|
-
# dream :val1, :class, 1 # => :val1
|
75
|
-
#
|
76
|
-
def dream(*args)
|
77
|
-
return @dream if args.empty?
|
78
|
-
@has_dream = true
|
79
|
-
@dream = args.shift
|
80
|
-
@format = args.shift if args.first.is_a? Symbol
|
81
|
-
@rcode = args.shift if args.first.is_a? Fixnum
|
82
|
-
@emsg = args.shift if args.first.is_a? String
|
83
|
-
end
|
84
|
-
|
85
|
-
def output(*args); return @output if args.empty?; @output = args.first; end
|
86
|
-
def format(*args); return @format if args.empty?; @format = args.first; end
|
87
|
-
def rcode(*args); return @rcode if args.empty?; @rcode = args.first; end
|
88
|
-
def emsg(*args); return @emsg if args.empty?; @emsg = args.first; end
|
89
|
-
|
90
|
-
end
|
91
32
|
|
92
33
|
def initialize(name, dtype, command=nil, *args)
|
93
34
|
raise "Must supply command for dtype :cli" if dtype == :cli && command.nil?
|
94
35
|
raise "#{dtype} is not a valid drill type" if !@@valid_dtypes.member?(dtype)
|
95
36
|
@name, @dtype, @command = name, dtype, command
|
96
|
-
@drills, @
|
37
|
+
@drills, @dream_catcher = [], []
|
97
38
|
@passed, @failed = 0, 0
|
98
39
|
end
|
99
40
|
|
@@ -108,13 +49,17 @@ class Tryouts
|
|
108
49
|
|
109
50
|
# Execute all Drill objects
|
110
51
|
def run
|
111
|
-
update_drills! # Ensure all drills have all known dreams
|
112
52
|
DrillContext.module_eval &setup if setup.is_a?(Proc)
|
113
53
|
puts Tryouts::TRYOUT_MSG.bright % @name
|
114
54
|
@drills.each do |drill|
|
115
|
-
drill.run
|
116
|
-
|
117
|
-
|
55
|
+
drill.run DrillContext.new
|
56
|
+
note = @dream ? '' : '(nodream)'
|
57
|
+
puts drill.success? ? "PASS".color(:green) : "FAIL #{note}".color(:red)
|
58
|
+
puts " #{drill.reality.output.inspect}" if Tryouts.verbose > 0
|
59
|
+
if Tryouts.verbose > 1
|
60
|
+
drill.reality.stash.each_pair do |n,v|
|
61
|
+
puts '%14s: %s' % [n,v.inspect]
|
62
|
+
end
|
118
63
|
end
|
119
64
|
drill.success? ? @passed += 1 : @failed += 1
|
120
65
|
end
|
@@ -126,25 +71,23 @@ class Tryouts
|
|
126
71
|
return true if success?
|
127
72
|
failed = @drills.select { |d| !d.success? }
|
128
73
|
failed.each_with_index do |drill,index|
|
74
|
+
dream, reality = drill.dream, drill.reality
|
129
75
|
title = ' %-59s' % %Q{ERROR #{index+1}/#{failed.size} "#{drill.name}"}
|
130
76
|
puts $/, ' ' << title.color(:red).att(:reverse)
|
131
77
|
|
132
|
-
if
|
133
|
-
puts '%
|
134
|
-
puts '%
|
135
|
-
|
136
|
-
|
137
|
-
puts '%24s: %s' % ["expected error msg", drill.dream.emsg.inspect]
|
138
|
-
puts '%24s: %s' % ["actual error msg", drill.reality.emsg.inspect]
|
78
|
+
if dream
|
79
|
+
puts '%12s: %s' % [ "expected", dream.output.inspect]
|
80
|
+
puts '%12s: %s' % ["returned", reality.output.inspect]
|
81
|
+
unless reality.error.nil?
|
82
|
+
puts '%12s: %s' % ["error", reality.error.inspect]
|
139
83
|
end
|
140
|
-
|
141
|
-
|
142
|
-
puts
|
143
|
-
puts drill.reality.backtrace, $/
|
84
|
+
unless reality.trace.nil?
|
85
|
+
puts '%12s: %s' % ["trace", reality.trace.join($/ + ' '*14)]
|
86
|
+
puts
|
144
87
|
end
|
145
88
|
else
|
146
|
-
puts '%
|
147
|
-
puts '%
|
89
|
+
puts '%12s: %s' % ["expected", "[nodream]"]
|
90
|
+
puts '%12s: %s' % ["returned", reality.output.inspect]
|
148
91
|
end
|
149
92
|
|
150
93
|
end
|
@@ -158,26 +101,15 @@ class Tryouts
|
|
158
101
|
@success = !(@drills.collect { |r| r.success? }.member?(false))
|
159
102
|
end
|
160
103
|
|
161
|
-
# Add a Drill object to the list for this Tryout. If there is
|
162
|
-
#
|
163
|
-
# the Drill before its added to the list.
|
104
|
+
# Add a Drill object to the list for this Tryout. If there is one or
|
105
|
+
# more dreams in +@dream_catcher+, it will be added to drill +d+.
|
164
106
|
def add_drill(d)
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
# Goes through the list of Drill objects (@drills) and gives each
|
171
|
-
# one its associated Dream object (if available).
|
172
|
-
#
|
173
|
-
# This method is called before Tryout#run, but is only necessary in
|
174
|
-
# the case where dreams where loaded after the drills were defined.
|
175
|
-
def update_drills!
|
176
|
-
return if @dreams.nil?
|
177
|
-
@drills.each do |drill|
|
178
|
-
next unless @dreams.has_key?(drill.name)
|
179
|
-
drill.add_dream @dreams[drill.name]
|
107
|
+
unless @dream_catcher.empty?
|
108
|
+
d.add_dream @dream_catcher.first
|
109
|
+
@dream_catcher.clear
|
180
110
|
end
|
111
|
+
drills << d
|
112
|
+
d
|
181
113
|
end
|
182
114
|
|
183
115
|
## --------------------------------------- EXTERNAL DSL -----
|
@@ -199,28 +131,30 @@ class Tryouts
|
|
199
131
|
# +args+ is sent directly to the Drill class. The values are specific on the Sergeant.
|
200
132
|
def drill(dname, *args, &definition)
|
201
133
|
raise "Empty drill name (#{@name})" if dname.nil? || dname.empty?
|
202
|
-
|
203
|
-
|
204
|
-
|
134
|
+
if definition.nil?
|
135
|
+
drill = Tryouts::Drill.new(dname, @dtype, :output => args.first)
|
136
|
+
else
|
137
|
+
drill = Tryouts::Drill.new(dname, @dtype, args.first, &definition)
|
138
|
+
end
|
139
|
+
self.add_drill drill
|
205
140
|
end
|
206
141
|
# A quick way to comment out a drill
|
207
142
|
def xdrill(*args, &b); end # ignore calls to xdrill
|
208
143
|
|
209
|
-
|
210
|
-
# +output+ A String or Array of expected output. A Dream object will be created using this value (optional)
|
211
|
-
# +definition+ is a block which will be run on an instance of Dream
|
144
|
+
|
212
145
|
#
|
213
146
|
# NOTE: This method is DSL-only. It's not intended to be used in OO syntax.
|
214
|
-
def dream(
|
215
|
-
|
216
|
-
if output.nil?
|
217
|
-
raise "No output or block for '#{dname}' (#{@name})" if definition.nil?
|
147
|
+
def dream(*args, &definition)
|
148
|
+
if args.empty?
|
218
149
|
dobj = Tryouts::Drill::Dream.from_block definition
|
219
150
|
else
|
220
|
-
|
221
|
-
|
151
|
+
if args.size == 1
|
152
|
+
dobj = Tryouts::Drill::Dream.new(args.shift) # dream 'OUTPUT'
|
153
|
+
else
|
154
|
+
dobj = Tryouts::Drill::Dream.new(*args.reverse) # dream :form, 'OUTPUT'
|
155
|
+
end
|
222
156
|
end
|
223
|
-
@
|
157
|
+
@dream_catcher << dobj
|
224
158
|
dobj
|
225
159
|
end
|
226
160
|
# A quick way to comment out a dream
|
data/tryouts.gemspec
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
@spec = Gem::Specification.new do |s|
|
2
|
+
s.name = "tryouts"
|
3
|
+
s.rubyforge_project = "tryouts"
|
4
|
+
s.version = "0.6.0"
|
5
|
+
s.summary = "Tryouts are high-level tests for your Ruby code. May all your dreams come true!"
|
6
|
+
s.description = s.summary
|
7
|
+
s.author = "Delano Mandelbaum"
|
8
|
+
s.email = "tryouts@solutious.com"
|
9
|
+
s.homepage = "http://github.com/delano/tryouts"
|
10
|
+
|
11
|
+
# = EXECUTABLES =
|
12
|
+
# The list of executables in your project (if any). Don't include the path,
|
13
|
+
# just the base filename.
|
14
|
+
s.executables = %w[sergeant]
|
15
|
+
|
16
|
+
# Directories to extract rdocs from
|
17
|
+
s.require_paths = %w[lib]
|
18
|
+
|
19
|
+
# Specific files to include rdocs from
|
20
|
+
s.extra_rdoc_files = %w[README.rdoc LICENSE.txt]
|
21
|
+
|
22
|
+
# Update --main to reflect the default page to display
|
23
|
+
s.rdoc_options = ["--line-numbers", "--title", "Tryouts: #{s.summary}", "--main", "README.rdoc"]
|
24
|
+
|
25
|
+
# = DEPENDENCIES =
|
26
|
+
# Add all gem dependencies
|
27
|
+
s.add_dependency 'drydock', '>= 0.6.5'
|
28
|
+
s.add_dependency 'rye', '>= 0.8.2'
|
29
|
+
s.add_dependency 'sysinfo', '>= 0.5.1'
|
30
|
+
|
31
|
+
# = MANIFEST =
|
32
|
+
# The complete list of files to be included in the release. When GitHub packages your gem,
|
33
|
+
# it doesn't allow you to run any command that accesses the filesystem. You will get an
|
34
|
+
# error. You can ask your VCS for the list of versioned files:
|
35
|
+
# git ls-files
|
36
|
+
# svn list -R
|
37
|
+
s.files = %w(
|
38
|
+
CHANGES.txt
|
39
|
+
LICENSE.txt
|
40
|
+
README.rdoc
|
41
|
+
Rakefile
|
42
|
+
bin/mockout
|
43
|
+
bin/sergeant
|
44
|
+
lib/tryouts.rb
|
45
|
+
lib/tryouts/cli.rb
|
46
|
+
lib/tryouts/cli/run.rb
|
47
|
+
lib/tryouts/drill.rb
|
48
|
+
lib/tryouts/drill/context.rb
|
49
|
+
lib/tryouts/drill/response.rb
|
50
|
+
lib/tryouts/drill/sergeant/api.rb
|
51
|
+
lib/tryouts/drill/sergeant/cli.rb
|
52
|
+
lib/tryouts/mixins.rb
|
53
|
+
lib/tryouts/mixins/hash.rb
|
54
|
+
lib/tryouts/orderedhash.rb
|
55
|
+
lib/tryouts/tryout.rb
|
56
|
+
tryouts.gemspec
|
57
|
+
)
|
58
|
+
|
59
|
+
s.has_rdoc = true
|
60
|
+
s.rubygems_version = '1.3.0'
|
61
|
+
|
62
|
+
if s.respond_to? :specification_version then
|
63
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
64
|
+
s.specification_version = 2
|
65
|
+
|
66
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
67
|
+
s.add_runtime_dependency(%q<RedCloth>, [">= 4.0.4"])
|
68
|
+
else
|
69
|
+
s.add_dependency(%q<RedCloth>, [">= 4.0.4"])
|
70
|
+
end
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<RedCloth>, [">= 4.0.4"])
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delano-tryouts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.8.2
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: sysinfo
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- lib/tryouts/cli.rb
|
73
73
|
- lib/tryouts/cli/run.rb
|
74
74
|
- lib/tryouts/drill.rb
|
75
|
+
- lib/tryouts/drill/context.rb
|
75
76
|
- lib/tryouts/drill/response.rb
|
76
77
|
- lib/tryouts/drill/sergeant/api.rb
|
77
78
|
- lib/tryouts/drill/sergeant/cli.rb
|
@@ -79,6 +80,7 @@ files:
|
|
79
80
|
- lib/tryouts/mixins/hash.rb
|
80
81
|
- lib/tryouts/orderedhash.rb
|
81
82
|
- lib/tryouts/tryout.rb
|
83
|
+
- tryouts.gemspec
|
82
84
|
has_rdoc: true
|
83
85
|
homepage: http://github.com/delano/tryouts
|
84
86
|
post_install_message:
|