Monday, July 12, 2010

dotCover 1.0 beta -- first impressions

The beta of the coverage tool from the same people who brought you Resharper came out late last week, and I took the chance to have a quick play with what it offers.

As expected, it integrates smoothly with the R# unit test running -- you can see exactly what code your test or set of tests cover; marked in green overlay in the source view for covered by the test(s) you just ran, red elsewhere, in a manner reminiscent of NCoverExplorer.

There is also a command-line option

Usage: JetBrains.dotCover.ConsoleRunner.exe /Executable='executable' [/Arguments='arguments'] [/WorkingDir='working dir'] /Output='output' 

Not having R# at home -- because I rarely use C# even if I'm writing for .net -- it's this which interested me more. So, I gave it a try on my current F# project

>& 'C:\Program Files\JetBrains\dotCover\v1.0\Bin\JetBrains.dotCover.ConsoleRunner.exe' /executable='..\..\..\_Tools\Microsoft FxCop 1.36\FxCopCmd.exe' /Arguments='/q /s /console /f:Tinesware.Recorder.dll /f:Tinesware.Instrumentation.exe /f: Tinesware.Infrastructure.dll /f:Tinesware.Rules.dll /f:Tinesware.InfrastructureTests.dll /f:BaseTests.dll  /rule:Tinesware.Rules.dll /o:fxcop.xml  /rule:.\Rules /dictionary:..\..\..\CustomDictionary.xml' /workingdir=. /output=dotcover.xml

which yields a bald total coverage number

JetBrains dotCover Console Runner v1.0.56.11 JetBrains s.r.o.
Coverage session started [12/07/2010 20:14:16]
Coverage session finished [12/07/2010 20:14:28]
Index files: ...AppData\Local\Temp\ssc06AE2.tmp
Log files: ...AppData\Local\Temp\lgc02A14.tmp
Opening snapshot...
Done.
Generating report...
Done.
Total coverage: 78%

and an XML report file that makes it clear that that percentage is based on all assemblies dragged into the AppDomain, counting those which have no pdb information as containing no statements to cover, which means if you're running unit tests with Rhino.Mocks that it includes things like

<Assembly Name="021925b1-cbe9-42d3-ad44-a39206195c2a" CoveredStatements="0" TotalStatements="0" CoveragePercent="0">
    <Type Name="IsolatorProxyb66a653c9a984566ac790c4fa654cab5" CoveredStatements="0" TotalStatements="0" CoveragePercent="0">
      <Type Name="InvocationShouldCallOriginal_1" CoveredStatements="0" TotalStatements="0" CoveragePercent="0">
        <Member Name="HandleEvent" CoveredStatements="0" TotalStatements="0" CoveragePercent="0" />

emanating from dynamic assemblies. And it seems from simple experiment that the filters that you can apply in Visual Studio don't seem to carry over to the command-line version.

The report is formatted as shown above, with hierarchy

Root -> Assembly -> Namespace -> Type -> Nested Type or Member (repeating Type as often as necessary)

There’s also no granularity below Member, so even for code with .pdb information available the reports only look like

<Type Name="Local" CoveredStatements="166" TotalStatements="173" CoveragePercent="95">
...
        <Member Name="get_Mutex" CoveredStatements="0" TotalStatements="0" CoveragePercent="0" />
        <Member Name="ExpandFile" CoveredStatements="2" TotalStatements="4" CoveragePercent="50" />
        <Member Name="LoadFile" CoveredStatements="4" TotalStatements="7" CoveragePercent="57" />
        <Member Name="op_GreaterQmarkGreater" CoveredStatements="4" TotalStatements="4" CoveragePercent="100" />
        <Member Name="op_GreaterPlusQmarkQmark" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="op_GreaterMultiplyGreater" CoveredStatements="4" TotalStatements="5" CoveragePercent="80" />
        <Member Name="op_GreaterPlusQmark" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="op_GreaterPlus" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="GetXmlData" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="DoWithLock" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="op_Append" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="GetByName" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="SetByName" CoveredStatements="1" TotalStatements="1" CoveragePercent="100" />
        <Member Name="GetStatementRange" CoveredStatements="2" TotalStatements="2" CoveragePercent="100" />
        <Member Name="FindSignatureForMethod" CoveredStatements="8" TotalStatements="8" CoveragePercent="100" />
        <Member Name="FindXmlForMethod" CoveredStatements="7" TotalStatements="7" CoveragePercent="100" />
        <Member Name="get_DeclaredExempt" CoveredStatements="0" TotalStatements="0" CoveragePercent="0" />
        <Member Name="get_AutomaticExempt" CoveredStatements="0" TotalStatements="0" CoveragePercent="0" />
