specdown 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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