2. Module Overview
1. Why Tests Are Important
2. The Different Types of Tests
3. What is a Unit Test
4. Your First Unit Test - Hello World
5. What to Unit Test
6. Benefits of Unit Tests
7. What is *not* a Unit Test
3. Why are people writing unit tests?
They need to prove they are smart
They want to charge more
They want to spend more time
coding before they ship
They like more lines of code on
their stats
They want to look good in
code reviews
?
8. Save Time: Avoid Debuggerment
Whenever you are tempted to type something into a print statement or a debugger
expression, write it as a test instead. - Fowler
9. Pay a little now
or
Pay a lot later
Why are people writing unit tests?
11. Why Tests Are Important
Tests Reduce Bugs in New Features
Tests Reduce Bugs in Existing Features
Tests Are Great Documentation
Tests Improve Design
Testing Makes Development Faster
http://www.ssw.com.au/ssw/standards/rules/RulesToBetterUnitTests.aspx#WhyUnitTests
15. Our First Unit Test
[TestMethod]
public void TestCalculation()
{
var orderManager = new OrderManager();
using (var db = new NorthwindDataContext())
{
var order = db.Orders.FirstOrDefault();
var actual = orderManager.GetTotalIncGST(order);
var expected = order.OrderItems.Sum(oi => oi.Qty * price) * 1.1;
Assert.AreEqual(actual, expected);
}
}
16. “A unit test is a fast, in-memory, consistent, automated and
repeatable test of a functional unit-of-work in the system.”
“A unit of work is any functional scenario in the system that contains
logic. It can be as short as a function, or it can span multiple
classes and functions, and it provides internal or business value to
the system under test.”
“Art of Unit Testing” Roy Osherove
What is a Unit test?
17. What makes something a UNIT test ?
Small: Validates a single concern / unit of work
Repeatable: You can rerun the same test as many times
as you want.
Consistent: Every time you run it, you get the same
result.
In Memory: It has no “hard” dependencies on anything
not in memory (such as file system, databases, network)
Fast: It should take a fraction of a second to run a unit test.
18. Readable
Understand!
What? Scenario? Expectation?
Maintainable
We change our application
Trustworthy
All The code covered by unit tests works as expected
Attributes of a good Unit test
19. What is wrong with this test?
[TestMethod]
public void TestCalculation()
{
var orderManager = new OrderManager();
using (var db = new NorthwindDataContext())
{
var order = db.Orders.FirstOrDefault();
var actual = orderManager.GetTotalIncGST(order);
var expected = order.OrderItems.Sum(oi => oi.Qty * price) * 1.1;
Assert.AreEqual(actual, expected);
}
}
22. public static class StringValidation
{
public static bool IsValidEmailAddress(this string txtEmail)
{
return false;
}
Red
23. public static class StringValidation
{
public static bool IsValidEmailAddress(this string email)
{
Regex r = new Regex(@"^[w-]+(?:.[w-]+)*@(?:[w-]+.)+[a-zA-Z]{2,7}$");
Match match = r.Match(email);
return match.Success;
}
Green
24. [TestClass]
public class StringValidationTests_MSTest
{
[TestMethod]
public void IsValidEmailAddress_ForValidEmail_ReturnsTrue()
{
string email = "adam@stephensen.com";
bool result = email.IsValidEmailAddress();
Assert.IsTrue(result);
}
[TestMethod]
public void IsValidEmailAddress_ForEmailWithoutAmpersand_ReturnsFalse()
{
string email = "adamstephensen.com";
var result = email.IsValidEmailAddress();
Assert.IsFalse(result);
}
}
Test Both Ways
25. NUnit Test Fixtures
[TestFixture]
public class StringValidationTests_Nunit
{
[TestCase("adam@domain.com",Description="Valid simple email")]
[TestCase("adam-stephensen@domain-name.com", Description = "Valid email can contain hyphens")]
[TestCase("adam.stephensen.more@domain.com.au", Description = "Valid email with >1 periods")]
public void IsValidEmailAddress_ForValidEmails_ReturnsTrue(string email)
{
bool result = email.IsValidEmailAddress();
Assert.IsTrue(result);
}
[TestCase("adam@domain&more.com", Description = "Invalid email containing ampersand")]
[TestCase("@domain&other.com", Description = "Invalid email with no text before @")]
[TestCase("adam@", Description = "Invalid email with no text after @")]
[TestCase("adam@domain", Description = "Invalid email with no period after @")]
[TestCase("adam-domain.com", Description = "Email does not contain @")]
[TestCase("adam.@domain.com", Description = "Email cannot contain period directly before @")]
[TestCase("adam@.domain.com", Description = "Email cannot contain period directly after @")]
[TestCase(".adam@domain.com", Description = "Email cannot start with period")]
[TestCase("adam@domain.com.", Description = "Email cannot end with period")]
public void IsValidEmailAddress_ForInvalidEmail_ReturnsFalse(string email)
{
var result = email.IsValidEmailAddress();
Assert.IsFalse(result);
}
}
27. Do You Know What Code To Unit
Test?
Unit tests should be written for:
Fragile Code - e.g. Regular Expressions -
see below
When errors can be difficult to spot - e.g.
Rounding, arithmetic, calculations - see
below
Unit tests should not be written for:
Generated Code
Private methods
Dependencies - e.g. Database Schema,
Datasets, Web Services - see below
Performance - e.g. Slow forms, Time
critical applications - see below
http://www.ssw.com.au/ssw/standards/rules/RulesToBetterUnitTests.aspx#HowMany
33. Isolate each part of the program and check that the individual
parts work
Strict, written contract that the piece of code must satisfy
Allows you to refactor code and make sure it still works
correctly (regression testing)
Benefits of Unit Tests (1)
34. Simplifies integration
Testing the parts of a program first, and then testing their
integration
Provides documentation
Clients and other developers can look at their unit tests to gain
a basic understanding of the APIs and determine how to use
the module to fit their needs
Improve code quality
Code that cannot be easily tested is not factored properly
Benefits of Unit Tests (2)
35. Code with automated validation reduces the time spent
manually testing, manually debugging, and hunting for errors
Writing tests as the code is written lets you fail fast (find errors
early). Bugs are cheaper/faster to fix the earlier they are found
Unit testing lets you refactor safely, finding any regressions as
they are introduced
Unit Tests Save Time
37. Pop Quiz – What’s NQR ?
[TestMethod]
public void TestCalculation()
{
var orderManager = new OrderManager();
using (var db = new NorthwindDataContext())
{
var order = db.Orders.FirstOrDefault();
var actual = orderManager.GetTotalIncGST(order);
var expected = order.OrderItems.Sum(oi => oi.Qty
* price) * 1.1;
Assert.AreEqual(actual, expected);
}
}
1. What are we testing?
2. Database Access !
38. It talks to the database
It communicates across the network
It touches the file system
It cannot be run in isolation from any other unit test
It can't run at the same time as any of your other unit tests
You have to do special things to your environment to run it
(e.g. editing config files / registry settings)
You are not testing a class in isolation from other concrete classes
When is a test *not* a Unit test?
http://www.ssw.com.au/ssw/standards/rules/RulesToBetterUnitTests.aspx#DependenciesDB
40. Test the Integration of multiple components
UI, Business Layer, Database
Not in memory
Touches
File system
Registry
Database
Other shared resources
Integration test
41. Run much slower
not run in-memory
Less consistent
Dependent from external resources
Has side effects
Harder to prepare
E.g. Database setup
Integration test
42. Great when writing code to integrate to 3rd party APIs
Great for finding out when there is a problem with a large
complex system (is it the code, the database or a dependency)
Great for ensuring availability of external components
(zsValidate)
Integration test
43. Different Levels of Attention
Unit tests – should ALWAYS pass.
- Should be run on every CI Build
Integration tests – will sometimes be red
- Should be excluded from CI Build
44. Module Summary
1. Why Tests Are Important
2. The Different Types of Tests
3. What is a Unit Test
4. Your First Unit Test
5. What to Unit Test
6. Benefits of Unit Tests
7. What is NOT a Unit Test
45. Unit Testing References
Roy Osherove
Book http://www.artofunittesting.com/
Blog http://weblogs.asp.net/ROsherove/
Unit test definition
http://weblogs.asp.net/ROsherove/archive/2009/09/28/unit-test-definition-2-0.aspx
Michael Feathers
Blog http://www.artima.com/weblogs/index.jsp?blogger=mfeathers
What is not a unit test? http://www.artima.com/weblogs/viewpost.jsp?thread=126923
Unit Testing Rules
http://www.artima.com/weblogs/viewpost.jsp?thread=126923
http://www.slideshare.net/nickokiss/unit-testing-best-practices
http://www.nickokiss.com/2009/09/unit-testing.html