...
      </Type>

So there can be no useful equivalent of NCoverExplorer for after the fact detail – to get detailed line un-coverage information you actually have to run every one of your unit tests in Visual Studio in one big bang.

Its metric of what counts as a statement is subtly different from what NCover (free) and the other tools I've been working on recently. It reports an F# property like

let AutomaticExempt = "-2"

or an equivalent C# automatic property, for that matter, as having 0 lines, rather than N/A and 1 respectively; but that aside it seems to be counting the self-same list of sequence points.

So, it seems that this is primarily a tool for interactive use and positive coverage testing -- "Does this set of tests cover this line, and if so, which one(s)?"; in a build process environment the lack of ability to focus down to only the assemblies of interest in the report (discarding tool and system code), and of per-statement reporting it is less interesting.

However it did take the F# code which PartCover had balked at in its stride.

Meanwhile in other news

There is a branch of PartCover that supports .net 4 originally on GitHub and which has now been merged into the main-line at SourceForge, removing one of the objections to using this tool. There also seems to be rather more life in this than there was six months ago when I tried it, so I shall have to revisit it and see if the IL issue is also resolved.

Sunday, June 06, 2010

Cycling Holiday

This time based at Seckford Hall Hotel, just across the A12 from Woodbridge. This meant that going anywhere by bike meant heading west into the country lanes first; and that routes were circumscribed by not wanting to cross the A12 or A14.

After a wet day on Tuesday, driving to the hotel and dining there, the rest of the week was glorious early summer -- bright, dry, and with cooling onshore breezes holding the temperature to sensible levels.

First day I decided to strike out a long route, starting with following a cycle route across the top of Ipswich, then clipping a corner -- with a little bit of dead reckoning -- and around, arriving at Pin Mill for lunch.

Pin Mill

Pin Mill

I did a loop round Alton Water to return, and then into Ipswich and through rather than retrace the loop. There had been enough cycle provision in the bit I had done before that it seemed resonable; though on the return leg there were a lot of cyclelanes interrupted by traffic calming islands. The bit through the centre I wheeled the bike, but otherwise it was no problem.


View 2-Jun-2010 in a larger map

Second day, out to the coast, into the strong breeze; cool enough by the time I was approaching Orford to want to put a long-sleeved shirt on. This time, crossing the A12 at a cycle crossing with lights, and cruising through Woodbridge.

Castle and chestnuts

Orford Castle

Return via Snape, and a familiar route -- indeed a lot of the suggested routes on this holiday were ones I'd taken when wanting to lengthen the ride on others.


View 3-Jun-2010 in a larger map

The last day started and finished the same, and I headed up to Framlingham, to check out whether Off the Square was functional again for lunch -- alas it seemed to be re-booting (adverts in the windows for head and sous-chef; no menu displayed). So looped back after a pub lunch at the Old Mill House at Saxtead Green.

Saxtead Mill

Saxtead Mill


View 4-Jun-2010 in a larger map

Wednesday, May 19, 2010

F# -- excessively lazy sequences and stateful visitors

Doing something a little bit complicated here: the functional equivalent of a visitor pattern, where I want to apply a few functions to a long and potentially expensive to traverse sequence of items (so ruling out a series of iterations over the visited nodes) --

BuildNodeSequence itself returns a nested sequence expression of the data to visit, and state is well, expected to be handled by mutable out-of-band means.

This works nicely, but is impure -- so let's try to fix that by having the visitor function update itself with the transient state we need to carry between (there will still be side-effects for output). The code becomes

where the Fix delegate type is a way of reifying an otherwise infinite type Node ->'a where 'a is also Node ->'a through

and have it build

Well, I run this and...

Nothing happens -- or at least apply gets called for every node to visit, but invoke never did; until I forced the evaluation of the visitors sequence by

