Tuesday, May 13, 2008

Announcing Gallio v3.0 Alpha 3

Today we have released Gallio v3.0 Alpha 3, including a preview of MbUnit v3.  Gallio Leaf

The installer is available here: GallioBundle-3.0.0.247-Setup.exe (temporary link)

It will also be available from the Gallio website shortly: www.gallio.org.

There has been quite a lot of progress in this release including new features, bug fixes, and various internal changes to make it easier for runner and framework authors to build new cool stuff on top of Gallio.

Here is a quick summary of these changes.

New and Notable

New Features

1. Annotations

Annotations are a means for test frameworks to communicate errors, warnings and informational messages to the user in association with particular code elements.

MbUnit v3 uses annotations to inform the user about improperly used attributes and to highlight points of interest such as ignored or pending tests.

Annotations are displayed as messages in test reports.

image

They manifest as error/warning stripes in R#.

image

Graham Hay has also added an Annotation view in the Icarus GUI.  Double-clicking on the annotation displays the source code.

image

2. Report Enhancements

HTML reports now include navigation stripes to provide a quick overview of the contents of the report and to navigate to failed, inconclusive and skipped tests.

When JavaScript is enabled, test results are automatically collapsed for ease of reading.  They are automatically expanded during navigation.

image

HTML reports can grow to become quite large when there are many tests.  Accordingly, we have added a "Condensed" version of this report that omits passing tests.  This is particularly useful in combination with CruiseControl.Net.

image 

3. Icarus Test Execution Log

Graham Hay has added a new Execution Log view to Icarus.  You can view test results here while tests execute.   If you periodically refresh the view then you can watch test execution in near real-time including output from long-running tests that are still in flight.

 image

4. Test Assembly Configuration Files

Gallio now provides all of the machinery required to support test assembly configuration files.  All frameworks and adapters can benefit from this support, including MbUnit v3.  Just create a configuration file named: "MyTestAssembly.dll.config" and put it next to your test assembly (assuming it is called MyTestAssembly).

5. MSTest Adapter

Julian Hidalgo implemented an adapter for MSTest.  This feature enables all Gallio runners to run MSTest tests.  One of the interesting consequences of this design is that R# v3.1 is now capable of viewing and running MSTest tests via Gallio.

image

6. Visual Studio Team System Integration (Experimental)

Gallio now includes an experimental ITip provider for integration with Visual Studio Team System 2008.

To use it, be sure to select the feature in the Gallio Installer.  It is currently excluded from installation by default because of its experimental nature.

Then just load up your favorite test project in Visual Studio 2008 and run a Build.  The tests should now appear in the Visual Studio Test View.  You can then run them from there.  It should work with all supported test frameworks.

image

As far as I know, we are the first Open Source testing project to provide this kind of integration.

If would like to contribute to the development of this feature please let me know!

7. Test Runner Extensions

Many new features can be added to Gallio by implementing plug-ins.  However, some users have requested the ability to extend test runners to change how test results are reported.

Gallio Alpha 2 included an ITestMonitor interface that roughly served this purposes by making it possible to inject additional behavior into the test runner's event handlers.  In Gallio Alpha 3, we have introduced the ITestRunnerExtension interface and provided a mechanism for loading extensions into the runners by means of an additional argument.

Implementing a test runner extension is straightforward:

  1. Create a new assembly for your extension.
  2. Add a reference to Gallio.dll.
  3. Create a subclass of TestRunnerExtension.
  4. In the Initialize method, register event handlers on the Events object provided to the extension.
  5. Build your assembly.
  6. Copy the file wherever you like.

Using a test runner extension is similar to registering an MSBuild logger.

  • If you are using Gallio.Echo.exe (the command-line test runner), add an argument like: "/extension:MyFancyExtension,MyFancyExtension.dll".
  • If you are using the Gallio NAnt or MSBuild tasks, the process is similar.  Refer to the documentation of these tasks for details.
  • There is a built-in extension for debugging.  Add "/extension:DebugExtension,Gallio" or an equivalent argument to enable it.  Be sure to also set the message verbosity to Debug.

