Jeffrey Palermo (.com)

Sponsors

The Lounge

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
How to integrate FitNesse acceptance tests into your CC.Net build - level 300

I'm doing a lot with FitNesse lately, and it's going quite well.  Unit testing ensures that each component is doing what it is supposed to, and integration testing ensures that the components work well together.  Acceptance tests are a bit different.  They actually test that the software does what the customers think it's doing.  They test that the developer understood the business need.  They give the customer (or product manager) assurance that the system actually works.

With FitNesse, our product manager (and crew) can  use a simple wiki to exercise the system.  The developers create test Fixtures that speak in the domain language but actually exercise the system under test.  A user may type:

!|fit.ActionFixture|
|start|Emailer|
|press|SendDefaultEmail|
|check|NumEmailsSent|

This simple table is enough to actually exercise the system under test and get it to do something.  If all is well, the Emailer will send a default email.  If this test fails, it saves the company from a black eye when a user encounters the problem.

It was a little tricky to get the FitNesse test integrated with our CC.Net build.  We wanted the acceptance test to be a current status report of where we are.  When all the acceptance tests are passing, we are done.  Consequently, we didn't want failing acceptance tests to break the build.  Only NUnit tests break the build because they should _always_ be passing.  No problem.  We create a new target with some exec tasks:

<exec program="<path to TestRunner.exe>" commandline="-results <some directory>\FitNesse-Results.html <FitNesse server> <port> <TestSuite>" failonerror="false"/>

This will actually call the FitNesse server (with the wiki on it) and execute all the acceptance tests.  This will produce a file in the raw FitNesse format.  We'd like it in xml so we can incorporate it in the CC.Net build report.  Xml transforming isn't a part of the .Net port, but it is in the Java version, so we'll just use it.

<exec program="java.exe" commandline="-cp bin\fit\fitnesse.jar fitnesse.runner.FormattingOption <some directory>\FitNesse-Results.html xml <some directory>\Fit-Results.xml <FitNesse server> <port> <TestSuite>" failonerror="false"/>

This hooks into the transform logic on the FitNesse server to change our raw output file to a nice Xml format.  Now we have something that CruiseControl.Net can use for a build report and email.  We will have to make an Xsl, though.  Here's a simple Xsl that will pull out the FitNesse summary information and through it out to your CC.Net build summary:

<?xml version="1.0"?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html"/>

<xsl:variable name="fit.result.list" select="//testResults/result"/>

<xsl:variable name="fit.wrongpagecount" select="countU$fit.result.list/counts/wrong[text() > 0])" />

<xsl:variable name="fit.ignorespagecount" select="countU$fit.result.list/counts/ignores[text() > 0])" />

<xsl:variable name="fit.exceptionspagecount" select="countU$fit.result.list/counts/exceptions[text() > 0])" />

<xsl:variable name="fit.correctpagecount" select="countU$fit.result.list/counts[wrong/text() = 0 and exceptions/text() = 0 and ignores/text() = 0])" />

<xsl:variable name="fit.correctcount" select="//testResults/finalCounts/right"/>

<xsl:variable name="fit.failures" select="//testResults/finalCounts/wrong"/>

<xsl:variable name="fit.notrun" select="//testResults/finalCounts/ignores"/>

<xsl:variable name="fit.exceptions" select="//testResults/finalCounts/exceptions"/>

<xsl:variable name="fit.case.list" select="$fit.result.list//test-case"/>

<xsl:variable name="fit.suite.list" select="$fit.result.list//test-suite"/>

<xsl:variable name="fit.failure.list" select="$fit.case.list//failure"/>

<xsl:variable name="fit.notrun.list" select="$fit.case.list//reason"/>

<xsl:variable name="colorClass">

<xsl:choose>

<xsl:when test="$fit.exceptionspagecount > 0">fiterror</xsl:when>

<xsl:when test="$fit.ignorespagecount > 0">fitignore</xsl:when>

<xsl:when test="$fit.wrongpagecount > 0" >fitfail</xsl:when>

<xsl:otherwise>fitpass</xsl:otherwise>

</xsl:choose>

</xsl:variable>

<xsl:variable name="fit.tests.present" select="countU//testResults/result) > 0 or count(/cruisecontrol/build/buildresults//testsuite) > 0" />

<xsl:template match="/">

<xsl:choose>

<xsl:when test="$fit.tests.present">

<style>

*.fitpass{

background-color: #AAFFAA;

}

*.fitfail{

background-color: #FFAAAA;

}

*.fiterror

{

background-color: #FFFFAA;

}

*.fitignore

{

background-color: #CCCCCC;

}

*.fitheader{

border: solid 1px black;

margin: 1px;

padding: 2px;

}

