mikeobrien.net Curriculum Vitae Blog Labs
Wednesday, November 18, 2009

Gallio is a fantastic test runner that integrates with a number of tools (like R#, which I love) and a ton of testing frameworks. So I set out to modify our NAnt build scripts to use Gallio instead of invoking tests directly with a particular testing framework. Here is how the setup went having NAnt invoke Gallio which invoked NUnit tests (Thanks to Rob Reynolds for his insights):

1) Download and unzip the Gallio distro from here: http://www.gallio.org/Downloads.aspx

2) Setup the NAnt tasks as follows (To run all tests in an assembly). You can get more info on the Gallio NAnt task properties here. The filter defaults to all but I included it for demo purposes. Error code 16 means that there were no tests. I ignored it since I was reorganizing the test suites and some didn’t have tests yet.

<loadtasks assembly="<GalioBinFolder>\Gallio.NAntTasks.dll" />
<gallio working-directory="<TestSuiteWorkingFolder>"
        report-types="Xml-Inline"
        report-directory="<ReportFolder>"
        report-name-format="gallio-results"
        show-reports="false"
        failonerror="false"
        verbosity="Normal"
        echo-results="false"
        filter="include *"
        result-property="GallioResult">
  <files>
    <include name="<PathToATestSuiteAssembly>"/>
  </files>
</gallio>
<fail if="${GallioResult != '0' and GallioResult != '16'}" >
One or more tests failed (Error code ${GallioResult}).
Please check the log for more details</fail>

3) Copy the \GallioBundle-x-x-x\bin\Resources folder to \CruiseControl.NET\webdashboard or another location that is accessible from the web.

4) Copy \GallioBundle-x-x-x\bin\Resources\xsl\*.xsl to \CruiseControl.NET\webdashboard\xsl. You don't actually need all those files, but who knows, that may change in the future.

5) Edit the Gallio-Report.ccnet-details.xsl and Gallio-Report.ccnet-details-condensed.xsl files in the \CruiseControl.NET\webdashboard\xsl folder from step 4. Set the cssDir, jsDir, imgDir variables to the url of the files you copied in step 3.

6) Open the \CruiseControl.NET\webdashboard\dashboard.config file and add the following entries:

<dashboard>
  ...
  <plugins>
    ...
    <buildPlugins>
      <buildReportBuildPlugin>
        <xslFileNames>
          ...
          <xslFile>xsl\Gallio-Report.ccnet-details-condensed.xsl</xslFile>
          ...
        </xslFileNames>
      </buildReportBuildPlugin>
      ...
      <xslReportBuildPlugin description="Test Summary" actionName="GallioSummary"
                  xslFileName="xsl\Gallio-Report.ccnet-details-condensed.xsl" />
      <xslReportBuildPlugin description="Test Details" actionName="GallioDetails"
                  xslFileName="xsl\Gallio-Report.ccnet-details.xsl" />
      ...
    </buildPlugins>
    ...
  </plugins>
</dashboard>

Unfortunately Gallio doesn't currently have an email friendly report stylesheet so you’ll have to roll your own.

Wednesday, November 18, 2009 10:50:03 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Monday, January 26, 2009

There are a number of ways to setup configuration in the development, pre production and production environments. One way is to maintain independent .config files for different environments\developers and manually copy the appropriate file to the target during deployment. I've never warmed up to this approach as it leads to obvious headaches like difficulty keeping the config files in sync (And making sure everyone is using the most up to date config file), its error prone, and there ends up being many different .config files. I have been using an approach that I really like where there is one and only one .config file for all developers and all environments (Per project of course). Developers all share the same config file and thus the same configuration. When the config file is deployed to different environments, like UAT, staging and production, the deployment NANT script modifies the configuration during deployment (I also enforce a separation between NAnt script and configuration so setting and maintaining of configuration is fairly trivial). When the config file is modified it is automatically propagated to developers when they do an update and the new schema is guaranteed to make it to all the different environments. Of course the down side to this approach is the same as the up side, every developer has the same configuration... It would really be a pain to force every developer to have a strictly defined development environment; there is no flexibility and leeway for developer preference. In order to get the best of both worlds I've been using the hosts file and symbolic links to "map" the common configuration to the developers configuration.  For example the default developer config (In source control) might look like this:

<configuration>
  <sweetApp>
    <paths>
      <mediaFiles localPath="C:\SweetCompany\SweetApp\SweetApp.Web.UI\MediaFiles"/>
      <uploads localPath="C:\SweetCompany\SweetApp\Uploads"/>
    paths>
    <web>
      <sites errorPage="/SystemMessage.aspx">
        <main domainName="www.dev.sweetapp.com" />
        <services domainName="services.dev.sweetapp.com" />
        <administration domainName="admin.dev.sweetapp.com" />
      sites>
    web>
  sweetApp>
  <system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="admin@sweetapp.com">
        <network host="smtp.dev.sweetapp.com" port="25" 
                 defaultCredentials="true"/>
      smtp>
    mailSettings>
  system.net>
configuration>

The hosts file, under %SystemRoot%\system32\drivers\etc\, allows you to point a network name to an IP address (You probably already know this...). So in the example above the developer could add to the following to their host file.

# SweetApp Dev Mappings
127.0.0.1          www.dev.sweetapp.net
127.0.0.1     services.dev.sweetapp.net
127.0.0.1        admin.dev.sweetapp.net
127.0.0.1         smtp.dev.sweetapp.net

This will of course map all these network names the local machine. But if, for example, the developer wanted to run parts of their environment in a VM or on another box altogether they could easily point to the IP address elsewhere. If your creating a hosts file entry for your local SQL Server that you will be connecting to with Windows Auth, be sure to setup an alias as described here

The other issue is paths. I personally keep all my "data" (Including code) under a second partition. And I like to keep things under a particular folder structure. Others may not roll this way and have different path/drive preferences. Using directory junctions you can create a "shortcut" to another folder. This can be easily accomplished with the mklink command in Vista/Server 08 (In XP and earlier there is another utility in the resource kit but I forget the name.) For the above example you could issue the following command to create a junction that links to a working folder on the D: drive.

mklink /J c:\SweetCompany\SweetApp d:\Dev\WorkApps\SweetApp

This essentially maps the first folder to the second folder so the path references in the config file will be valid but the developer can work out of the path they choose. You can also accomplish something similar with the subst command (Which maps a drive letter to a path). The problem with this approach is that the mapping is only recognized in the current login session. An ASP.NET page, for example, will know nothing about it since its running under the logon session of its process identity.

Monday, January 26, 2009 11:05:32 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Creative Commons License