specdown 0.4.0.beta.1 → 0.4.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG.markdown +4 -0
  2. data/README.markdown +4 -10
  3. data/VERSION +1 -1
  4. data/features/exception_facade.feature +8 -8
  5. data/features/readme.feature +97 -0
  6. data/features/report_summary.feature +13 -13
  7. data/features/step_definitions/exception_facade.rb +1 -1
  8. data/features/step_definitions/{runner.rb → readme.rb} +2 -2
  9. data/features/step_definitions/report_summary.rb +1 -1
  10. data/features/step_definitions/reporter.rb +3 -3
  11. data/features/step_definitions/test.rb +129 -0
  12. data/features/test.feature +131 -0
  13. data/lib/specdown.rb +9 -15
  14. data/lib/specdown/command.rb +16 -11
  15. data/lib/specdown/event_handlers/command.rb +4 -0
  16. data/lib/specdown/event_handlers/readme.rb +7 -0
  17. data/lib/specdown/event_handlers/test.rb +8 -0
  18. data/lib/specdown/readme.rb +58 -0
  19. data/lib/specdown/{runner → readme}/exception_facade.rb +3 -3
  20. data/lib/specdown/readme/report_summary.rb +37 -0
  21. data/lib/specdown/readme/stats.rb +29 -0
  22. data/lib/specdown/reporter.rb +6 -6
  23. data/lib/specdown/reporters/color_terminal_reporter.rb +2 -2
  24. data/lib/specdown/reporters/terminal_reporter.rb +6 -6
  25. data/lib/specdown/reporters/text_reporter.rb +5 -5
  26. data/lib/specdown/specdown.rb +15 -4
  27. data/lib/specdown/templates/color_summary.erb +9 -11
  28. data/lib/specdown/templates/summary.erb +8 -10
  29. data/lib/specdown/test.rb +37 -0
  30. data/lib/specdown/tree.rb +0 -3
  31. metadata +40 -27
  32. data/features/runner.feature +0 -99
  33. data/lib/specdown/event_handlers/after_test.rb +0 -4
  34. data/lib/specdown/event_handlers/before_test.rb +0 -4
  35. data/lib/specdown/event_handlers/command_complete.rb +0 -4
  36. data/lib/specdown/event_handlers/run_complete.rb +0 -3
  37. data/lib/specdown/event_handlers/run_started.rb +0 -3
  38. data/lib/specdown/event_handlers/test_failed.rb +0 -3
  39. data/lib/specdown/event_handlers/test_passed.rb +0 -3
  40. data/lib/specdown/event_handlers/test_pending.rb +0 -3
  41. data/lib/specdown/event_handlers/test_undefined.rb +0 -3
  42. data/lib/specdown/hook.rb +0 -20
  43. data/lib/specdown/hooks.rb +0 -40
  44. data/lib/specdown/runner.rb +0 -61
  45. data/lib/specdown/runner/report_summary.rb +0 -37
  46. data/lib/specdown/runner/stats.rb +0 -31
data/CHANGELOG.markdown CHANGED
@@ -1,5 +1,9 @@
1
1
  ## CHANGELOG
2
2
 
3
+ ## 0.4.0.beta.2
4
+
5
+ Refactoring everything. Hopefully it all works.
6
+
3
7
  ## 0.4.0.beta.1
4
8
 
5
9
  First beta release with implicit specs support. See the "Implicit Specs"
data/README.markdown CHANGED
@@ -210,6 +210,8 @@ executed, then just don't specifically flag it as Ruby:
210
210
 
211
211
  ## Implicit Specs
212
212
 
213
+ **Note: This feature requires version 0.4.0.beta.1 or greater.**
214
+
213
215
  In all of the examples so far, we've made all code that we want executed
214
216
  explicit within the markdown. Sometimes, however, it's advantageous to
215
217
  simply state a specification, and then map that to code