So, what I finally ended up with is

where the inner iterable is evaluated eagerly, rather than being left to lazy IEnumerable expansion; and this then works.

Monday, May 17, 2010

An interesting bit of F# behaviour

In one assembly, define a public static class in C#:

In another do something similar in F#:

which Reflector tells us is equivalent to

inside namespace ClassLibrary1. Now create another F# library referencing the previous two containing

The first line compiles; the second doesn't, failing with compile error error FS0039: The type 'Module1' is not defined.

Clearly the CompilationMapping is being sniffed by the typeof operation, because that is the only difference between the two.

Friday, May 07, 2010

No real change here then

Conservative 47.4; Liberal Democrat 34.1; Labour 10.2; Constituency Swing 2.5% From CON to LD since last time (continuing small erosion).

At least the only fascist party standing locally came last -- and the local character and UKIP ejectee standing as an independent came in 4th, narrowly beating UKIP into 5th place out of six.

Whoever emerges from the rest of the shambles will probably be calling in the IMF in a few months, so it makes little difference.

Wednesday, April 28, 2010

Spring

The garden is in full flush at the moment. The forsythia, daffs, plum blossom, primroses and tulips are just fading, while the Morello, Bramley and grape hyacinths are at their peak, and the bluebells, the Charles Ross and the lilac are just starting to burst their buds.

Cut and come again salad I planted in the greenhouse is starting to germinate, and today a batch of plants arrived, so as soon as I was back from work it was time to pot up sweet-peas and squash, to add leaf beet half the salad bed and the rest in the sunny herb bed, and put the tomato plants into grow-bags in the greenhouse. Between that, mowing the lawn and cooking dinner, I hardly stopped before it was getting dark, taking advantage of the last of this good run of almost summer weather before we get typical Bank Holiday cold and wet.

More project type tricks

The trick to make an F# project launch in the Visual Studio web server is a further application of a little trick I picked up a while back for Vs2008.

There I wanted to retrofit a Windows Workflow into an existing plain C# library project; which I started by building the workflow in a scratch project and copying the source across -- but then in the copy I lost the designer. So I looked at the project file and immediately I saw

