specdown 0.1.1 → 0.1.2

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.
Files changed (29) hide show
  1. data/CHANGELOG.markdown +4 -0
  2. data/README.markdown +40 -2
  3. data/bin/specdown +2 -2
  4. data/features/hooks.feature +125 -0
  5. data/features/specdown_examples/after_hooks/specdown/env.rb +1 -0
  6. data/features/specdown_examples/after_hooks/specdown/hooks.rb +3 -0
  7. data/features/specdown_examples/after_hooks/specdown/parser_example.markdown +21 -0
  8. data/features/specdown_examples/around_hooks/specdown/env.rb +1 -0
  9. data/features/specdown_examples/around_hooks/specdown/hooks.rb +3 -0
  10. data/features/specdown_examples/around_hooks/specdown/parser_example.markdown +9 -0
  11. data/features/specdown_examples/before_hooks/specdown/env.rb +1 -0
  12. data/features/specdown_examples/before_hooks/specdown/hooks.rb +3 -0
  13. data/features/specdown_examples/before_hooks/specdown/parser_example.markdown +22 -0
  14. data/features/specdown_examples/scoped_hooks/specdown/env.rb +1 -0
  15. data/features/specdown_examples/scoped_hooks/specdown/hooks.rb +11 -0
  16. data/features/specdown_examples/scoped_hooks/specdown/parser_example.markdown +21 -0
  17. data/features/specdown_examples/scoped_hooks/specdown/spec1.fun.markdown +9 -0
  18. data/features/specdown_examples/scoped_hooks/specdown/spec2.fun.markdown +10 -0
  19. data/features/specdown_examples/scoped_hooks/specdown/spec3.markdown +10 -0
  20. data/features/step_definitions/hooks.rb +35 -0
  21. data/features/support/hooks.rb +1 -1
  22. data/lib/specdown.rb +4 -0
  23. data/lib/specdown/event_handlers/after_test.rb +4 -0
  24. data/lib/specdown/event_handlers/before_test.rb +4 -0
  25. data/lib/specdown/hook.rb +20 -0
  26. data/lib/specdown/hooks.rb +40 -0
  27. data/lib/specdown/runner.rb +6 -4
  28. data/lib/specdown/specdown.rb +17 -0
  29. metadata +41 -3
data/CHANGELOG.markdown CHANGED
@@ -1,5 +1,9 @@
1
1
  ## CHANGELOG
2
2
 
3
+ ## 0.1.2
4
+
5
+ New feature added: test hooks. (see the README)
6
+
3
7
  ## 0.1.1 (2012/01/02)
4
8
 
5
9
  Bug fix: better report formatting for multi-markdown test suites.
data/README.markdown CHANGED
@@ -160,12 +160,50 @@ Specdown::Config.expectations = :test_unit
160
160
 
161
161
  You can now use [Test::Unit::Assertions](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/test/unit/rdoc/Test/Unit/Assertions.html) inside your tests.
162
162
 
163
+ ## Test hooks (before/after/around)
164
+
165
+ You can create test hooks that run before, after, and around tests. You can create global hooks, or hooks that run only for specific specdown files.
166
+
167
+ ### Global hooks
168
+
169
+ To create a global before hook, use the `Specdown.before` method:
170
+
171
+ Specdown.before do
172
+ puts "I run before every single test!"
173
+ end
174
+
175
+ That before hook will - you guessed it - RUN BEFORE EVERY SINGLE TEST.
176
+
177
+ Similary, you can run some code after every single test via the `Specdown.after` method:
178
+
179
+ Specdown.after do
180
+ puts "I run after every single test!"
181
+ end
182
+
183
+ Whenever you need some code to run before _and_ after every single test, use the `Specdown.around` method:
184
+
185
+ Specdown.around do
186
+ puts "I run before _AND_ after every single test!"
187
+ end
188
+
189
+ ### Scoping your hooks to specific markdown files
190
+
191
+ You might, at times, want hooks to run only for certain files.
192
+
193
+ You can pass filenames (or regular expressions) to the `Specdown.before`, `Specdown.after`, and `Specdown.around` methods. The hooks will then execute whenever you execute any markdown file with matching filenames.
194
+
195
+ Specdown.before "somefile.markdown", /^.*\.database.markdown$/ do
196
+ puts "This runs before every test within 'somefile.markdown', and
197
+ before every test in any markdown file whose filename ends
198
+ with '.database.markdown'"
199
+ end
200
+
201
+
163
202
  ## TODO
164
203
 