The plan is to open up more of the platform to lightweight extensions of this sort.

8. Parameterized Test Enhancements

MbUnit v3 now fully supports generic test fixtures and test methods and various other parameterizations.

A test can now be parameterized in any of the following ways:

  • Adding a method parameter to a test method.
  • Adding a generic method parameter to a test method.
  • Adding a constructor parameter to a test fixture.
  • Adding a field to a test fixture.
  • Adding a writable property to a test fixture.
  • Adding a generic type parameter to a test fixture.

Correspondingly data-source attributes can be specified on any of the following code elements:

  • Test methods.
  • Test method parameters.
  • Test method generic parameters.
  • Test fixture types.
  • Test fixture constructors.
  • Test fixture constructor parameters.
  • Test fixture fields.
  • Test fixture properties.
  • Test fixture generic parameters.

So there are many choices, but each choice is quite simple.

Here are a few interesting combinations.

A basic "Row"-test.

Note: The [RowTest] attribute is not needed anymore and has been eliminated.

[TestFixture]
public class Fixture
{
    [Test]
    [Row(3, 4, 5, true)]
    [Row(1, 2, 3, false)]
    public void Test(int a, int b, int c, bool expectedResult)
    {
        Assert.AreEqual(expectedResult, Math.IsPythagoreanTriple(a, b, c));
    }
}

A generic "Type"-test.

Note: The [TypeFixture] attribute is not needed anymore and has been eliminated.

[TestFixture]
[Row(typeof(List<int>))]
[Row(typeof(LinkedList<int>))]
public class Fixture<T> where T : IList<int>, new()
{
    [Test]
    public void Test()
    {
        T list = new T();
        list.Add(123);
        Assert.AreEqual(1, list.Count);
    }
}

A combinatorial test.

Note: The [CombinatorialTest] attribute is not needed anymore and has been eliminated.

[Test]
public void Test([Column(0, 1)] int a, [Column("a", "b")] string b, [Column(false, true)] bool c)
{
    // Test something with the specified combination.
    // Will be executed 8 times total.
}

A pairwise test.

Only tests all combinations of pairs of values.  Can yield a significant reduction in test cases compared to ordinary combinatorial tests while still obtaining great coverage.  See also: www.pairwise.org.

[Test, PairwiseJoin]
public void Test([Column(0, 1)] int a, [Column("a", "b")] string b, [Column(false, true)] bool c)
{
    // Test something with the specified combination.
    // Will be executed only 4 times instead of 8.
}

A CSV data source.

Just one of many external data sources to be implemented.

[Test]
[CsvData(ResourcePath="CsvDataTest.csv", HasHeader=true)]
public void ImplicitlyScopedResourceWithHeader(decimal price, string item)
{
    Log.WriteLine("{0}: {1}", item, price);
}

Automatic data type conversions.

Can automatically convert strings into DateTimes and doubles into decimals for example.

Architecture Improvements

There were a number of internal architecture improvements in Gallio Alpha 3.  Here's a quick summary.

1. Unified Hosting Apparatus

In Gallio Alpha 2 there was some duplication between the responsibilities of the IHost and ITestDomain components.  These abstractions have been refactored.  As a result, ITestDomain was replaced by ITestDriver to handle the specific needs of setting up a testing environment.

The IHost abstraction provides a mechanism for Gallio to run code remotely such as in an isolated AppDomain or another process.

2. Pattern Test Framework Refactoring

There was an important piece missing from the data binding story in Alpha 2 that prevented certain kinds of parameterized tests from being expressed.  This has been resolved by refactoring of the Pattern Test Framework (from which MbUnit v3 is derived) and introducing the concept of a test data context.  IPattern is significantly simpler now.

This work also prompted the introduction of the Annotations mechanism  when it became clear that we needed a much more direct mechanism for reporting semantic errors in a test to the user.

3. Reflection Policy Enhancements

