|
1 |
|
2 require 'rspec/core/formatters/base_text_formatter' |
|
3 |
|
4 ### SpeckyFormatter: A basic RSpec 2.x text formatter, to be used |
|
5 ### with the 'Specky' vim plugin (or from the command line, if you |
|
6 ### dig it over the default 'documentation' format!) |
|
7 ### |
|
8 ### rspec -r /path/to/this/specky_formatter.rb -f SpeckyFormatter specs |
|
9 ### |
|
10 class SpeckyFormatter < RSpec::Core::Formatters::BaseTextFormatter |
|
11 |
|
12 def initialize( *args ) |
|
13 super |
|
14 @indent_level = 0 |
|
15 @failure_index = 0 |
|
16 @failures = [] |
|
17 end |
|
18 |
|
19 ######################################################################## |
|
20 ### R S P E C H O O K S |
|
21 ######################################################################## |
|
22 |
|
23 ### Example group hook -- increase indentation, emit description |
|
24 ### |
|
25 def example_group_started( example_group ) |
|
26 output.puts |
|
27 self.out '+', '-' * (example_group.description.length + 2), '+' |
|
28 self.out '| ', example_group.description, ' |' |
|
29 self.out '+', '-' * (example_group.description.length + 2), '+' |
|
30 @indent_level += 1 |
|
31 end |
|
32 |
|
33 |
|
34 ### Example group hook -- decrease indentation |
|
35 ### |
|
36 def example_group_finished( example_group ) |
|
37 @indent_level -= 1 |
|
38 end |
|
39 |
|
40 |
|
41 ### Called on example success |
|
42 ### |
|
43 def example_passed( example ) |
|
44 msg = self.format_example( example ) |
|
45 msg << ')' |
|
46 self.out msg |
|
47 end |
|
48 |
|
49 |
|
50 ### Called on a pending example |
|
51 ### |
|
52 def example_pending( example ) |
|
53 msg = self.format_example( example ) |
|
54 pending_msg = example.metadata[ :execution_result ][ :pending_message ] |
|
55 msg << ", PENDING%s)" % [ ": #{pending_msg}" || '' ] |
|
56 self.out msg |
|
57 end |
|
58 |
|
59 |
|
60 ### Called on example failure |
|
61 ### |
|
62 def example_failed( example ) |
|
63 @failure_index += 1 |
|
64 msg = self.format_example( example ) |
|
65 msg << ", FAILED - #%d)" % [ @failure_index ] |
|
66 self.out msg |
|
67 |
|
68 @failures << example |
|
69 end |
|
70 |
|
71 |
|
72 ### Called after all examples are run. Emit details for each failed example, |
|
73 ### for Vim to fold. |
|
74 ### |
|
75 def dump_failures |
|
76 self.out "\n\n\n" unless @failures.empty? |
|
77 |
|
78 @failures.each_with_index do |example, index| |
|
79 desc = example.metadata[ :full_description ] |
|
80 exception = example.execution_result[ :exception ] |
|
81 |
|
82 self.out "FAILURE - #%d)" % [ index + 1 ] |
|
83 |
|
84 if RSpec::Core::PendingExampleFixedError === exception |
|
85 self.out "%s FIXED" % [ desc ] |
|
86 self.out "Expected pending '%s' to fail. No error was raised." % [ |
|
87 example.metadata[ :execution_result ][ :pending_message ] |
|
88 ] |
|
89 else |
|
90 self.out desc |
|
91 self.out "Failure/Error: %s" % [ read_failed_line( exception, example).strip ] |
|
92 exception.message.split("\n").each {|l| self.out l} |
|
93 |
|
94 # logic taken from the base class |
|
95 example.example_group.ancestors.push(example.example_group).each do |group| |
|
96 if group.metadata[:shared_group_name] |
|
97 self.out "Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " + |
|
98 "#{backtrace_line(group.metadata[:example_group][:location])}" |
|
99 break |
|
100 end |
|
101 end |
|
102 end |
|
103 self.out "\n" |
|
104 end |
|
105 end |
|
106 |
|
107 |
|
108 ### Emit summary data for all examples. |
|
109 ### |
|
110 def dump_summary( duration, example_count, failure_count, pending_count ) |
|
111 succeeded = example_count - failure_count - pending_count |
|
112 self.out '+', '-' * 49, '+' |
|
113 self.out '|', ' ' * 18, '-- Summary --', ' ' * 18, '|' |
|
114 self.out '+----------+-----------+--------+---------+-------+' |
|
115 self.out '| Duration | Succeeded | Failed | Pending | Total |' |
|
116 self.out '+----------+-----------+--------+---------+-------+' |
|
117 |
|
118 self.out "| %7ss | %9s | %6s | %7s | %5s |" % [ |
|
119 "%0.3f" % duration, succeeded, failure_count, |
|
120 pending_count, example_count |
|
121 ] |
|
122 |
|
123 self.out '+----------+-----------+--------+---------+-------+' |
|
124 end |
|
125 |
|
126 |
|
127 ######### |
|
128 protected |
|
129 ######### |
|
130 |
|
131 ### Send a string to the output IO object, after indentation. |
|
132 ### |
|
133 def out( *msg ) |
|
134 msg = msg.join |
|
135 output.puts "%s%s" % [ ' ' * @indent_level, msg ] |
|
136 end |
|
137 |
|
138 ### Format the basic example information, along with the run duration. |
|
139 ### |
|
140 def format_example( example ) |
|
141 metadata = example.metadata |
|
142 duration = metadata[ :execution_result ][ :run_time ] |
|
143 description = metadata[ :description ] |
|
144 return "| %s (%0.3fs" % [ description, duration ] |
|
145 end |
|
146 end # SpeckyFormatter |
|
147 |