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.
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.
|
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
|
|
Please login to rate or to leave a comment.