Thursday, September 10, 2009

Executing PartCover from NAnt

I wanted to replace NCover with PartCover. PartCover is a new code coverage tool, and its still a freeware.

With NCover I had to run NUnit twice, first to get the unit test results, and then another run to get the code coverage. (At least with the last freeware version of NCover, 1.5.8. I have not tried the commercial versions)

With PartCover its possible to run the tests AND get the coverage at the same time.

Another advantage is that I can use newer versions of NUnit. The NCover 1.5.8 does not work with NUnit from version 2.5.

It seemed rather easy, but I had problems with quotes in the NAnt build file. The PartCover always terminated with an exception, whatever I tried; quotes, variables, expressions:

Invalid option '--target=C:\Program Files\NUnit 2.4.5\bin\nunit-console.exe'

One work-around is to use a NUnit or PartCover configuration file, but I wanted the NAnt build file to be independent.

The solution was to use HTML character entity references, i.e. a double quote (“) can be written as ".

Example of NAnt target that executes PartCover which in turn produces both a coverage report and a unit test report in a specified folder:

  <target name="unitTest">

    <!-- Get all unit test assemblies -->
    <foreach item="File" property="filename">
      <in>
        <items basedir=".">
          <include name="${Build.Output}\bin\${MyProject}.Test.dll"></include>
          <include name="${Build.Output}\bin\${MyProject}.*.Test.dll"></include>
        </items>
      </in>
      <do>

        <echo message="Unittesting ${filename}"/>

        <exec program="${PartCoverHome}\Partcover.exe" failonerror="true">
          <arg line="--target &quot;${NUnitExePath}&quot;" />
          <arg line="--target-work-dir ${Build.Output}\bin"/>
          <arg line="--target-args &quot;${filename} /xml=${Build.Reports}\${path::get-file-name-without-extension(filename)}-UnitTest.xml&quot;" />
          <arg line="--include [${MyProject}.*]*" />
          <arg line="--exclude [${MyProject}.*Test*]*" />
          <arg line="--output ${Build.Reports}\${path::get-file-name-without-extension(filename)}-Coverage.xml" />
        </exec>
      </do>
    </foreach>
  </target>  

Tuesday, July 7, 2009

Register WCF COM proxies with WIX

This is how I get the registration of WCF COM Proxies to work in WIX installation packets.

The CLSID and APPID are regenerated by the framework each time the version of the assembly is changed by. Avoid that by adding a Guid attribute to the COM proxy interface file (that’s the one generated with svcutil.exe).
I have still not managed to define all guid’s in the WCF Service interface file which I would prefer, as the proxy interface file changes are destroyed each time its regenerated.

namespace MyComProxy
{
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(Namespace="http://myservices.com", ConfigurationName="MyService.IMyInterface")]
    [Guid("E055A238-F196-3EF1-ADE2-AB124C197A1F")]
    public interface IMyInterface
    {
        [System.ServiceModel.OperationContractAttribute(Action="http://myservices.com/IMyInterface/DoSomething", ReplyAction="http://myservices.com/IMyInterface/DoSomethingResponse")]
        string DoSomething(string newValue);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [Guid("D1902FA8-A2DC-39BD-8009-6047F340E1CC")]
    public interface IMyInterfaceChannel : MyService.IMyInterface, System.ServiceModel.IClientChannel
    {
    }
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [Guid("3BAA7AE8-70C7-3D37-92B9-39971872567D")]
    public partial class MyInterface : System.ServiceModel.ClientBase&lt;MyService.IMyInterface&gt;, MyService.IMyInterface
    {
...
Remember to add the Guid attributes again if the file has to be regenerated with svcutil.

Now its time to use heat.exe to generate the Registry keys that makes the proxy visible to COM clients.

Verify that the “Register for COM interop” is checked for the COM Proxy project. Visual Studio then creates a type library file during compilation.

comreg

First generate the keys for the type library (it’s not recommended to use the WIX Typelib element, that’s why I specify –scom to get the actual Registry keys):

heat file -scom MyService.tlb -out tlbtags.wxs

Copy the Registry tags from the output file and add them to the tlb-component in the wxs-file.

Then generate Registry keys for the assembly:

heat file MyService.dll -out dlltags.wxs

Copy those keys to the dll-component in the wxs-file (ignore the <Class> tags). The Codebase keys can be removed.

Thursday, May 28, 2009

Empty Actions when mocking Java Web Service

I get the
System.InvalidOperationException: The operations methodX and methodY have the same action ().  Every operation must have a unique action value”, when trying to mock a Java Web Service with Rhino Mocks in CSharp.

The WSDL-file that was downloaded from the Java Web Service declared an empty soap action for each exported operation.
For example:

<operation name="aMethod">
  <soap:operation soapAction="" /> 
  <input>
   <soap:body use="literal" /> 
  </input>
  <output>
   <soap:body use="literal" /> 
  </output>
  <fault name="MyWebServiceException">
   <soap:fault name="MyWebServiceException" use="literal" /> 
  </fault>
</operation>

WCF uses the action to dispatch an incoming message to the correct method, see Action Property. Each method must have a unique action value.

I solved it by downloading the WSDL-file and remove all soap action declarations:

<soap:operation soapAction="" />

I ran the svcutil.exe on the changed WSDL-file.
WCF then creates unique action values in the service interface file, and the service can be mocked (as I described in Mocking WCF service).