<br><font size=2 face="sans-serif">At the same time, we can also format
the build details chunk that is displayed to the /projects dashboard. That
page is going to get a lot of hits, so it should be as fast as we can make
it.</font>
<br>
<br><font size=2 face="sans-serif">Alex</font>
<br>
<br>
<br>
<br>
<br>
<table width=100%>
<tr valign=top>
<td width=40%><font size=1 face="sans-serif"><b>Alexey Verkhovsky <averkhov@thoughtworks.com></b>
</font>
<br><font size=1 face="sans-serif">Sent by: cruisecontrolrb-developers-bounces@rubyforge.org</font>
<p><font size=1 face="sans-serif">02/10/2007 09:55 AM</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">rpotter@anl.gov, cruisecontrolrb-developers@rubyforge.org</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">Re: [Cruisecontrolrb-developers] [patch]
rspec support (partial)</font></table>
<br>
<table>
<tr valign=top>
<td>
<td></table>
<br></table>
<br>
<br>
<br><font size=2 face="sans-serif"><br>
Thanks a lot!</font><font size=3> <br>
</font><tt><font size=2><br>
> 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 <rpotter@anl.gov></b>
<br>
Sent by: cruisecontrolrb-developers-bounces@rubyforge.org</font><font size=3>
</font>
<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%><font size=1 face="sans-serif">cruisecontrolrb-developers@rubyforge.org</font><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>
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 (revision 181)<br>
+++ app/models/test_failure_parser.rb (working copy)<br>
@@ -1,25 +1,51 @@<br>
class TestFailureParser <br>
- TEST_NAME_REGEX = /\S+/<br>
- MESSAGE_REGEX = /\]\:\n([\s\S]+)/<br>
- STACK_TRACE_REGEX = /\[([\s\S]*?)\]\:/<br>
- TEST_FAILURE_BLOCK_REGEX = /^\s+\d+\) Failure:\n([\S\s]*?)\n\n/<br>
+<br>
+ TEST_FAILURE_BLOCK_REGEX = /^\s+?\d+\)(( Failure:)?\n[\S\s]*?)\n\n/<br>
+ <br>
+ SPEC_FAILURE_FORMAT = /^'[\s\S]+'\sFAILED[\s\S]*?/<br>
+ TEST_UNIT_FAILURE_FORMAT = / <br>
Failure:\n(\S+)\n?\s+?\[([\s\S]*?)\]:\n([\s\S]+)/<br>
+ <br>
def get_test_failures(log)<br>
testFailures = Array.new<br>
<br>
log.gsub(TEST_FAILURE_BLOCK_REGEX) do |text|<br>
content = $1<br>
- <br>
- begin<br>
- test_name = content.match(TEST_NAME_REGEX).to_s
<br>
- message = content.match(MESSAGE_REGEX)[1]<br>
- stack_trace = content.match(STACK_TRACE_REGEX)[1]<br>
- <br>
- testFailures << TestErrorEntry.create_failure(test_name,
<br>
message, stack_trace)<br>
- rescue<br>
- # Do Nothing, Pattern does not match<br>
- end <br>
+ <br>
+ if content.match(TEST_UNIT_FAILURE_FORMAT)<br>
+ testFailures << parse_as_test_unit(content)<br>
+ elsif content.gsub("\n",'').match(SPEC_FAILURE_FORMAT)<br>
+ testFailures << parse_as_rspec(content)<br>
+ else<br>
+ # no failures or we don't recognize
it<br>
+ end<br>
+ <br>
end<br>
<br>
testFailures<br>
end<br>
-end<br>
\ No newline at end of file<br>
+ <br>
+ private<br>
+ <br>
+ # parse Test::Unit log message and return TestErrorEntry<br>
+ def parse_as_test_unit(content)<br>
+ <br>
+ test_name = content.match(TEST_UNIT_FAILURE_FORMAT)[1].to_s
<br>
+ message = content.match(TEST_UNIT_FAILURE_FORMAT)[3]<br>
+ stack_trace = content.match(TEST_UNIT_FAILURE_FORMAT)[2]<br>
+ <br>
+ TestErrorEntry.create_failure(test_name, message, stack_trace)<br>
+ end<br>
+ <br>
+ # parse rspec log message and return TestErrorEntry<br>
+ def parse_as_rspec(content)<br>
+ <br>
+ spec_arr = content.split("\n")<br>
+ <br>
+ test_name = spec_arr[1].match(/^'([\s\S]+)' FAILED$/)[1].to_s
<br>
+ message = spec_arr[2].to_s<br>
+ stack_trace = spec_arr.slice(3..spec_arr.length).join("\n")<br>
+ <br>
+ TestErrorEntry.create_failure(test_name, message, stack_trace)<br>
+ end<br>
+ <br>
+end<br>
<br>
--- test/unit/test_failure_parser_test.rb (revision 181)<br>
+++ working_copy/test/unit/test_failure_parser_test.rb (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 = <<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 = <<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>
def test_should_not_find_test_failures_with_a_build_with_test_errors<br>
testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_TEST_ERRORS)<br>
assert_equal 0, testFailures.length<br>
@@ -87,19 +115,30 @@<br>
assert_equal 0, testFailures.length
<br>
end<br>
<br>
+ def test_should_find_no_spec_failures_with_successful_build<br>
+ testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_NO_SPEC_FAILURE)<br>
+ assert_equal 0, testFailures.length
<br>
+ end<br>
+ <br>
def test_should_find_test_failures<br>
testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_TEST_FAILURE)<br>
assert_equal 2, testFailures.length<br>
assert_equal expected_first_test_failure, testFailures[0]<br>
assert_equal expected_second_test_failure, testFailures[1]<br>
end<br>
- <br>
+ <br>
+ def test_should_find_spec_failures<br>
+ testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_SPEC_FAILURE)<br>
+ assert_equal 1, testFailures.length<br>
+ assert_equal expected_first_spec_failure, testFailures[0]<br>
+ end<br>
+ <br>
def test_should_correctly_parse_mocha_test_failures<br>
testFailures = <br>
TestFailureParser.new.get_test_failures(LOG_OUTPUT_WITH_MOCK_TEST_FAILURE)<br>
assert_equal 1, testFailures.length<br>
assert_equal expected_mock_test_failure, testFailures[0]<br>
end<br>
- <br>
+ <br>
def expected_first_test_failure<br>
<br>
TestErrorEntry.create_failure("test_should_fail(SubversionLogParserTest)",<br>
"<1> expected
but was\n<\"abc\">.",<br>
@@ -121,5 +160,15 @@<br>
<br>
"#<Mocha::Mock:0x-245ec74a>.force_build_if_requested - expected
calls: <br>
1, actual calls: 2",<br>
<br>
"./test/unit/polling_scheduler_test.rb:44")<br>
end<br>
+<br>
+ def expected_first_spec_failure<br>
+ TestErrorEntry.create_failure("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",<br>
+
"nil should be a kind
of Array",<br>
+
<br>
"./spec/controllers/consultant_controller_spec.rb:47:\n" +<br>
+
<br>
"/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:36:in
<br>
`run'\n" +<br>
+
<br>
"/cruisecontrol/builds/ccs/work/config/../lib/tasks/cruise.rake:47:\n"
+<br>
+
<br>
"/cruisecontrol/tasks/cc_build.rake:32:\n" +<br>
+
"-e:1:")<br>
+ end<br>
<br>
end<br>
\ No newline at end of file<br>
<br>
<br>
_______________________________________________<br>
Cruisecontrolrb-developers mailing list<br>
Cruisecontrolrb-developers@rubyforge.org<br>
http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers</font></tt><font size=3><br>
</font><tt><font size=2>_______________________________________________<br>
Cruisecontrolrb-developers mailing list<br>
Cruisecontrolrb-developers@rubyforge.org<br>
http://rubyforge.org/mailman/listinfo/cruisecontrolrb-developers<br>
</font></tt>
<br>