@@ -267,9 +269,9 @@ The article should now be deleted from the database.
267
269
  ```
268
270
 
269
271
  The ".specdown" file is simply a markdown file with a different
270
- extension. It should consist of an unordered list of spec / definition pairs.
272
+ extension. It should consist simply of headings (of any level) and code blocks. Any other elements within the file will simply be ignore by `specdown`. This allows you to organize the file and add extra comments into it in any way you desire.
271
273
 
272
- Note that we didn't surround our code with a github-flavored backtick
274
+ Also, Note that we didn't surround our code with a github-flavored backtick
273
275
  fence. Since ".specdown" files are solely used for defining implicit
274
276
  specifications, it's assumed that all code blocks (unless they're
275
277
  spefically marked as something other than ruby) will be executed.
@@ -418,14 +420,6 @@ Specdown::Config.format = :short
418
420
 
419
421
  The default is `:condensed`.
420
422
 
421
- ## TODO
422
-
423
- This library is quite new, but I am rapidly adding features to it. Here's what is on the immediate horizon:
424
-
425
- * allow flagged text in the markdown to execute code, like a cucumber step definition
426
- * offer the option of outputing the actual markdown while it executes, instead of "..F....FF......"
427
- * Better stack traces / reporting
428
-
429
423
  ## LICENSE
430
424
 
431
425
  This software is [public domain](http://en.wikipedia.org/wiki/Public_domain). GO WILD
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0.beta.1
1
+ 0.4.0.beta.2
@@ -6,14 +6,14 @@ Feature: Specdown::ExceptionFacade
6
6
 
7
7
  exception = Exception.new "exception simulation"
8
8
 
9
- And given the following fake test_runner:
9
+ And given the following fake test readme:
10
10
 
11
- runner = Class.new { attr_accessor :file_name }.new
12
- runner.file_name = "test_file.markdown"
11
+ readme = Class.new { attr_accessor :file_name }.new
12
+ readme.file_name = "test_file.markdown"
13
13
 
14
14
  We can now generate an exception facade:
15
15
 
16
- exception_facade = Specdown::ExceptionFacade.new exception, runner
16
+ exception_facade = Specdown::ExceptionFacade.new exception, readme
17
17
 
18
18
  exception_facade.test_filename.should == "test_file.markdown"
19
19
  exception_facade.exception_class.should == Exception
@@ -26,15 +26,15 @@ Feature: Specdown::ExceptionFacade
26
26
  @exception = Exception.new "exception simulation"
27
27
  """
28
28
 
29
- And the following fake runner:
29
+ And the following fake readme:
30
30
  """
31
- @runner = Class.new { attr_accessor :file_name }.new
32
- @runner.file_name = "test_file.markdown"
31
+ @readme = Class.new { attr_accessor :file_name }.new
32
+ @readme.file_name = "test_file.markdown"
33
33
  """
34
34
 
35
35
  When I generate an exception facade:
36
36
  """
37
- @exception_facade = Specdown::ExceptionFacade.new @exception, @runner
37
+ @exception_facade = Specdown::ExceptionFacade.new @exception, @readme
38
38
  """
39
39
 
40
40
  Then it should return all kinds of information about the exception and it's context:
@@ -0,0 +1,97 @@
1
+ Feature: Specdown::Readme
2
+
3
+ The `Specdown::Readme` class accepts a markdown parse tree, and runs the tests found within.
4
+
5
+ Imagine we start with this markdown file (saved at "specdown.markdown"):
6
+
7
+ \# Specdown Example
8
+
9
+ This is an example specdown file.
10
+
11
+ \## Child Node
12
+
13
+ This section is a child node. It contains some ruby code:
14
+
15
+ ```ruby
16
+ "simple code".should_not be(nil)
17
+ ```
18
+
19
+ \### First Leaf
20
+
21
+ This section has a failure simulation:
22
+
23
+ ```ruby
24
+ raise "specdown error simulation!"
25
+ ```
26
+
27
+ \## Last Leaf
28
+
29
+ This section is a leaf node. It contains some ruby code:
30
+
31
+ ```ruby
32
+ 1.should satisfy(&:odd?)
33
+ ```
34
+
35
+ We can generate a `Specdown::Readme` instance and run the tests in our markdown by simply passing the filename on instantiation:
36
+
37
+ readme = Specdown::Readme.new "specdown.markdown"
38
+ readme.run
39
+
40
+ While running, it will emit events during the processing to the Specdown::EventServer. This enables all kinds of functionality, like printing the progress of the tests.
41
+
42
+ We can access statistics about the readme execution programatically:
43
+
44
+ readme.stats.num_tests #==> 2
45
+ readme.stats.num_failing #==> 1
46
+ readme.stats.num_passing #==> 1
47
+
48
+ Scenario: Running tests
49
+
50
+ Given the following specdown example file:
51
+ """
52
+ # Specdown Example
53
+
54
+ This is an example specdown file.
55
+
56
+ ## Child Node
57
+
58
+ This section is a child node. It contains some ruby code:
59
+
60
+ ```ruby
61
+ "simple code".should_not be(nil)
62
+ ```
63
+
64
+ ### First Leaf
65
+
66
+ This section has a failure simulation:
67
+
68
+ ```ruby
69
+ raise "specdown error simulation!"
70
+ ```
71
+
72
+ ## Last Leaf
73
+
74
+ This section is a leaf node. It contains some ruby code:
75
+
76
+ ```ruby
77
+ 1.should satisfy(&:odd?)
78
+ ```
79
+ """
80
+
81
+ When I generate a `Specdown::Readme` instance from it:
82
+ """
83
+ @readme = Specdown::Readme.new "features/fixtures/parser_example.markdown"
84
+ """
85
+
86
+ Then I should be able to execute the tests:
87
+ """
88
+ @readme.execute
89
+ """
90
+
91
+ And I should be able to access the report data programatically:
92
+ """
93
+ @readme.file_name.should == 'parser_example.markdown'
94
+ @readme.stats.num_tests.should == 2
95
+ @readme.stats.num_failing.should == 1
96
+ @readme.stats.num_passing.should == 1
97
+ """
@@ -1,14 +1,14 @@
1
1
  Feature: Specdown::ReportSummary
2
2
 
3
- A `Specdown::ReportSummary` will provide you with aggregate statistical information about your test suite runners.
3
+ A `Specdown::ReportSummary` will provide you with aggregate statistical information about your readmes.
4
4
 
5
- For example, suppose you have several runners that you've executed. You could pass one or more of them off to a `Specdown::ReportSummary` to obtain the aggregate totals:
5
+ For example, suppose you have several readmes that you've executed. You could pass one or more of them off to a `Specdown::ReportSummary` to obtain the aggregate totals:
6
6
 
7
- summary = Specdown::ReportSummary.new(runners)
7
+ summary = Specdown::ReportSummary.new(readmes)
8
8
  summary.num_markdowns
9
9
  summary.num_tests
10
- summary.num_failures
11
- summary.num_successes
10
+ summary.num_failing
11
+ summary.num_passing
12
12
 
13
13
  Scenario: A Specdown::Reporter instantiated with a single stats object
14
14
 
@@ -43,23 +43,23 @@ Feature: Specdown::ReportSummary
43
43
  ```