Introduced the concept of a typed ConstantValue for performing reflection over unevaluated attribute values.  For example, when populating tests for the ReSharper add-in we may encounter attribute values that are of type Type.  It's quite possible for those types to not be loaded in the runtime (since we're performing reflection against an in-memory code model).  So instead we can obtain a ConstantValue that represents the Type without actually loading it.

Gallio Alpha 3 also includes a Cecil-based reflection policy for scanning disk-based assemblies without loading them into the runtime.  The Visual Studio Team System add-in uses this policy to perform reflection without locking assemblies or introducing memory leaks.

4. Test Runner Redesign

The ITestRunner interface has been completely redesigned to make it easier to use and more versatile.  For one, the reporting functionality has now been integrated somewhat more tightly into the runner itself.  An ITestRunnerExtension can register new behaviors on a test runner using the ITestRunnerEvents interface.

5. Aggregate Test Drivers

Supporting test assembly configuration files is not as easy as it sounds.  For one, it requires us to create a separate AppDomain for each test assembly.  Then we have to somehow merge the test model and results.

Gallio Alpha 3 introduces an aggregate test driver to help with this.  However, the current design is still somewhat in flux.  I'd appreciate some feedback on how we can improve and simplify the test framework integration story overall.

Bugs Fixed

Here are a few of the bugs from Alpha 2 that have been fixed:

  • Icarus now unloads assemblies promptly to avoid locking them.  You can also enable shadow-copy mode for improved efficiency.
  • MbUnit v2 version compatibility problems fixed.  Should work with any version of MbUnit v2.4+.
  • Hung Gallio.Host.exe processes are no more.
  • xUnit.Net adapter has been upgraded to v1.0 RTM.
  • Installer PATH variable corruption.
  • Castle dependencies have been internalized to avoid version mismatches.
  • Default thread apartment state is STA and can be overridden with the [ApartmentState] attribute.
  • [Explicit] tests are now silent and do not display any output in reports unless explicitly selected, not even a message to say they are being skipped.  If you want noisy output, use [Ignore], [Pending] or [Annotation] instead.
Technorati Tags: ,

Monday, May 12, 2008

Openings at Ingenio

ggbridge

We're hiring!  Want to work with me?

To learn more or to apply, send an email with your résumé to jobs@ingenio.com.

Also check out this link for more opportunities at Ingenio.

Platform Toolsmith

Do you love building tools?  Do you get a kick out of building integrated systems that just work?

Ingenio is looking for someone to help build a robust and highly integrated platform for software development, deployment and testing.   Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to assemble these pieces and to verify that they work together correctly to provide a compelling user experience.

We need an experienced toolsmith who understands the challenge of release engineering, system monitoring, infrastructure build-out and software architecture to help us keep our coders coding, our testers testing, our users using, and our systems running smoothly.

Sample projects:

  • Build new plug-ins for our distributed system monitoring application.
  • Develop a new deployment tool for coordinating updates to our server farm.
  • Implement a SIP phone emulator for testing telephony applications.
  • Plan SOA and ESB middleware deployment projects.
  • Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN.

What we will look for in you:

  • You love to program!
  • You like to tinker and take things apart... and put them back together better than they were before.
  • You have great communication skills.
  • You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++.
  • You have experience with release engineering and deployments.
  • You have a 4 year degree in computer science or engineering.

Location: San Francisco, CA.  Downtown with easy access to BART and Muni.

Test Automation Guru (Lead)

Do you love testing?  Do you love working with testers, teaching them new tricks, designing systems and building tools?

Ingenio is looking for someone to lead our test automation effort.

Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  There are many challenges involved in the construction of controlled test environments that can obtain reliable results and find bugs.  We need an experienced lead who thoroughly groks testing and can help us take test automation to the next level.

Sample projects:

  • Design a virtual automation test environment.
  • Build test tools and monitoring infrastructure.
  • Implement model-based and automated exploratory testing approaches.
  • Plan comprehensive automation test projects.
  • Mentor junior members of the test automation team.
  • Hire more smart people to work with.
  • Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN.

