<br><font size=2 face="sans-serif">Sounds sensible.</font>
<br>
<br><font size=2 face="sans-serif">Questions are:</font>
<br><font size=2 face="sans-serif">* what determines the order of sections?</font>
<br><font size=2 face="sans-serif">* build.log itself (formatted) is a
section, isn't it?</font>
<br>
<br><font size=3>&gt; maybe these should all live in a folder /links/</font>
<br><font size=3>My opinion: this sacrifices some usability by placing
custom build artifacts one click further away in the file system, and the
complexity saved by this sacrifice is not big enough to justify the sacrifice.</font>
<br>
<br><font size=2 face="sans-serif">Alex</font>
<br>
<br>
<br>
<br>
<table width=100%>
<tr valign=top>
<td width=40%><font size=1 face="sans-serif"><b>&quot;Jeremy Stell-Smith&quot;
&lt;jeremystellsmith@gmail.com&gt;</b> </font>
<p><font size=1 face="sans-serif">02/10/2007 02:24 PM</font>
<td width=59%>
<table width=100%>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">To</font></div>
<td><font size=1 face="sans-serif">&quot;Alexey Verkhovsky&quot; &lt;averkhov@thoughtworks.com&gt;</font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">cc</font></div>
<td><font size=1 face="sans-serif">rpotter@anl.gov, cruisecontrolrb-developers@rubyforge.org</font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">Subject</font></div>
<td><font size=1 face="sans-serif">Re: [Cruisecontrolrb-developers] [patch]
rspec support (partial)</font></table>
<br>
<table>
<tr valign=top>
<td>
<td></table>
<br></table>
<br>
<br>
<br><font size=3>I would suggest that our artifacts directory look something
like this :<br>
</font><font size=3 face="Courier"><br>
&lt;project&gt;/build-&lt;label&gt;/build.log<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; /build_status.&lt;status&gt;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; /sections/change_set.html<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/.change_set.html<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/test_results.html <br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/something.html<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/something else.txt<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; /unit test coverage/...<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; /other stuff.html<br>
</font><font size=3><br>
so, the only &quot;special&quot; files are build.log, build_status.*, and
the sections directory<br>
<br>
anything else in the artifacts directory will be displayed as a link from
the build page (maybe these should all live in a folder /links/?) - this
is implemented now <br>
<br>
anything in /sections will be displayed as a collapsible section on the
build page, if it's an html file, we include it outright, otherwise we
either put it in a pre section or format it so that it looks as if we did.
<br>
<br>
how's that sound?<br>
<br>
Jeremy<br>
<br>
PS. Thanks for the patch, Randall!<br>
</font>
<br><font size=3>On 2/10/07, <b>Alexey Verkhovsky </b>&lt;</font><a href=mailto:averkhov@thoughtworks.com><font size=3 color=blue><u>averkhov@thoughtworks.com</u></font></a><font size=3>&gt;
wrote:</font>
<br><font size=2 face="sans-serif"><br>
Thanks a lot!</font><font size=3> <br>
</font><tt><font size=2><br>
&gt; Is this the appropriate way to submit patches?</font></tt><font size=3>
</font><font size=2 face="sans-serif"><br>
Yes, until we have a more appropriate way (aka a bug tracker).</font><font size=3>
<br>
</font><font size=2 face="sans-serif"><br>
This submission raises a question that was at the back of my mind ever
since we had Test::Unit results formatter in this codebase.</font><font size=3>
</font><font size=2 face="sans-serif"><br>
Custom formatting of build log is going to be in demand. How do we pluginize
it? </font><font size=3><br>
</font><font size=2 face="sans-serif"><br>
How about this solution:</font><font size=3> </font><font size=2 face="sans-serif"><br>
* Let's make formatting of build log a builder's responsibility.</font><font size=3>
</font><font size=2 face="sans-serif"><br>
* This can be done by a builder plugin in response to :build_finished event</font><font size=3>
<br>
</font><font size=2 face="sans-serif"><br>
Another question then arises: what do we want to do with intermediate build
products? We don't really want to delete them (troubleshooting), but we
also don't want to display links to them on the dashboard. I think, use
hidden files for that. </font><font size=3><br>
</font><font size=2 face="sans-serif"><br>
I.e., you start with build.log file. Format it and write the output into
build.log.html (without html and body tags though, because we are displaying
it on the dashboard page). It's also a good time to merge it with the changeset
etc. Finally, hide the originals from the dashboard by renaming build.log
to .build.log and changeset.log to .changeset.log.</font><font size=3>
<br>
</font><font size=2 face="sans-serif"><br>
Thoughts?</font><font size=3> <br>
</font><font size=2 face="sans-serif"><br>
Best regards,</font><font size=3> </font><font size=2 face="sans-serif"><br>
Alex</font><font size=3> <br>
<br>
<br>
<br>
<br>
</font>
<table width=100%>
<tr valign=top>
<td width=47%><font size=1 face="sans-serif"><b>Randall Potter &lt;</b></font><a href=mailto:rpotter@anl.gov target=_blank><font size=1 color=blue face="sans-serif"><b><u>rpotter@anl.gov</u></b></font></a><font size=1 face="sans-serif"><b>&gt;</b>
<br>
Sent by: </font><a href="mailto:cruisecontrolrb-developers-bounces@rubyforge.org" target=_blank><font size=1 color=blue face="sans-serif"><u>cruisecontrolrb-developers-bounces@rubyforge.org
</u></font></a>
<p><font size=1 face="sans-serif">02/10/2007 12:23 AM</font><font size=3>
</font>
<td width=52%>
<br>
<table width=100%>
<tr valign=top>
<td width=12%>
<div align=right><font size=1 face="sans-serif">To</font></div>
<td width=87%><a href="mailto:cruisecontrolrb-developers@rubyforge.org" target=_blank><font size=1 color=blue face="sans-serif"><u>cruisecontrolrb-developers@rubyforge.org</u></font></a><font size=3>
</font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">cc</font></div>
<td>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">Subject</font></div>
<td><font size=1 face="sans-serif">[Cruisecontrolrb-developers] [patch]
rspec support (partial)</font></table>
<br>
<br>
<table width=100%>
<tr valign=top>
<td width=50%>
<td width=50%></table>
<br></table>
<br><font size=3><br>
<br>
</font><tt><font size=2><br>
story:<br>
 &nbsp; As a Dev, I would like CC.rb to display rspec failures in 'Test
