As part of the latest release of xunitcontrib, I’ve added two new features, support for ReSharper’s External Annotations and Live Templates.
ReSharper performs some static analysis on your code, and displays a blue squiggly error indicator over anything it thinks will be a problem. One great example is possible System.NullReferenceExceptions – using an object which may be null.
One thing you might notice from that screenshot is that we’ve got an Assert.NotNull in there. This method throws an exception if the “otherFlagsAttribute” is null, meaning we can’t get a NullReferenceException. But ReSharper doesn’t know that, and so we still get the warning.
As I understand it, ReSharper can only analyse your source code, and not any compiled assemblies. So how do we tell it that Assert.NotNull ensures that we don’t get a NullReferenceException?
Well, ReSharper makes available an assembly called JetBrains.Annotations.dll that provides a number of attributes that can handle this scenario (plus a whole bunch more, like not null parameters, or marking parameters as string format specifiers). Handy, but a bit intrusive to your code, and not much use if you’ve not got the code available to change.
And that’s where External Annotations come in. You can now unobtrusively apply these attributes to the code through xml files. (And the ReSharper guys have very nicely produced files for the entire .net framework…)
So, that’s what this feature is. It adds the xml file telling ReSharper that xunit’s Assert.NotNull is an assert method that will stop execution of the method if the parameter is null. Similarly, there’s annotations for Assert.Null, Assert.True and Assert.False.
(Interestingly, it’s easy to concoct an example for NotNull and also for True or False (simply create an expression that is always false or always true) but I can’t create an example for Assert.Null. Answers on a postcard, please…)
To install, simply drop the xunit.xml file into ProgramFiles\JetBrains\ReSharper\v4.x\bin\External Annotations.
Live Templates are very much like Visual Studio’s built in snippets feature (I guess I ought to look into porting this to snippets…) but with a bit more oomph. They allow you to type an identifier that automatically expands into something useful. For example, the Live Template provided expands the word “fact” into:
Which has the method name highlighted ready to edit, and when you hit enter, places the cursor into the body of the method. It also automatically adds any using statements necessary.
These are very useful, especially with the smart Intellisense shown for the assert templates:
I’ve actually released two versions of this. One which uses acronyms such as “ae” and “ann” to represent “Assert.Equal” and “Assert.NotNull”, and another that uses similar acronyms, but beginning with “x” (“xe”, “xnn”). This is to avoid a collision with Live Templates for a certain other unit testing framework that I use.
Here’s a list of the Live Templates included (the words wrapped in dollar signs like $this$ are macros, and are quickly edited by pressing tab, and usually display some sort of useful Intellisense):
|Shortcut #1 ||Shortcut #2 ||Expands to |
|ae ||xe ||Assert.Equal($expected$, $actual$) |
|at ||xt ||Assert.True($value$) |
|af ||xf ||Assert.False($value$) |
|ac ||xc ||Assert.Contains($expected$, $actual$) |
|an ||xn ||Assert.Null($value$) |
|ann ||xnn ||Assert.NotNull($value$) |
|athr ||xthr ||Assert.Throws<$T$>() |
|aiaf ||xiaf ||Assert.IsAssignableFrom<$T$>($object$) |
|ait ||xit ||Assert.IsType<$T$>($object$) |
|fact ||fact ||Creates an attributed test/fact method |
|fa ||fa ||[Fact] |
|theory ||theory ||Creates an attributes theory method |
|ta ||ta ||[Theory] |
|ida ||ida ||[InlineData()] |
Note that not all of the assert methods are there. Only the most common have been added. And I haven’t added Assert.Same, namely because “as” is a poor acronym to go for.
This is a little trickier to install. In Visual Studio, go to ReSharper –> Live Templates, then click the button to “Mount storage” and navigate to and select the live template file of your choice (“ae” or “xe” format).
If you mount the file, then any changes are saved back to this file. If you import it, then any changes are kept in a copy of the config file. I prefer mounting the file, as it gives me more flexibility to change the templates and pass the changes around.
So that covers external annotations and live templates. As ever, if you have any bugs or comments, please use the Issues and Discussion pages of the CodePlex project site. And feel free to get in touch on Twitter, too (via @citizenmatt or #xunitcontrib).