Monday, November 06, 2006

That blasted VSMDI file.  Well Buck, Tom and crew did it.  They have finally given us the ability to run tests ( albeit all ) found in an assembly regardless of test lists.  http://blogs.msdn.com/buckh/archive/2006/11/04/how-to-run-tests-without-test-metadata-files-and-test-lists-vsmdi-files.aspx I am currently integrating this into TfsAlert and will post my findings.

posted on Monday, November 06, 2006 8:40:13 AM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback
 Monday, January 23, 2006

Based on some conversations I had today, here is a simple NMock example.

NMockExample.zip (17.19 KB)

posted on Monday, January 23, 2006 8:17:23 PM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback

Code Snippets just rock.  I thought I would post my testing code snippets.

CSTestSnippets.zip (2.2 KB)

VBTestSnippets.zip (2.13 KB)

Just add them to the appropriate place under "My Documents\Visual Studio 2005\Code Snippets\"

posted on Monday, January 23, 2006 3:26:51 PM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback
 Saturday, January 21, 2006

Short answer.

It's as simple as adding one line to your csproj which in turn tells the IDE to treat that project like a test project.  Add the following line to your main PropertyGroup:

<ProjectGuid>{04082EBA-C85C-4336-B3FD-9891096BAA0F}</ProjectGuid>

Then just reference Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll and you are on your way.  Be sure to verify that Guid between releases. 

Long Answer.

When I start a project I create the base set of known assemblies that project will need.  I also add an additional test project which will contain any Scenario, Load and Stored Procedure tests.  Then I convert all assemblies to test projects.  I am a firm believer in Test Driven Development.  IMHO it is the only way to properly write code.  Having said that over the years I have developed my own set of TDD practices; one of which is the physical placement of your unit test classes in the assembly their testing.  Why? Well I will explain that in a future post call Unit Testing with Partial Classes.

With any decision there are of course trade-offs. In this case the trade-off is around the IDE interaction with hosting type projects, ie exe or web.  After you convert an exe to a test project, when you decide to run ( F5 ) it will actually fire off Test Manager rather than the launch app.  If you are a TDD bigot like me this is actually the correct action; if your not, I know your already complaining.  BUT all is not lost!  There is a little tool us TDD bigots keep in our back pocket at all times, TestDriven.Net.  This is an Visual Studio add-in and it allows you to execute your unit tests with just a right click.  If you choose to use this tool it isn't necessary to convert your project to a test project but rather just reference the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll.  This will allow you to fire your app as intended and run your tests with the same project configuration.

Disclaimer: this is not a Microsoft recommend practice.  You can find more information about the Visual Studio Team System Testing Framework here.

posted on Saturday, January 21, 2006 8:36:27 AM (Central Standard Time, UTC-06:00)  #    Comments [2] Trackback
 Friday, January 20, 2006

Mark Seemann recently published a great post demonstrating the use of anonymous methods in unit testing events.  Testing Events Using Anonymous Methods

That just rocks, thanks Mark!

posted on Friday, January 20, 2006 7:14:39 PM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback
 Monday, January 16, 2006

While you cannot validate you exception's message in the ExpectedException attribute all is not lost.  Lets walk through three scenarios.

In all three tests you will see an Assert.Fail in the try block.  You need this statement in case the target doesn't throw any exceptions, therefor failing the test.  The first example is a passing test, throw and exception with a message, catch it and compare the message string. 

   [TestMethod]
   public void PassingException()
   {
      const string expectedExceptionMessage = "Foobar Message";

      try
      {
         throw new ApplicationException( expectedExceptionMessage );
         Assert.Fail( "Expected an exception to get thrown by target" );
      }

      catch ( ApplicationException ex )
      {
         Assert.AreEqual<string>( expectedExceptionMessage, ex.Message );
      }
   }  

Here we see the same test failing only because the message contained in the exception is different.

   [TestMethod]
   public void FailingOnExceptionMessage()
   {
      const string expectedExceptionMessage = "Foobar Message";

      try
      {
         throw new ApplicationException( "Invalid" );
         Assert.Fail( "Expected an exception to get thrown by target" );
      }

      catch ( ApplicationException ex )
      {
         Assert.AreEqual<string>( expectedExceptionMessage, ex.Message );
      }
   }

While this last test follows the same pattern seen above the test is really only testing for the type of exception being throw.  This should be refactored to use the ExpectedException attribute.

   [TestMethod]
   public void FailingOnExceptionType()
   {
      const string expectedExceptionMessage = "Foobar Message";

      try
      {
         throw new Exception( expectedExceptionMessage );
         Assert.Fail( "Expected an exception to get thrown by target" );
      }

      catch ( ApplicationException ex )
      {     
      }

      catch
      {
         Assert.Fail( "Incorrect Exception type was thrown by target" );
      }
   }

Same test refactored, this test still fails but only to illustrate that example.

   [TestMethod, ExpectedException ( typeof ( ApplicationException) )]
   public void FailingOnExceptionType()
   {
      throw new Exception( "..." );
   }

posted on Monday, January 16, 2006 9:27:52 AM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback
 Friday, January 13, 2006

If you've switched from NUnit to the VSTS Unit Testing then I am pretty sure you've used the ExpectedException attribute. If you haven't it looks something like this:

[ExpectedException( typeof( ApplicationException ), "Message" )]

Using it with a test would look like the following:

[TestMethod, ExpectedException( typeof ( ApplicationException ) ) ]
public void ut1()
{
   throw new ApplicationException();
}

[TestMethod, ExpectedException( typeof( ApplicationException ), "foo" )]
public void ut2()
{
   throw new ApplicationException("bar");
}

You would naturally expect test ut1 to pass and ut2 to fail.  ut2 should fail on the bases that the message contained within the exception was in fact different.  Not true.  Both actually pass and not because of a bug but rather a new feature introduced to the attribute.  The Message property is actually a message that prints out with the test when it fails; just like the optional message property you find on all of the Assert methods.

   Assert.IsTrue( false == true, "Developer put explanation if this test was to fail" );

That message will print with the output of the test like so:

Error 1 TestCase 'ExpectedExceptionTest.ExpectedException.ut3' failed: Assert.IsTrue failed. Developer put explanation if this test was to fail
at ExpectedExceptionTest.ExpectedException.ut3() in C:\MyPrograms\ExpectedException\ExpectedExceptionTest\ExpectedException.cs:line 26 C:\MyPrograms\ExpectedException\ExpectedExceptionTest\ExpectedException.cs 26 

Lets correct ut2:

[TestMethod, ExpectedException( typeof( ApplicationException ), "I failed because I am looking for the wrong excpeption type" )]
public void newUt2()
{
   throw new Exception( "foobar" );
}

This will in fact fail because the Exception type thrown was different.  When it fails we will see that message in the output.

Having said all that, there is in fact a bug.  When you run a test with that ExpectedException attribute in Visual Studio you will not see the message on the failure output; if you run it in MSTest.exe you will.

ExpectedException.cs (.75 KB)

posted on Friday, January 13, 2006 11:34:54 AM (Central Standard Time, UTC-06:00)  #    Comments [0] Trackback