specdown 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/CHANGELOG.markdown +6 -0
  2. data/README.markdown +18 -10
  3. data/features/command.feature +2 -2
  4. data/features/config.feature +22 -11
  5. data/features/exception_facade.feature +46 -0
  6. data/features/report_summary.feature +61 -0
  7. data/features/{report.feature → reporter.feature} +19 -18
  8. data/features/reporter_factory.feature +63 -0
  9. data/features/runner.feature +1 -1
  10. data/features/specdown_examples/after_hooks/specdown/env.rb +1 -0
  11. data/features/specdown_examples/around_hooks/specdown/env.rb +1 -0
  12. data/features/specdown_examples/before_hooks/specdown/env.rb +1 -0
  13. data/features/specdown_examples/nested_directories_test/specdown/env.rb +1 -0
  14. data/features/specdown_examples/no_ruby/specdown/env.rb +1 -0
  15. data/features/specdown_examples/scoped_hooks/specdown/env.rb +1 -0
  16. data/features/specdown_examples/with_ruby/specdown/env.rb +1 -0
  17. data/features/step_definitions/config.rb +5 -2
  18. data/features/step_definitions/exception_facade.rb +16 -0
  19. data/features/step_definitions/report_summary.rb +3 -0
  20. data/features/step_definitions/{report.rb → reporter.rb} +8 -0
  21. data/features/step_definitions/reporter_factory.rb +39 -0
  22. data/lib/specdown/config.rb +8 -1
  23. data/lib/specdown/event_handlers/command_complete.rb +1 -2
  24. data/lib/specdown/event_handlers/test_failed.rb +1 -1
  25. data/lib/specdown/event_handlers/test_passed.rb +1 -1
  26. data/lib/specdown/reporter/color_terminal_reporter.rb +29 -0
  27. data/lib/specdown/reporter/terminal_reporter.rb +40 -0
  28. data/lib/specdown/reporter_factory.rb +18 -0
  29. data/lib/specdown/runner/exception_facade.rb +24 -0
  30. data/lib/specdown/runner/report_summary.rb +29 -0
  31. data/lib/specdown/runner/reporter.rb +27 -0
  32. data/lib/specdown/runner.rb +1 -1
  33. data/lib/specdown/specdown.rb +4 -0
  34. data/lib/specdown/templates/color_summary.erb +15 -0
  35. data/lib/specdown/templates/summary.erb +14 -0
  36. data/lib/specdown.rb +8 -1
  37. metadata +50 -13
  38. data/lib/specdown/runner/report.rb +0 -46
data/CHANGELOG.markdown CHANGED
@@ -1,5 +1,11 @@
1
1
  ## CHANGELOG
2
2
 
3
+ ## 0.1.5
4
+
5
+ Terminal output is now colorized, by default. To turn it off, add the following to your env.rb:
6
+
7
+ Specdown::Config.reporter = :terminal
8
+
3
9
  ## 0.1.4
4
10
 
5
11
  The `specdown` command now allows you to pass off directories of tests as well as individual tests.
data/README.markdown CHANGED
@@ -36,13 +36,16 @@ This is our very first test. It's going to blow your mind.
36
36
 
37
37
  Ok, if you've been following along, then `ls -R` should return the following directory structure:
38
38
 
39
- $ ls -R
40
-
41
- specdown/
42
- example.markdown
39
+ ```sh
40
+ $ ls -R
41
+
42
+ specdown/
43
+ example.markdown
44
+ ```
43
45
 
44
46
  Great. Now run the `specdown` command:
45
47
 
48
+ ```sh
46
49
  $ specdown
47
50
 
48
51
  .
@@ -50,6 +53,7 @@ Great. Now run the `specdown` command:
50
53
  1 markdown
51
54
  1 test
52
55
  0 failures
56
+ ```
53
57
 
54
58
  Booya!
55
59
 
@@ -89,16 +93,19 @@ Read through that. I'm giving you some important scoping hints in it.
89
93
 
90
94
  Save it, run it.
91
95
 
92
- $ specdown
96
+ ```sh
97
+ $ specdown
93
98
 
94
- ..
95
-
96
- 1 markdown
97
- 2 tests
98
- 0 failures
99
+ ..
100
+
101
+ 1 markdown
102
+ 2 tests
103
+ 0 failures
104
+ ```
99
105
 
100
106
  Notice how the headers in your markdown form a tree?
101
107
 
108
+ ```sh
102
109
  #Our first test!
103
110
  / \
104
111
  / \
@@ -112,6 +119,7 @@ Notice how the headers in your markdown form a tree?
112
119
  /
113
120
  /
114
121
  ###A sub subsection
122
+ ```
115
123
 
