Re-reading Michael Feathers nice article on "Testable Java" I decided to see how the same thing looks in C#. Now, Java and C# aren't too far a part, so the difference isn't huge.
The "Testable Java" article gives a simple rule for how we can write code that is friendly to unit tests. -As the article points out the rule is superflous if we follow TDD stricly. But - being human - we don't always do that. Sometimes we write only integration tests or even acceptance tests here and now, and postposne unit tests. Sometimes we skip the automated tests altogether. In these cases it's an advantage to have code that is at least friendly to unit tests. If so, it's afordable to add the unit tests later.
Feathers' rule is:
"Never hide a TUF within a TUC"and Feathers goes on to define TUF as a "Test Unfriendly Feature" and TUC as a "Test Unfriendly Construct". Now TUFs are things that we want to mock out in many unit tests, but TUCs are language constructs that are hard to substitute for testing.
Examles, from the article, of TUFs:
- Database access
- File system access
- Network access
- Access to side effecting APIs
- Long running computations
- Inscrutable computations
- Static variable usage
The first three are basically I/O, and in general I/O is test unfriendly because it is slow, and usually assumes things about the outside world - like "the webservice is reachable" or "the robot arm is connected through the serial port".
The next - side effects - is about avoiding tests that changes something and annoys somebody.
Long running computations are a nuisance, and will make you skip test runs.
Inscrutable computations, are things that are just plain hard to understand - maybe due the "clever" code-smell or to essential complexity.
These TUFs are all TUFs in .NET as well.
The article lists a number of Java TUCs. This is my ported list of C# TUCs:
- Sealed classes
- Static methods
- Private methods
- Static initializers
- Static constructors
- New expressions
and these are few more C# TUCs IMHO:
- Non-virtual methods
- Internal methods
- Internal classes
The point is to remember - even when you skip the TDD strictness - that testability is an important part of maintainability. So if maintainability is quality attribute you want, then keep an eye on the testability. If not, those TUFs inside of TUCs will come back and bite you.
Oh, and the other point: Go read Michael Feathers' article. It's well worth it.