What we will look for in you:

  • You have experience leading, teaching and motivating others to excellence.
  • You have a strong programming background.
  • You have great communication skills.
  • You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++.
  • You are familiar with at least one xUnit testing tool such as MbUnit, NUnit or JUnit.
  • You grok test automation.

Location: San Francisco, CA.  Downtown with easy access to BART and Muni.

Test Automation Wizard

Do you love programming and testing?  Do you enjoy writing high-quality code using the latest tools?  Do you hate bugs?  Do you like solving challenging system integration problems?

Ingenio is looking for test automation engineers to develop a comprehensive and maintainable test suite for our products.

Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  We need talented tester/developers and developer/testers to decide what to test, to write tests and to adopt novel testing strategies.

Sample projects:

  • Write automated tests for our system using C#.
  • Implement model-based and automated exploratory testing approaches.
  • Build infrastructure for deploying, running and monitoring tests.
  • Plan comprehensive automation test projects.
  • Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN.

What we will look for in you:

  • You love to program!
  • You are smart, passionate, eager to learn and get things done.
  • You have great communication skills.
  • You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++.
  • You are familiar with at least one xUnit testing tool such as MbUnit, NUnit or JUnit.
  • You have prior experience writing automated tests.

Location: San Francisco, CA.  Downtown with easy access to BART and Muni.

Test Automation Apprentice (Intern)

Do you enjoy programming?  Are you curious about test automation?  Do you want to get a head start in the industry?

Ingenio is looking for smart students to bring in fresh ideas, challenge the established order and remind us all to have fun.

Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  As part of that effort, we officially sponsor the development of MbUnit, an Open Source testing framework.  We are constantly searching for ways to improve our processes.

We hope to learn as much from you as we promise to teach you.

Sample projects:

  • Create something new and fantastic that we haven't thought of yet in this list...
  • Develop a tool to automatically spider our web sites using C# and find bugs.
  • Write automated tests for our system using C#.
  • Build infrastructure for deploying, running and monitoring tests.
  • Create test reports.
  • Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN.

What we will look for in you:

  • You love to program!
  • You are smart, passionate, eager to learn and get things done.
  • You have great communication skills.
  • You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++.
  • You are currently enrolled or have recently graduated from an accredited university.

Location: San Francisco, CA.  Downtown with easy access to BART and Muni.

Technorati Tags:

Google Code Download WTF

I was getting ready to publish Gallio Alpha 3 tonight but we're out of space on Google Code.

Ok, no problem... I'll just delete some stuff.

Google Code had other ideas:

image

Uhh... But I don't need this version anymore: I've archived it myself and I need the free space right now!

Meanwhile my request for more quota is still pending...

