Headline: This contains the code for the first code snippet I install when I have a new installation of Visual Studio along with the steps to get it into the right location.
The Result
The first time I saw this format for unit tests was in some work the Microsoft ASP.NET MVC (Model View Controller) team released. I’m sure it had roots elsewhere… I’ve not tracked those down, but I really like the idea.
Guidelines
Here are some of the concepts that are part of this test outline:
- DO name your test so others know what it does.
- DO have a single line in the Act. That makes it easy to understand what you are testing.
- DO have an assert. It’s not really a test unless there is an assert.
Result
So when I type testmc snippet shortcut in my unit test file, this is what I will see (after I typed the name of the test – which is what the snippet will have you do):
- [TestMethod]
- public void Demo_Test_5_Plus_5_Is_10()
- {
- // Arrange
- var expected = ;
- // Act
- var actual = ;
- // Assert
- Assert.AreEqual(expected, actual);
- // Assert – No Assert, Exception expected
- }
So how did I get that?
The Snippet Code
Here is the actual code from a file called testmethodcommented.snippet.
- <?xml version="1.0" encoding="utf-8"?>
- <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
- <CodeSnippet Format="1.0.0">
- <Header>
- <SnippetTypes>
- <SnippetType>Expansion</SnippetType>
- </SnippetTypes>
- <Title>Test Method Commented</Title>
- <Shortcut>testmc</Shortcut>
- <Description>Code snippet for a test method with comments.</Description>
- <Author>Karl Zachry</Author>
- </Header>
- <Snippet>
- <Imports>
- <Import>
- <Namespace>Microsoft.VisualStudio.TestTools.UnitTesting</Namespace>
- </Import>
- </Imports>
- <References>
- <Reference>
- <Assembly>Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll</Assembly>
- </Reference>
- </References>
- <Declarations>
- <Literal>
- <ID>name</ID>
- <ToolTip>Replace with the name of the test method</ToolTip>
- <Default>MyTestMethod</Default>
- </Literal>
- <Literal Editable="false">
- <ID>TestMethod</ID>
- <Function>SimpleTypeName(global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod)</Function>
- </Literal>
- </Declarations>
- <Code Language="csharp"><![CDATA[[$TestMethod$]
- public void $name$()
- {
- // Arrange
- var expected = $end$;
- // Act
- var actual = ;
- // Assert
- Assert.AreEqual(expected, actual);
- // Assert – No Assert, Exception expected
- }]]></Code>
- </Snippet>
- </CodeSnippet>
- </CodeSnippets>
I realize it seems long, but it if you just copy from here, it is really quite simple.
Where to Place the File
The testmethodcommented.snippet file should be placed in C:\Users\<username>\Documents\Visual Studio 2012\Code Snippets\Visual C#\My Code Snippets path. You might need to adjust the drive letter. This is the path on a Windows 8 machine.
I did this a long time ago, so I don’t know whether you need to start Visual Studio for the snippet to be recognized – if you don’t see it, then restart Visual Studio.
An Example
So here is a quick, trivial example of the file. You can see that I followed the guidelines.
- [TestMethod]
- public void Demo_Test_5_Plus_5_Is_10()
- {
- // Arrange
- var expected = 10;
- var a = 5;
- var b = 5;
- // Act
- var actual = Add(a, b);
- // Assert
- Assert.AreEqual(expected, actual);
- }
- public int Add(int a, int b)
- {
- return a + b;
- }
Tests Expecting Exceptions
You’ll notice in the last example that this line was missing:
- // Assert – No Assert, Exception expected
I put both in the snippet, because on the rare occasion that I need to test for an exception, it is easier to delete the lines I don’t need than to type them. If you never test exceptions, then you might removed that line to save having to delete it.
A Poor Exception Example
So now let’s look at testing an exception. Here is a simple test that you are likely to see in documentation on the subject:
- [TestMethod]
- [ExpectedException(typeof(NotImplementedException))]
- public void A_Poor_Subtract_Exception_Test()
- {
- // Arrange
- var a = GetMyANumber();
- var b = 10;
- // Act
- var actual = Subtract(a, b);
- // Assert – No Assert, Exception expected
- }
- // This is usually in the resources.resx file,
- // but I'm putting it here just for this example.
- public const string SubtractNotImplentedExceptionMessage = "Subtract has not yet been implemented.";
- public int Subtract(int a, int b)
- {
- throw new NotImplementedException(SubtractNotImplentedExceptionMessage);
- }
- public int GetMyANumber()
- {
- throw new NotImplementedException();
- }
But what you’ll see is that it is the NotImplementedException from the GetMyANumber method that causes the test to pass, not the one we really expected in the unit test.
A Better Exception Example
So here is the way that I design those tests. There are other ways. One might ask, “Why not just stop at the Assert and forget the ExpectedException attribute all together?” I think it improves the readability that what you’re really expecting from the test it the Exception. All a matter of taste…
With with this test, if GetMyANumber throws an execption, the test will Fail because it is not the exception we were expecting.
- [TestMethod]
- [ExpectedException(typeof(NotImplementedException))]
- public void A_Better_Subtract_Exception_Test()
- {
- // Arrange
- var expected = SubtractNotImplentedExceptionMessage;
- try
- {
- var a = GetMyANumber();
- var b = 10;
- // Act
- var result = Subtract(a, b);
- // Assert
- }
- catch (NotImplementedException ex)
- {
- var actual = ex.Message;
- Assert.AreEqual(expected, actual);
- throw;
- }
- // Assert – No Assert, Exception expected
- }
I hope this helps you right unit tests quickly but with high standards.
Leave a Reply