Programming is not just an art, not just a science, but a discipline. Part of what we all know we should be doing includes solid unit testing. Below is my list of best practices, feel free to comment and add others I enjoy feedback.
- Create a separate assembly for your test fixtures
- i.e. don't be lazy and put your test fixtures in the same assembly as the application code)
- Create a bin folder per solution and place nunit.framework.dll in there
- Each project should copy their binaries to the solution bin folder. Your Post-Build event should look like this: copy $(TargetFileName) "../../../bin/"
- Categorize your test fixtures such as DAO, ETL and BusinessRules. This will let you test pieces of your application more easily: [Category("ETL")]
- Once you have the basic interface of a class written, it is time to write your unit test for it. Even though it will fail it will at least serve as a place holder to go back to as well as serving as a test for when things are working
- Make sure each test is atomic. Therefore if you are inserting data into a table and you know say CustomerName must be unique, then the second time you run your test it will fail because of uniqueness. For this reason have your persistence tests be all inclusive, include an insert, update and delete. Put your delete code into a finally so that it is always executed regardless of if the other tests succeed or not
- If you notice all of your test fixtures perform certain setup every time, create a base class for this, let's say each one of your DAO classes will be instantiating a connection and opening it before starting and this connection needs to be closed at the end of testing whether it fails or succeeds
- Obviously we would never want to handle connection objects in our Unit Tests, this would be bad design, in the real world it may be a stream or nhibernate session that you are configuring.
[TestFixture]
public class DAOBaseFixture
{
SqlConnection cn;
[SetUp]
public void Init()
{
cn = new SqlConnection();
cn.Open("...");
}
[TearDown]
public Cleanup()
{
cn.Close();
}}
Now derivatives of this class won't even have to implement the [TestFixture] attribute nor take care of their setup. They will be free to just take care of their own tests.
public class CustomerDAOTests : DAOBaseFixture{[Test][Category("DAO")]public void FindAll(){...}}
I still recommend to people writing .Net code to use NUnit. First it's free and you don't have to own any version of Visual Studio to support it. Therefore if you have programmers or testers offshore who only have Visual Studio Pro they can still run it. You don't even need a Visual Studio license to run it. Finally it's a very mature product and it's semantics are well accepted and somewhat portable from language to language.