<br>
Failures and Errors', so that I can use rspec.<br>
<br>
Is this the appropriate way to submit patches?<br>
<br>
Thank you in advance for your time,<br>
<br>
rpotter<br>
<br>
--- app/models/test_failure_parser.rb &nbsp; &nbsp;(revision 181)<br>
+++ app/models/test_failure_parser.rb &nbsp; &nbsp;(working copy)<br>
@@ -1,25 +1,51 @@<br>
class TestFailureParser &nbsp; <br>
- &nbsp;TEST_NAME_REGEX = /\S+/<br>
- &nbsp;MESSAGE_REGEX = /\]\:\n([\s\S]+)/<br>
- &nbsp;STACK_TRACE_REGEX = /\[([\s\S]*?)\]\:/<br>
- &nbsp;TEST_FAILURE_BLOCK_REGEX = /^\s+\d+\) Failure:\n([\S\s]*?)\n\n/<br>
+<br>
+ &nbsp;TEST_FAILURE_BLOCK_REGEX = /^\s+?\d+\)(( Failure:)?\n[\S\s]*?)\n\n/<br>
+ <br>
+ &nbsp;SPEC_FAILURE_FORMAT = /^'[\s\S]+'\sFAILED[\s\S]*?/<br>
+ &nbsp;TEST_UNIT_FAILURE_FORMAT = / <br>
Failure:\n(\S+)\n?\s+?\[([\s\S]*?)\]:\n([\s\S]+)/<br>
+ <br>
 &nbsp;def get_test_failures(log)<br>
 &nbsp; &nbsp;testFailures = Array.new<br>
 &nbsp; <br>
 &nbsp; &nbsp;log.gsub(TEST_FAILURE_BLOCK_REGEX) do |text|<br>
 &nbsp; &nbsp; &nbsp;content = $1<br>
