diddy 0.7.0 → 0.8.0
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.
- data/diddy.gemspec +2 -2
- data/lib/diddy/context.rb +9 -0
- data/lib/diddy/run_result.rb +119 -0
- data/lib/diddy/run_result_printer.rb +74 -0
- data/lib/diddy/scenario.rb +113 -0
- data/lib/diddy/script.rb +67 -164
- data/lib/diddy/shared_scope.rb +1 -2
- data/lib/diddy/step.rb +53 -2
- data/lib/diddy/steps.rb +41 -0
- data/lib/diddy.rb +4 -0
- metadata +7 -3
data/diddy.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "diddy"
|
7
|
-
gem.version = '0.
|
7
|
+
gem.version = '0.8.0'
|
8
8
|
gem.authors = ["Diederick Lawson", "Marcel de Graaf"]
|
9
9
|
gem.email = ["diederick@altovista.nl", "mail@marceldegraaf.net"]
|
10
10
|
gem.description = %q{Diddy script runner}
|
@@ -16,5 +16,5 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
17
|
gem.require_paths = ["lib"]
|
18
18
|
|
19
|
-
gem.add_development_dependency "term/
|
19
|
+
gem.add_development_dependency "term/ansicolor"
|
20
20
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Diddy
|
2
|
+
class RunResult
|
3
|
+
attr_accessor :scripts
|
4
|
+
|
5
|
+
#
|
6
|
+
# Starts the run of a script. Call this before running a scenario.
|
7
|
+
#
|
8
|
+
def run_script(description)
|
9
|
+
@scripts ||= []
|
10
|
+
@current_script = Script.new(description)
|
11
|
+
@scripts << @current_script
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Start the run of an entire scenario.
|
16
|
+
#
|
17
|
+
def run_scenario(description)
|
18
|
+
@current_scenario = Scenario.new(description)
|
19
|
+
@current_scenario.script = @current_script
|
20
|
+
|
21
|
+
@current_script.scenarios << @current_scenario
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Starts run of a step
|
26
|
+
#
|
27
|
+
def run_step(description)
|
28
|
+
@current_step = Step.new(description)
|
29
|
+
@current_step.scenario = @current_scenario
|
30
|
+
|
31
|
+
@current_scenario.steps << @current_step
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Starts run of a sub step
|
36
|
+
#
|
37
|
+
def run_sub_step(description)
|
38
|
+
@current_sub_step = SubStep.new(description)
|
39
|
+
@current_sub_step.step = @current_step
|
40
|
+
|
41
|
+
@current_step.sub_steps << @current_sub_step
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Sets the result of the current step
|
46
|
+
#
|
47
|
+
def set_step_result(result)
|
48
|
+
@current_step.result = result
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Sets the result to false and logs the exception of the step
|
53
|
+
#
|
54
|
+
def set_step_exception(exception)
|
55
|
+
@current_step.result = false
|
56
|
+
@current_step.exception = exception
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Sets the result of the sub step
|
61
|
+
#
|
62
|
+
def set_sub_step_result(result)
|
63
|
+
@current_sub_step.result = result
|
64
|
+
end
|
65
|
+
|
66
|
+
# helper classes
|
67
|
+
class Script
|
68
|
+
attr_accessor :scenarios, :description
|
69
|
+
|
70
|
+
def initialize(description)
|
71
|
+
self.description = description
|
72
|
+
end
|
73
|
+
|
74
|
+
def scenarios
|
75
|
+
@scenarios ||= []
|
76
|
+
end
|
77
|
+
|
78
|
+
def result
|
79
|
+
scenarios.all? { |scenario| scenario.result }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Scenario
|
84
|
+
attr_accessor :steps, :description, :script
|
85
|
+
|
86
|
+
def initialize(description)
|
87
|
+
self.description = description
|
88
|
+
end
|
89
|
+
|
90
|
+
def steps
|
91
|
+
@steps ||= []
|
92
|
+
end
|
93
|
+
|
94
|
+
def result
|
95
|
+
steps.all? { |step| step.result }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Step
|
100
|
+
attr_accessor :description, :sub_steps, :result, :scenario, :exception
|
101
|
+
|
102
|
+
def initialize(description)
|
103
|
+
self.description = description
|
104
|
+
end
|
105
|
+
|
106
|
+
def sub_steps
|
107
|
+
@sub_steps ||= []
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class SubStep
|
112
|
+
attr_accessor :description, :result, :step
|
113
|
+
|
114
|
+
def initialize(description)
|
115
|
+
self.description = description
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Diddy
|
2
|
+
class RunResultPrinter
|
3
|
+
attr_accessor :run_result
|
4
|
+
|
5
|
+
def initialize(run_result)
|
6
|
+
self.run_result = run_result
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
# Converts the result to HTML
|
11
|
+
#
|
12
|
+
# @TODO needs to be refactored to a templating language. Quick hack for now.
|
13
|
+
#
|
14
|
+
def to_html
|
15
|
+
html = "<html><head><style type='text/css'>.error { color: red }; pre { display: block; margin: 1em; };</style><title>Run results</title></head><body>"
|
16
|
+
|
17
|
+
# walk over all scripts
|
18
|
+
run_result.scripts.each do |script|
|
19
|
+
html << "<h2>#{script.description}</h2>"
|
20
|
+
|
21
|
+
# walk of the scenarios
|
22
|
+
script.scenarios.each do |scenario|
|
23
|
+
# result was ok? than only log the scenario itself
|
24
|
+
if scenario.result
|
25
|
+
html << "<h3>#{scenario.description}</h3>"
|
26
|
+
else
|
27
|
+
# log the error and it's steps
|
28
|
+
html << "<h3 class='error'>#{scenario.description}</h3>"
|
29
|
+
html << "<ul>"
|
30
|
+
|
31
|
+
# walk over the steps
|
32
|
+
scenario.steps.each do |step|
|
33
|
+
# output step
|
34
|
+
if step.result
|
35
|
+
html << "<li>#{step.description}"
|
36
|
+
else
|
37
|
+
html << "<li class='error'>#{step.description}"
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# was there an exception?
|
42
|
+
if step.exception
|
43
|
+
html << "<pre>#{step.exception.message}\n\n#{step.exception.backtrace.join("\n")}</pre>"
|
44
|
+
end
|
45
|
+
|
46
|
+
# are there any sub steps?
|
47
|
+
if step.sub_steps.any?
|
48
|
+
html << "<ul>"
|
49
|
+
|
50
|
+
# walk over sub steps
|
51
|
+
step.sub_steps.each do |sub_step|
|
52
|
+
if sub_step.result
|
53
|
+
html << "<li>#{sub_step.description}</li>"
|
54
|
+
else
|
55
|
+
html << "<li class='error'>#{sub_step.description}</li>"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
html << "</ul></li>"
|
60
|
+
else
|
61
|
+
html << "</li>"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
html << "</ul>"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
html << "</body>"
|
71
|
+
html
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Diddy
|
2
|
+
#
|
3
|
+
# A scenario contains several steps. This is where the real work is done.
|
4
|
+
#
|
5
|
+
class Scenario
|
6
|
+
attr_accessor :script, :context, :description, :steps, :run_result
|
7
|
+
|
8
|
+
#
|
9
|
+
# Creates a scenario
|
10
|
+
#
|
11
|
+
def initialize(options = {})
|
12
|
+
options.each { |k,v| send("#{k}=", v) }
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Determines which step classes should be used
|
17
|
+
#
|
18
|
+
def uses(klass)
|
19
|
+
@steps_instances ||= []
|
20
|
+
@steps_instances << klass.new(shared_scope)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Describes which step should be run
|
25
|
+
#
|
26
|
+
def step(description)
|
27
|
+
@steps ||= []
|
28
|
+
|
29
|
+
# find step klass
|
30
|
+
steps_instance = find_steps_instance_for(description)
|
31
|
+
|
32
|
+
# check if step exists
|
33
|
+
if steps_instance && steps_instance.class.has_step?(description)
|
34
|
+
@steps << Diddy::Step.new(
|
35
|
+
description: description,
|
36
|
+
steps_instance: steps_instance,
|
37
|
+
definition: steps_instance.class.definition(description)
|
38
|
+
)
|
39
|
+
else
|
40
|
+
raise "Step '#{description}' not defined"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Runs all the steps in the script
|
46
|
+
#
|
47
|
+
def run
|
48
|
+
begin
|
49
|
+
@steps.each do |step|
|
50
|
+
run_step(step)
|
51
|
+
end
|
52
|
+
|
53
|
+
true
|
54
|
+
|
55
|
+
rescue ScenarioAborted
|
56
|
+
false
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Runs one step
|
63
|
+
#
|
64
|
+
def run_step(step)
|
65
|
+
# run proc on this instance as scope
|
66
|
+
begin
|
67
|
+
step.run_result = run_result
|
68
|
+
result = step.run
|
69
|
+
|
70
|
+
rescue Exception => exception
|
71
|
+
print_exception(exception)
|
72
|
+
run_result.set_step_exception(exception)
|
73
|
+
|
74
|
+
raise ScenarioAborted.new
|
75
|
+
end
|
76
|
+
|
77
|
+
unless result
|
78
|
+
raise ScenarioAborted.new
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Prints exception thrown by step, on screen
|
84
|
+
#
|
85
|
+
def print_exception(exception)
|
86
|
+
print("\n")
|
87
|
+
|
88
|
+
# print backtrace
|
89
|
+
puts("- #{exception.message}")
|
90
|
+
puts(" #{exception.backtrace.join("\n ")}")
|
91
|
+
puts("\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Finds the instance of the steps definition by step name
|
96
|
+
#
|
97
|
+
def find_steps_instance_for(description)
|
98
|
+
@steps_instances.each do |instance|
|
99
|
+
if instance.class.steps && instance.class.steps.has_key?(description)
|
100
|
+
return instance
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def shared_scope
|
108
|
+
@shared_scope ||= SharedScope.new
|
109
|
+
end
|
110
|
+
|
111
|
+
class ScenarioAborted < Exception; end
|
112
|
+
end
|
113
|
+
end
|
data/lib/diddy/script.rb
CHANGED
@@ -1,216 +1,119 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Diddy
|
3
|
+
#
|
4
|
+
# A script contains several scenarios. A script can be a recipe, an application etc.
|
5
|
+
#
|
3
6
|
class Script
|
4
|
-
|
5
|
-
STATE_FAILED = 2
|
6
|
-
STATE_EXCEPTION = 3
|
7
|
+
attr_accessor :scenarios, :description, :context, :run_result
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
# Creates a script
|
12
|
-
#
|
13
|
-
def initialize(scenario)
|
14
|
-
@scenario = scenario
|
9
|
+
def initialize(description)
|
10
|
+
self.description = description
|
15
11
|
end
|
16
12
|
|
17
13
|
#
|
18
|
-
#
|
14
|
+
# Defines a new scenario
|
19
15
|
#
|
20
|
-
|
21
|
-
|
22
|
-
@steps_instances << klass.new(shared_scope)
|
23
|
-
end
|
24
|
-
|
16
|
+
# scenario('Do something') do
|
17
|
+
# uses SomeSteps
|
25
18
|
#
|
26
|
-
#
|
19
|
+
# step 'Do this'
|
20
|
+
# step 'Do that'
|
21
|
+
# end
|
27
22
|
#
|
28
|
-
def
|
29
|
-
@
|
30
|
-
end
|
23
|
+
def scenario(description, &block)
|
24
|
+
@scenarios ||= []
|
31
25
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
steps_instance: steps_instance,
|
46
|
-
definition: steps_instance.class.definition(description)
|
47
|
-
)
|
48
|
-
else
|
49
|
-
raise "Step '#{description}' not defined"
|
50
|
-
end
|
26
|
+
# instantiate scenario
|
27
|
+
scenario = Scenario.new(
|
28
|
+
script: self,
|
29
|
+
context: context,
|
30
|
+
description: description,
|
31
|
+
run_result: run_result
|
32
|
+
)
|
33
|
+
|
34
|
+
# run the DSL
|
35
|
+
scenario.instance_eval(&block)
|
36
|
+
|
37
|
+
# add to our collection of scenarios
|
38
|
+
@scenarios << scenario
|
51
39
|
end
|
52
40
|
|
53
41
|
#
|
54
|
-
#
|
42
|
+
# Run the script
|
55
43
|
#
|
56
44
|
def run
|
57
|
-
|
58
|
-
|
45
|
+
scenarios.each_with_index do |scenario, index|
|
46
|
+
# print on screen
|
47
|
+
puts("Scenario #{index + 1}: #{scenario.description}")
|
59
48
|
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
return true
|
49
|
+
# also log
|
50
|
+
run_result.run_scenario("Scenario #{index + 1}: #{scenario.description}")
|
64
51
|
|
65
|
-
|
66
|
-
|
67
|
-
|
52
|
+
# run all the steps within the scenario
|
53
|
+
scenario.run_result = run_result
|
54
|
+
scenario.run
|
68
55
|
|
56
|
+
puts("\n")
|
69
57
|
end
|
70
58
|
end
|
71
59
|
|
72
60
|
#
|
73
|
-
#
|
61
|
+
# Defines a new script
|
74
62
|
#
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
#
|
80
|
-
#
|
63
|
+
# Diddy::Script.define('Some recipe') do
|
64
|
+
# scenario('Putting stuff in a bowl') do
|
65
|
+
# step 'Put milk in it'
|
66
|
+
# step 'Drink from bowl'
|
67
|
+
# end
|
68
|
+
# end
|
81
69
|
#
|
82
|
-
|
83
|
-
# uses ApiSteps
|
84
|
-
# uses LoginSteps
|
85
|
-
#
|
86
|
-
# step 'Do something'
|
87
|
-
# step 'Do something else'
|
88
|
-
# end
|
89
|
-
#
|
90
|
-
def self.define(scenario, &block)
|
70
|
+
def self.define(description, &block)
|
91
71
|
@scripts ||= []
|
92
72
|
|
93
|
-
script = self.new(
|
73
|
+
script = self.new(description)
|
94
74
|
script.instance_eval(&block)
|
95
75
|
|
96
76
|
@scripts << script
|
97
|
-
end
|
98
|
-
|
99
|
-
#
|
100
|
-
# Runs all defined scripts. Returns true if and only if all indivudial
|
101
|
-
# scripts returned true. Otherwise returns false.
|
102
|
-
#
|
103
|
-
def self.run_all
|
104
|
-
# empty log
|
105
|
-
@last_log = ""
|
106
|
-
|
107
|
-
write_log("[#{Time.now}] Diddy starting to run #{@scripts.size} scripts")
|
108
|
-
|
109
|
-
# Run all scripts and remember their return status
|
110
|
-
status = @scripts.map do |script|
|
111
|
-
# run the script
|
112
|
-
result = script.run
|
113
|
-
|
114
|
-
# concat log of script to general log
|
115
|
-
write_log(script.log)
|
116
77
|
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
write_log("[#{Time.now}] Diddy finished running #{@scripts.size} scripts")
|
121
|
-
|
122
|
-
# If one of the scripts returned with "false"; make the entire run
|
123
|
-
# return false as well
|
124
|
-
status.include?(false) ? false : true
|
78
|
+
script
|
125
79
|
end
|
126
80
|
|
127
81
|
#
|
128
|
-
#
|
82
|
+
# Returns all the defined scripts
|
129
83
|
#
|
130
|
-
def self.only_run(scenario)
|
131
|
-
@scripts.select { |script| script.scenario == scenario }.first.run
|
132
|
-
end
|
133
|
-
|
134
84
|
def self.scripts
|
135
85
|
@scripts
|
136
86
|
end
|
137
87
|
|
138
|
-
private
|
139
|
-
|
140
|
-
def self.write_log(message, print = true)
|
141
|
-
puts(message) if print
|
142
|
-
self.last_log << "#{message}\n"
|
143
|
-
end
|
144
|
-
|
145
88
|
#
|
146
|
-
# Runs
|
89
|
+
# Runs a given script
|
147
90
|
#
|
148
|
-
def
|
149
|
-
#
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
rescue Exception => exception
|
154
|
-
log_step(step, STATE_EXCEPTION)
|
155
|
-
print_exception(step, exception)
|
156
|
-
raise ScriptAborted.new
|
157
|
-
end
|
158
|
-
|
159
|
-
if result
|
160
|
-
log_step(step, STATE_OK)
|
161
|
-
else
|
162
|
-
log_step(step, STATE_FAILED)
|
163
|
-
raise ScriptAborted.new
|
164
|
-
end
|
165
|
-
end
|
91
|
+
def self.run(run_result, description, options = {})
|
92
|
+
# find script
|
93
|
+
script = scripts.find { |script| script.description == description }
|
94
|
+
raise CannotFindScriptError.new("Cannot find script #{description}") unless script
|
166
95
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
def log_step(step, state)
|
171
|
-
if state == STATE_FAILED || state == STATE_EXCEPTION
|
172
|
-
print(red(bold("✕ #{step.description}")))
|
173
|
-
self.class.write_log("✕ #{step.description}", false)
|
174
|
-
|
175
|
-
if state == STATE_EXCEPTION
|
176
|
-
print(" [EXCEPTION]")
|
177
|
-
print("\n\n")
|
178
|
-
self.class.write_log("[EXCEPTION]", false)
|
179
|
-
end
|
96
|
+
# output and run
|
97
|
+
if options.any?
|
98
|
+
vars = " (" + options.map { |k, v| "#{k}=#{v}" }.join(', ') + ")"
|
180
99
|
else
|
181
|
-
|
182
|
-
self.class.write_log("✓ #{step.description}", false)
|
100
|
+
vars = ""
|
183
101
|
end
|
184
|
-
end
|
185
102
|
|
186
|
-
|
187
|
-
|
188
|
-
#
|
189
|
-
def print_exception(current_step, exception)
|
190
|
-
# print backtrace
|
191
|
-
self.class.write_log("- #{exception.message}")
|
192
|
-
self.class.write_log(" #{exception.backtrace.join("\n ")}")
|
193
|
-
self.class.write_log("\n")
|
194
|
-
end
|
103
|
+
# print to screen what we are doing
|
104
|
+
puts(bold("Running #{description}#{vars}"))
|
195
105
|
|
196
|
-
|
197
|
-
|
198
|
-
#
|
199
|
-
def find_steps_instance_for(description)
|
200
|
-
@steps_instances.each do |instance|
|
201
|
-
if instance.class.steps && instance.class.steps.has_key?(description)
|
202
|
-
return instance
|
203
|
-
end
|
204
|
-
end
|
106
|
+
# also log to result logger
|
107
|
+
run_result.run_script("Running #{description}#{vars}")
|
205
108
|
|
206
|
-
|
207
|
-
|
109
|
+
# apply the context and run result
|
110
|
+
script.context = Context.new(options)
|
111
|
+
script.run_result = run_result
|
208
112
|
|
209
|
-
|
210
|
-
|
113
|
+
# run the entire script
|
114
|
+
script.run
|
211
115
|
end
|
212
116
|
|
213
|
-
class
|
214
|
-
|
117
|
+
class CannotFindScriptError < StandardError; end
|
215
118
|
end
|
216
119
|
end
|
data/lib/diddy/shared_scope.rb
CHANGED
data/lib/diddy/step.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Diddy
|
3
3
|
class Step
|
4
|
-
|
4
|
+
STATE_OK = 1
|
5
|
+
STATE_FAILED = 2
|
6
|
+
STATE_EXCEPTION = 3
|
7
|
+
STATE_PENDING = 4
|
8
|
+
|
9
|
+
attr_accessor :description, :definition, :steps_instance, :run_result
|
5
10
|
|
6
11
|
#
|
7
12
|
# Initializes step
|
@@ -14,7 +19,53 @@ module Diddy
|
|
14
19
|
# Runs the step
|
15
20
|
#
|
16
21
|
def run
|
17
|
-
|
22
|
+
# set the sub steps to 0
|
23
|
+
steps_instance.sub_steps = []
|
24
|
+
|
25
|
+
# write to screen
|
26
|
+
print(blue(". #{description}"))
|
27
|
+
|
28
|
+
# and to log
|
29
|
+
run_result.run_step(description)
|
30
|
+
|
31
|
+
# eval the step
|
32
|
+
steps_instance.current_step = self
|
33
|
+
|
34
|
+
# run the step itself
|
35
|
+
result = steps_instance.instance_eval(&definition)
|
36
|
+
|
37
|
+
# check if there were any sub steps
|
38
|
+
# if so, the result is dependent of those substeps
|
39
|
+
if steps_instance.sub_steps.size > 0
|
40
|
+
# check result of all sub_steps
|
41
|
+
result = steps_instance.sub_steps.all? { |step| step[:valid] }
|
42
|
+
|
43
|
+
# also log
|
44
|
+
steps_instance.sub_steps.each do |sub_step|
|
45
|
+
run_result.run_sub_step(sub_step[:description])
|
46
|
+
run_result.set_sub_step_result(sub_step[:valid])
|
47
|
+
end
|
48
|
+
|
49
|
+
# faulty
|
50
|
+
print("\n")
|
51
|
+
else
|
52
|
+
print("\r")
|
53
|
+
|
54
|
+
if result
|
55
|
+
print(green("✓ #{description}"))
|
56
|
+
else
|
57
|
+
print(red(bold("✕ #{description}")))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# log result of step
|
62
|
+
run_result.set_step_result(result)
|
63
|
+
|
64
|
+
# next line
|
65
|
+
print("\n")
|
66
|
+
|
67
|
+
# return the result
|
68
|
+
result
|
18
69
|
end
|
19
70
|
end
|
20
71
|
end
|
data/lib/diddy/steps.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
module Diddy
|
2
3
|
class Steps
|
3
4
|
include Helpers
|
4
5
|
|
6
|
+
attr_accessor :sub_steps, :current_step
|
7
|
+
|
5
8
|
def initialize(shared_scope)
|
6
9
|
@shared_scope = shared_scope
|
7
10
|
end
|
@@ -17,6 +20,20 @@ module Diddy
|
|
17
20
|
# Steps must return TRUE to keep the script running.
|
18
21
|
# When a step returns a FALSE, it will stop the script.
|
19
22
|
#
|
23
|
+
# It is also to use sub_steps (not to confuse with dubstep).
|
24
|
+
#
|
25
|
+
# step('Do something crazy') do
|
26
|
+
# sub_step('Eat brains') do
|
27
|
+
# a == true
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# sub_step('Go insane') do
|
31
|
+
# b == true
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# In the case above, every sub_step needs to return true.
|
36
|
+
#
|
20
37
|
def self.step(description, &block)
|
21
38
|
@steps ||= {}
|
22
39
|
@steps[description] = block
|
@@ -49,5 +66,29 @@ module Diddy
|
|
49
66
|
def shared
|
50
67
|
@shared_scope
|
51
68
|
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Adds a sub_step
|
72
|
+
#
|
73
|
+
def sub_step(description, &block)
|
74
|
+
# print pending to screen
|
75
|
+
print("\n")
|
76
|
+
print(blue(" . #{description}"))
|
77
|
+
|
78
|
+
# yield the block
|
79
|
+
valid = yield(block)
|
80
|
+
|
81
|
+
# jump back to beginning of line
|
82
|
+
print("\r")
|
83
|
+
|
84
|
+
# print out success or failure
|
85
|
+
if valid
|
86
|
+
print(green(" ✓ #{description}"))
|
87
|
+
else
|
88
|
+
print(red(bold(" ✕ #{description}")))
|
89
|
+
end
|
90
|
+
|
91
|
+
self.sub_steps << { description: description, valid: valid }
|
92
|
+
end
|
52
93
|
end
|
53
94
|
end
|
data/lib/diddy.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diddy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,10 +10,10 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-10-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name: term/
|
16
|
+
name: term/ansicolor
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
@@ -43,7 +43,11 @@ files:
|
|
43
43
|
- diddy-0.1.0.gem
|
44
44
|
- diddy.gemspec
|
45
45
|
- lib/diddy.rb
|
46
|
+
- lib/diddy/context.rb
|
46
47
|
- lib/diddy/helpers.rb
|
48
|
+
- lib/diddy/run_result.rb
|
49
|
+
- lib/diddy/run_result_printer.rb
|
50
|
+
- lib/diddy/scenario.rb
|
47
51
|
- lib/diddy/script.rb
|
48
52
|
- lib/diddy/shared_scope.rb
|
49
53
|
- lib/diddy/step.rb
|