nukumber 0.4.1

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.
@@ -0,0 +1,19 @@
1
+ module Nukumber
2
+
3
+ module Reporter
4
+
5
+ class Mono < Colour
6
+
7
+ protected
8
+
9
+ def puts_colour_indent(text, *)
10
+ out = text
11
+ @indent.times { out = INDENT + out }
12
+ @outstream.puts out
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,237 @@
1
+ module Nukumber
2
+
3
+ class Runtime
4
+
5
+ def initialize(dirs, filenames, filters, reporter)
6
+
7
+ @reporter = reporter
8
+
9
+ builder = Nukumber::GherkinBuilder.new
10
+
11
+ if filters.empty?
12
+ filter_f = builder
13
+ else
14
+ filter_f = Gherkin::Formatter::FilterFormatter.new(builder, filters)
15
+ end
16
+ tag_f = Gherkin::Formatter::TagCountFormatter.new(filter_f, {})
17
+ parser = Gherkin::Parser::Parser.new(tag_f)
18
+
19
+ parse_feature_files(parser, dirs, filenames)
20
+ validate_features(builder.features)
21
+
22
+ $before_hooks = {}
23
+ $after_hooks = {}
24
+ old_methods = Object.private_methods
25
+
26
+ # Load all user-space Ruby files
27
+ Dir[Dir.pwd + "/#{dirs[:features]}/#{dirs[:support]}/env.rb"].each { |f| load f }
28
+ Dir[Dir.pwd + "/#{dirs[:features]}/#{dirs[:support]}/*.rb"].each { |f| load f }
29
+ Dir[Dir.pwd + "/#{dirs[:features]}/#{dirs[:definitions]}/*.rb"].each { |f| load f }
30
+
31
+ user_methods = Object.private_methods - old_methods
32
+
33
+ @expected_steps = []
34
+ @tests_passed = []
35
+ @tests_failed = []
36
+ @tests_pending = []
37
+ @tests_undefined = []
38
+
39
+ # Run all relevant features
40
+ builder.features.each { |feature| run_feature feature }
41
+
42
+ # Report
43
+ @reporter.final_report(@tests_passed, @tests_failed, @tests_pending, @tests_undefined)
44
+
45
+ # Provide code snippets as appropriate
46
+ @reporter.print_skeleton_code @tests_undefined unless @tests_undefined.empty?
47
+
48
+ @reporter.terminate
49
+
50
+ user_methods.each { |method_sym| Object.send(:remove_method, method_sym) }
51
+
52
+ end
53
+
54
+ def pass (step_name)
55
+ raise "Tried to pass without a step name" unless step_name.is_a? String
56
+ if @expected_steps.empty?
57
+ raise "Tried to pass unexpected step \"#{step_name}\" (expected test to be finished)"
58
+ elsif @expected_steps.first.name != step_name
59
+ raise "Tried to pass unexpected step \"#{step_name}\" (expected \"#{@expected_steps.first.name}\")"
60
+ else
61
+ @reporter.print_step(@expected_steps.first, :passed) unless @executing_element.is_a? Nukumber::Model::ScenarioOutline
62
+ @expected_steps.shift
63
+ end
64
+ end
65
+
66
+ def pending (*)
67
+ raise Nukumber::PendingTestError
68
+ end
69
+
70
+ def fail (err_msg = nil)
71
+ err_msg = ": #{err_msg}" unless err_msg.nil?
72
+ if @expected_steps.empty?
73
+ raise "Failed after all steps completed#{err_msg}"
74
+ else
75
+ raise "Failed step \"#{@expected_steps.first.name}\"#{err_msg}"
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def parse_feature_files(parser, dirs, filenames)
82
+ Dir[Dir.pwd + "/#{dirs[:features]}/*.feature"].each do |ff_path|
83
+ unless filenames.empty?
84
+ skip = false
85
+ filenames.each { |f| skip = true unless ff_path.include? f }
86
+ next if skip
87
+ end
88
+ $feature_file_path = ff_path # TODO: this global is crap
89
+ parser.parse(IO.read(ff_path), ff_path, 0)
90
+ end
91
+ end
92
+
93
+ def validate_features(features)
94
+ features.each do |f|
95
+ f.feature_elements.each do |e|
96
+ id = "#{e.name}, #{f.file_path}:#{e.line}"
97
+ if e.is_a? Nukumber::Model::ScenarioOutline and e.examples.nil?
98
+ raise Nukumber::SyntaxError, "Missing examples from element: #{id}"
99
+ end
100
+ if e.is_a? Nukumber::Model::ScenarioOutline and e.examples.table.rows.empty?
101
+ raise Nukumber::SyntaxError, "Example table from element has no rows: #{id}"
102
+ end
103
+ e.steps.each do |s|
104
+ if !s.args.empty? and s.args.rows.empty?
105
+ raise Nukumber::SyntaxError, "Arguments table in element has no rows: #{id}"
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def check_for_element_method(element)
113
+ raise Nukumber::UndefinedTestError unless respond_to?(element.shortsym, true) or respond_to?(element.longsym, true)
114
+ end
115
+
116
+ def run_feature(feature)
117
+ @reporter.begin_feature feature
118
+
119
+ all_elements = []
120
+ all_elements << feature.background unless feature.background.nil?
121
+ all_elements += feature.feature_elements
122
+
123
+ # find undefined tests
124
+ all_elements.each do |element|
125
+ begin
126
+ check_for_element_method(element)
127
+ rescue Nukumber::UndefinedTestError
128
+ @tests_undefined << element
129
+ end
130
+ end
131
+
132
+ # and attempt to run tests
133
+ @background_undefined = false
134
+ all_elements.each do |element|
135
+ begin
136
+ check_for_element_method element
137
+ @reporter.begin_element element
138
+ @executing_element = element
139
+ run_outline_element(element) if element.is_a? Nukumber::Model::ScenarioOutline
140
+ run_single_element(element) unless element.is_a? Nukumber::Model::ScenarioOutline
141
+ rescue Nukumber::UndefinedTestError
142
+ @reporter.undefined_element(element)
143
+ @background_undefined = true if element.is_a? Nukumber::Model::Background
144
+ next
145
+ rescue
146
+ return if element.is_a? Nukumber::Model::Background
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+ def run_single_element(element)
153
+ if element.is_a? Nukumber::Model::Background
154
+ elements_at_stake = element.feature.feature_elements
155
+ else
156
+ elements_at_stake = [element]
157
+ end
158
+ $example = nil
159
+ status = nil
160
+ begin
161
+ before_hooks(element)
162
+ execute_element(element)
163
+ @tests_passed << element unless element.is_a? Nukumber::Model::Background
164
+ status = :passed
165
+ rescue Nukumber::PendingTestError
166
+ @expected_steps.each { |s| @reporter.print_step(s, :pending) }
167
+ @tests_pending += elements_at_stake
168
+ status = :pending
169
+ raise RuntimeError if element.is_a? Nukumber::Model::Background
170
+ rescue => e
171
+ @reporter.print_step(@expected_steps.first, :failed) unless @expected_steps.empty?
172
+ @expected_steps.shift
173
+ @expected_steps.each { |s| @reporter.print_step(s, :pending) }
174
+ @reporter.error(e, element)
175
+ @tests_failed += elements_at_stake
176
+ status = :failed
177
+ raise RuntimeError if element.is_a? Nukumber::Model::Background
178
+ ensure
179
+ after_hooks(element, status)
180
+ end
181
+ end
182
+
183
+ def run_outline_element(element)
184
+ element.examples.table.rows.size.times do |i|
185
+ $example = element.examples.table.row_hash(i)
186
+ status = nil
187
+ begin
188
+ before_hooks(element)
189
+ execute_element(element)
190
+ @reporter.print_example(element.examples.table, i, :passed)
191
+ @tests_passed << element
192
+ status = :passed
193
+ rescue Nukumber::PendingTestError
194
+ @reporter.print_example(element.examples.table, i, :pending)
195
+ @tests_pending << element
196
+ status = :pending
197
+ rescue => e
198
+ @reporter.print_example(element.examples.table, i, :failed)
199
+ @reporter.error(e, element)
200
+ @tests_failed << element
201
+ status = :failed
202
+ ensure
203
+ after_hooks(element, status)
204
+ end
205
+ end
206
+ end
207
+
208
+ def before_hooks(element)
209
+ $before_hooks[:each].each { |p| self.instance_eval &p } if $before_hooks[:each]
210
+ element.tags.each do |t|
211
+ $before_hooks[t.to_sym].each { |p| self.instance_eval &p } if $before_hooks[t.to_sym]
212
+ end
213
+ end
214
+
215
+ def after_hooks(element, status)
216
+ element.tags.each do |t|
217
+ $after_hooks[t.to_sym].each { |p| instance_exec(element, status, &p) } if $after_hooks[t.to_sym]
218
+ end
219
+ $after_hooks[:each].each { |p| instance_exec(element, status, &p) } if $after_hooks[:each]
220
+ end
221
+
222
+ def execute_element(element)
223
+ @expected_steps = element.steps.clone
224
+ $args = element.step_args
225
+ raise Nukumber::PendingTestError if @background_undefined
226
+
227
+ send(element.shortsym) if respond_to?(element.shortsym, true)
228
+ send(element.longsym) if respond_to?(element.longsym, true)
229
+
230
+ unless @expected_steps.empty?
231
+ raise "Last #{@expected_steps.size > 1 ? "#{@expected_steps.size} steps" : 'step'} not passed"
232
+ end
233
+ end
234
+
235
+ end
236
+
237
+ end
@@ -0,0 +1,7 @@
1
+ module Nukumber
2
+ major = 0
3
+ minor = 4
4
+ release = 1
5
+
6
+ VERSION = "#{major}.#{minor}.#{release}"
7
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nukumber
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ibrahim Sha'ath
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gherkin
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.11.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.11.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.5'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.5'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ description: Specify your tests using Gherkin, but avoid the hassle of step definitions
63
+ email: nukumber@ibrahimshaath.co.uk
64
+ executables:
65
+ - nukumber
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/nukumber/builder.rb
70
+ - lib/nukumber/cli.rb
71
+ - lib/nukumber/errors.rb
72
+ - lib/nukumber/helpers.rb
73
+ - lib/nukumber/hooks.rb
74
+ - lib/nukumber/model/background.rb
75
+ - lib/nukumber/model/examples.rb
76
+ - lib/nukumber/model/feature.rb
77
+ - lib/nukumber/model/feature_element.rb
78
+ - lib/nukumber/model/scenario.rb
79
+ - lib/nukumber/model/scenario_outline.rb
80
+ - lib/nukumber/model/step.rb
81
+ - lib/nukumber/model/table.rb
82
+ - lib/nukumber/model.rb
83
+ - lib/nukumber/reporter/colour.rb
84
+ - lib/nukumber/reporter/html.rb
85
+ - lib/nukumber/reporter/html_css.rb
86
+ - lib/nukumber/reporter/mono.rb
87
+ - lib/nukumber/reporter.rb
88
+ - lib/nukumber/runtime.rb
89
+ - lib/nukumber/version.rb
90
+ - lib/nukumber.rb
91
+ - bin/nukumber
92
+ homepage: https://github.com/ibsh/nukumber
93
+ licenses: []
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 1.8.24
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: Run Gherkin feature files a bit more simply
116
+ test_files: []
117
+ has_rdoc: