0% found this document useful (0 votes)
406 views15 pages

The Art of Unit Testing

This document provides an overview of unit testing concepts and test-driven development (TDD) processes. It defines terms like unit of work, unit test, integration test, and legacy code. It describes properties of good unit tests and differences between integration and unit tests. It also explains the TDD process of writing a test first, making it pass with minimal code, and then refactoring. The goal of TDD is to design testable and maintainable code through writing automated tests before production code.

Uploaded by

sb8714
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
406 views15 pages

The Art of Unit Testing

This document provides an overview of unit testing concepts and test-driven development (TDD) processes. It defines terms like unit of work, unit test, integration test, and legacy code. It describes properties of good unit tests and differences between integration and unit tests. It also explains the TDD process of writing a test first, making it pass with minimal code, and then refactoring. The goal of TDD is to design testable and maintainable code through writing automated tests before production code.

Uploaded by

sb8714
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 15

The Art of Unit Testing

Second Edition: with examples in C#

Part 1: Getting Started


Chapter 1 The Basics of Unit Testing
Chapter 2 A First Unit Test

Chapter 1 The Basics of Unit


Testing
Definitions
Properties of a good unit test
Integration Tests
To test or not to test?
A Simple Unit Test
Traditional Development vs Test-Driven Development
Test-Driven Development Process
Refactoring
Successful TDD

Definitions Unit of Work


A unit of work is the sum of actions that take place between the
invocation of a public method in the system and a single noticeable end
result by a test of that system. A noticeable end result can be observed
without looking at the internal state of the system and only through its
public APIs and behavior. An end result is any of the following:
The invoked public method returns a value (a function thats not void).
Theres a noticeable change to the state or behavior of the system before and
after invocation that can be determined without interrogating private state.
(Examples: the system can log in a previously nonexistent user, or the systems
properties change if the system is a state machine.)
Theres a callout to a third-party system over which the test has no control, and
that third-party system doesnt return any value, or any return value from that
system is ignored. (Example: calling a third-party logging system that was not
written by you and you dont have the source to.)

Definitions Unit Test


A unit test is an automated piece of code that invokes
the unit of work being tested, and then checks some
assumptions about a single end result of that unit. A
unit test is almost always written using a unit testing
framework. It can be written easily and runs quickly. Its
trustworthy, readable, and maintainable. Its consistent
in its results as long as production code hasnt changed.

Definitions Integration Test


Integration testing is testing a unit of work without
having full control over all of it and using one or more of
its real dependencies, such as time, network, database,
threads, random number generators, and so on.

Definitions Legacy Code


Legacy code is defined by Wikipedia as source code that
relates to a no-longer supported or manufactured
operating system or other computer technology, but
many shops refer to any older version of the application
currently under maintenance as legacy code. It often refers to
code thats hard to work with, hard to test, and usually even
hard to read.
Many people like to define legacy code as code that has no
tests. Working Effectively with Legacy Code by Michael
Feathers (Prentice Hall, 2004) uses this as an official definition
of legacy code, and its a definition to be considered while
reading this book.

Properties of a Good Unit Test


A unit test should have the following properties:

It should be automated and repeatable.


It should be easy to implement.
It should be relevant tomorrow.
Anyone should be able to run it at the push of a button.
It should run quickly.
It should be consistent in its results (it always returns the same result if
you dont change anything between runs).
It should have full control of the unit under test.
It should be fully isolated (runs independently of other tests).
When it fails, it should be easy to detect what was expected and
determine how to pinpoint the problem.

Integration Tests
Integration tests differ from unit tests:
May not execute quickly
May not use static test values and therefore execute
differently every time they are run
May use one or more real dependencies
e.g. System time, file system, production/test database

May test more than one thing at once

Organization:
Should be separated from unit tests to achieve a feeling of
safe green zone (discussed later in book)

To test or not to test?


What to test?
Any code that contains one or more of the following: an if statement, a loop,
switch, or case statement, calculations, or any other type of decision-making code.
Service code (e.g. Data Models Service, Communications Service), View Models,
Converters, Attached Behaviors/Properties, Extension classes/methods, module
files

What not to test?


Properties usually dont contain any logic and therefore dont require specific
targeting as it will likely get tested by the unit of work being tested. However,
once any check is added inside a property that logic will need to be tested.
Data models usually dont require direct testing as they will be covered through
testing of the data models service and/or view models except in cases where there
is logic in the data models code.

A Simple Unit Test


public class SimpleParser
{
public int ParseAndSum(string numbers)
{
if(numbers.Length == 0)
{
return 0;
}
if(!numbers.Contains(@","))
{
return int.Parse(numbers);
}
else
{
throw new InvalidOperationException(
@"I can only handle 0 or 1 numbers for now!");
}
}
}

public class SimpleParserTests


{
public static void TestReturnsZeroWhenEmptyString()
{
try
{
SimpleParser p = new SimpleParser();
int result = p.ParseAndSum(string.Empty);
if(result != 0)
{
Console.WriteLine(
@"***SimpleParserTests.TestReturnsZeroWhenEmptyString:
Parse and sum should have returned 0 on an empty string");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}

Traditional Development vs
Test-Driven Development
Traditional Development

Test-First Development

Test-Driven Development Process


1.Write a test as if the production code or functionality were already
working.
In order to compile, an empty method stub in the production code will need to
be written as well
The code will compile and the test will fail because the functionality for the
production code has yet to implemented

2.Make the test pass by writing production code that meets the
expectations of your test. The production code should be kept as
simple as possible.
3.When the test passes, youre free to move on to the next unit test or
to refactor your code to make it more readable, to remove code
duplication, and so on.

TDD Mantra: Red, Green, Refactor!

Refactorting
Refactoring means changing a piece of code without
changing its functionality. If youve ever renamed a
method, youve done refactoring. If youve ever split a
large method into multiple smaller method calls, youve
refactored your code. The code still does the same thing,
but it becomes easier to maintain, read, debug, and
change.
Refactoring can be done after writing several tests or after
writing each test. Its an important practice, because it
ensures your code gets easier to read and maintain, while
still passing all of the previously written tests.

Successful TDD Skills


1. Know how to write good unit tests
2. Write tests first
3. Design well make your code beautiful and maintainable

Suggested Reading:
.(1) This book
.(2) Test-Driven Development: by Example by Kent Beck (Addison-Wesley
Professional, 2002)
.(3) Growing Object-Oriented Software, Guided by Tests by Steve
Freeman & Nat Pryce (Addison-Wesley Professional, 2009)
.(3) Clean Code by Robert C. Martin (Prentice Hall, 2008)

You might also like