44
44
  """
45
45
 
46
- And the following runner:
46
+ And the following readme:
47
47
  """
48
- @runner = Specdown::Runner.new("features/fixtures/parser_example.markdown")
48
+ @readme = Specdown::Readme.new("features/fixtures/parser_example.markdown")
49
49
  """
50
50
 
51
- When I run the tests in the runner:
51
+ When I run the tests in the readme:
52
52
  """
53
- @runner.run
53
+ @readme.execute
54
54
  """
55
55
 
56
- Then `Specdown::ReportSummary.new(@runner)` should give me aggregate statistics about my run:
56
+ Then `Specdown::ReportSummary.new(@readme)` should give me aggregate statistics about my readme execution:
57
57
  """
58
- summary = Specdown::ReportSummary.new(@runner)
58
+ summary = Specdown::ReportSummary.new(@readme)
59
59
  summary.num_markdowns.should == 1
60
60
  summary.num_tests.should == 2
61
- summary.num_failures.should == 1
62
- summary.num_successes.should == 1
61
+ summary.num_failing.should == 1
62
+ summary.num_passing.should == 1
63
63
  summary.exceptions.count.should == 1
64
64
  summary.exceptions.first.test_filename.should == "parser_example.markdown"
65
65
  summary.exceptions.first.exception_class.should == RuntimeError
