ALT.NET Open Spaces
Sunday, March 1, 2009
Session: Writing Good Unit Tests
Format: Discussion
Host: Michael Scott <mscott@eskimo.com>
PRE-SESSION RESEARCH
General Tips for Writing Good/Maintainable Unit Tests
- Don't write too many unit tests
- DRT Principle
(Don't Repeat Tests)
- Only have 1 test for each unit of functionality
- Unit Test ALL of your functionality
- Only have 1 assertion per test (maybe two)
- Write your tests first (before writing code) - TDD
- forces you to design your application better
- forces you to write testable code
- writing unit tests becomes a habit
- Use Assert.That (constraint model)
(easier to read)
- Avoid writing comments in your tests
(these must be maintained whenever your test changes)
- Avoid specifying message text in your Asserts
(extra work for little additional value)
- Design your code to be testable
- Use Stubs / Mocks
- each test should only test the logic for that specific unit of functionality
- Integration Tests are not Unit Tests
- Don't write tests for each method, write tests for each application behavior
- allows you to refactor your code without breaking your tests
(since application functionality has not changed)
Further Information
Book: Working Effectively with Legacy Code
- by Michael Feathers
SESSION DISCUSSION
Unit Test definitions
- 1 single test that tests one single piece of functionality
- A unit test is a method that tests a single unit of code with no dependencies (within reason).
General Principles of Unit Testing
- Make sure that your Unit Tests are not so brittle you have to rewrite them every time your code changes or is refactored.
- Unit Test results should be deterministic (i.e. Regardless of how many times a Test is run, it should pass if the functionality it is testing is working correctly).
- usually don't want to use random numbers in tests
- Each Unit Test should only test one thing.
- Each Unit Test should only have one Assert.
- Don’t test core framework functions such as random, string, etc. Must assume that the underlying framework code has been tested (unless this is causing tests to fail).
- Don't need to Unit Test everything (isn't actually possible to test everything).
- Write enough Unit Tests so you are confident with the stability of your code.
- Instead of testing entire range of values, test upper, lower bounds and a few values in between.
1. Test interaction and how state changes
2. Test the result
Testers are developers who write software that tests development.
One way to learn good Unit Testing quickly: Hire someone who can pair program with you.
Mocks/Stubs/Fakes
Stub or Fake – an implementation that does nothing – it exists to support a dependency
Stub or Fake – won’t be used, but needs to be there
(some disagreement about definitions for Stubs and Fakes)
TDD = Test Driven Development
BDD = Behavior Driven Development
[FixtureSetup]
- Can make code in the individual Unit Tests more readable.
- But, some people don't like the idea of a FixtureSetup - everything should be in your tests.
General patterns for Unit Tests
- Arrange, act, assert (AAA)
Arrange - set up test
Act - do something in the test
Assert - verify that conditions are what you expect them to be
- Because X, when I execute, should get Y
- State, action, expectation
Commenting
- Unit tests should not need comments.
- Use good names for your Unit Tests instead. Good naming conventions for Unit Tests will adequately communicate what the tests are doing.
(For that matter don't comment any of your code. Commenting is often a sign that your code is not well written. Other developers should be able to read and understand the code alone, if it is written well.)
Sample Unit Test Names
ShuffleSeedSeedNumberOneVerifyThat
WhenAUserLogsInExpectThat...
One naming convention for tests
State_Action_Expectation
Example Unit Test
TwoPeople_P1InteractsWithP2_P1IsAnnoyed
{
IPerson P1 = JA;
IPersone P2 = JT;
P1.Interact(P2);
Assert.That(P1.IsAnnoyed)
}
QUESTIONS FOR FURTHER DISCUSSION
- How isolated should a unit test be?
- Should you use test doubles or the real code?
- What is a mock framework?
- What is a fake vs. what is a stub?
- Any object?
- What are some resources to learn how to write the correct tests?