(I'm just glad I never wrote a script to upload nighty builds.)

Sunday, May 4, 2008

Another Programmer Bites the Dust

I've been struggling with Carpal Tunnel Syndrome for 6 or 8 months now.

I don't quite remember when it started.  I've had bouts of muscle tension on and off throughout my life.  After all, I've pretty much spent every other waking hour in front of a computer for the last 18 years or so (total of 22 years programming but during my early years I did not have a computer at home).  But recently I started noticing different symptoms.

  1. Numbness and tingling are now commonplace occurrences.
  2. It does not go away after a night's rest.
  3. It does not go away after a day or two of not using the computer.
  4. It has invaded other aspects of my life including cooking, recreation, sleep and sex.
  5. I find myself searching for ways to work differently and to avoid sustained typing or mousing.
  6. I find myself wishing for an eye-tracker and decent voice recognition to help out around the edges.
  7. It's made me cry...

I have already made many adjustments to my ergonomics and home life style.

  1. I use a keyboard tray tilted at a negative angle.
  2. I use a Microsoft Natural Wireless Ergonomic Keyboard and Mouse combo.
  3. I wear elbow braces during the day.
  4. I wear write braces during the night.
  5. I try to sit properly.
  6. My wife opens jars for me.

But it's still getting worse.

Today I installed Workrave to help remind me to take breaks, do my exercises and quit after working a long day.

*sigh*

Flip Side

I am now taking more active leadership roles.  I am a Lead Software Engineer at the office and the MbUnit / Gallio Lead on the side. 

There's just so much cool stuff to build out there!  And I know all sorts of smart people that I can set to the task of building it.  :-)

Friday, May 2, 2008

A Good Test Finds Bugs

This evening I found myself thinking about what my favourite test in Gallio must be.

It could be the formatter tests that are simple and to the point and leverage many of the good traits of the MbUnit Row-test, including generic method parameters.

It could be the MbUnit integration tests that self-host Gallio within itself to run tests and carefully analyze their output.

Nahh...

My favourite Gallio test is the abstract reflection policy exhaustive test suite!  It's not pure.  It's not pretty.  It's not tightly focused.  It's not short.  It's not precise.  It's not self contained  (it uses native .Net reflection as an oracle).  But boy does it find bugs!  All sorts of obscure deviations from expected behaviour in each of the 4 current reflection policy implementations.

It's an awful test but it does what a test should do: it finds bugs...

Technorati Tags: ,

Tuesday, April 29, 2008

Death By a Thousand Cuts

It feels like I'll never get this release out.

I'm currently facing an interesting flavour of DLL hell (tastes like bananas) resulting from copy-local assemblies that get loaded into the same application (Visual Studio) in different load contexts.  Basically, ReSharper and Visual Studio Team Test both want to load Gallio.dll but they do it in different ways from different locations.  This results in some rather curious behavior because two identical copies of the assembly will be loaded but they are nevertheless considered different from one another.

It would be nice if we could just tell ReSharper and Visual Studio Team Test to load my add-in assemblies from the Gallio installation path, but neither of them actually support that behavior.  They both require their add-ins to be copied into very specific folders.

I can think of two possible fixes right now:

  1. Add some hacks to install a custom assembly resolver just in time at all entry points into the add-ins so that we can control more precisely how Gallio.dll gets loaded.  That way we can avoid having multiple copies of Gallio.dll.
  2. Put Gallio.dll into the GAC.

I previously used option #1 for the Gallio ReSharper add-in.  It was a real pain because I had to carefully instrument all entry points into the add-in and avoid referencing any Gallio types until the assembly resolver hook was installed.  I ripped this brittle code out a couple of weeks ago since I figured just copying Gallio.dll locally would be good enough.  (guess again!)

So option #2 really seems best.  Keep in mind that the copy of Gallio in the GAC should only be used for external tools integration.  I don't anticipate test assemblies or the basic standalone runner actually referring to anything in the GAC so Gallio should still be usable in-place without requiring any installation steps (except for these add-ins of course).

However, it's 4am now so I'm going to sleep on it for a little while.  It may be that using the GAC will cause more headaches such as problems with the NAnt or MSBuild tasks that might also involve a little non-standard assembly resolver-foo of their own.

 

Next problem: Throw out NSIS (finally!) and rewrite the installer using WiX...

Technorati Tags:

Monday, April 28, 2008

The C# Null-Coalescing Operator, PEVerify and ILMerge

It seems I errantly blamed ILMerge for those PEVerify errors. At worst it may be a C# compiler optimization gone awry or it may be that PEVerify is not smart enough.

The Source

Consider this code:

public IList<ITestCommand> Children
{
    get { return children ?? (IList<ITestCommand>)EmptyArray<ITestCommand>.Instance; }
}

The left-hand side of the null-coalescing operator has type: List<ITestCommand>.

The right-hand side of the null-coalescing operator has type: ITestCommand[] before the cast.

The result has type: IList<ITestCommand>.

So we need a little silent cast in there to make the types match up on either side.  Really, it's just providing a compatible upper bound to which both sides can be converted.  At runtime, this operation is a no-op.  Technically it's something that the compiler itself could have inferred if it were smart enough.

The Unoptimized IL

Let's take a quick look at the IL that the C# compiler generates for a standard unoptimized build.

Notice that the castclass operator appears in the listing.  There is also quite a bit of jiggery-pokery involving a compiler generated temporary local variable.

.method public hidebysig specialname newslot virtual final instance class [mscorlib]System.Collections.Generic.IList`1<class Gallio.Model.Execution.ITestCommand> get_Children() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [mscorlib]System.Collections.Generic.IList`1<class Gallio.Model.Execution.ITestCommand> CS$1$0000)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldfld class [mscorlib]System.Collections.Generic.List`1<class Gallio.Model.Execution.ITestCommand> Gallio.Model.Execution.ManagedTestCommand::children
    L_0007: dup 
    L_0008: brtrue.s L_0015
    L_000a: pop 
    L_000b: ldsfld !0[] Gallio.Collections.EmptyArray`1<class Gallio.Model.Execution.ITestCommand>::Instance
    L_0010: castclass [mscorlib]System.Collections.Generic.IList`1<class Gallio.Model.Execution.ITestCommand>
    L_0015: stloc.0 
    L_0016: br.s L_0018
    L_0018: ldloc.0 
    L_0019: ret 
}

The Optimized IL

When generating optimized code, the C# compiler realizes that the castclass is unnecessary.  So it drops it.  It also drops the unnecessary load/stores to a local variable and we end up with the following code.

.method public hidebysig specialname newslot virtual final instance class [mscorlib]System.Collections.Generic.IList`1<class Gallio.Model.Execution.ITestCommand> get_Children() cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: ldfld class [mscorlib]System.Collections.Generic.List`1<class Gallio.Model.Execution.ITestCommand> Gallio.Model.Execution.ManagedTestCommand::children
    L_0006: dup 
    L_0007: brtrue.s L_000f
    L_0009: pop 
    L_000a: ldsfld !0[] Gallio.Collections.EmptyArray`1<class Gallio.Model.Execution.ITestCommand>::Instance
    L_000f: ret 
}


