Unit Test Rulz
I've used these rules with a large number of teams. They encourage good design and rapid feedback and they seem to help teams avoid a lot of
trouble.
---
A test is not a unit test if:
1) It talks to the database
2) It communicates across the network
3) It touches the file system
4) It can't run correctly at the same time as any of your other unit tests
5) You have to do special things to your environment (such as editing config files) to run it.
Tests that do things things aren't bad. Often they are worth writing, and they can be written in a unit test harness. However, it is important to be able to separate them from true unit tests so that we can keep a set of tests that we can run fast whenever we make our changes.
Michael Feathers
www.objectmentor.com
zhaorui 2008-04-27: 有一些地方我不是特别的明白,因为我也是最近才开始准备在写程序之前先写一些单元测试;不连接数据库,我也许可以使用mock来模拟;可是如果对于一个需要生成文件的函数,如果我不能接触文件系统(touches the file system),那么我怎么能够测试?我觉得可能我对file system的理解有问题。
update: ms 似乎也曾经对 TDD 指手画脚,2004年的时候就已经有书出版,不过也有不少批评的声音,下面这个应该算是比较合理的一种说法。vs2005中可以很方便的建立unit test,不过我还是更喜欢/习惯 NUnit 的风格。
MSDN: Characteristics of a Good Unit Test
A good unit test has the following characteristics.
* Runs fast, runs fast, runs fast. If the tests are slow, they will not be run often.
* Separates or simulates environmental dependencies such as databases, file systems, networks, queues, and so on. Tests that exercise these will not run fast, and a failure does not give meaningful feedback about what the problem actually is.
* Is very limited in scope. If the test fails, it's obvious where to look for the problem. Use few Assert calls so that the offending code is obvious. It's important to only test one thing in a single test.
* Runs and passes in isolation. If the tests require special environmental setup or fail unexpectedly, then they are not good unit tests. Change them for simplicity and reliability. Tests should run and pass on any machine. The "works on my box" excuse doesn't work.
* Often uses stubs and mock objects. If the code being tested typically calls out to a database or file system, these dependencies must be simulated, or mocked. These dependencies will ordinarily be abstracted away by using interfaces.
* Clearly reveals its intention. Another developer can look at the test and understand what is expected of the production code.