*.line{

margin: 5px;

}

</style>

<div>

<div class="{$colorClass} fitheader">

<strong>FitNesse Summary -- Test Pages:</strong> <xsl:value-of select="$fit.correctpagecount"/> right, <xsl:value-of select="$fit.wrongpagecount"/> wrong,

<xsl:value-of select="$fit.ignorespagecount"/> ignored, <xsl:value-of select="$fit.exceptionspagecount"/> exceptions

<strong>Assertions:</strong> <xsl:value-of select="$fit.correctcount"/> right, <xsl:value-of select="$fit.failures"/> wrong,

<xsl:value-of select="$fit.notrun"/> ignored, <xsl:value-of select="$fit.exceptions"/> exceptions

</div>

<xsl:for-each select="$fit.result.list">

<xsl:variable name="colorClass">

<xsl:choose>

<xsl:when test="counts/exceptions > 0">fiterror</xsl:when>

<xsl:when test="counts/ignores > 0">fitignore</xsl:when>

<xsl:when test="counts/wrong > 0" >fitfail</xsl:when>

<xsl:otherwise>fitpass</xsl:otherwise>

</xsl:choose>

</xsl:variable>

<div class="line">

<span class="{$colorClass}" style="padding:2px;" ><xsl:value-of select="counts/right"/> right, <xsl:value-of select="counts/wrong"/> wrong,

<xsl:value-of select="counts/ignores"/> ignored, <xsl:value-of select="counts/exceptions"/> exceptions </span>

<span style="padding:2px;"><xsl:value-of select="relativePageName"/></span>

</div>

</xsl:for-each>

</div>

</xsl:when>

</xsl:choose>

</xsl:template>

</xsl:stylesheet>

 

Hook this Xsl into your CC.Net configuration, and that's as hard as it is!  FitNesse results "magically" show up in the build summary.  It's really a big win for visibility into the state of the software.  The build summary is now the actual status report of the software, and it's not subjective.  What does 83% actually mean?  With a list of acceptance tests to fulfill, we know exactly when we are done.


 


Posted 09-13-2005 11:30 AM by Jeffrey Palermo
Filed under:

[Advertisement]

Comments

Robin Curry wrote How to integrate FitNesse acceptance tests into your CC.Net build
on 09-14-2005 11:04 AM
Chris Gardner wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 09-16-2005 6:13 PM
Thanks for putting this script together. I had to tweak, though, to get it to work with CruiseControl (did not try it with CC.Net). Here are my changes. Hopefully they won't get corrupted in this post.

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html"/>

<xsl:variable name="fit.result.list" select="//testResults/result"/>

<xsl:variable name="fit.wrongpagecount"
select="count($fit.result.list/counts/wrong[text() > 0])" />

<xsl:variable name="fit.ignorespagecount"
select="count($fit.result.list/counts/ignores[text() > 0])" />

<xsl:variable name="fit.exceptionspagecount"
select="count($fit.result.list/counts/exceptions[text() > 0])" />

<xsl:variable name="fit.correctpagecount"
select="count($fit.result.list/counts[wrong/text() = 0 and exceptions/text() = 0 and ignores/text() = 0])" />

<xsl:variable name="fit.correctcount"
select="//testResults/finalCounts/right"/>

<xsl:variable name="fit.failures"
select="//testResults/finalCounts/wrong"/>

<xsl:variable name="fit.notrun"
select="//testResults/finalCounts/ignores"/>

<xsl:variable name="fit.exceptions"
select="//testResults/finalCounts/exceptions"/>

<xsl:variable name="fit.case.list"
select="$fit.result.list//test-case"/>

<xsl:variable name="fit.suite.list"
select="$fit.result.list//test-suite"/>

<xsl:variable name="fit.failure.list"
select="$fit.case.list//failure"/>

<xsl:variable name="fit.notrun.list"
select="$fit.case.list//reason"/>

<xsl:variable name="colorClass">
<xsl:choose>
<xsl:when test="$fit.exceptionspagecount > 0">fiterror</xsl:when>
<xsl:when test="$fit.ignorespagecount > 0">fitignore</xsl:when>
<xsl:when test="$fit.wrongpagecount > 0" >fitfail</xsl:when>
<xsl:otherwise>fitpass</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:variable name="fit.tests.present"
select="count($fit.result.list) > 0 or count(//cruisecontrol/build/buildresults//testsuite) > 0" />

<xsl:template match="/" mode="fitnesse">
<xsl:choose>

<xsl:when test="$fit.tests.present">
<style>

*.fitpass{

background-color: #AAFFAA;

}

*.fitfail{

background-color: #FFAAAA;

}