PEVerify Has a Conniption

Without the castclass in the optimized code, the IL is now missing a crucial piece of information: what is the type of the value of the top of the stack when we reach the ret instruction?

In one case, we may have duplicated the value produced by the ldfld instruction so the top has type List<ITestCommand>.

In the other case, we have discarded the original value and instead loaded an array from somewhere else using ldsfld so the top has type ITestCommand[].

Uh oh!

[IL]: Error: [C:\Source\MbUnit\v3\src\Gallio\Gallio\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Children][offset 0x0000000F][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack.

Without the castclass PEVerify has to do some rather more complicated work to figure out whether the types are compatible.  Apparently, it fails.  But it does get far enough to realize that one of the values can be converted to IEnumerable.

Is This a Problem?

I don't know.  Apparently we have been running this code in Gallio release builds for many months now and not seen any InvalidProgramException errors.  So even though PEVerify is confused, the CLR at least does not choke on the code.

In any case, it's definitely not ILMerge's fault.  (Sorry Mike!)

Technorati Tags:

ILMerge redux

In my previous post, I mentioned a problem I was having with ILMerge and how I fixed it.

It turns out that code security attributes were not the only problem.  ILMerge is no longer complaining, but it is generating a bad output assembly just the same.  This is preventing the C# compiler from linking to the merged assembly.  Most immediately it manifested as XmlSerializers not working.

PEVerify shows a long stream of errors:

C:\Source\MbUnit\v3>"c:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\PEVerify.exe" build\target\bin\Gallio.dll

Microsoft (R) .NET Framework PE Verifier.  Version  2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

[MD]: Error: TypeDef is marked Nested but has no enclosing type. [token:0x020004
40]
[MD]: Warning: MemberRef has a duplicate,  token=0x0a0004f3. [token:0x0A0001AB]
[MD]: Warning: MemberRef has a duplicate, token=0x0a0004f4. [token:0x0A0001AC]

...

*sigh*

More Good Fortune?

I upgraded ILMerge from 2.8.0202 to 2.8.0422 and now it seems to be working a little better.

Now the TypeDef error is gone but we're still getting MemberRef warnings.  Makes me a bit nervous but at least the C# compiler is happy enough linking to the merged assembly and the XmlSerializer problem seems to be resolved.

However, there was nothing in the change history to suggest that any bug were fixed.

Or Maybe Not?

Turns out I missed these errors:

[IL]: Error: [C:\Source\MbUnit\v3\build\target\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Children][offset 0x00000012][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack.
[IL]: Error: [C:\Source\MbUnit\v3\build\target\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Dependencies][offset 0x00000012][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack.
2 Errors Verifying build\target\bin\Gallio.dll

Just great.  Well, I guess Gallio Alpha 3 will be delayed a little bit further while I cook up a workaround or something.

Technorati Tags:

Don't use self-referential Code Access Security attributes.

I encountered an interesting little problem today after completing a small refactoring of Gallio.  ILMerge broke!

An exception occurred during merging:
ILMerge.Merge: The assembly 'Gallio' was not merged in correctly. It is still listed as an external reference in the target assembly.
   at ILMerging.ILMerge.Merge()
   at ILMerging.ILMerge.Main(String[] args)

True enough, the merged assembly contained a self-reference.

The proximate cause seems to be the fact that the Gallio assembly defined a code access security attribute that it itself used.  Ordinarily these attributes should be defined in other assemblies.  Indeed, the compiler will enforce the constraint for any assembly-level permission requests.  I assume ILMerge is doing a little magic here to try to enforce similar properties.

Ahh well.  I eliminated the custom attribute and all is well.

Leap of Faith

Julian suggested I blog about this issue because of the manner in which I resolved it.

Internal dialogue:
  1. ILMerge is breaking because I am using it on a different assembly than I was before.  So there's something essentially wrong about this assembly or with ILMerge.
  2. Google turns up this error message but only in circumstances involving the ASP.Net merge tool and user error.  I don't think that's the case here.
  3. The documentation doesn't say anything about this.
  4. Renaming files around and messing with the command-line arguments doesn't change anything.
  5. Panic!
Time passes...
  1. Hmm.  When skimming the ILMerge change history to find the entry about to the addition of this error message didn't I see something about fixing security attributes?  I wonder what that was about.
  2. Gallio uses a custom security attribute.
  3. Security attributes are subject to these interesting cross-assembly reference constraints when used to declare minimum permission requests...
  4. Oh!

Now I have no idea why the mention of security attributes in the change history caught my attention, but it did.

You might call it lateral thinking, but I'll call it sheer luck!

Technorati Tags:

Thursday, April 24, 2008

Gallio integration with Visual Studio Team System

One of the questions I've often received about Gallio has been about whether it would integrate with MSTest and Visual Studio Team System.

Gallio running MSTest tests in Icarus

Julian did the work of writing a Gallio adapter plugin for MSTest tests.  Gallio explores MSTest tests using reflection and runs them by shelling out to MSTest.exe and parsing the test result XML file.

Here's a screenshot of the Gallio Icarus GUI running some MSTest tests.

An MSTest test running in Icarus courtesy of Gallio

Gallio running MSTest tests in ReSharper

Of course, you can use any Gallio test runner to run MSTest tests.  That means you automatically get ReSharper integration too!  (And in all of the other runners too.)

An MSTest test running in ReSharper courtesy of Gallio

 

MSTest running Gallio tests in Visual Studio

Another common request has been to provide integration so that Visual Studio Team Test can run Gallio tests in the IDE and using the MSTest.exe command-line.

This particular request was echoed to me a couple of times at ALT.Net from people who, for good or ill, have been instructed by management to use the Team System test runner instead of TestDriven.Net or ReSharper.  So I decided to give it a shot.

Gallio Alpha 3 now includes an experimental package for Visual Studio to do just that.  (It also works on the command-line).

An MbUnit test running inside of Visual Studio Team System

Technorati Tags: ,