<ProjectTypeGuids>{14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

Copying that into the otherwise vanilla C# project not only gave me the workflow designer, but also the workflow and activity items on the Add> menu. There is also a

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.Targets" />

but not copying that didn't seem to have any noticeable effect.

And, while I've not yet had cause to look, projects that bring in their own specialist types and designers will presumably have their own GUID values.

Adding

<ProjectTypeGuids>{14822709-B5A1-4724-98CA-57A101D1B079};{F2A71F9B-5D33-465A-A702-920D77279786}</ProjectTypeGuids>

to an F# project gives the extra additions to the menus -- but without templates, and, more importantly partial class support -- you won't get much benefit from them, unlike with the web app launching.

Links for 28-Apr

StyleCop now open-sourced.

Mono's C# compiler-as-service -- now works in .net too!

IronRuby+Rails+Rack+IIS7 -- between this stack and the same for JRuby in Tomcat. cross platform web-apps have become fun!

No Bugs (e-book).

Unit testing FxCop rules.

Axum (Concurrency focussed language on .net) for VS2010

Snap! -- Aspect-oriented support library for .net

Double-dispatch as a code smell.

F#

Iron* console for VS2010.

Tuesday, April 27, 2010

Launching an F# web application inside VS2010 as if it were C#

This is a follow-up to my comments on VS launcher for F# web apps, where I can put an example of the changed markup to the F# class library project to make it act like a web project and launch a browser with your Default.aspx page when you hit F5.

First, add the highlighted element to the topmost <PropertyGroup> clause in the .fsproj file thus:

where the first GUID is for web app, and the second for F# (as you can see by looking for the project in the solution file).

At the bottom of a C# web application .csproj you will find a block of code like

which you just want to copy and paste into your F# project following the

or equivalent line.

Now adding a trivial Default.aspx file containing

Welcome to ASP.NET on F#!

and the default web.config from a C# web project to the F# library, and running the project launches me that trivial web page into Firefox.

Actually getting F# to play nice with ASP.Net, I leave to those more versed in the latter.

Sunday, April 18, 2010

coverage.exe and instrumenting F# files

I observed yesterday that coverage.exe balked in PdbReader.GetSegmentsByMethod() when trying to instrument F#-derived assemblies.

By checking to see whether a new CodeSegment entry would provoke the exception by having an identical offset to a pre-existing one, and dumping both old and new to the console, I observed that at least one, and often both, had associated line number 0x00Feefee -- i.e. were compiler generated code with no source reference.

And in the method Executor.ProcessMethod(), which is the only place to call PdbReader.GetSegmentsByMethod(), entries with this line number are discarded before beginning to instrument the IL code -- so it would seem to make perfect sense to discard these CodeSegments before putting them in the dictionary. With that change, instrumentation completes cleanly.

Of course, having built coverage.exe with C#4 for .net 4, the helper DLL it built is compiled for .net 4 as well, which has stymied my first test attempt. Oh well, enough for today.

Getting coverage.exe (trunk) to work with nUnit and .net 4

Following up from yesterday, about an instrumenting coverage tool that I'd spotted on Googlecode (Apr 2015 : rescued to GitHub), what I needed to do to get the instrumenting coverage tool working under .net 3.5sp1 with nUnit 2.5.2 driving unit tests.

First, the command line looks like

[path to]\ClassLibrary1.dll [path to]\UnitTestClassLibrary1.dll /x coverage.xml /r /exe [tool path to]\nunit-console.exe [path to]\UnitTestClassLibrary1.dll

where the /r (backup and replace) flag is essential; so you need to work on a copy directory with your assemblies and their .pdb files.

Second, you need to make the following change to the coverage main program in Runner.cs, line 92 from

to be

The hard-coded relative path could be added as yet another argument instead; and I've not played around with the shadow-copy parameter.

But that at least -- with a totally trivial test set -- provided me with a clean run and non-empty coverage data.

So the next thing to do will be to port the whole lot to .net 4 and see what gives. Also, it will be worth trying the teamcity branch (faking NCover 1.x) to see whether the different AppDomain usage there means we don't have to resort to this trick.

Later: doing a rebuild of Coverage and the sample test under .net 4, with command line

[path to]\ClassLibrary1.dll [path to]\UnitTestClassLibrary1.dll /x coverage.xml /r /exe [tool path to nunint 2.5.4]\nunit-console.exe /framework=net-4.0.30319 [path to]\UnitTestClassLibrary1.dll

where the nunit-console.exe.config has been adjusted appropriately, I get

Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, lexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment -
   OS Version: Microsoft Windows NT 6.0.6002 Service Pack 2
  CLR Version: 2.0.50727.4200 ( Net 2.0 )

ProcessModel: Default    DomainUsage: Multiple
Execution Runtime: net-4.0.30319
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object.

Server stack trace:
   at NUnit.Util.ProcessRunner.Load(TestPackage package)
   at NUnit.Core.ProxyTestRunner.Load(TestPackage package)
   at NUnit.Util.RemoteTestAgent.AgentRunner.Load(TestPackage package)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at NUnit.Core.TestRunner.Load(TestPackage package)
   at NUnit.Core.ProxyTestRunner.Load(TestPackage package)
   at NUnit.Util.ProcessRunner.Load(TestPackage package)
   at NUnit.ConsoleRunner.ConsoleUi.Execute(ConsoleOptions options)
   at NUnit.ConsoleRunner.Runner.Main(String[] args)

However, if I do this as a two-stage operation

[path to]\ClassLibrary1.dll [path to]\UnitTestClassLibrary1.dll /x coverage.xml /r

to instrument the code and create a coverage file with zero visit counts throughout -- and then run nunit separately with rest of the command line

[tool path to nunint 2.5.4]\nunit-console.exe /framework=net-4.0.30319 [path to]\UnitTestClassLibrary1.dll

this then fills in the visit counts as expected.

We have code coverage for .net 4 -- at least under some conditions! And without having to rebuild any tools apart from coverage.exe!

Later yet (refrigerator logic) -- of course when working coverage in two passes, I don't need to do the fiddle to change the settings for the AppDomain. And I don't need to have coverage built in the same .net version as I want to run nUnit in, either. I can use the code as synched from Googlecode built under .net 3.5 even for .net 4 codebases; all I have to do now is fix the problems with running it over F# code.