12 def initialize( *args ) |
12 def initialize( *args ) |
13 super |
13 super |
14 @indent_level = 0 |
14 @indent_level = 0 |
15 @failure_index = 0 |
15 @failure_index = 0 |
16 @failures = [] |
16 @failures = [] |
|
17 @txt = '' |
|
18 @summary = '' |
17 end |
19 end |
|
20 |
18 |
21 |
19 ######################################################################## |
22 ######################################################################## |
20 ### R S P E C H O O K S |
23 ### R S P E C H O O K S |
21 ######################################################################## |
24 ######################################################################## |
22 |
25 |
23 ### Example group hook -- increase indentation, emit description |
26 ### Example group hook -- increase indentation, emit description |
24 ### |
27 ### |
25 def example_group_started( example_group ) |
28 def example_group_started( example_group ) |
26 output.puts |
|
27 self.out '+', '-' * (example_group.description.length + 2), '+' |
29 self.out '+', '-' * (example_group.description.length + 2), '+' |
28 self.out '| ', example_group.description, ' |' |
30 self.out '| ', example_group.description, ' |' |
29 self.out '+', '-' * (example_group.description.length + 2), '+' |
31 self.out '+', '-' * (example_group.description.length + 2), '+' |
30 @indent_level += 1 |
32 @indent_level += 1 |
31 end |
33 end |
71 |
73 |
72 ### Called after all examples are run. Emit details for each failed example, |
74 ### Called after all examples are run. Emit details for each failed example, |
73 ### for Vim to fold. |
75 ### for Vim to fold. |
74 ### |
76 ### |
75 def dump_failures |
77 def dump_failures |
76 self.out "\n\n\n" unless @failures.empty? |
78 self.out "\n" unless @failures.empty? |
77 |
79 |
78 @failures.each_with_index do |example, index| |
80 @failures.each_with_index do |example, index| |
79 desc = example.metadata[ :full_description ] |
81 desc = example.metadata[ :full_description ] |
80 exception = example.execution_result[ :exception ] |
82 exception = example.execution_result[ :exception ] |
|
83 file = line = nil |
81 |
84 |
|
85 if exception.backtrace.first =~ /(.*):(\d+)/ |
|
86 file, line = $1, $2.to_i |
|
87 end |
82 self.out "FAILURE - #%d)" % [ index + 1 ] |
88 self.out "FAILURE - #%d)" % [ index + 1 ] |
|
89 self.out "%s:%d" % [ file, line ] |
83 |
90 |
84 if RSpec::Core::PendingExampleFixedError === exception |
91 if RSpec::Core::PendingExampleFixedError === exception |
85 self.out "%s FIXED" % [ desc ] |
92 self.out "%s FIXED" % [ desc ] |
86 self.out "Expected pending '%s' to fail. No error was raised." % [ |
93 self.out "Expected pending '%s' to fail. No error was raised." % [ |
87 example.metadata[ :execution_result ][ :pending_message ] |
94 example.metadata[ :execution_result ][ :pending_message ] |
98 "#{backtrace_line(group.metadata[:example_group][:location])}" |
105 "#{backtrace_line(group.metadata[:example_group][:location])}" |
99 break |
106 break |
100 end |
107 end |
101 end |
108 end |
102 end |
109 end |
103 self.out "\n" |
110 |
|
111 self.out exception_source( file, line ) if file && line |
104 end |
112 end |
|
113 end |
|
114 |
|
115 |
|
116 ### Emit the source of the exception, with context lines. |
|
117 ### |
|
118 def exception_source( file, line ) |
|
119 context = '' |
|
120 low, high = line - 3, line + 3 |
|
121 |
|
122 File.open( file ).each_with_index do |cline, i| |
|
123 cline.chomp!.rstrip! |
|
124 next unless i >= low && i <= high |
|
125 context << " %s%4d: %s\n" % [ ( i == line ? '>>' : ' |' ), i, cline ] |
|
126 end |
|
127 |
|
128 return context |
|
129 |
|
130 rescue |
|
131 'Unable to parse exception context lines.' |
105 end |
132 end |
106 |
133 |
107 |
134 |
108 ### Emit summary data for all examples. |
135 ### Emit summary data for all examples. |
109 ### |
136 ### |
110 def dump_summary( duration, example_count, failure_count, pending_count ) |
137 def dump_summary( duration, example_count, failure_count, pending_count ) |
111 succeeded = example_count - failure_count - pending_count |
138 succeeded = example_count - failure_count - pending_count |
112 self.out '+', '-' * 49, '+' |
139 @summary << "+%s+\n" % [ '-' * 49 ] |
113 self.out '|', ' ' * 18, '-- Summary --', ' ' * 18, '|' |
140 @summary << "|%s-- Summary --%s|\n" % [ ' ' * 18, ' ' * 18 ] |
114 self.out '+----------+-----------+--------+---------+-------+' |
141 @summary << "+----------+-----------+--------+---------+-------+\n" |
115 self.out '| Duration | Succeeded | Failed | Pending | Total |' |
142 @summary << "| Duration | Succeeded | Failed | Pending | Total |\n" |
116 self.out '+----------+-----------+--------+---------+-------+' |
143 @summary << "+----------+-----------+--------+---------+-------+\n" |
117 |
144 |
118 self.out "| %7ss | %9s | %6s | %7s | %5s |" % [ |
145 @summary << "| %7ss | %9s | %6s | %7s | %5s |\n" % [ |
119 "%0.3f" % duration, succeeded, failure_count, |
146 "%0.3f" % duration, succeeded, failure_count, |
120 pending_count, example_count |
147 pending_count, example_count |
121 ] |
148 ] |
122 |
149 |
123 self.out '+----------+-----------+--------+---------+-------+' |
150 @summary << "+----------+-----------+--------+---------+-------+\n\n" |
|
151 end |
|
152 |
|
153 |
|
154 ### End of run. Dump it all out! |
|
155 ### |
|
156 def close |
|
157 output.puts @summary |
|
158 output.puts @txt |
124 end |
159 end |
125 |
160 |
126 |
161 |
127 ######### |
162 ######### |
128 protected |
163 protected |
130 |
165 |
131 ### Send a string to the output IO object, after indentation. |
166 ### Send a string to the output IO object, after indentation. |
132 ### |
167 ### |
133 def out( *msg ) |
168 def out( *msg ) |
134 msg = msg.join |
169 msg = msg.join |
135 output.puts "%s%s" % [ ' ' * @indent_level, msg ] |
170 @txt << "%s%s\n" % [ ' ' * @indent_level, msg ] |
136 end |
171 end |
137 |
172 |
138 ### Format the basic example information, along with the run duration. |
173 ### Format the basic example information, along with the run duration. |
139 ### |
174 ### |
140 def format_example( example ) |
175 def format_example( example ) |