The process of using F5 to start a debugging session is a ubiquitous practice in .NET development with Visual Studio. Despite that, developers are noticing and employing other methods of testing and writing software as these methods can provide better results and a more smooth development experience.
The debugging cycle of doom
The entire process of writing some code, compiling, then pressing F5 to walk through code, can be a tedious way to develop software, especially in larger applications. In general, many consider this type of testing as a smoke test. Smoke tests are fragile, error prone, and nowhere near as comprehensive as they should be, except in cases of automated testing (e.g., record/playback).
Consider the following common development scenario: You need to fix a bug in your code that calculates the total for an order. You would normally start debugging via F5, and try to reproduce the problem, so you can get to the code to fix it. This involves only a few steps; however, they're very time consuming, interwoven, efforts:
Reviewing the steps...
- Navigate to the section of application as described by the bug report, using the UI as a user would.
- Attempt to reproduce the problem by interacting with the UI. This means filling in forms, submitting data, and using links and other page UI elements, again, just as a user would.
- Step through and investigate code with debugging tools.
- Return to code editor, locate source with error, and modify code.
- Repeat steps 1-5 several times.
Because this is the customary way to debug using Visual Studio, this may not seem time consuming, especially in a small application. However, this process often takes much more time than is needed to write code, fix bugs or resolve issues. It's also rare that developers - even ninja developers - will actually fix the bug on the first shot without causing other bugs, so the process continues over and over again, except now, you're aiming at a moving target. As often as not, it's easy enough to find yourself "going down the rabbit hole", which usually ends up with a rather unpleasant undo checkout command at the end of it all.
(Yep, it feels like this, doesn't it? Img src: http://www.seussville.com/)
Let's not forget, after you fix the bug, you still need to update the requirements documentation. This step is usually brushed off as a low priority, and then causes the requirements to become out of sync with the code base. As you can see, The F5 Way does nothing to help you code understand requirements, produce documentation, or add any extra business value.
Break away from debugging tedium with unit tests.
Now, consider the same development scenario: You need to fix a bug in your code that calculates the total for an order, but this time, going the unit test route.
- Run tests.
- Inspect failed test and fix the bug in the code it tests.
- Repeat steps 1-2 if red. If green, your bug is fixed. 
Note/Disclaimer for purists: Depending on whether you're doing TDD or not, the exact process (e.g., test first vs.test later) will be different. This blog post in particular is trying to demonstrate what I believe is more likely to be seen in real world apps based on personal experience - i.e., test later, rather than test first, if they're testing at all! Your mileage may vary.
Not only are there less steps involved with unit testing, but you're also saving a great deal of time. Unit tests also serve as documentation, not only saving even more time, but also while adding value by using unit tests as living, up to date, requirements documentation.
Additionally, try to ensure your tests are isolated to one unit of code (one primary/entry point method a maybe a few supporting ones) as it’s easier to find the defect since you aren’t looking through n layers of architecture, classes and methods to find where the defect is occurring. This helps you test easier, as well as leads you toward writing cleaner code.
Fixing bugs with unit tests
After a user files a bug report claiming that the the program calculates the total incorrectly, you investigate the code at question, which might not appear out of order at first glance.
But, how can you know for sure? You can run the application from Visual Studio, using breakpoints and other debugging tools. Since this code doesn't throw an exception, the app appears to be doing what it should. However, an important calculation is incorrect! We can know that the code is correct with unit tests.
A unit test that will verify if the code is indeed, doing what it should be doing. Inside the unit test method that you specify the exact parameter values to test as inputs, and exactly what you expect as a result. Once the test is setup, call the code in question, and then verify the results. The best way to structure the tests by using the fashionable "Arrange, Act, Assert" technique, as described here:
- Arrange: Declare variables and instantiate objects or mocks needed for the test.
- Act: Execute the code in question, by calling a method or property of the object.
- Assert: Use the Assert object to determine if the results are what you expect.
The unit test code below demonstrates testing the calculation for an order using Arrange, Act, Assert.
The [TestMethod()] attribute denotes that this particular method is only meant for unit testing. Aside from the [TestMethod()] attribute, the code inside unit tests is the same type of code you would normally write any other day. Code that creates instances of objects, calls methods, and uses assertions and logic.
Unit test classes live in their own code files and projects, separate from other projects in the solution, so they won't get in your way, and you can run them separately from your core projects.
When you run the test(s), you can see right away, which ones passed and which ones failed.
Note: This sample demonstrates using MS Test, however any good testing framework will provide a test runner that does the same basic thing - run tests and output pass/fail statuses.
Since the test failed, you then need to investigate the OrdersBLL.CalculateTotal() method in the OrdersBLL class, since that's the method this unit test is testing.
The original developer is using the tax argument as a percentage, rather than just adding the pre-calculated tax amount, which is the original intent of this method. Now that you've found the bug, you can modify the code and re-run the tests.
Now that the test(s) show green, you can feel safe knowing that you've fixed the issue.
Although you may have to modify and run the tests a few times, there will be no UI interaction, as the testing framework will output the results quickly and clearly. To reiterate, the time saved compared to F5 debugging are huge, as most tests can complete running before Visual Studio can even load a web application. This means you'll already be in the code making the right modification rather than wasting time fishing around in the UI and guessing.
(Development feels more like this when unit testing. Img source: cattearoom.com)
This doesn't mean you'll never use F5 again, since you'll still need to run smoke tests, but with far less hunting, pecking, and changing than with F5 debugging. Plus, most developers just like to poke around in the code, tweak, and refactor as well.
Now that you've seen the benefits of unit testing, here are some popular frameworks you can use to get started.
MS Test: Built into Visual Studio 2010, MS Test  is a nice testing framework, especially for those getting started. There's no extra installation required and, of course, it's fully integrated with the IDE, so there's less friction for testing novices.
xUnit: xUnit is a unit testing framework written by ASP.NET team member Brad Wilson , and Jim Newkirk. xUnit is easy to use, and works with many Visual Studio add-ins and 3rd party libraries. xUnit also has built in MVC test project support, and works with .NET versions 2.0 and later.
nUnit: nUnit, like xUnit, nUnit is a testing framework that is also easy to use, and like xUnit, integrates with Visual Studio add-ins and 3rd party libraries. nUnit is one of the more mature unit testing libraries available for .NET developers.
Want to compare these frameworks? Check out the unit testing features comparison at the xUnit site on CodePlex.
There will always be at least some learning curve and friction to those beginning anything new and unit testing is no different. However, most developers are quick to get the hang of it, and quick to start enjoying writing tests and seeing results quickly. It does take a shift in mindset, but the payoff is more than worth it, as unit testing is one of the best ways to bake quality into your application from the start.
The book is an enjoyable read, with great explanations and well written code.
 It is possible that you have written your test(s) incorrectly, but for the purposes of demonstration, this sample assumes the tests are well written.
 See the Visual Studio 2010 features to determine if your edition of VS works with MS Test.
 Brad is my BFF. :-D