- &nbsp; &nbsp;<br>
- &nbsp; &nbsp; &nbsp;begin<br>
- &nbsp; &nbsp; &nbsp; &nbsp;test_name = content.match(TEST_NAME_REGEX).to_s
&nbsp; &nbsp; <br>
- &nbsp; &nbsp; &nbsp; &nbsp;message = content.match(MESSAGE_REGEX)[1]<br>
- &nbsp; &nbsp; &nbsp; &nbsp;stack_trace = content.match(STACK_TRACE_REGEX)[1]<br>
- &nbsp; &nbsp; &nbsp; <br>
- &nbsp; &nbsp; &nbsp; &nbsp;testFailures &lt;&lt; TestErrorEntry.create_failure(test_name,
<br>
message, stack_trace)<br>
- &nbsp; &nbsp; &nbsp;rescue<br>
- &nbsp; &nbsp; &nbsp; &nbsp;# Do Nothing, Pattern does not match<br>
- &nbsp; &nbsp; &nbsp;end &nbsp; &nbsp; <br>
+ &nbsp; &nbsp; <br>
+ &nbsp; &nbsp; &nbsp;if content.match(TEST_UNIT_FAILURE_FORMAT)<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;testFailures &lt;&lt; parse_as_test_unit(content)<br>
+ &nbsp; &nbsp; &nbsp;elsif content.gsub(&quot;\n&quot;,'').match(SPEC_FAILURE_FORMAT)<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;testFailures &lt;&lt; parse_as_rspec(content)<br>
+ &nbsp; &nbsp; &nbsp;else<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;# &nbsp;no failures or we don't recognize
it<br>
+ &nbsp; &nbsp; &nbsp;end<br>
+ &nbsp; &nbsp; <br>
 &nbsp; &nbsp;end<br>
 &nbsp; <br>
 &nbsp; &nbsp;testFailures<br>
 &nbsp;end<br>
