tryouts 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +10 -0
- data/README.rdoc +28 -17
- data/lib/tryouts/cli/run.rb +3 -3
- data/lib/tryouts/drill.rb +24 -9
- data/lib/tryouts/stats.rb +5 -1
- data/lib/tryouts/tryout.rb +4 -7
- data/lib/tryouts.rb +14 -5
- data/tryouts/01_mixins_tryouts.rb +2 -5
- data/tryouts/10_syntax_tryouts.rb +14 -10
- data/tryouts/50_class_context_tryouts.rb +2 -3
- data/tryouts.gemspec +4 -4
- metadata +5 -5
data/CHANGES.txt
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
TRYOUTS, CHANGES
|
2
2
|
|
3
3
|
|
4
|
+
#### 0.7.2 (2009-06-26) ###############################
|
5
|
+
|
6
|
+
NOTE: You will need to make a syntax change to your tryouts.
|
7
|
+
OLD: dream OUTPUT, :format
|
8
|
+
NEW: dream :format, OUTPUT
|
9
|
+
|
10
|
+
* CHANGE: Order of dream arguments is reversed!
|
11
|
+
* CHANGE: Reduced CLI width to 79
|
12
|
+
|
13
|
+
|
4
14
|
#### 0.7.1 (2009-06-26) ###############################
|
5
15
|
|
6
16
|
* FIXED: Updated manifest in gemspec
|
data/README.rdoc
CHANGED
@@ -11,11 +11,21 @@ A tryout is made up of one of more drills. The return value of the drill block i
|
|
11
11
|
* Drill Sergeant: The class responsible for executing a drill.
|
12
12
|
* Dream: the expected outcome of a drill. There's always one or more dream per drill.
|
13
13
|
|
14
|
-
== Installation
|
14
|
+
== Installation
|
15
15
|
|
16
|
-
{{{
|
17
16
|
$ gem install tryouts
|
18
|
-
|
17
|
+
|
18
|
+
|
19
|
+
== NOTICE (2009-06-26): DSL Syntax Change
|
20
|
+
|
21
|
+
The order of dream arguments has reversed between 0.7.1 and 0.7.2. It is now:
|
22
|
+
|
23
|
+
* <tt>dream :method, 'Expected value'</tt>
|
24
|
+
|
25
|
+
This is a return to the original syntax and I think it's the right way to go because it reads more naturally:
|
26
|
+
|
27
|
+
* <tt>drill 'test name', 'return value', :class, String</tt>
|
28
|
+
|
19
29
|
|
20
30
|
== Examples
|
21
31
|
|
@@ -23,9 +33,9 @@ The examples below are a complete overview of Tryouts syntax.
|
|
23
33
|
|
24
34
|
=== Testing Ruby Codes (:api)
|
25
35
|
|
26
|
-
library :
|
36
|
+
library :gibbler, "../path/to/gibbler/lib"
|
27
37
|
|
28
|
-
tryouts "Common Usage" do
|
38
|
+
tryouts "Common Usage", :api do
|
29
39
|
|
30
40
|
# This drill block should return 3.
|
31
41
|
drill "Maths R Us", 3 do
|
@@ -34,26 +44,26 @@ The examples below are a complete overview of Tryouts syntax.
|
|
34
44
|
|
35
45
|
# You can specify a method to execute
|
36
46
|
# on the return value of the drill block.
|
37
|
-
drill "We want a symbol",
|
47
|
+
drill "We want a symbol", :class, Symbol do
|
38
48
|
orange.methods.first
|
39
49
|
end
|
40
50
|
|
41
51
|
# Dreams can also be specified explicitly which is
|
42
52
|
# important b/c it's possible to specify multiple.
|
43
|
-
dream
|
53
|
+
dream :class, Array
|
44
54
|
dream [:a, :b, :c]
|
45
55
|
drill "Should return a list of 3" do
|
46
56
|
Letters.list(3)
|
47
57
|
end
|
48
58
|
|
49
59
|
# Drills can pass based on an exception too.
|
50
|
-
dream
|
60
|
+
dream :exception, NameError
|
51
61
|
drill "Something failed" do
|
52
62
|
raise NameError
|
53
63
|
end
|
54
64
|
|
55
65
|
# We can even put simple drills on a single line.
|
56
|
-
drill
|
66
|
+
drill 'Small, fast, and furious', 'Muggsy Bogues', :match, /Mug+sy Bogu?es/
|
57
67
|
|
58
68
|
end
|
59
69
|
|
@@ -69,18 +79,18 @@ You can also use Tryouts to run benchmarks. The tryouts method takes a second pa
|
|
69
79
|
@@array = (1..100000).map { rand }
|
70
80
|
end
|
71
81
|
|
72
|
-
dream 3.0
|
73
|
-
dream 0.1
|
82
|
+
dream :mean, 3.0 # The mean should be <= 3.0 seconds
|
83
|
+
dream :sdev, 0.1 # and the standard deviation <= 0.1
|
74
84
|
drill("Array sort!") { @@array.dup.sort! }
|
75
85
|
|
76
86
|
# You can also include a dream inline
|
77
|
-
drill("Array sort", 3.0
|
87
|
+
drill("Array sort", :mean, 3.0) { @@array.dup.sort }
|
78
88
|
|
79
89
|
# The 3rd argument is the number of times to
|
80
90
|
# execute the drill block. The mean and sdev
|
81
91
|
# are calculate based on all iterations. The
|
82
92
|
# default is 5 and the maximum is 30.
|
83
|
-
dream 0.1,
|
93
|
+
dream :sdev, 0.1, 15
|
84
94
|
drill("Array sort") { @@array.dup.sort }
|
85
95
|
|
86
96
|
end
|
@@ -95,17 +105,18 @@ http://github.com/delano/tryouts/raw/gh-pages/screens/tryouts-1-failure.png
|
|
95
105
|
|
96
106
|
The drill that failed looks like this:
|
97
107
|
|
98
|
-
dream :
|
99
|
-
dream 'ab33b9dec202d136d0e695a3a7b06ee678134882'
|
100
|
-
drill
|
108
|
+
dream :respond_to?, :to_gibble
|
109
|
+
dream :to_gibble, 'ab33b9dec202d136d0e695a3a7b06ee678134882'
|
110
|
+
drill Array, "Array"
|
101
111
|
|
102
112
|
|
103
113
|
== BETA Notice
|
104
114
|
|
105
|
-
|
115
|
+
Tryouts is very new (est. 2009-05-19) and has not been vetted by the scrutiny of time. In particular you can expect:
|
106
116
|
|
107
117
|
* The test definition syntax may change in future releases.
|
108
118
|
* Unexpected errors.
|
119
|
+
* Bugs! I love fixing bugs so if you find one let me know.
|
109
120
|
|
110
121
|
|
111
122
|
== On Threads
|
data/lib/tryouts/cli/run.rb
CHANGED
@@ -47,7 +47,7 @@ class Run < Drydock::Command
|
|
47
47
|
|
48
48
|
passed, failed = 0, 0
|
49
49
|
Tryouts.instances.each_pair do |group,tryouts_inst|
|
50
|
-
puts '', ' %-
|
50
|
+
puts '', ' %-79s'.att(:reverse) % group unless Tryouts.verbose < 0
|
51
51
|
puts " #{tryouts_inst.paths.join("\n ")}" if Tryouts.verbose > 0
|
52
52
|
tryouts_inst.tryouts.each_pair do |name,to|
|
53
53
|
begin
|
@@ -63,11 +63,11 @@ class Run < Drydock::Command
|
|
63
63
|
end
|
64
64
|
|
65
65
|
unless tryouts_inst.errors.empty?
|
66
|
-
title = '%-
|
66
|
+
title = '%-78s' % " RUNTIME ERRORS !?"
|
67
67
|
puts $/, ' ' << title.color(:red).att(:reverse).bright
|
68
68
|
tryouts_inst.errors.each do |ex|
|
69
69
|
trace = Tryouts.verbose > 1 ? ex.backtrace : [ex.backtrace.first]
|
70
|
-
puts '%
|
70
|
+
puts '%4s%s: %s' % ['', ex.class, ex.message.to_s.split($/).join($/ + ' '*16)]
|
71
71
|
puts
|
72
72
|
puts '%14s %s' % ["", trace.join($/ + ' '*16)]
|
73
73
|
puts
|
data/lib/tryouts/drill.rb
CHANGED
@@ -32,8 +32,19 @@ class Tryouts
|
|
32
32
|
# A Reality object (the actual output of the test)
|
33
33
|
attr_reader :reality
|
34
34
|
|
35
|
-
@@valid_dtypes = [:
|
35
|
+
@@valid_dtypes = [:api, :benchmark]
|
36
36
|
|
37
|
+
# * +name+ The display name of this drill
|
38
|
+
# * +dtype+ A Symbol representing the drill type. One of: :api, :benchmark
|
39
|
+
# * +args+ These are dependent on the drill type. See the Sergeant classes
|
40
|
+
# * +&drill+ The body of the drill. The return value of this block
|
41
|
+
# is compared to the exepected output of the dreams.
|
42
|
+
#
|
43
|
+
# The DSL syntax:
|
44
|
+
# * dream OUTPUT
|
45
|
+
# * dream FORMAT, OUTPUT
|
46
|
+
# * dream FORMAT, OUTPUT, REPS (benchmark only)
|
47
|
+
#
|
37
48
|
def initialize(name, dtype, *args, &drill)
|
38
49
|
@name, @dtype, @drill, @skip = name, dtype, drill, false
|
39
50
|
@dreams = []
|
@@ -42,14 +53,17 @@ class Tryouts
|
|
42
53
|
@sergeant = Tryouts::Drill::Sergeant::CLI.new *args
|
43
54
|
when :api
|
44
55
|
default_output = drill.nil? ? args.shift : nil
|
56
|
+
dream_output, format = *(args.size == 1 ? args.first : args.reverse)
|
45
57
|
@sergeant = Tryouts::Drill::Sergeant::API.new default_output
|
46
|
-
|
58
|
+
unless args.empty?
|
59
|
+
@dreams << Tryouts::Drill::Dream.new(dream_output, format)
|
60
|
+
end
|
47
61
|
when :benchmark
|
48
|
-
|
49
|
-
@sergeant = Tryouts::Drill::Sergeant::Benchmark.new reps
|
62
|
+
dream_output, format, reps = *(args.size == 1 ? args.first : [args[1], args[0], args[2]])
|
63
|
+
@sergeant = Tryouts::Drill::Sergeant::Benchmark.new reps
|
50
64
|
@dreams << Tryouts::Drill::Dream.new(Tryouts::Stats, :class)
|
51
|
-
unless
|
52
|
-
@dreams << Tryouts::Drill::Dream.new(
|
65
|
+
unless dream_output.nil?
|
66
|
+
@dreams << Tryouts::Drill::Dream.new(dream_output, format)
|
53
67
|
end
|
54
68
|
when :skip
|
55
69
|
@skip = true
|
@@ -63,6 +77,7 @@ class Tryouts
|
|
63
77
|
@reality = Tryouts::Drill::Reality.new
|
64
78
|
end
|
65
79
|
|
80
|
+
def self.valid_dtypes; @@valid_dtypes; end
|
66
81
|
def self.valid_dtype?(t); @@valid_dtypes.member?(t); end
|
67
82
|
|
68
83
|
def skip?; @skip; end
|
@@ -128,9 +143,9 @@ class Tryouts
|
|
128
143
|
|
129
144
|
@dreams.each do |dream|
|
130
145
|
next if dream == reality #? :normal : :red
|
131
|
-
out.puts '%12s: %s'.color(@clr) % ["
|
132
|
-
out.puts '%12s: %s' % ["
|
133
|
-
out.puts '%12s: %s' % ["
|
146
|
+
out.puts '%12s: %s'.color(@clr) % ["failed", dream.test_to_string(@reality)]
|
147
|
+
out.puts '%12s: %s' % ["drill", @reality.comparison_value(dream).inspect]
|
148
|
+
out.puts '%12s: %s' % ["dream", dream.comparison_value.inspect]
|
134
149
|
out.puts
|
135
150
|
end
|
136
151
|
|
data/lib/tryouts/stats.rb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
# are not stored but instead all the values are calculated on the fly.
|
18
18
|
class Tryouts
|
19
19
|
class Stats
|
20
|
-
attr_reader :sum, :sumsq, :n, :min, :max
|
20
|
+
attr_reader :sum, :sumsq, :n, :min, :max, :name
|
21
21
|
|
22
22
|
def initialize(name=:unknown)
|
23
23
|
@name = name
|
@@ -34,6 +34,8 @@ class Tryouts
|
|
34
34
|
@max = 0.0
|
35
35
|
end
|
36
36
|
|
37
|
+
def samples; @n; end
|
38
|
+
|
37
39
|
# Adds a sampling to the calculations.
|
38
40
|
def sample(s)
|
39
41
|
@sum += s
|
@@ -88,5 +90,7 @@ class Tryouts
|
|
88
90
|
sample(now - @last_time)
|
89
91
|
@last_time = now
|
90
92
|
end
|
93
|
+
|
94
|
+
|
91
95
|
end
|
92
96
|
end
|
data/lib/tryouts/tryout.rb
CHANGED
@@ -57,7 +57,7 @@ class Tryouts
|
|
57
57
|
DrillContext.module_eval &setup if setup.is_a?(Proc)
|
58
58
|
puts "\n %s ".bright % @name unless Tryouts.verbose < 0
|
59
59
|
@drills.each do |drill|
|
60
|
-
print ' %-
|
60
|
+
print ' %-69s ' % "\"#{drill.name}\"" unless Tryouts.verbose < 0
|
61
61
|
drill.run DrillContext.new
|
62
62
|
if drill.skip?
|
63
63
|
@skipped += 1
|
@@ -77,7 +77,7 @@ class Tryouts
|
|
77
77
|
return if Tryouts.verbose < 0
|
78
78
|
failed = @drills.select { |d| !d.skip? && !d.success? }
|
79
79
|
failed.each_with_index do |drill,index|
|
80
|
-
title = ' %-
|
80
|
+
title = ' %-69s %2d/%-2d ' % ["\"#{drill.name}\"", index+1, failed.size]
|
81
81
|
puts $/, ' ' << title.color(:red).att(:reverse)
|
82
82
|
puts drill.report
|
83
83
|
end
|
@@ -136,11 +136,8 @@ class Tryouts
|
|
136
136
|
if args.empty?
|
137
137
|
dobj = Tryouts::Drill::Dream.from_block definition
|
138
138
|
else
|
139
|
-
|
140
|
-
|
141
|
-
else
|
142
|
-
dobj = Tryouts::Drill::Dream.new(*args) # dream 'OUTPUT', :format
|
143
|
-
end
|
139
|
+
args = args.size == 1 ? [args.first] : args.reverse
|
140
|
+
dobj = Tryouts::Drill::Dream.new(*args)
|
144
141
|
end
|
145
142
|
@dream_catcher.push dobj
|
146
143
|
dobj
|
data/lib/tryouts.rb
CHANGED
@@ -30,9 +30,18 @@ class Tryouts
|
|
30
30
|
class Exception < RuntimeError; end
|
31
31
|
# = BadDreams
|
32
32
|
# Raised when there is a problem loading or parsing a Tryouts::Drill::Dream object
|
33
|
-
class
|
33
|
+
class BadDream < Exception; end
|
34
34
|
|
35
|
-
|
35
|
+
class NoDrillType < Exception
|
36
|
+
attr_accessor :tname
|
37
|
+
def initialize(t); @tname = t; end
|
38
|
+
def message
|
39
|
+
vdt = Tryouts::Drill.valid_dtypes
|
40
|
+
"Tryout '#{@tname}' has no drill type. Should be: #{vdt.join(', ')}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
VERSION = "0.7.2"
|
36
45
|
|
37
46
|
require 'tryouts/mixins'
|
38
47
|
require 'tryouts/tryout'
|
@@ -167,7 +176,7 @@ class Tryouts
|
|
167
176
|
|
168
177
|
# Create a new Tryout object and add it to the list for this Tryouts class.
|
169
178
|
# * +name+ is the name of the Tryout
|
170
|
-
# * +
|
179
|
+
# * +dtype+ is the default drill type for the Tryout.
|
171
180
|
# * +command+ when type is :cli, this is the name of the Rye::Box method that we're testing. Otherwise ignored.
|
172
181
|
# * +b+ is a block definition for the Tryout. See Tryout#from_block
|
173
182
|
#
|
@@ -177,7 +186,7 @@ class Tryouts
|
|
177
186
|
dtype ||= @dtype
|
178
187
|
command ||= @command if dtype == :cli
|
179
188
|
|
180
|
-
raise
|
189
|
+
raise NoDrillType, name if dtype.nil?
|
181
190
|
|
182
191
|
to = find_tryout(name, dtype)
|
183
192
|
if to.nil?
|
@@ -240,6 +249,7 @@ class Tryouts
|
|
240
249
|
file_content = File.read(fpath)
|
241
250
|
to = Tryouts.new
|
242
251
|
begin
|
252
|
+
to.paths << fpath
|
243
253
|
to.instance_eval file_content, fpath
|
244
254
|
# After parsing the DSL, we'll know the group name.
|
245
255
|
# If a Tryouts object already exists for that group
|
@@ -248,7 +258,6 @@ class Tryouts
|
|
248
258
|
to = @@instances[to.group]
|
249
259
|
to.instance_eval file_content, fpath
|
250
260
|
end
|
251
|
-
to.paths << fpath
|
252
261
|
rescue SyntaxError, LoadError, Exception, TypeError,
|
253
262
|
RuntimeError, NoMethodError, NameError => ex
|
254
263
|
to.errors << ex
|
@@ -1,10 +1,7 @@
|
|
1
1
|
|
2
|
-
library :tryouts, File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
2
|
|
4
3
|
group "Mixins"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
5
|
test_hash = {
|
9
6
|
:level1 => {
|
10
7
|
:level2 => {},
|
@@ -15,12 +12,12 @@ test_hash = {
|
|
15
12
|
}
|
16
13
|
|
17
14
|
|
18
|
-
tryouts "Hash" do
|
15
|
+
tryouts "Hash", :api do
|
19
16
|
setup do
|
20
17
|
|
21
18
|
end
|
22
19
|
|
23
20
|
drill "knows the deepest point", test_hash.deepest_point, 3
|
24
|
-
drill "has a last method", {}
|
21
|
+
drill "has a last method", {} #, :respond_to?, :last
|
25
22
|
|
26
23
|
end
|
@@ -1,17 +1,21 @@
|
|
1
1
|
|
2
2
|
tryout "DSL Syntax", :api do
|
3
3
|
|
4
|
+
drill "can specify a dream inline", 3 do
|
5
|
+
12 / 4
|
6
|
+
end
|
7
|
+
|
4
8
|
dream 4770744
|
5
9
|
drill "can specify dream above the drill" do
|
6
10
|
4770744
|
7
11
|
end
|
8
12
|
|
9
|
-
dream
|
13
|
+
dream :class, Array
|
10
14
|
drill "can pass based on output object class" do
|
11
15
|
[1,2,3]
|
12
16
|
end
|
13
17
|
|
14
|
-
dream
|
18
|
+
dream :exception, NameError
|
15
19
|
drill "can pass based on exception class" do
|
16
20
|
bad_method_call
|
17
21
|
end
|
@@ -22,19 +26,19 @@ tryout "DSL Syntax", :api do
|
|
22
26
|
|
23
27
|
drill "inline true values will pass too", true
|
24
28
|
drill "can specify inline return values", :food, :food
|
25
|
-
drill "can specify match format", 'mahir', /..hi./i
|
29
|
+
drill "can specify match format", 'mahir', :match, /..hi./i
|
26
30
|
|
27
31
|
dream "big"
|
28
|
-
dream
|
29
|
-
dream /\Ab.g\z
|
32
|
+
dream :class, String
|
33
|
+
dream :match, /\Ab.g\z/
|
30
34
|
drill "can handle multiple dreams" do
|
31
35
|
"big"
|
32
36
|
end
|
33
37
|
|
34
|
-
drill "can specify gt (>) format", 2,
|
35
|
-
drill "can specify gte (>=) format", 2,
|
36
|
-
drill "can specify lt (<) format", 1,
|
37
|
-
drill "can specify lte (<=) format", 2,
|
38
|
+
drill "can specify gt (>) format", 2, :gt, 1
|
39
|
+
drill "can specify gte (>=) format", 2, :gte, 2
|
40
|
+
drill "can specify lt (<) format", 1, :lt, 2
|
41
|
+
drill "can specify lte (<=) format", 2, :lte, 2
|
38
42
|
|
39
|
-
drill "can run arbitrary formats", [3,1,2], [1,2,3]
|
43
|
+
drill "can run arbitrary formats", [3,1,2], :sort, [1,2,3]
|
40
44
|
end
|
@@ -8,7 +8,7 @@ tryout "Setting class variables", :api do
|
|
8
8
|
@from_setup = true
|
9
9
|
end
|
10
10
|
|
11
|
-
drill "can't access class var created in setup (1.9 only)",
|
11
|
+
drill "can't access class var created in setup (1.9 only)", :exception, NameError do
|
12
12
|
@@from_setup
|
13
13
|
end
|
14
14
|
|
@@ -25,6 +25,5 @@ tryout "Setting class variables", :api do
|
|
25
25
|
@@from_drill.class.to_s
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
drill "Knows where Santa Claus lives", 'H0H 0H0'
|
28
|
+
drill 'Small, fast, and furious', 'Muggsy Bogues', :match, /Mug+sy Bogu?es/
|
30
29
|
end
|
data/tryouts.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "tryouts"
|
3
3
|
s.rubyforge_project = "tryouts"
|
4
|
-
s.version = "0.7.
|
4
|
+
s.version = "0.7.2"
|
5
5
|
s.summary = "Tryouts are high-level tests for your Ruby code. May all your dreams come true!"
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
@@ -24,9 +24,9 @@
|
|
24
24
|
|
25
25
|
# = DEPENDENCIES =
|
26
26
|
# Add all gem dependencies
|
27
|
-
s.add_dependency 'rye'
|
28
|
-
s.add_dependency 'drydock'
|
29
|
-
s.add_dependency 'sysinfo'
|
27
|
+
s.add_dependency 'rye'
|
28
|
+
s.add_dependency 'drydock'
|
29
|
+
s.add_dependency 'sysinfo'
|
30
30
|
|
31
31
|
# = MANIFEST =
|
32
32
|
# The complete list of files to be included in the release. When GitHub packages your gem,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tryouts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-26 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0
|
23
|
+
version: "0"
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: drydock
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0
|
33
|
+
version: "0"
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: sysinfo
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0
|
43
|
+
version: "0"
|
44
44
|
version:
|
45
45
|
description: Tryouts are high-level tests for your Ruby code. May all your dreams come true!
|
46
46
|
email: tryouts@solutious.com
|