Published: 18 Feb 2010
By: Manning Publications

In this article, taken from the book "The Art of Unit Testing" by Roy Osherove, we'll take a look at using state-based testing methods in our unit tests.

Contents [hide]

About the book

This is a sample chapter of the book The Art of Unit Testing. It has been published with the exclusive permission of Manning.


Written by: Roy Osherove
Pages: 320
Publisher: Manning
ISBN: 1933988274

Get 30% discount

DotNetSlacker readers can get 30% off the full print book or ebook at www.manning.com using the promo code dns30 at checkout.

Indirect testing of state

State-based testing (also called state verification) determines whether the exercised method worked correctly by examining the state of the system under test and its collaborators (dependencies) after the method is exercised.

Let's consider a simple state-based testing example using the LogAnalyzer class, which we can't test simply by calling one method in our test. Listing 1 shows the code for this class.

Listing 1: Testing the property value by calling IsValidLogFileName

As you can see in this code, LogAnalyzer remembers what the last outcome of a validation check was. Because the logic depends on having another method invoked first, we can't simply test this functionality by writing a test that gets a return value from a method; we have to use alternative means to see if the logic works. First, we have to identify where the logic we're testing is located. Is it in the new property called wasLastFileNameValid? Not really; it's in the IsValidLogFileName method, so our test should start with the name of that method. Listing 2 shows a simple test to see if the outcome is remembered.

Listing 2: Testing a class by calling a method and checking the value of a property

Notice that we're testing the functionality of the IsValidLogFileName method by asserting against code in a different location than the piece of code under test. Listing 3 shows another example (that will be used again in chapter 3). This one looks into the functionality of a built-in memory calculator. (Take a look at Calculator.cs under CH3 and CalculatorTests.cs in the book's sample code.)

Listing 3: The Add() and Sum() methods

The Calculator class works a lot like the pocket calculator you know and love. You can click a number, then click Add, then click another number, then click Add again, and so on. When you're done, you can click Equals and you'll get the total so far.

Where do you start testing the Sum() function? You should always consider the simplest test to begin with, such as testing that Sum() returns 0 by default. This is shown in listing 4.

Listing 4: The simplest test for Calculator’s Sum()

We can't write any other test without first invoking the Add() method, so our next test will have to call Add() and assert against the number returned from Sum(). Listing 5 shows our test class with this new test.

Listing 5: The two tests, with the second one calling the Add() method

Notice that this time the tests initialize the Calculator object in a [SetUp]-related method. This is a good idea, because it saves time writing the tests, makes the code smaller, and makes sure Calculator is always initialized the same way. It's also better for test maintainability, because if the constructor for Calculator changes, you only need to change the initialization in one place instead of going through each test and changing the new call.

So far, so good. But what happens when the method we're testing depends on an external resource, such as the filesystem, a database, a web service, or anything else that's hard for us to control? That's when we start creating test stubs, fake objects, and mock objects, which are discussed in the next few chapters.

Summary

In this chapter, we looked at using NUnit to write simple tests against simple code. We used the [SetUp] and [TearDown] attributes to make sure our tests always use new and untouched state. We used [Ignore] to skip tests that need to be fixed. Test categories can help us group tests in a logical way rather than by class and namespace, and [ExpectedException] helps us make sure our code throws exceptions when it should. Finally, we looked at what happens when we aren't facing a simple method with a return value, and we need to test the end state of an object. This attribute is handy, and you'll use it in many of your future tests.

This isn't enough though. Most test code has to deal with far more difficult coding issues. The next couple of chapters will give you some more basic tools for writing unit tests. You'll need to pick and choose from these tools when you write tests for various difficult scenarios you'll come across.

Get 30% discount

DotNetSlacker readers can get 30% off the full print book or ebook at www.manning.com using the promo code dns30 at checkout.

<<  Previous Article Continue reading and see our next or previous articles Next Article >>

About Manning Publications

Manning Publication publishes computer books for professionals--programmers, system administrators, designers, architects, managers and others. Our focus is on computing titles at professional levels. We care about the quality of our books. We work with our authors to coax out of them the best writi...

This author has published 33 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category


Android for .NET Developers - Location and Maps
In Windows Phone and iOS getting the current position of the device in terms of latitude and longitu...
Android for .NET Developers - Using Web Views
In this article, I'll show a native app that contains a web-based view. The great news is that HTML ...
Android for .NET Developers - Building a Twitter Client
In this article, I'll discuss the features and capabilities required by an Android application to ta...
Ref and Out (The Inside Story)
Knowing the power of ref and out, a developer will certainly make full use of this feature of parame...
Developing a Hello World Java Application and Deploying it in Windows Azure - Part II
In this article we will see the steps involved in deploying the WAR created in the first part of thi...

You might also be interested in the following related blog posts


Testing.StackExchange – The “StackOverflow” for Software Testers read more
Dovetail is Hiring a Junior-to-Mid-level .NET Developer read more
Building Parallel Applications using Axum read more
Web Forms vs. ASP.NET MVC read more
Dispatcher, Cross-Thread Property Setting & Lambda Expressions read more
'Oslo' SDK - January 2009 CTP read more
Separating configuration from data lowers total cost of ownership read more
Collecting Twitter stats using a Twitter Bot read more
Book Review: Clean Code read more
OUTPUTing Data from the Just-Inserted, Updated, or Deleted Row(s) read more
Top
 
 
 

Please login to rate or to leave a comment.