*.fiterror

{

background-color: #FFFFAA;

}

*.fitignore

{

background-color: #CCCCCC;

}

*.fitheader{

border: solid 1px black;

margin: 1px;

padding: 2px;

}

*.line{

margin: 5px;

}

</style>

<div>

<div class="{$colorClass} fitheader">

<strong>FitNesse Summary -- Test Pages:</strong> <xsl:value-of select="$fit.correctpagecount"/> right, <xsl:value-of select="$fit.wrongpagecount"/> wrong,

<xsl:value-of select="$fit.ignorespagecount"/> ignored, <xsl:value-of select="$fit.exceptionspagecount"/> exceptions

<strong>Assertions:</strong> <xsl:value-of select="$fit.correctcount"/> right, <xsl:value-of select="$fit.failures"/> wrong,

<xsl:value-of select="$fit.notrun"/> ignored, <xsl:value-of select="$fit.exceptions"/> exceptions

</div>

<xsl:for-each select="$fit.result.list">

<xsl:variable name="colorClass">

<xsl:choose>

<xsl:when test="counts/exceptions > 0">fiterror</xsl:when>

<xsl:when test="counts/ignores > 0">fitignore</xsl:when>

<xsl:when test="counts/wrong > 0" >fitfail</xsl:when>

<xsl:otherwise>fitpass</xsl:otherwise>

</xsl:choose>

</xsl:variable>

<div class="line">

<span class="{$colorClass}" style="padding:2px;" ><xsl:value-of select="counts/right"/> right, <xsl:value-of select="counts/wrong"/> wrong,

<xsl:value-of select="counts/ignores"/> ignored, <xsl:value-of select="counts/exceptions"/> exceptions </span>

<span style="padding:2px;"><xsl:value-of select="relativePageName"/></span>

</div>

</xsl:for-each>

</div>

</xsl:when>

</xsl:choose>

</xsl:template>

</xsl:stylesheet>
Bernard Vander Beken wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 09-20-2005 10:32 AM
Thanks for this info.

What is the approach you use to keep the Fitnesse server running? Do you run it in its default mode, or do you run it as a service?
Jeffrey Palermo wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 09-20-2005 1:51 PM
We started out running it manually, but now we've integrated it with ServiceAny that allows any command to be run as a service. Another option we considered was using the Windows scheduler to ensure that it is always running.
Jeffrey Palermo wrote Mike Roberts integrates FitNesse with CruiseControl.Net and Subversion - level 300
on 12-29-2005 2:32 PM
A while back, I posted about how my team integrated and versioned our FitNesse wiki with CruiseControl.Net...
Jeffrey Palermo wrote Benefits of FIT tests for systems without a UI - level 200
on 02-23-2006 9:20 AM
Sam Gentile reminds us of the value of FIT when requirements might be vague _and_ complicated.&amp;nbsp;...
Jeffrey Palermo wrote Benefits of FIT tests for systems without a UI - level 200
on 03-02-2006 10:23 AM
Sam Gentile reminds us of the value of FIT when requirements might be vague _and_ complicated.&amp;nbsp;...
Jeffrey Palermo wrote Mike Roberts integrates FitNesse with CruiseControl.Net and Subversion - level 300
on 03-02-2006 10:26 AM
A while back, I posted about how my team integrated and versioned our FitNesse wiki with CruiseControl.Net...
Jeremy D. Miller -- The Shade Tree Developer wrote Automated Web Testing with Selenium Driven by .Net
on 05-14-2006 11:52 PM
The Agile development community has struggled for years with an array of solutions for automated testing...
Ruslan Trifonov's blog wrote Automated Acceptance Testing with Fitnesse, Selenium and .NET 2.0
on 09-21-2006 5:39 PM

I&#39;m digging lately with my team into our new product. We are using a full stack of buzz words in

TestingGeek wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 08-09-2007 10:14 AM

That's quite nice.. looks like I have got all the material that I needed to integrate FitNesse test suite with Version Control and Cruise Control.. Thanks a bunch.

Power Boots wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 10-30-2007 5:18 PM

Hi Jeffrey, as always, thinks are not crystal clear.

What do you mean by "Hook this Xsl into your CC.Net configuration"?

CC.net 1.3 already comes with fitnesse.xsl and fit.xsl.

And I still cannot see the Fitnesse summary into CruiseControl dashboard...

Anyhow, you did a great job!

Chandu wrote re: How to integrate FitNesse acceptance tests into your CC.Net build - level 300
on 03-17-2008 11:54 AM

Hi All,

Can anyone please tell me how to convert the Fitnesse output to HTML format??

Thanks in Advance.

Chandu.