The point of unit testing is to keep your code "fixed" such that if you change the implementation, you do so knowing that you haven't broken anything, or that if you do break something you immediately know exactly what it is you broke.
A side benefit of this is knowing that your code as it is currently written does what you want it to do, but that is not (or not necessarily) the primary goal of unit testing. Unit testing is so that you can change your code with confidence.
If such a class as above is not unit tested, then the class can be broken without causing any test to fail. E.g.:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get { return "Smith"; } set { FirstName = value; } }
public Address Address { get; set; }
}
With unit tests you can know that something like this has not happened across your entire code base. (Is this specific example likely? maybe not. But something like this is very possible and basically innevitable.)
With just four simple unit tests, you can make this code "fixed", knowing that it cannot possibly change it's behaviour without a test failing*:
[TestMethod]
public void TestId() {
var emp = new Employee { Id = 3 };
Assert.AreEqual(3, emp.Id);
}
[TestMethod]
public void TestFirstName() {
var emp = new Employee { FirstName = "asdf" };
Assert.AreEqual("asdf", emp.FirstName);
}
[TestMethod]
public void TestLastName() {
var emp = new Employee { LastName = "asdf" };
Assert.AreEqual("asdf", emp.LastName);
}
[TestMethod]
public void TestAddress() {
var address = new Address();
var emp = new Employee { Address = address };
Assert.AreEqual(address, emp.Address);
}
(*maybe except the side case of the broken implementation mimicking the values you use to test)
I won't implement it here, but you can also use reflection to make writing these kinds of tests easier. For example, you can build something relatively easily that would allow you to do the following:
[TestClass]
public sealed TestEmployee {
[TestMethod]
public void TestSimpleProperties() {
Assert.IsTrue(
SimplePropertyTester.Create(
new SimplePropertyTestCollection<Employee> {
{ emp => emp.Id, 3 },
{ emp => emp.FirstName, "asdf" },
{ emp => emp.LastName, "1234" },
{ emp => emp.Address, new Address() }
}
).Test()
);
}
}
You lose the benefit of having each property in its own test, but you gain the ability to modify the set of tests very easily.
You could also build a separate tester with a single test for each unit test, and then you keep the tests separate, but it's not a lot different than just writing them manually, and you end up writing basically the exact same line of code over and over and over.
One thing you can do is put Console.WriteLine
statements in the Test()
method, and then you should be able to have some textual output to look at to pinpoint the problem a lot faster.
EDIT: Actually I've now gotten these to look like the following:
[TestClass]
public sealed TestEmployee {
[TestMethod]
public void TestSimpleProperties() {
var factory = SimplePropertyTestFactory.Create<Employee>();
new SimplePropertyTestCollection<Employee> {
factory.IntTest(emp => emp.ID),
factory.StringTest(emp => emp.FirstName),
factory.StringTest(emp => emp.LastName),
factory.ReferenceTest(emp => emp.Address)
}.Test();
}
}