116
124
  Specdown turned that tree into two tests. The first test (#Our first test! --> ##A Subsection --> ###A sub subsection):
117
125
 
@@ -91,8 +91,8 @@ Feature: `specdown` command
91
91
  2 tests
92
92
  2 failures
93
93
 
94
- In parser_example.markdown: <NoMethodError> undefined method `be'
95
- In parser_example.markdown: <NoMethodError> undefined method `satisfy'
94
+ In parser_example.markdown: <#NoMethodError> undefined method `be'
95
+ In parser_example.markdown: <#NoMethodError> undefined method `satisfy'
96
96
  """
97
97
 
98
98
 
@@ -35,12 +35,29 @@ Feature: Specdown::Config
35
35
  assert_equal 1, 1
36
36
  end
37
37
 
38
+ \### Colorized Terminal Output
38
39
 
39
- Scenario: Reset the Specdown::Config
40
+ By default, Specdown will colorize your terminal output. If you'd prefer Specdown not to colorize your terminal output, simply set the `reporter` to `:terminal`:
41
+
42
+ Specdown.reporter == :terminal
43
+
44
+ \## Other reporting formats
45
+
46
+ If you prefer that specdown not output your test results to STDOUT, you can choose two other formats: `:text` and `:html`.
40
47
 
48
+
49
+ Scenario: Specdown::Config defaults
50
+ * Specdown::Config.expectations #==> nil
51
+ * Specdown::Config.reporter #==> :color_terminal
52
+ * Specdown::Config.root #==> "specdown"
53
+
54
+
55
+ Scenario: Reset the Specdown::Config
41
56
  Given I have configured Specdown:
42
57
  """
43
58
  Specdown::Config.expectations = :rspec
59
+ Specdown::Config.reporter = :html
60
+ Specdown::Config.root = "dir/"
44
61
  """
45
62
 
46
63
  When I reset Specdown:
@@ -48,11 +65,10 @@ Feature: Specdown::Config
48
65
  Specdown::Config.reset!
49
66
  """
50
67
 
51
- Then my specdown configuration should return to it's defaults:
52
- """
53
- Specdown::Config.expectations.should be(nil)
54
- """
55
-
68
+ Then my specdown configuration should return to its defaults:
69
+ * Specdown::Config.expectations #==> nil
70
+ * Specdown::Config.reporter #==> :color_terminal
71
+ * Specdown::Config.root #==> "specdown"
56
72
 
57
73
  Scenario: Default to Rspec expectations
58
74
 
@@ -89,8 +105,3 @@ Feature: Specdown::Config
89
105
  assert_equal 1, 1
90
106
  end
91
107
  """
92
-
93
-
94
-
95
-
96
-
@@ -0,0 +1,46 @@
1
+ Feature: Specdown::ExceptionFacade
2
+
3
+ A `Specdown::ExceptionFacade` is simply a convenient, no fuss way to retrieve useful information about an exception thrown during a specdown test run. You simply have to supply it with a stat, and the raw exception, and Specdown will do the rest.
4
+
5
+ For example, given the following exception:
6
+
7
+ exception = Exception.new "exception simulation"
8
+
9
+ And given the following fake test_runner:
10
+
11
+ runner = Class.new { attr_accessor :file_name }.new
12
+ runner.file_name = "test_file.markdown"
13
+
14
+ We can now generate an exception facade:
15
+
16
+ exception_facade = Specdown::ExceptionFacade.new exception, runner
17
+
18
+ exception_facade.test_filename.should == "test_file.markdown"
19
+ exception_facade.exception_class.should == Exception
20
+ exception_facade.exception_backtrace.should include("exception simulation")
21
+
22
+
23
+ Scenario: Exception report generated from a test run
24
+ Given the following exception:
25
+ """
26
+ @exception = Exception.new "exception simulation"
27
+ """
28
+
29
+ And the following fake runner:
30
+ """
31
+ @runner = Class.new { attr_accessor :file_name }.new
32
+ @runner.file_name = "test_file.markdown"
33
+ """
34
+
35
+ When I generate an exception facade:
36
+ """
37
+ @exception_facade = Specdown::ExceptionFacade.new @exception, @runner
38
+ """
39
+
40
+ Then it should return all kinds of information about the exception and it's context:
41
+ """
42
+ @exception_facade.test_filename.should == "test_file.markdown"
43
+ @exception_facade.exception_class.should == Exception
44
+ @exception_facade.exception_backtrace.should be(nil)
45
+ """
46
+
@@ -0,0 +1,61 @@
1
+ Feature: Specdown::ReportSummary
2
+
3
+ A `Specdown::ReportSummary` will provide you with aggregate statistical information about your test suite runners.
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:
6
+
7
+ summary = Specdown::ReportSummary.new(runners)
8
+ summary.num_markdowns
9
+ summary.num_tests
10
+ summary.num_failures
11
+ summary.num_successes
12
+
13
+ Scenario: A Specdown::Reporter instantiated with a single stats object
14
+
15
+ Given the following specdown example file located at 'features/fixtures/parser_example.markdown':
16
+ """
17
+ # Specdown Example
18
+
19
+ This is an example specdown file.
20
+
21
+ ## Child Node
22
+
23
+ This section is a child node. It contains some ruby code:
24
+
25
+ "simple code".should_not == nil
26
+
27
+ ### First Leaf
28
+
29
+ This section has a failure simulation:
30
+
31
+ raise "specdown error simulation!"
32
+
33
+ ## Last Leaf
34
+
35
+ This section is a leaf node. It contains some ruby code:
36
+
37
+ 1.should == 1
38
+ """
39
+
40
+ And the following runner:
41
+ """
42
+ @runner = Specdown::Runner.new("features/fixtures/parser_example.markdown")
43
+ """
44
+
45
+ When I run the tests in the runner:
46
+ """
47
+ @runner.run
48
+ """
49
+
50
+ Then `Specdown::ReportSummary.new(@runner)` should give me aggregate statistics about my run:
51
+ """
52
+ summary = Specdown::ReportSummary.new(@runner)
53
+ summary.num_markdowns.should == 1
54
+ summary.num_tests.should == 2
55
+ summary.num_failures.should == 1
56
+ summary.num_successes.should == 1
57
+ summary.exceptions.count.should == 1
58
+ summary.exceptions.first.test_filename.should == "parser_example.markdown"
59
+ summary.exceptions.first.exception_class.should == RuntimeError
60
+ summary.exceptions.first.exception_message.should include("specdown error simulation!")
61
+ """
@@ -1,7 +1,6 @@
1
- Feature: Report
1
+ Feature: Reporter
2
2
 
3
- Specdown comes with a generic reporting class. If you provide it with a runner (or an array of runners), then it will generate a report for you.
4
-
3
+ Specdown comes with a generic reporting class. By itself, the Specdown::Reporter does little (most methods throw a `NotImplementedError` exception). However, the `Specdown::ReporterFactory` will generate an instance of this class, then decorate based on your configuration.
5
4
 
6
5
  For example, suppose we have the following markdown file:
7
6
 
@@ -32,19 +31,17 @@ Feature: Report
32
31
  runner = Specdown::Runner.new("/features/fixtures/parser_example.markdown")
33
32
  runner.run
34
33
 
35
- We could then pass it off to our reporter class and receive the following report:
34
+ We could then retrieve a report summary like so:
36
35
 
37
- Specdown::Report.new(runner).generate.should == %{
38
- 1 markdown
39
- 3 tests
40
- 2 successes
41
- 1 failure
36
+ Specdown::Reporter.new.summary(runner).class.should == Specdown::ReportSummary
42
37
 
43
- StandardError: error simulation
44
- %}
38
+ The generic reporter doesn't actually print anything:
39
+
40
+ proc { Specdown::Reporter.new.print_summary(runner) }.should raise_exception(NotImplementedError)
41
+ proc { Specdown::Reporter.new.print_success(test) }.should raise_exception(NotImplementedError)
42
+ proc { Specdown::Reporter.new.print_failure(test) }.should raise_exception(NotImplementedError)
45
43
 
46
-
47
- Scenario: A Specdown::Report instantiated with a single stats object
44
+ Scenario: A Specdown::Reporter instantiated with a single stats object
48
45
 
49
46
  Given the following specdown example file located at 'features/fixtures/parser_example.markdown':
50
47
  """
@@ -81,11 +78,15 @@ Feature: Report
81
78
  @runner.run
82
79
  """
83
80
 
84
- Then `Specdown::Report.new(@runner).generate` should include the following output:
81
+ Then `Specdown::Reporter.new.summary(@runner)` should return a report summary object:
82
+ """
83
+ @reporter = Specdown::Reporter.new
84
+ @reporter.summary(@runner).class.should == Specdown::ReportSummary
85
85
  """
86
- 1 markdown
87
- 2 tests
88
- 1 failure
89
86
 
90
- error simulation
87
+ And the generic reporter shouldn't actually print anything:
88
+ """
89
+ proc { @reporter.print_summary(nil) }.should raise_exception(NotImplementedError)
90
+ proc { @reporter.print_success(nil) }.should raise_exception(NotImplementedError)
91
+ proc { @reporter.print_failure(nil) }.should raise_exception(NotImplementedError)
91
92
  """
@@ -0,0 +1,63 @@
1
+ Feature: Specdown::ReporterFactory
2
+
3
+ The `Specdown::ReporterFactory` will generate a `Specdown::Reporter` instance, then decorate it in various ways depending on your specdown configuration.
4
+
5
+ The `Specdown::ReporterFactory` has an API that allows you to configure new decorators for reports. Use the `Specdown::ReporterFactory.decorate` method:
6
+
7
+ Specdown::ReporterFactory.decorate do |report|
8
+ if Specdown::Config.reporter == :color_terminal
9
+ report.extend MyDecoratorModule
10
+ end
11
+ end
12
+
13
+ For example, if you configure specdown to output colorized terminal output (the default value for Specdown::Config.reporter, :color_terminal), then `Specdown::ReporterFactory` will mix the `Specdown::AnsiColor` decorator into your `Specdown::Reporter` instance.
14
+
15
+ Specdown::Config.reporter = :color_terminal
16
+ Specdown::ReporterFactory.generate.ancestors.should include(Specdown::AnsiColor)
17
+
18
+
19
+ Scenario: Adding a new decorator to Specdown::ReporterFactory
20
+
21
+ Given I have added the following decorator to `Specdown::ReporterFactory`:
22
+ """
23
+ Specdown::ReporterFactory.decorate do |reporter|
24
+ module FactoryTester
25
+ end
26
+
27
+ reporter.extend FactoryTester
28
+
29
+ reporter
30
+ end
31
+ """
32
+
33
+ Then reporters should be decorated with my new decorator:
34
+ """
35
+ Specdown::ReporterFactory.generate.kind_of?(FactoryTester).should be(true)
36
+ """
37
+
38
+
39
+ Scenario: Specdown::Config.reporter = :terminal
40
+
41
+ Given that I want a non-colorized text output report:
42
+ """
43
+ Specdown::Config.reporter = :terminal
44
+ """
45
+
46
+ Then `Specdown::ReporterFactory.generate` should return a `Specdown::Reporter` decorated with `Specdown::TerminalReporter`:
47
+ """
48
+ Specdown::ReporterFactory.generate.kind_of?(Specdown::TerminalReporter).should be(true)
49
+ """
50
+
51
+
52
+ Scenario: Specdown::Config.reporter = :color_terminal
53
+
54
+ Given that I want a colorized Specdown::Reporter:
55
+ """
56
+ Specdown::Config.reporter = :color_terminal
57
+ """
58
+
59
+ Then `Specdown::ReporterFactory.generate` should return a `Specdown::Reporter` decorated with `Specdown::TerminalReporter` and `Specdown::ColorTerminalReporter`:
60
+ """
61
+ Specdown::ReporterFactory.generate.kind_of?(Specdown::TerminalReporter).should be(true)
62
+ Specdown::ReporterFactory.generate.kind_of?(Specdown::ColorTerminalReporter).should be(true)
63
+ """
@@ -83,5 +83,5 @@ Feature: Runner
83
83
  @runner.stats.tests.should == 2
84
84
  @runner.stats.failures.should == 1
85
85
  @runner.stats.successes.should == 1
86
- @runner.stats.exceptions.map(&:to_s).should == ["specdown error simulation!"]
86
+ @runner.stats.exceptions.map(&:exception_message).should == ["specdown error simulation!"]
87
87
  """
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :rspec
2
+ Specdown::Config.reporter = :terminal
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :rspec
2
+ Specdown::Config.reporter = :terminal
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :rspec
2
+ Specdown::Config.reporter = :terminal
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :test_unit
2
+ Specdown::Config.reporter = :terminal
@@ -0,0 +1 @@
1
+ Specdown::Config.reporter = :terminal
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :rspec
2
+ Specdown::Config.reporter = :terminal
@@ -1 +1,2 @@
1
1
  Specdown::Config.expectations = :test_unit
2
+ Specdown::Config.reporter = :terminal
@@ -6,8 +6,7 @@ When /^I reset Specdown:$/ do |string|
6
6
  eval string
7
7
  end
8
8
 
9
- Then /^my specdown configuration should return to it's defaults:$/ do |string|
10
- eval string
9
+ Then /^my specdown configuration should return to its defaults:$/ do
11
10
  end
12
11
 
13
12
  Given /^I have rspec installed$/ do
@@ -32,3 +31,7 @@ end
32
31
  Then /^Specdown should provide Test::Unit assertions within the sandbox:$/ do |string|
33
32
  eval string
34
33
  end
34
+
35
+ Given /^Specdown::Config\.([^\ ]+)\ *#==>\ *(.*)$/ do |config_key, default_value|
36
+ Specdown::Config.send(config_key).should == eval(default_value)
37
+ end
@@ -0,0 +1,16 @@
1
+
2
+ Given /^the following exception:$/ do |string|
3
+ eval string
4
+ end
5
+
6
+ Given /^the following fake runner:$/ do |string|
7
+ eval string
8
+ end
9
+
10
+ When /^I generate an exception facade:$/ do |string|
11
+ eval string
12
+ end
13
+
14
+ Then /^it should return all kinds of information about the exception and it's context:$/ do |string|
15
+ eval string
16
+ end
@@ -0,0 +1,3 @@
1
+ Then /^`Specdown::ReportSummary\.new\(@runner\)` should give me aggregate statistics about my run:$/ do |string|
2
+ eval string
3
+ end
@@ -16,3 +16,11 @@ end
16
16
  Given /^the following of Specdown::Stats instances:$/ do |string|
17
17
  eval string
18
18
  end
19
+
20
+ Then /^`Specdown::Reporter\.new\.summary\(@runner\)` should return a report summary object:$/ do |string|
21
+ eval string
22
+ end
23
+
24
+ Then /^the generic reporter shouldn't actually print anything:$/ do |string|
25
+ eval string
26
+ end
@@ -0,0 +1,39 @@
1
+ Given /^that I want a non\-colorized text output report:$/ do |string|
2
+ eval string
3
+ end
4
+
5
+ Then /^`Specdown::ReporterFactory\.generate` should return a undecorated `Specdown::Reporter`:$/ do |string|
6
+ eval string
7
+ end
8
+
9
+ Given /^that I want a colorized Specdown::Reporter:$/ do |string|
10
+ eval string
11
+ end
12
+
13
+ Then /^`Specdown::ReporterFactory\.generate` should return a `Specdown::Reporter` decorated with `Specdown::AnsiColor`$/ do |string|
14
+ eval string
15
+ end
16
+
17
+ Given /^that I want an html report:$/ do |string|
18
+ eval string
19
+ end
20
+
21
+ Then /^`Specdown::ReporterFactory\.generate` should return a `Specdown::Reporter` decorated with `Specdown::HtmlReporter`$/ do |string|
22
+ eval string
23
+ end
24
+
25
+ Given /^I have added the following decorator to `Specdown::ReporterFactory`:$/ do |string|
26
+ eval string
27
+ end
28
+
29
+ Then /^reporters should be decorated with my new decorator:$/ do |string|
30
+ eval string
31
+ end
32
+
33
+ Then /^`Specdown::ReporterFactory\.generate` should return a `Specdown::Reporter` decorated with `Specdown::TerminalReporter`:$/ do |string|
34
+ eval string
35
+ end
36
+
37
+ Then /^`Specdown::ReporterFactory\.generate` should return a `Specdown::Reporter` decorated with `Specdown::TerminalReporter` and `Specdown::ColorTerminalReporter`:$/ do |string|
38
+ eval string
39
+ end
@@ -5,9 +5,16 @@ module Specdown
5
5
  attr_accessor :expectations
6
6
  attr_accessor :tests
7
7
  attr_accessor :root
8
+ attr_accessor :reporter
9
+
10
+ def reporter
11
+ @reporter ||= :color_terminal
12
+ end
8
13
 
9
14
  def reset!
10
- self.expectations = nil
15
+ @expectations = nil
16
+ @reporter = nil
17
+ @root = nil
11
18
  end
12
19
 
13
20
  def root
@@ -1,4 +1,3 @@
1
1
  Specdown::EventServer.register :command_complete do |results|
2
- puts "\n\n"
3
- puts Specdown::Report.new(results).generate
2
+ Specdown.reporter.print_summary(results)
4
3
  end
@@ -1,3 +1,3 @@
1
1
  Specdown::EventServer.register :test_failed do
2
- print "F"
2
+ Specdown.reporter.print_failure nil
3
3
  end
@@ -1,3 +1,3 @@
1
1
  Specdown::EventServer.register :test_passed do
2
- print "."
2
+ Specdown.reporter.print_success nil
3
3
  end
@@ -0,0 +1,29 @@
1
+ module Specdown
2
+ module ColorTerminalReporter
3
+ def success
4
+ super.green
5
+ end
6
+
7
+ def failure
8
+ super.red.bold
9
+ end
10
+
11
+ private
12
+ def template
13
+ ERB.new File.read(File.join(File.dirname(__FILE__), "../templates/color_summary.erb"))
14
+ end
15
+ end
16
+ end
17
+
18
+ Specdown::ReporterFactory.decorate do |reporter|
19
+ if Specdown::Config.reporter == :color_terminal
20
+ class ::String
21
+ include ::Term::ANSIColor
22
+ end
23
+
24
+ reporter.extend Specdown::TerminalReporter
25
+ reporter.extend Specdown::ColorTerminalReporter
26
+ end
27
+
28
+ reporter
29
+ end
@@ -0,0 +1,40 @@
1
+ module Specdown
2
+ module TerminalReporter
3
+ def success
4
+ "."
5
+ end
6
+
7
+ def failure
8
+ "F"
9
+ end
10
+
11
+ def print_success(test)
12
+ print success
13
+ end
14
+
15
+ def print_failure(test)
16
+ print failure
17
+ end
18
+
19
+ def print_summary(runners)
20
+ @report_summary = summary(runners)
21
+ template.run(proc {})
22
+ end
23
+
24
+ private
25
+ def template
26
+ ERB.new File.read(File.join(File.dirname(__FILE__), "../templates/summary.erb"))
27
+ end
28
+
29
+ def format_stat(word, number)
30
+ "#{number} #{number == 1 ? word : word + "s"}"
31
+ end
32
+ end
33
+ end
34
+
35
+ Specdown::ReporterFactory.decorate do |reporter|
36
+ if Specdown::Config.reporter == :terminal
37
+ reporter.extend Specdown::TerminalReporter
38
+ end
39
+ reporter
40
+ end
@@ -0,0 +1,18 @@
1
+ module Specdown
2
+ module ReporterFactory
3
+ extend self
4
+
5
+ def decorate(&block)
6
+ decorators << block
7
+ end
8
+
9
+ def generate
10
+ decorators.inject(Reporter.new) {|reporter, decorator| decorator.call(reporter) }
11
+ end
12
+
13
+ private
14
+ def decorators
15
+ @decorators ||= []
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module Specdown
2
+ class ExceptionFacade
3
+ def initialize(exception, runner)
4
+ @exception = exception
5
+ @runner = runner
6
+ end
7
+
8
+ def exception_class
9
+ @exception.class
10
+ end
11
+
12
+ def exception_backtrace
13
+ @exception.backtrace
14
+ end
15
+
16
+ def exception_message
17
+ @exception.to_s
18
+ end
19
+
20
+ def test_filename
21
+ @runner.file_name
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module Specdown
2
+ class ReportSummary
3
+ attr_reader :runners
4
+
5
+ def initialize(runners)
6
+ @runners = runners.respond_to?(:map) ? runners : [runners]
7
+ end
8
+
9
+ def num_markdowns
10
+ @num_markdowns ||= @runners.count
11
+ end
12
+
13
+ def num_tests
14
+ @num_tests ||= @runners.map(&:stats).map(&:tests).inject(0, &:+)
15
+ end
16
+
17
+ def num_failures
18
+ @num_failures ||= @runners.map(&:stats).map(&:failures).inject(0, &:+)
19
+ end
20
+
21
+ def num_successes
22
+ @num_successes ||= @runners.map(&:stats).map(&:successes).inject(0, &:+)
23
+ end
24
+
25
+ def exceptions
26
+ @exceptions ||= @runners.map(&:stats).map(&:exceptions).flatten
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module Specdown
2
+ class Reporter
3
+ def summary(runners)
4
+ ReportSummary.new(runners)
5
+ end
6
+
7
+ def success
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def failure
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def print_summary(runners)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def print_success(test)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def print_failure(test)
24
+ raise NotImplementedError
25
+ end
26
+ end
27
+ end
@@ -43,7 +43,7 @@ module Specdown
43
43
  EventServer.event :test_passed, self
44
44
 
45
45
  rescue Exception => e
46
- @stats.exceptions << e
46
+ @stats.exceptions << ExceptionFacade.new(e, self)
47
47
 
48
48
  EventServer.event :test_failed, self
49
49
  end
@@ -10,6 +10,10 @@ module Specdown
10
10
  SandboxFactory.generate
11
11
  end
12
12
 
13
+ def reporter
14
+ @reporter ||= ReporterFactory.generate
15
+ end
16
+
13
17
  def before(*filters, &callback)
14
18
  Hooks.before << Hook.new(*filters, &callback)
15
19
  end
@@ -0,0 +1,15 @@
1
+
2
+
3
+ ---------------------------------------------------------------------------
4
+ <%= format_stat("markdown", @report_summary.num_markdowns).bold %>
5
+ <%= format_stat("test", @report_summary.num_tests).bold %>
6
+ <%= format_stat("success", @report_summary.num_successes).green %>
7
+ <%= format_stat("failure", @report_summary.num_failures).red %>
8
+ ---------------------------------------------------------------------------
9
+
10
+ <% runners.map(&:stats).each do |stat| %>
11
+ <% stat.exceptions.each do |e| %>
12
+ <%= "In #{e.test_filename}".blue.bold %>: <%= "#<#{e.exception_class}>:".red.bold%> <%=e.exception_message%>
13
+ <%= e.exception_backtrace.join("\n").red %>
14
+ <% end %>
15
+ <% end %>
@@ -0,0 +1,14 @@
1
+
2
+
3
+ ---------------------------------------------------------------------------
4
+ <%= format_stat("markdown", @report_summary.num_markdowns) %>
5
+ <%= format_stat("test", @report_summary.num_tests) %>
6
+ <%= format_stat("success", @report_summary.num_successes) %>
7
+ <%= format_stat("failure", @report_summary.num_failures) %>
8
+ ---------------------------------------------------------------------------
9
+ <% runners.map(&:stats).each do |stat| %>
10
+ <% stat.exceptions.each do |e| %>
11
+ In <%=e.test_filename%>: <#<%=e.exception_class%>> <%=e.exception_message%>
12
+ <%= e.exception_backtrace.join "\n" %>
13
+ <% end %>
14
+ <% end %>
data/lib/specdown.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  require 'kramdown'
2
+ require 'term/ansicolor'
3
+ require 'erb'
2
4
  require 'optparse'
3
5
  require 'specdown/parser'
4
6
  require 'specdown/node'
5
7
  require 'specdown/tree'
6
8
  require 'specdown/runner'
7
- require 'specdown/runner/report'
9
+ require 'specdown/runner/reporter'
8
10
  require 'specdown/runner/stats'
9
11
  require 'specdown/command'
10
12
  require 'specdown/event_server'
@@ -21,3 +23,8 @@ require 'specdown/sandbox_factory'
21
23
  require 'specdown/hooks'
22
24
  require 'specdown/hook'
23
25
  require 'specdown/command/option_parser'
26
+ require 'specdown/reporter_factory'
27
+ require 'specdown/runner/report_summary'
28
+ require 'specdown/runner/exception_facade'
29
+ require 'specdown/reporter/terminal_reporter'
30
+ require 'specdown/reporter/color_terminal_reporter'
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: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 4
10
- version: 0.1.4
9
+ - 5
10
+ version: 0.1.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Parker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-04 00:00:00 Z
18
+ date: 2012-01-08 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: kramdown
@@ -34,9 +34,25 @@ dependencies:
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
- name: cucumber
37
+ name: term-ansicolor
38
38
  prerelease: false
39
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 25
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 7
49
+ version: 1.0.7
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: cucumber
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
57
  requirements:
42
58
  - - ">="
@@ -46,11 +62,11 @@ dependencies:
46
62
  - 0
47
63
  version: "0"
48
64
  type: :development
49
- version_requirements: *id002
65
+ version_requirements: *id003
50
66
  - !ruby/object:Gem::Dependency
51
67
  name: rspec
52
68
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
54
70
  none: false
55
71
  requirements:
56
72
  - - ">="
@@ -60,7 +76,7 @@ dependencies:
60
76
  - 0
61
77
  version: "0"
62
78
  type: :development
63
- version_requirements: *id003
79
+ version_requirements: *id004
64
80
  description:
65
81
  email: moonmaster9000@gmail.com
66
82
  executables:
@@ -86,11 +102,18 @@ files:
86
102
  - lib/specdown/hooks.rb
87
103
  - lib/specdown/node.rb
88
104
  - lib/specdown/parser.rb
89
- - lib/specdown/runner/report.rb
105
+ - lib/specdown/reporter/color_terminal_reporter.rb
106
+ - lib/specdown/reporter/terminal_reporter.rb
107
+ - lib/specdown/reporter_factory.rb
108
+ - lib/specdown/runner/exception_facade.rb
109
+ - lib/specdown/runner/report_summary.rb
110
+ - lib/specdown/runner/reporter.rb
90
111
  - lib/specdown/runner/stats.rb
91
112
  - lib/specdown/runner.rb
92
113
  - lib/specdown/sandbox_factory.rb
93
114
  - lib/specdown/specdown.rb
115
+ - lib/specdown/templates/color_summary.erb
116
+ - lib/specdown/templates/summary.erb
94
117
  - lib/specdown/tree.rb
95
118
  - lib/specdown.rb
96
119
  - bin/specdown
@@ -99,10 +122,13 @@ files:
99
122
  - features/command.feature
100
123
  - features/config.feature
101
124
  - features/event_server.feature
125
+ - features/exception_facade.feature
102
126
  - features/fixtures/parser_example.markdown
103
127
  - features/hooks.feature
104
128
  - features/parser.feature
105
- - features/report.feature
129
+ - features/report_summary.feature
130
+ - features/reporter.feature
131
+ - features/reporter_factory.feature
106
132
  - features/runner.feature
107
133
  - features/specdown_examples/after_hooks/specdown/env.rb
108
134
  - features/specdown_examples/after_hooks/specdown/hooks.rb
@@ -117,6 +143,7 @@ files:
117
143
  - features/specdown_examples/nested_directories_test/specdown/tests/1.markdown
118
144
  - features/specdown_examples/nested_directories_test/specdown/tests/2.markdown
119
145
  - features/specdown_examples/nested_directories_test/specdown/tests/3.markdown
146
+ - features/specdown_examples/no_ruby/specdown/env.rb
120
147
  - features/specdown_examples/no_ruby/specdown/parser_example.markdown
121
148
  - features/specdown_examples/scoped_hooks/specdown/env.rb
122
149
  - features/specdown_examples/scoped_hooks/specdown/hooks.rb
@@ -129,9 +156,12 @@ files:
129
156
  - features/step_definitions/command.rb
130
157
  - features/step_definitions/config.rb
131
158
  - features/step_definitions/event_server.rb
159
+ - features/step_definitions/exception_facade.rb
132
160
  - features/step_definitions/hooks.rb
133
161
  - features/step_definitions/parser.rb
134
- - features/step_definitions/report.rb
162
+ - features/step_definitions/report_summary.rb
163
+ - features/step_definitions/reporter.rb
164
+ - features/step_definitions/reporter_factory.rb
135
165
  - features/step_definitions/runner.rb
136
166
  - features/support/env.rb
137
167
  - features/support/hooks.rb
@@ -172,10 +202,13 @@ test_files:
172
202
  - features/command.feature
173
203
  - features/config.feature
174
204
  - features/event_server.feature
205
+ - features/exception_facade.feature
175
206
  - features/fixtures/parser_example.markdown
176
207
  - features/hooks.feature
177
208
  - features/parser.feature
178
- - features/report.feature
209
+ - features/report_summary.feature
210
+ - features/reporter.feature
211
+ - features/reporter_factory.feature
179
212
  - features/runner.feature
180
213
  - features/specdown_examples/after_hooks/specdown/env.rb
181
214
  - features/specdown_examples/after_hooks/specdown/hooks.rb
@@ -190,6 +223,7 @@ test_files:
190
223
  - features/specdown_examples/nested_directories_test/specdown/tests/1.markdown
191
224
  - features/specdown_examples/nested_directories_test/specdown/tests/2.markdown
192
225
  - features/specdown_examples/nested_directories_test/specdown/tests/3.markdown
226
+ - features/specdown_examples/no_ruby/specdown/env.rb
193
227
  - features/specdown_examples/no_ruby/specdown/parser_example.markdown
194
228
  - features/specdown_examples/scoped_hooks/specdown/env.rb
195
229
  - features/specdown_examples/scoped_hooks/specdown/hooks.rb
@@ -202,9 +236,12 @@ test_files:
202
236
  - features/step_definitions/command.rb
203
237
  - features/step_definitions/config.rb
204
238
  - features/step_definitions/event_server.rb
239
+ - features/step_definitions/exception_facade.rb
205
240
  - features/step_definitions/hooks.rb
206
241
  - features/step_definitions/parser.rb
207
- - features/step_definitions/report.rb
242
+ - features/step_definitions/report_summary.rb
243
+ - features/step_definitions/reporter.rb
244
+ - features/step_definitions/reporter_factory.rb
208
245
  - features/step_definitions/runner.rb
209
246
  - features/support/env.rb
210
247
  - features/support/hooks.rb
@@ -1,46 +0,0 @@
1
- module Specdown
2
- class Report
3
- def initialize(runners)
4
- runners = [runners] unless runners.respond_to?(:map)
5
- @stats = runners.map &:stats
6
- end
7
-
8
- def generate
9
- [
10
- format_stat("markdown", markdowns),
11
- format_stat("test", tests),
12
- format_stat("failure", failures)
13
- ].join("\n") + "\n\n" + exceptions.join("\n\n")
14
- end
15
-
16
- private
17
- def format_stat(word, number)
18
- "#{number} #{number == 1 ? word : word + "s"}"
19
- end
20
-
21
- def tests
22
- @tests ||= @stats.inject(0) {|sum, stat| sum += stat.tests}
23
- end
24
-
25
- def failures
26
- @failures ||= @stats.inject(0) {|sum, stat| sum += stat.failures}
27
- end
28
-
29
- def markdowns
30
- @stats.count
31
- end
32
-
33
- def exceptions
34
- formatted_exceptions = []
35
- @stats.each do |stat|
36
- formatted_exceptions << stat.exceptions.map do |e|
37
- [
38
- (stat.runner ? "In #{stat.runner.file_name}: " : "") + "<#{e.class}> #{e}",
39
- e.backtrace
40
- ].join "\n"
41
- end
42
- end
43
- formatted_exceptions.flatten
44
- end
45
- end
46
- end