-end<br>
\ No newline at end of file<br>
+ <br>
+ &nbsp;private<br>
+ <br>
+ &nbsp;# &nbsp;parse Test::Unit log message and return TestErrorEntry<br>
+ &nbsp;def parse_as_test_unit(content)<br>
+ &nbsp; <br>
+ &nbsp; &nbsp;test_name = content.match(TEST_UNIT_FAILURE_FORMAT)[1].to_s
&nbsp; &nbsp; <br>
+ &nbsp; &nbsp;message = content.match(TEST_UNIT_FAILURE_FORMAT)[3]<br>
+ &nbsp; &nbsp;stack_trace = content.match(TEST_UNIT_FAILURE_FORMAT)[2]<br>
+ &nbsp; <br>
+ &nbsp; &nbsp;TestErrorEntry.create_failure(test_name, message, stack_trace)<br>
+ &nbsp;end<br>
+ <br>
+ &nbsp;# &nbsp;parse rspec log message and return TestErrorEntry<br>
+ &nbsp;def parse_as_rspec(content)<br>
+ &nbsp; <br>
+ &nbsp; &nbsp;spec_arr = content.split(&quot;\n&quot;)<br>
+ &nbsp; <br>
+ &nbsp; &nbsp;test_name = spec_arr[1].match(/^'([\s\S]+)' FAILED$/)[1].to_s
&nbsp; &nbsp; <br>
+ &nbsp; &nbsp;message = spec_arr[2].to_s<br>
+ &nbsp; &nbsp;stack_trace = spec_arr.slice(3..spec_arr.length).join(&quot;\n&quot;)<br>
+ &nbsp; <br>
+ &nbsp; &nbsp;TestErrorEntry.create_failure(test_name, message, stack_trace)<br>
+ &nbsp;end<br>
+ <br>
+end<br>
<br>
--- test/unit/test_failure_parser_test.rb &nbsp; &nbsp;(revision 181)<br>
+++ working_copy/test/unit/test_failure_parser_test.rb &nbsp; &nbsp;(working
copy)<br>
@@ -77,6 +77,34 @@<br>
83 tests, 185 assertions, 2 failures, 0 errors<br>
EOF<br>
<br>
+LOG_OUTPUT_WITH_NO_SPEC_FAILURE = &lt;&lt;EOF<br>
+<br>
+.............................................................<br>
+<br>
+Finished in 1.199703 seconds<br>
+<br>
+61 specifications, 0 failures<br>
+EOF<br>
+<br>
+LOG_OUTPUT_WITH_SPEC_FAILURE = &lt;&lt;EOF<br>
+/usr/local/bin/spec:17:Warning: require_gem is obsolete. Use gem instead.<br>
+<br>
+....F....<br>
+<br>
+1)<br>
+'Given a request to edit with a week and year the controller should <br>
return a hash of one blank row if data ! found' FAILED<br>
+nil should be a kind of Array<br>
+./spec/controllers/consultant_controller_spec.rb:47:<br>
+/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:36:in `run'<br>
+/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:47:<br>
+/cruisecontrol/tasks/cc_build.rake:32:<br>
+-e:1:<br>
+<br>
+Finished in 0.484439 seconds<br>
+<br>
+9 specifications, 1 failure<br>
+EOF<br>
+<br>
 &nbsp;def test_should_not_find_test_failures_with_a_build_with_test_errors<br>
 &nbsp; &nbsp;testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_TEST_ERRORS)<br>
 &nbsp; &nbsp;assert_equal 0, testFailures.length<br>
@@ -87,19 +115,30 @@<br>
 &nbsp; &nbsp;assert_equal 0, testFailures.length &nbsp; &nbsp; &nbsp;
<br>
 &nbsp;end<br>
 <br>
+ &nbsp;def test_should_find_no_spec_failures_with_successful_build<br>
+ &nbsp; &nbsp;testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_NO_SPEC_FAILURE)<br>
+ &nbsp; &nbsp;assert_equal 0, testFailures.length &nbsp; &nbsp; &nbsp;
<br>
+ &nbsp;end<br>
+ <br>
 &nbsp;def test_should_find_test_failures<br>
 &nbsp; &nbsp;testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_TEST_FAILURE)<br>
 &nbsp; &nbsp;assert_equal 2, testFailures.length<br>
 &nbsp; &nbsp;assert_equal expected_first_test_failure, testFailures[0]<br>
 &nbsp; &nbsp;assert_equal expected_second_test_failure, testFailures[1]<br>
 &nbsp;end<br>
- &nbsp; &nbsp; &nbsp; <br>
+ <br>
+ &nbsp;def test_should_find_spec_failures<br>
+ &nbsp; &nbsp;testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_SPEC_FAILURE)<br>
+ &nbsp; &nbsp;assert_equal 1, testFailures.length<br>
+ &nbsp; &nbsp;assert_equal expected_first_spec_failure, testFailures[0]<br>
+ &nbsp;end<br>
+ <br>
 &nbsp;def test_should_correctly_parse_mocha_test_failures<br>
 &nbsp; &nbsp;testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_MOCK_TEST_FAILURE)<br>
 &nbsp; &nbsp;assert_equal 1, testFailures.length<br>
 &nbsp; &nbsp;assert_equal expected_mock_test_failure, testFailures[0]<br>
 &nbsp;end<br>
- &nbsp; &nbsp; &nbsp; <br>
+ <br>
 &nbsp;def expected_first_test_failure<br>
 &nbsp; &nbsp;<br>
TestErrorEntry.create_failure(&quot;test_should_fail(SubversionLogParserTest)&quot;,<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;&lt;1&gt; expected
but was\n&lt;\&quot;abc\&quot;&gt;.&quot;,<br>
@@ -121,5 +160,15 @@<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;#&lt;Mocha::Mock:0x-245ec74a&gt;.force_build_if_requested - expected
calls: <br>
1, actual calls: 2&quot;,<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;./test/unit/polling_scheduler_test.rb:44&quot;)<br>
 &nbsp;end<br>
+<br>
+ &nbsp;def expected_first_spec_failure<br>
+ &nbsp; &nbsp;TestErrorEntry.create_failure(&quot;Given a request to edit
with a week <br>
and year the controller should return a hash of one blank row if data !
<br>
found&quot;,<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;nil should be a kind
of Array&quot;,<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;./spec/controllers/consultant_controller_spec.rb:47:\n&quot; +<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:36:in
<br>
`run'\n&quot; +<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:47:\n&quot;
+<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>
&quot;/cruisecontrol/tasks/cc_build.rake:32:\n&quot; +<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;-e:1:&quot;)<br>
+ &nbsp;end<br>
 <br>
end<br>
\ No newline at end of file<br>
<br>
<br>
_______________________________________________<br>
Cruisecontrolrb-developers mailing list</font></tt><tt><font size=2 color=blue><u><br>
</u></font></tt><a href="mailto:Cruisecontrolrb-developers@rubyforge.org" target=_blank><tt><font size=2 color=blue><u>Cruisecontrolrb-developers@rubyforge.org</u></font></tt></a><tt><font size=2 color=blue><u><br>
</u></font></tt><a href="http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers" target=_blank><tt><font size=2 color=blue><u>http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers</u></font></tt></a><font size=3><br>
</font>
<br><font size=3><br>
_______________________________________________<br>
Cruisecontrolrb-developers mailing list</font><font size=3 color=blue><u><br>
</u></font><a href="mailto:Cruisecontrolrb-developers@rubyforge.org"><font size=3 color=blue><u>Cruisecontrolrb-developers@rubyforge.org</u></font></a><font size=3 color=blue><u><br>
</u></font><a href="http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers" target=_blank><font size=3 color=blue><u>http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers
</u></font></a><font size=3><br>
</font>
<br>
<br>