@@ -3,7 +3,7 @@ Given /^the following exception:$/ do |string|
3
3
  eval string
4
4
  end
5
5
 
6
- Given /^the following fake runner:$/ do |string|
6
+ Given /^the following fake readme:$/ do |string|
7
7
  eval string
8
8
  end
9
9
 
@@ -1,8 +1,8 @@
1
- When /^I generate a `Specdown::Runner` instance from it:$/ do |string|
1
+ When /^I generate a `Specdown::Readme` instance from it:$/ do |string|
2
2
  eval string
3
3
  end
4
4
 
5
- Then /^I should be able to run the tests:$/ do |string|
5
+ Then /^I should be able to execute the tests:$/ do |string|
6
6
  eval string
7
7
  end
8
8
 
@@ -1,3 +1,3 @@
1
- Then /^`Specdown::ReportSummary\.new\(@runner\)` should give me aggregate statistics about my run:$/ do |string|
1
+ Then /^`Specdown::ReportSummary\.new\(@readme\)` should give me aggregate statistics about my readme execution:$/ do |string|
2
2
  eval string
3
3
  end
@@ -1,8 +1,8 @@
1
- Given /^the following runner:$/ do |string|
1
+ Given /^the following readme:$/ do |string|
2
2
  eval string
3
3
  end
4
4
 
5
- When /^I run the tests in the runner:$/ do |string|
5
+ When /^I run the tests in the readme:$/ do |string|
6
6
  eval string
7
7
  end
8
8
 
@@ -17,7 +17,7 @@ Given /^the following of Specdown::Stats instances:$/ do |string|
17
17
  eval string
18
18
  end
19
19
 
20
- Then /^`Specdown::Reporter\.new\.summary\(@runner\)` should return a report summary object:$/ do |string|
20
+ Then /^`Specdown::Reporter\.new\.summary\(@readme\)` should return a report summary object:$/ do |string|
21
21
  eval string
22
22
  end
23
23
 
