Damian Hickey

Mostly software and .NET related. Mostly.

Getting ReSharper to natively support xUnit

So I started a little online campaign yesterday to get the JetBrains folks to natively support xUnit in ReSharper. It already supports NUnit and MSTest (ugh) so what are the business cases for supporting xUnit?

  1. xUnit was part created by the same guy who was also involed in crating NUnit, Jame NewKirk. He details his leasons learned here, and thus can be argued that xUnit is a more modern version of NUnit.
  2. On NuGet gallery, NUnit has ~75K downloads compared to xUnit's ~14K, about 19% of NUnit's total. Not an insignificant market share.
  3. xUnit stats show a slow, but steady increase in adoption rates.
  4. xUnit-contrib, a projects whose predominate purpose is to provide a plugin for the ReSharper runner, also shows steady adoption. This project always lags behind the ReSharper releases and completely unusable during EAP phases due to API churn.
  5. xUnit, current version being 1.9, has had a version independent runner since 1.6. Thus ReSharper and the developer won't be constrained to any particular xUnit version, as long as it's > 1.6.

I hypothsized that xUnit adoption is being held back because ReSharper doesn't natively support it. That is, people are using it because using something else is simply too much friction. JetBrains ran a (non-scientific) poll to see of the NUnit/MSTest user base, who would move to another unit test framework if the friction is removed. As of posting, this is the current result:

The interesting thing is that over 54% of respondents would make a move if there was no friction. And at 39%, I am concluding from that that native xUnit support is a desired feature by ReSharper's customers. I hope JetBrains arrive at the same conclusion.

To vote on the offical issue, do so here http://youtrack.jetbrains.com/issue/RSRP-205721

On ReSharper, object initializers, disposables and code analysis rule CA2000

Given a disposable class and a consumer:

public class DisposableClass : IDisposable
{
	public string Text { get; set; }

	public void Dispose()
	{}
}

public class Consumer
{
	public Consumer()
	{
		var disposableClass = new DisposableClass();
		disposableClass.Text = "S";
	}
}

ReSharper's quick fix will suggest to use object initializer:

Following this suggestion gives:

public class Consumer
{
	public Consumer()
	{
		var disposableClass = new DisposableClass { Text = "S" };
	}
}

But there is is a problem with this. If you run code analysis you will get the the following warning:

CA2000 : Microsoft.Reliability : In method 'Consumer.Consumer()', call System.IDisposable.Dispose on object '<>g__initLocal0' before all references to it are out of scope.

The problem is that under the hood, the compiler is creating a temporary local of DisposableClass, <>g_intLocal0, initializing it, then assigning it to variable disposableClass.

It's this local that it not getting disposed that causes the code analysis warning.

Perhaps the compiler could do a better job here but ReSharper could definitely do a better job:

  • Only suggest the object initializer quick fix for classes that are not disposable.
  • Include a quick fix to remove object initializers from disposable objects.

The issue has been reported, but infortunately JetBrains have marked it as "Won't Fix".

Edit 22/09/12: Looks like this will be fixed in Resharper 7.1.