marso 0.1.5297 → 0.1.15089
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/marso.rb +2 -0
- data/lib/marso/assert.rb +2 -2
- data/lib/marso/config.rb +25 -0
- data/lib/marso/scenario.rb +278 -0
- data/lib/marso/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9dd68ffdf94aa8dc6c18a66a1be55774e8aa2b4b
|
|
4
|
+
data.tar.gz: 07415303338d5c40520661aa865a656b171cb148
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1386739d560795b6bcc2e6e74a59030aa46e9eeacfe3951bc3d62fbb58b9b48da18ea7ba2e7cb0374c151e9699e04ccc8595725e2e2ce38115034e529dad03db
|
|
7
|
+
data.tar.gz: fab73a4f66f4856dc1f2500f0aeeb9693bd9240caa7f0ca12d9a8f6b35812635dff42fc7e7fabd4e88a006392f0277502fbff4917abc9a3c393dc9660b260f66
|
data/lib/marso.rb
CHANGED
data/lib/marso/assert.rb
CHANGED
|
@@ -3,7 +3,7 @@ require "colorize"
|
|
|
3
3
|
module Marso
|
|
4
4
|
module_function
|
|
5
5
|
|
|
6
|
-
def assert
|
|
6
|
+
def assert(message, &block)
|
|
7
7
|
begin
|
|
8
8
|
if (block.call)
|
|
9
9
|
puts "Assert #{message}: PASSED".green
|
|
@@ -11,7 +11,7 @@ module Marso
|
|
|
11
11
|
puts "Assert #{message}: FAILED".red
|
|
12
12
|
end
|
|
13
13
|
rescue Exception => e
|
|
14
|
-
puts "Assert #{message} FAILED with exception #{e}".red
|
|
14
|
+
puts "Assert #{message} FAILED with exception #{e.message}".red
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
data/lib/marso/config.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Marso
|
|
2
|
+
class Config
|
|
3
|
+
@@configuration={
|
|
4
|
+
# If true, the result of each step is output to the console in realtime.
|
|
5
|
+
# The consequence os setting that config to true is that steps
|
|
6
|
+
# may be harder to read together when multiple scenarios are executed
|
|
7
|
+
# paralell. Steps of different scenarios may indeed be intertwined in the
|
|
8
|
+
# console
|
|
9
|
+
:realtime_step_stdout => false,
|
|
10
|
+
|
|
11
|
+
# If true, all steps of the same scenario defined after a broken step(i.e.
|
|
12
|
+
# step in status :failed, :error, or :cancelled) will not be executed, and
|
|
13
|
+
# will all be set so their status is :cancelled
|
|
14
|
+
:cancel_steps_upon_issues => true
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def self.set(config_name, config_value)
|
|
18
|
+
@@configuration[config_name] = config_value if @@configuration.key?(config_name)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.get(config_name)
|
|
22
|
+
@@configuration[config_name]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
require 'colorize'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
require_relative 'config'
|
|
4
|
+
|
|
5
|
+
module Marso
|
|
6
|
+
|
|
7
|
+
class Scenario
|
|
8
|
+
ISSUES_LIST = [:error, :failed, :cancelled]
|
|
9
|
+
@@color_options=nil
|
|
10
|
+
@@color_options_size=0
|
|
11
|
+
attr_reader :name, :steps, :id, :status, :color_theme, :cancel_steps_upon_issues,
|
|
12
|
+
:realtime_step_stdout
|
|
13
|
+
|
|
14
|
+
# name: Scenario's name
|
|
15
|
+
# options:
|
|
16
|
+
# :id => hex string (length 8). Default is randomly generated
|
|
17
|
+
# :steps => array of Step objects
|
|
18
|
+
# :color_theme => color from gem 'colorize'(e.g. :blue). That allows
|
|
19
|
+
# to visually group all steps from the same scenario.
|
|
20
|
+
# Default is randomly choosen from the available set
|
|
21
|
+
# :cancel_steps_upon_issues => Boolean. If true, all steps defined after
|
|
22
|
+
# a broken step(i.e. step in status :failed,
|
|
23
|
+
# :error, or :cancelled) will not be
|
|
24
|
+
# executed, and will all be set so their
|
|
25
|
+
# status is :cancelled. If defined, it
|
|
26
|
+
# overrides the Config.cancel_steps_upon_issues
|
|
27
|
+
# setting.
|
|
28
|
+
def initialize(name, options={})
|
|
29
|
+
|
|
30
|
+
if @@color_options.nil?
|
|
31
|
+
@@color_options = String.colors
|
|
32
|
+
@@color_options_size = @@color_options.size
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@name = name
|
|
36
|
+
@id =
|
|
37
|
+
options.key?(:id) ?
|
|
38
|
+
options[:id] :
|
|
39
|
+
SecureRandom.hex(4)
|
|
40
|
+
|
|
41
|
+
@status =
|
|
42
|
+
options.key?(:status) ?
|
|
43
|
+
options[:status] :
|
|
44
|
+
:pending
|
|
45
|
+
|
|
46
|
+
@color_theme =
|
|
47
|
+
options.key?(:color_theme) ?
|
|
48
|
+
options[:color_theme] :
|
|
49
|
+
@@color_options[rand(@@color_options_size)]
|
|
50
|
+
|
|
51
|
+
@steps =
|
|
52
|
+
options.key?(:steps) ?
|
|
53
|
+
options[:steps].map { |s| Step.new(s.text, @id, @color_theme, s.status, &s.block) } :
|
|
54
|
+
[]
|
|
55
|
+
|
|
56
|
+
@cancel_steps_upon_issues =
|
|
57
|
+
options.key?(:cancel_steps_upon_issues) ?
|
|
58
|
+
options[:cancel_steps_upon_issues] :
|
|
59
|
+
Marso::Config.get(:cancel_steps_upon_issues)
|
|
60
|
+
|
|
61
|
+
@realtime_step_stdout =
|
|
62
|
+
options.key?(:realtime_step_stdout) ?
|
|
63
|
+
options[:realtime_step_stdout] :
|
|
64
|
+
Marso::Config.get(:realtime_step_stdout)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def given(assumption_text, *args, &block)
|
|
68
|
+
return add_step(:given, assumption_text, *args, &block)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def and(assumption_text, *args, &block)
|
|
72
|
+
return add_step(:and, assumption_text, *args, &block)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def when(assumption_text, *args, &block)
|
|
76
|
+
return add_step(:when, assumption_text, *args, &block)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def then(assumption_text, *args, &block)
|
|
80
|
+
return add_step(:then, assumption_text, *args, &block)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def but(assumption_text, *args, &block)
|
|
84
|
+
return add_step(:but, assumption_text, *args, &block)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def run
|
|
88
|
+
previous_step_status = nil
|
|
89
|
+
scenario_status = :passed
|
|
90
|
+
no_issues = true
|
|
91
|
+
puts "Scenario #{@id}".colorize(@color_theme) + ": " + "#{name}".blue if @realtime_step_stdout
|
|
92
|
+
|
|
93
|
+
processed_steps = @steps.map { |s|
|
|
94
|
+
executed_step = execute_step(s, previous_step_status)
|
|
95
|
+
|
|
96
|
+
print executed_step.print_context if @realtime_step_stdout
|
|
97
|
+
|
|
98
|
+
previous_step_status = executed_step.status
|
|
99
|
+
|
|
100
|
+
if no_issues
|
|
101
|
+
case previous_step_status
|
|
102
|
+
when :error
|
|
103
|
+
no_issues = false
|
|
104
|
+
scenario_status = :error
|
|
105
|
+
when :failed
|
|
106
|
+
no_issues = false
|
|
107
|
+
scenario_status = :failed
|
|
108
|
+
when :cancelled
|
|
109
|
+
no_issues = false
|
|
110
|
+
scenario_status = :failed
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
executed_step
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return Scenario.new(@name, {
|
|
118
|
+
:id => @id,
|
|
119
|
+
:steps => processed_steps,
|
|
120
|
+
:status => scenario_status,
|
|
121
|
+
:color_theme => @color_theme
|
|
122
|
+
})
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def context
|
|
126
|
+
return
|
|
127
|
+
"Scenario #{@id}: #{name}\n" +
|
|
128
|
+
(@steps.any? ? @steps.map { |s| s.context }.join("\n") : "")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def print_context
|
|
132
|
+
puts "Scenario #{@id}".colorize(@color_theme) + ": " + "#{name}".blue
|
|
133
|
+
@steps.map { |s| s.print_context } if !@steps.nil?
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def add_step(step_type, assumption_text, *args, &block)
|
|
140
|
+
body_msg = nil
|
|
141
|
+
status = :pending
|
|
142
|
+
step_name = step_type.to_s
|
|
143
|
+
|
|
144
|
+
begin
|
|
145
|
+
body_msg = "#{step_name} " + assumption_text % args
|
|
146
|
+
rescue Exception => e
|
|
147
|
+
status = :error
|
|
148
|
+
body_msg =
|
|
149
|
+
"#{assumption_text}: ERROR\n" +
|
|
150
|
+
"args: #{args.nil? ? '' : args.join(',')}\n" +
|
|
151
|
+
"#{e.message}\n" +
|
|
152
|
+
"#{e.backtrace}"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
new_step_series = @steps | [Step.new(body_msg, @id, color_theme, status, &block)]
|
|
156
|
+
|
|
157
|
+
return Scenario.new(@name, {
|
|
158
|
+
:id => @id,
|
|
159
|
+
:steps => new_step_series,
|
|
160
|
+
:status => @status,
|
|
161
|
+
:color_theme => @color_theme
|
|
162
|
+
})
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def execute_step(step, previous_step_status)
|
|
166
|
+
if ISSUES_LIST.include?(previous_step_status) && @cancel_steps_upon_issues
|
|
167
|
+
cancelled_step = Step.new(step.text, @id, @color_theme, :cancelled, &step.block)
|
|
168
|
+
return cancelled_step.execute
|
|
169
|
+
else
|
|
170
|
+
return step.execute
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# A 'Step' is a Scenario's part. It contains
|
|
176
|
+
# a text that describe what that step does, as well
|
|
177
|
+
# as a status that indicates whether or not that step
|
|
178
|
+
# has already been executed. This status can take the
|
|
179
|
+
# following values:
|
|
180
|
+
# => :pending
|
|
181
|
+
# => :passed
|
|
182
|
+
# => :failed
|
|
183
|
+
# => :cancelled
|
|
184
|
+
# => :error
|
|
185
|
+
class Step
|
|
186
|
+
attr_reader :text, :status, :color_theme, :scenario_id, :block
|
|
187
|
+
|
|
188
|
+
def initialize(text, scenario_id, color_theme, status=:pending, &block)
|
|
189
|
+
@text=text
|
|
190
|
+
@status=status
|
|
191
|
+
@block=block
|
|
192
|
+
@scenario_id=scenario_id
|
|
193
|
+
@color_theme = color_theme
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def execute
|
|
197
|
+
if @status != :cancelled
|
|
198
|
+
execute_block
|
|
199
|
+
else
|
|
200
|
+
return self
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def context
|
|
205
|
+
scenario_id = "#{@scenario_id}"
|
|
206
|
+
body = nil
|
|
207
|
+
case @status
|
|
208
|
+
when :pending
|
|
209
|
+
body = "#{@text}: PENDING"
|
|
210
|
+
when :passed
|
|
211
|
+
body = "#{@text}: PASSED"
|
|
212
|
+
when :failed
|
|
213
|
+
body = "#{@text}: FAILED"
|
|
214
|
+
when :cancelled
|
|
215
|
+
body = "#{@text}: CANCELLED"
|
|
216
|
+
when :error
|
|
217
|
+
body = "#{@text}"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
return "#{scenario_id}: #{body}"
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def print_context
|
|
225
|
+
scenario_id = "#{@scenario_id}".colorize(@color_theme)
|
|
226
|
+
body = nil
|
|
227
|
+
case @status
|
|
228
|
+
when :pending
|
|
229
|
+
body = "#{@text}: PENDING".light_yellow
|
|
230
|
+
when :passed
|
|
231
|
+
body = "#{@text}: PASSED".green
|
|
232
|
+
when :failed
|
|
233
|
+
body = "#{@text}: FAILED".red
|
|
234
|
+
when :cancelled
|
|
235
|
+
body = "#{@text}: CANCELLED".light_black
|
|
236
|
+
when :error
|
|
237
|
+
body = "#{@text}".red
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
puts "#{scenario_id}: #{body}"
|
|
241
|
+
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
private
|
|
245
|
+
def execute_block
|
|
246
|
+
operation = lambda { |x|
|
|
247
|
+
begin
|
|
248
|
+
result = @block.call
|
|
249
|
+
result_type = result.class
|
|
250
|
+
if result_type == TrueClass || result_type == FalseClass
|
|
251
|
+
if result
|
|
252
|
+
return :passed, nil
|
|
253
|
+
else
|
|
254
|
+
return :failed, nil
|
|
255
|
+
end
|
|
256
|
+
else
|
|
257
|
+
return :passed, nil
|
|
258
|
+
end
|
|
259
|
+
rescue Exception => e
|
|
260
|
+
return :error, e
|
|
261
|
+
end
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
status, err = operation.call(nil)
|
|
265
|
+
|
|
266
|
+
updated_text = @text
|
|
267
|
+
|
|
268
|
+
if status==:error
|
|
269
|
+
updated_text =
|
|
270
|
+
"#{text}: ERROR\n" +
|
|
271
|
+
"#{err.message}\n" +
|
|
272
|
+
"#{err.backtrace}"
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
return Step.new(updated_text, @scenario_id, @color_theme, status, &@block)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
data/lib/marso/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: marso
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.15089
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nicolas Dao
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-06-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -83,7 +83,9 @@ files:
|
|
|
83
83
|
- Rakefile
|
|
84
84
|
- lib/marso.rb
|
|
85
85
|
- lib/marso/assert.rb
|
|
86
|
+
- lib/marso/config.rb
|
|
86
87
|
- lib/marso/factories.rb
|
|
88
|
+
- lib/marso/scenario.rb
|
|
87
89
|
- lib/marso/version.rb
|
|
88
90
|
- marso.gemspec
|
|
89
91
|
homepage: https://github.com/nicolasdao/marso
|