Friday, October 29, 2010

Executing a PowerShell script from TFS 2010 workflow

  1. Add an InvokeProcess activity to the workflow.
  2. Set the DisplayName property to something useful for logging and debugging.
  3. Set the FileName property to "powershell.exe"
  4. Set the Arguments like this:
    "-file """ + SourcesDirectory + "\Scripts\SetAssemblyVersions.ps1"" " + MajorVersionNumber.ToString() + " " + MinorVersionNumber.ToString() + " " + BuildDetail.SourceGetVersion.Substring(1) + " " + BuildDetail.BuildNumber.Substring(BuildDetail.BuildNumber.LastIndexOf(".") + 1)
  5. Give names to the standard output and error output streams.
  6. Add a WriteBuildMessage activity under the Handle Standard Output field and set its Message property to the standard output stream defined above.
  7. Add a WriteBuildError activity under the Handle Error Output field and set its Message property to the error output stream defined above.

Thursday, October 28, 2010

Quotes I like

Give me six hours to chop down a tree and I will spend the first four sharpening the axe.
-- Abraham Lincoln

If you always put limit on everything you do, physical or anything else, it will spread into your work and into your life. There are no limits. There are only plateaus, and you must not stay there, you must go beyond them.
-- Bruce Lee

If I’d asked people what they wanted, they would have said a faster horse.
-- Henry Ford, car guy

Yesterday I tried to cut my steak with a spoon and that goddam spoon sucked-ass. Why the hell would anybody ever use a spoon for anything? They are completely useless!
-- Jason

I think that emphasizing heroics in any form usually does more harm than good.
-- Steve McConnell

Setting up FitNesse for .NET with SliM

Basic steps for setting up FitNesse for .NET with the wiki stored under source control. Review all code that you copy and paste from this page because it may need to be modified for your situation.

  1. Create a simple fixture:
    public class IsFitNesseCorrectlySetup
    {
        public int Value { get; set; }
    
        public int GetValueDoubled()
        {
            return Value * 2;
        }
    }
    
  2. Download FitNesse and SliM, and save these into separate folders under your third party folder in source control (everything here is presumed to be under source control).
  3. Create this .cmd file for testers to use (presumes TFS; will need to be modified for other source control systems):
    @echo off
    setlocal
    "%VS100COMNTOOLS%\..\IDE\TF.exe" get "%~dp0.." -r
    "%VS100COMNTOOLS%\..\IDE\TF.exe" checkout "%~dp0FitNesseRoot" -r
    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe "%~dp0..\Solution\Solution.sln" /p:configuration=release
    set FitNessePort=8084
    start /min /d "%~dp0..\ThirdParty\FitNesse" java -jar fitnesse.jar -p %FitNessePort% -d "%~dp0." -r FitNesseRoot
    start http://localhost:%FitNessePort%/
    endlocal
  4. Launch FitNesse and add the following to the root page (modifying paths to match your folder structure):
    !*****> Configuration
    !define TEST_SYSTEM {slim}
    !path .dll
    !define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,..\..\ThirdParty\FitSharp\fitsharp.dll %p}
    !define TEST_RUNNER {..\..\ThirdParty\FitSharp\Runner.exe}
    *****!
  5. Add a normal page (not a test page) called SetUp at the top level of your suite, and put the following in it to let FitNesse know which namespaces to find your fixtures in:
    !|import|
    |Your Fixture DLL namespace|
  6. Create a test page with this test:
    !|Is FitNesse correctly set up|
    |Value   |Get value doubled?  |
    |2       |4                   |
    |23      |46                  |
    |100     |200                 |
    |200     |399<_<401           |
    Run the test, which should pass.
Note that these files in the FitNesse wiki should not be checked in to source control:
  • *.zip
  • ErrorLogs\**
  • files\testResults\**
  • RecentChanges\**

Tuesday, October 19, 2010

Invalid code coverage item error in MSTest

I ran into the following running unit tests after a build under TFS 2010:

Invalid code coverage item: The pdb file name must contain at least one character.

I had modified the .testsettings file to use relative paths instead of absolute paths, but the build was failing with the above error.

The solution was to edit the .testsettings file to add a pdbFile attribute:

<CodeCoverageItem binaryFile="..\Utilities\%outdir%\Utilities.dll" pdbFile="..\Utilities\%outdir%\Utilities.pdb" instrumentInPlace="true" />

Continuous integration

This is what I like to run for continuous integration builds:
  1. Set version numbers in all assemblies.
  2. The release build.
  3. Code analysis (build breaker).
  4. Unit tests (build breaker).
  5. Integration tests (build stability).
  6. FitNesse tests (build stability).

Outputs I like to collect are:
  • Build outputs, including PDBs, ideally in a symbol server.
  • Code coverage percentage and details.
  • Test results.

Wednesday, October 13, 2010

Setting up code analysis in Visual Studio

Code Analysis Rule Files

Copy these files to an appropriate location in the source tree:
For test code:
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Test Code" Description="Rules for unit and integration test assemblies." ToolsVersion="11.0">
  <IncludeAll Action="Error" />
  <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
    <Rule Id="CA1004" Action="None" />
    <Rule Id="CA1014" Action="None" />
    <Rule Id="CA1020" Action="None" />
    <Rule Id="CA1024" Action="None" />
    <Rule Id="CA1026" Action="None" />
    <Rule Id="CA1031" Action="None" />
    <Rule Id="CA1062" Action="None" />
    <Rule Id="CA1300" Action="None" />
    <Rule Id="CA1303" Action="None" />
    <Rule Id="CA1502" Action="None" />
    <Rule Id="CA1506" Action="None" />
    <Rule Id="CA1702" Action="None" />
    <Rule Id="CA1707" Action="None" />
    <Rule Id="CA1709" Action="None" />
    <Rule Id="CA1822" Action="None" />
    <Rule Id="CA2204" Action="None" />
    <Rule Id="CA2210" Action="None" />
  </Rules>
</RuleSet>
For production code:
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Production Code" Description="Rules for production code." ToolsVersion="11.0">
  <IncludeAll Action="Error" />
  <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
    <Rule Id="CA1004" Action="None" />
    <Rule Id="CA1020" Action="None" />
    <Rule Id="CA1024" Action="None" />
    <Rule Id="CA1026" Action="None" />
    <Rule Id="CA1303" Action="None" />
    <Rule Id="CA1502" Action="None" />
    <Rule Id="CA1506" Action="None" />
    <Rule Id="CA1822" Action="None" />
    <Rule Id="CA2204" Action="None" />
    <Rule Id="CA2210" Action="None" />
  </Rules>
</RuleSet>

Language

I am not aware of a GUI that allows setting the language for Visual Studio code analysis.

To do this manually, add the following line to your .csproj files under the main <PropertyGroup> tag:

<CodeAnalysisCulture>en-NZ</CodeAnalysisCulture>

This setting is obviously for New Zealand English. Consult this table for the appropriate locale ID.

Custom Dictionary

Set up a custom dictionary file called CustomDictionary.xml and add a link to it in one of your projects. Set the build action (in the properties page) to CodeAnalysisDictionary. To duplicate this into other projects in the same solution, just drag into each of those solutions. I use the following as a default:
<Dictionary>
  <Words>
    <Unrecognized>
      <Word></Word>
    </Unrecognized>
    <Recognized>
      <Word>Mvc</Word>
      <Word>Serialise</Word>
      <Word>Serialisation</Word>
      <Word>Serialiser</Word>
      <Word>Deserialise</Word>
      <Word>Deserialised</Word>
      <Word>Deserialisation</Word>
      <Word>Nesse</Word>  <!--From FitNesse-->
    </Recognized>
    <Deprecated>
      <Term PreferredAlternate=""></Term>
    </Deprecated>
    <Compound>
      <Term CompoundAlternate=""></Term>
    </Compound>
    <DiscreteExceptions>
      <Term></Term>
    </DiscreteExceptions>
  </Words>
  <Acronyms>
  </Acronyms>
</Dictionary>

Project Configuration

In each project's property pages under the Code Analysis tab, set the rule set to either the test or production set, and enable the code analysis for release builds only. Running code analysis slows down the build and may not be suitable for debug builds.

TFS

In your continuous integration build definition, set code analysis to Always.