165
204
  This library is the result of just a couple of days worth of work. It's a basic minimum viable product, but there are tons of features I want to implement. Here's what's on my immediate horizon:
166
205
 
167
- * Better stack traces / reporting
168
- * Test hooks (before/after/around)
169
206
  * Run a single test
170
207
  * color code the terminal output
171
208
  * offer the option of outputing the actual markdown while it executes, instead of "..F....FF......"
209
+ * Better stack traces / reporting
data/bin/specdown CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'specdown'
3
3
 
4
- Dir["specdown/**/*.rb"].each do |ruby_file|
5
- require ruby_file
4
+ Dir["./specdown/**/*.rb"].each do |ruby_file|
5
+ load ruby_file
6
6
  end
7
7
 
8
8
  Specdown::Command.new.execute
@@ -0,0 +1,125 @@
1
+ Feature: Specdown test hooks
2
+
3
+ You can create test hooks that run before, after, and around tests. You can create global hooks, or hooks that run only for specific specdown files.
4
+
5
+ \## Global hooks
6
+
7
+ To create a global before hook, use the `Specdown.before` method:
8
+
9
+ Specdown.before do
10
+ puts "I run before every single test!"
11
+ end
12
+
13
+ That before hook will - you guessed it - RUN BEFORE EVERY SINGLE TEST.
14
+
15
+ Similary, you can run some code after every single test via the `Specdown.after` method:
16
+
17
+ Specdown.after do
18
+ puts "I run after every single test!"
19
+ end
20
+
21
+ Whenever you need some code to run before _and_ after every single test, use the `Specdown.around` method:
22
+
23
+ Specdown.around do
24
+ puts "I run before _AND_ after every single test!"
25
+ end
26
+
27
+ \### Scoping your hooks to specific markdown files
28
+
29
+ You might, at times, want hooks to run only for certain files.
30
+
31
+ You can pass filenames (or regular expressions) to the `Specdown.before`, `Specdown.after`, and `Specdown.around` methods. The hooks will then execute whenever you execute any markdown file with matching filenames.
32
+
33
+ Specdown.before "somefile.markdown", /^.*\.database.markdown$/ do
34
+ puts "This runs before every test within 'somefile.markdown', and
35
+ before every test in any markdown file whose filename ends
36
+ with '.database.markdown'"
37
+ end
38
+
39
+ Scenario: Before hook
40
+
41
+ Given a specdown directory with a markdown file with TWO tests
42
+ And an environment file with the following before hook:
43
+ """
44
+ Specdown.before do
45
+ puts "I run before every test!"
46
+ end
47
+ """
48
+
49
+ When I run the specdown command for that directory
50
+
51
+ Then I should see the following output 2 times:
52
+ """
53
+ I run before every test!
54
+ """
55
+
56
+
57
+ Scenario: After hook
58
+
59
+ Given a specdown directory with a markdown file with THREE tests
60
+ And an environment file with the following after hook:
61
+ """
62
+ Specdown.after do
63
+ puts "I run after every test!"
64
+ end
65
+ """
66
+
67
+ When I run the specdown command for that directory
68
+
69
+ Then I should see the following output 3 times:
70
+ """
71
+ I run after every test!
72
+ """
73
+
74
+
75
+ Scenario: Around hook
76
+
77
+ Given a specdown directory with a markdown file with ONE test
78
+ And an environment file with the following around hook:
79
+ """
80
+ Specdown.around do
81
+ puts "I run before and after every test!"
82
+ end
83
+ """
84
+
85
+ When I run the specdown command for that directory
86
+
87
+ Then I should see the following output 2 times:
88
+ """
89
+ I run before and after every test!
90
+ """
91
+
92
+ @focus
93
+ Scenario: Scoped hooks
94
+ Given a specdown directory containing markdown files named "spec1.fun.markdown", "spec2.fun.markdown", and "spec3.markdown" each containing a single test
95
+ And an environment file with the following hooks:
96
+ """
97
+ Specdown.around /fun/ do
98
+ puts "I run before and after fun tests."
99
+ end
100
+
101
+ Specdown.before "spec3.markdown" do
102
+ puts "I run before tests in spec3"
103
+ end
104
+
105
+ Specdown.after "spec1.markdown", /spec3/ do
106
+ puts "I run after tests in spec1 and spec3."
107
+ end
108
+ """
109
+
110
+ When I run the specdown command for that directory
111
+
112
+ Then I should see the following output 4 times:
113
+ """
114
+ I run before and after fun tests.
115
+ """
116
+
117
+ And I should see the following output 1 time:
118
+ """
119
+ I run before tests in spec3
120
+ """
121
+
122
+ And I should see the following output 2 times:
123
+ """
124
+ I run after tests in spec1 and spec3
125
+ """
@@ -0,0 +1 @@
1
+ Specdown::Config.expectations = :rspec
@@ -0,0 +1,3 @@
1
+ Specdown.after do
2
+ puts "I run after every test!"
3
+ end
@@ -0,0 +1,21 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
10
+
11
+ ## First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should satisfy(&:odd?)
@@ -0,0 +1 @@
1
+ Specdown::Config.expectations = :rspec
@@ -0,0 +1,3 @@
1
+ Specdown.around do
2
+ puts "I run before and after every test!"
3
+ end
@@ -0,0 +1,9 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
@@ -0,0 +1 @@
1
+ Specdown::Config.expectations = :rspec
@@ -0,0 +1,3 @@
1
+ Specdown.before do
2
+ puts "I run before every test!"
3
+ end
@@ -0,0 +1,22 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
10
+
11
+ ### First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should satisfy(&:odd?)
22
+
@@ -0,0 +1 @@
1
+ Specdown::Config.expectations = :rspec
@@ -0,0 +1,11 @@
1
+ Specdown.around /fun/ do
2
+ puts "I run before and after fun tests."
3
+ end
4
+
5
+ Specdown.before "spec3.markdown" do
6
+ puts "I run before tests in spec3"
7
+ end
8
+
9
+ Specdown.after "spec1.fun.markdown", /spec3/ do
10
+ puts "I run after tests in spec1 and spec3."
11
+ end
@@ -0,0 +1,21 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
10
+
11
+ ## First Leaf
12
+
13
+ This section has a failure simulation:
14
+
15
+ raise "specdown error simulation!"
16
+
17
+ ## Last Leaf
18
+
19
+ This section is a leaf node. It contains some ruby code:
20
+
21
+ 1.should satisfy(&:odd?)
@@ -0,0 +1,9 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
@@ -0,0 +1,10 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
10
+
@@ -0,0 +1,10 @@
1
+ # Specdown Example
2
+
3
+ This is an example specdown file.
4
+
5
+ ## Child Node
6
+
7
+ This section is a child node. It contains some ruby code:
8
+
9
+ "simple code".should_not be(nil)
10
+
@@ -0,0 +1,35 @@
1
+ Given /^a specdown directory with a markdown file with TWO tests$/ do
2
+ end
3
+
4
+ Given /^an environment file with the following before hook:$/ do |string|
5
+ @directory = "features/specdown_examples/before_hooks"
6
+ end
7
+
8
+ When /^I run the specdown command for that directory$/ do
9
+ @output = `cd #{@directory} && bundle exec ruby -I ../../../lib ../../../bin/specdown`
10
+ end
11
+
12
+ Then /^I should see the following output (\d+) times?:$/ do |n, string|
13
+ @output.split("\n").select {|line| line.strip =~ /#{string.strip}/}.count.should == n.to_i
14
+ end
15
+
16
+ Given /^a specdown directory with a markdown file with THREE tests$/ do
17
+ end
18
+
19
+ Given /^an environment file with the following after hook:$/ do |string|
20
+ @directory = "features/specdown_examples/after_hooks"
21
+ end
22
+
23
+ Given /^a specdown directory with a markdown file with ONE test$/ do
24
+ end
25
+
26
+ Given /^an environment file with the following around hook:$/ do |string|
27
+ @directory = "features/specdown_examples/around_hooks"
28
+ end
29
+
30
+ Given /^a specdown directory containing markdown files named ".*" each containing a single test$/ do
31
+ @directory = "features/specdown_examples/scoped_hooks"
32
+ end
33
+
34
+ Given /^an environment file with the following hooks:$/ do |string|
35
+ end
@@ -1,3 +1,3 @@
1
1
  Before do
2
- Specdown::Config.reset!
2
+ Specdown.reset!
3
3
  end
data/lib/specdown.rb CHANGED
@@ -7,6 +7,8 @@ require 'specdown/runner/report'
7
7
  require 'specdown/runner/stats'
8
8
  require 'specdown/command'
9
9
  require 'specdown/event_server'
10
+ require 'specdown/event_handlers/before_test'
11
+ require 'specdown/event_handlers/after_test'
10
12
  require 'specdown/event_handlers/command_complete'
11
13
  require 'specdown/event_handlers/run_complete'
12
14
  require 'specdown/event_handlers/run_started'
@@ -15,3 +17,5 @@ require 'specdown/event_handlers/test_passed'
15
17
  require 'specdown/config'
16
18
  require 'specdown/specdown'
17
19
  require 'specdown/sandbox_factory'
20
+ require 'specdown/hooks'
21
+ require 'specdown/hook'
@@ -0,0 +1,4 @@
1
+ Specdown::EventServer.register :after_test do |runner|
2
+ Specdown::Hooks.matching_after_hooks(runner.file_name).map &:call
3
+ Specdown::Hooks.matching_around_hooks(runner.file_name).map &:call
4
+ end
@@ -0,0 +1,4 @@
1
+ Specdown::EventServer.register :before_test do |runner|
2
+ Specdown::Hooks.matching_before_hooks(runner.file_name).map &:call
3
+ Specdown::Hooks.matching_around_hooks(runner.file_name).map &:call
4
+ end
@@ -0,0 +1,20 @@
1
+ module Specdown
2
+ class Hook
3
+ def initialize(*filters, &callback)
4
+ @filters = filters
5
+ @callback = callback
6
+ end
7
+
8
+ def matches?(filename)
9
+ return true if @filters.empty?
10
+
11
+ @filters.any? do |filter|
12
+ filter == filename || filter.match(filename)
13
+ end
14
+ end
15
+
16
+ def call
17
+ @callback.call
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ module Specdown
2
+ module Hooks
3
+ extend self
4
+
5
+ def reset!
6
+ @before = []
7
+ @after = []
8
+ @around = []
9
+ end
10
+
11
+ def matching_before_hooks(filename)
12
+ filter before, filename
13
+ end
14
+
15
+ def matching_after_hooks(filename)
16
+ filter after, filename
17
+ end
18
+
19
+ def matching_around_hooks(filename)
20
+ filter around, filename
21
+ end
22
+
23
+ def before
24
+ @before ||= []
25
+ end
26
+
27
+ def after
28
+ @after ||= []
29
+ end
30
+
31
+ def around
32
+ @around ||= []
33
+ end
34
+
35
+ private
36
+ def filter(hooks, filename)
37
+ hooks.select {|hook| hook.matches? filename}
38
+ end
39
+ end
40
+ end
@@ -13,15 +13,18 @@ module Specdown
13
13
  end
14
14
 
15
15
  def run
16
+ EventServer.event :run_starting, self
16
17
  depth_first_search @tree.root
17
- EventServer.event :run_complete
18
+ EventServer.event :run_complete, self
18
19
  self
19
20
  end
20
21
 
21
22
  private
22
23
  def depth_first_search(node, code=[])
23
24
  if node.children.empty?
25
+ EventServer.event :before_test, self
24
26
  execute_test(code + [node.code])
27
+ EventServer.event :after_test, self
25
28
  else
26
29
  node.children.each do |child|
27
30
  depth_first_search(child, (code + [node.code]))
@@ -37,13 +40,12 @@ module Specdown
37
40
  #{code.join("\n")}
38
41
  CODE
39
42
 
40
- EventServer.event :test_passed
43
+ EventServer.event :test_passed, self
41
44
 
42
45
  rescue Exception => e
43
46
  @stats.exceptions << e
44
47
 
45
- EventServer.event :test_failed
46
-
48
+ EventServer.event :test_failed, self
47
49
  end
48
50
  end
49
51
  end
@@ -1,7 +1,24 @@
1
1
  module Specdown
2
2
  extend self
3
3
 
4
+ def reset!
5
+ Config.reset!
6
+ Hooks.reset!
7
+ end
8
+
4
9
  def sandbox
5
10
  SandboxFactory.generate
6
11
  end
12
+
13
+ def before(*filters, &callback)
14
+ Hooks.before << Hook.new(*filters, &callback)
15
+ end
16
+
17
+ def after(*filters, &callback)
18
+ Hooks.after << Hook.new(*filters, &callback)
19
+ end
20
+
21
+ def around(*filters, &callback)
22
+ Hooks.around << Hook.new(*filters, &callback)
23
+ end
7
24
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specdown
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Parker
@@ -73,12 +73,16 @@ extra_rdoc_files:
73
73
  files:
74
74
  - lib/specdown/command.rb
75
75
  - lib/specdown/config.rb
76
+ - lib/specdown/event_handlers/after_test.rb
77
+ - lib/specdown/event_handlers/before_test.rb
76
78
  - lib/specdown/event_handlers/command_complete.rb
77
79
  - lib/specdown/event_handlers/run_complete.rb
78
80
  - lib/specdown/event_handlers/run_started.rb
79
81
  - lib/specdown/event_handlers/test_failed.rb
80
82
  - lib/specdown/event_handlers/test_passed.rb
81
83
  - lib/specdown/event_server.rb
84
+ - lib/specdown/hook.rb
85
+ - lib/specdown/hooks.rb
82
86
  - lib/specdown/node.rb
83
87
  - lib/specdown/parser.rb
84
88
  - lib/specdown/runner/report.rb
@@ -95,15 +99,32 @@ files:
95
99
  - features/config.feature
96
100
  - features/event_server.feature
97
101
  - features/fixtures/parser_example.markdown
102
+ - features/hooks.feature
98
103
  - features/parser.feature
99
104
  - features/report.feature
100
105
  - features/runner.feature
106
+ - features/specdown_examples/after_hooks/specdown/env.rb
107
+ - features/specdown_examples/after_hooks/specdown/hooks.rb
108
+ - features/specdown_examples/after_hooks/specdown/parser_example.markdown
109
+ - features/specdown_examples/around_hooks/specdown/env.rb
110
+ - features/specdown_examples/around_hooks/specdown/hooks.rb
111
+ - features/specdown_examples/around_hooks/specdown/parser_example.markdown
112
+ - features/specdown_examples/before_hooks/specdown/env.rb
113
+ - features/specdown_examples/before_hooks/specdown/hooks.rb
114
+ - features/specdown_examples/before_hooks/specdown/parser_example.markdown
101
115
  - features/specdown_examples/no_ruby/specdown/parser_example.markdown
116
+ - features/specdown_examples/scoped_hooks/specdown/env.rb
117
+ - features/specdown_examples/scoped_hooks/specdown/hooks.rb
118
+ - features/specdown_examples/scoped_hooks/specdown/parser_example.markdown
119
+ - features/specdown_examples/scoped_hooks/specdown/spec1.fun.markdown
120
+ - features/specdown_examples/scoped_hooks/specdown/spec2.fun.markdown
121
+ - features/specdown_examples/scoped_hooks/specdown/spec3.markdown
102
122
  - features/specdown_examples/with_ruby/specdown/env.rb
103
123
  - features/specdown_examples/with_ruby/specdown/parser_example.markdown
104
124
  - features/step_definitions/command.rb
105
125
  - features/step_definitions/config.rb
106
126
  - features/step_definitions/event_server.rb
127
+ - features/step_definitions/hooks.rb
107
128
  - features/step_definitions/parser.rb
108
129
  - features/step_definitions/report.rb
109
130
  - features/step_definitions/runner.rb
@@ -147,15 +168,32 @@ test_files:
147
168
  - features/config.feature
148
169
  - features/event_server.feature
149
170
  - features/fixtures/parser_example.markdown
171
+ - features/hooks.feature
150
172
  - features/parser.feature
151
173
  - features/report.feature
152
174
  - features/runner.feature
175
+ - features/specdown_examples/after_hooks/specdown/env.rb
176
+ - features/specdown_examples/after_hooks/specdown/hooks.rb
177
+ - features/specdown_examples/after_hooks/specdown/parser_example.markdown
178
+ - features/specdown_examples/around_hooks/specdown/env.rb
179
+ - features/specdown_examples/around_hooks/specdown/hooks.rb
180
+ - features/specdown_examples/around_hooks/specdown/parser_example.markdown
181
+ - features/specdown_examples/before_hooks/specdown/env.rb
182
+ - features/specdown_examples/before_hooks/specdown/hooks.rb
183
+ - features/specdown_examples/before_hooks/specdown/parser_example.markdown
153
184
  - features/specdown_examples/no_ruby/specdown/parser_example.markdown
185
+ - features/specdown_examples/scoped_hooks/specdown/env.rb
186
+ - features/specdown_examples/scoped_hooks/specdown/hooks.rb
187
+ - features/specdown_examples/scoped_hooks/specdown/parser_example.markdown
188
+ - features/specdown_examples/scoped_hooks/specdown/spec1.fun.markdown
189
+ - features/specdown_examples/scoped_hooks/specdown/spec2.fun.markdown
190
+ - features/specdown_examples/scoped_hooks/specdown/spec3.markdown
154
191
  - features/specdown_examples/with_ruby/specdown/env.rb
155
192
  - features/specdown_examples/with_ruby/specdown/parser_example.markdown
156
193
  - features/step_definitions/command.rb
157
194
  - features/step_definitions/config.rb
158
195
  - features/step_definitions/event_server.rb
196
+ - features/step_definitions/hooks.rb
159
197
  - features/step_definitions/parser.rb
160
198
  - features/step_definitions/report.rb
161
199
  - features/step_definitions/runner.rb