@@ -0,0 +1,129 @@
1
+ Given /^a `Specdown::Test` instance:$/ do |string|
2
+ eval string
3
+ @test.code.should be_empty
4
+ end
5
+
6
+ Then /^I should be able to add code to it:$/ do |string|
7
+ eval string
8
+ @test.code.should_not be_empty
9
+ end
10
+
11
+ Given /^a `Specdown::Test` instance `@test`$/ do
12
+ @test = Specdown::Test.new
13
+ end
14
+
15
+ Then /^I should be able to add undefined implicits to it:$/ do |string|
16
+ @test.undefined_implicits.should be_empty
17
+ eval string
18
+ @test.undefined_implicits.should_not be_empty
19
+ end
20
+
21
+ Given /^a `Specdown::Test` instance `@test` with undefined implicits$/ do
22
+ @test = Specdown::Test.new
23
+ @test.undefined_implicits << "1"
24
+ end
25
+
26
+ When /^I execute the test:$/ do |string|
27
+ eval string
28
+ end
29
+
30
+ Then /^`@test\.status` should be :([^\ ]*)$/ do |status|
31
+ @test.status.should == status.to_sym
32
+ end
33
+
34
+ When /^I execute it, the test status should be:$/ do
35
+ end
36
+
37
+ Given /^:passing if it doesn't throw any exceptions and has no undefined implicits$/ do
38
+ @test = generate_test(:passing)
39
+ @test.execute
40
+ @test.status.should == :passing
41
+ end
42
+
43
+ Given /^:undefined if it has any undefined implicits$/ do
44
+ @test = generate_test(:undefined)
45
+ @test.execute
46
+ @test.status.should == :undefined
47
+ end
48
+
49
+ Given /^:pending if it throws a `Specdown::Pending` exception$/ do
50
+ @test = generate_test(:pending)
51
+ @test.execute
52
+ @test.status.should == :pending
53
+ end
54
+
55
+ Given /^:failing if it throws an exception other than `Specdown::Pending`$/ do
56
+ @test = generate_test(:failing)
57
+ @test.execute
58
+ @test.status.should == :failing
59
+ end
60
+
61
+ Given /^If your test throws an exception, you can access it via the `exception` method$/ do
62
+ @test = generate_test :failing
63
+ @test.exception.should be(nil)
64
+ @test.execute
65
+ @test.exception.should_not be(nil)
66
+ end
67
+
68
+ Given /^The `Specdown::Test\.before_execute` method allows you to add code that runs before every test:$/ do |string|
69
+ before = false
70
+ Specdown::Test.before_execute do
71
+ before = true
72
+ end
73
+
74
+ Specdown::Test.new.execute
75
+ before.should be(true)
76
+ end
77
+
78
+ Given /^The `Specdown::Test\.after_execute` method allows you to add code that runs after every test:$/ do |string|
79
+ after = false
80
+ Specdown::Test.after_execute do
81
+ after = true
82
+ end
83
+
84
+ Specdown::Test.new.execute
85
+ after.should be(true)
86
+ end
87
+
88
+ Given /^The `Specdown::Test\.around_execute` method allows you to add code that runs around every test:$/ do |string|
89
+ around = nil
90
+ Specdown::Test.around_execute do
91
+ if around
92
+ around = false
93
+ else
94
+ around = true
95
+ end
96
+ end
97
+
98
+ Specdown::Test.new.execute
99
+ around.should be(false)
100
+ end
101
+
102
+ Given /^You can remove all `Specdown::Test` callbacks by calling `Specdown::Test\.remove_callbacks!`$/ do
103
+ Specdown::Test.before_execute do |test|
104
+ puts "I'm a callback!"
105
+ end
106
+
107
+ Specdown::Test.before_hooks["execute"].should_not be_empty
108
+
109
+ Specdown::Test.remove_callbacks!
110
+
111
+ Specdown::Test.before_hooks["execute"].should be_empty
112
+ end
113
+
114
+ def generate_test(status)
115
+ @test = Specdown::Test.new
116
+
117
+ case status
118
+ when :passing
119
+ @test.code << "1"
120
+ when :failing
121
+ @test.code << "raise 'exception!'"
122
+ when :undefined
123
+ @test.undefined_implicits << "undefined implicit!"
124
+ when :pending
125
+ @test.code << "pending"
126
+ end
127
+
128
+ @test
129
+ end
@@ -0,0 +1,131 @@
1
+ Feature: Specdown::Test
2
+
3
+ A `Specdown::Test` is constructed by specdown for every path from the root of a markdown file to a leaf section.
4
+
5
+ For example, consider the following markdown file:
6
+
7
+ \# The Calculator Gem
8
+
9
+ ...
10
+
11
+ \## A calculation object
12
+
13
+ ...
14
+
15
+ \### Basic Usage
16
+
17
+ ...
18
+
19
+ \## Static Operations
20
+
21
+ ...
22
+
23
+ \### Saving Results
24
+
25
+ ...
26
+
27
+ The headings in this markdown naturally form a tree:
28
+
29
+
30
+ The Calculator Gem
31
+ / \
32
+ / \
33
+ A calculation object Static Operations
34
+ / \
35
+ / \
36
+ Static Operations Saving Results
37
+
38
+
39
+ Specdown will construct a `Specdown::Test` object for each path from the root ("The Calculator Gem") to a leaf, gathering any code (whether explicit or implicit) along the way:
40
+
41
+ * The Calculator Gem -> A calculation object -> Static Operations
42
+ * The Calculator Gem -> Static Operations -> Saving Results
43
+
44
+ It will also tell the test about any undefined implicits it finds within the markdown.
45
+
46
+ You can add code to a test via the "code" array accessor:
47
+
48
+ test = Specdown::Test.new
49
+ test.code << "puts 'hi'"
50
+ test.code << "howdy"
51
+
52
+ If your markdown contains any undefined implicit specifications, you can add them to a `Specdown::Test` instance via the "undefined_implicits" method:
53
+
54
+ test.undefined_implicits << "I am an implicit specification that is not yet defined!"
55
+
56
+ You can execute the test via the "execute" method:
57
+
58
+ test.execute
59
+
60
+ After the test executes, you can get the status of the test via the `status` method. It will return one of the following symbols: `:passing`, `:failing`, `:pending`, `:undefined`.
61
+
62
+ If a test throws an exception, that exception will be captured and made accessible via the `exception` method.
63
+
64
+ You can add callbacks to tests via the "before_execute", "after_execute", and "around_execute" methods:
65
+
66
+ Specdown::Test.after_execute do |test|
67
+ case test.status
68
+ when :passing then Specdown.reporter.print_success(test)
69
+ when :failing then Specdown.reporter.print_failure(test)
70
+ when :pending then Specdown.reporter.print_pending(test)
71
+ when :undefined then Specdown.reporter.print_undefined(test)
72
+ end
73
+ end
74
+
75
+
76
+ Scenario: Reset callbacks
77
+ * You can remove all `Specdown::Test` callbacks by calling `Specdown::Test.remove_callbacks!`
78
+
79
+ Scenario: Add code
80
+ Given a `Specdown::Test` instance:
81
+ """
82
+ @test = Specdown::Test.new
83
+ """
84
+
85
+ Then I should be able to add code to it:
86
+ """
87
+ @test.code << "1"
88
+ @test.code << "2"
89
+ """
90
+
91
+
92
+ Scenario: Add undefined implicits
93
+ Given a `Specdown::Test` instance `@test`
94
+ Then I should be able to add undefined implicits to it:
95
+ """
96
+ @test.undefined_implicits << "implicit 1"
97
+ @test.undefined_implicits << "implicit 2"
98
+ """
99
+
100
+ Scenario: Status after test execution
101
+ Given a `Specdown::Test` instance `@test`
102
+ When I execute it, the test status should be:
103
+ * :passing if it doesn't throw any exceptions and has no undefined implicits
104
+ * :undefined if it has any undefined implicits
105
+ * :pending if it throws a `Specdown::Pending` exception
106
+ * :failing if it throws an exception other than `Specdown::Pending`
107
+
108
+ Scenario: Capturing exceptions
109
+ * If your test throws an exception, you can access it via the `exception` method
110
+
111
+ Scenario: Hooks
112
+ * The `Specdown::Test.before_execute` method allows you to add code that runs before every test:
113
+ """
114
+ Specdown::Test.before do |test|
115
+ puts "I run before every test!"
116
+ end
117
+ """
118
+
119
+ * The `Specdown::Test.after_execute` method allows you to add code that runs after every test:
120
+ """
121
+ Specdown::Test.after do |test|
122
+ puts "I run after every test!"
123
+ end
124
+ """
125
+
126
+ * The `Specdown::Test.around_execute` method allows you to add code that runs around every test:
127
+ """
128
+ Specdown::Test.around do |test|
129
+ puts "I run around every test!"
130
+ end
131
+ """