So what if my method-under-test is responsible for coordinating and setting up multiple things? How do you verify that each thing has been set up properly by this method without doing multiple asserts?
Oran: I'd advise a separate test for each check, each one calling the method on an preinitialized object and then doing one assert.
That way each test can also be named appropriately.
While I completely agree with you in theory, I find it very time consuming to do that and I feel that the benefit isn't always warranted.
For example, say you create a simple class and you write some tests for it.
I'd start of with making sure that the constructor satisfied the invariants (like:
User u = new User("Fred", "Flinstone");
Assert.AreEqual("Fred", u.FirstName, "First name wasn't set");
Assert.AreEqual("Flinstone", u.LastName, "Last name wasn't set");
in this example I do 2 asserts, but the test is really CanCreateUserWithInvariants(). The message can tell me which assert failed. Is this wrong? would you really separate this into 2 tests?
My 2nd comment (really a question) is this:
I find myself wanting to create DEPENDENT tests, and before you shudder think of this: Say you have some functionality that you build upon in your tests. Your model grows and each addition is well tested. Now you want to test higher level abstractions, so these tests now DEPEND on the functionality of other tests, like making sure our User class can actually set its own properties.
If that part fails now I have 2 (or likely a lot more) failing tests. If NUnit had an attribute or something that specified DependsOn("CanCreateUserWithInvariants") then the GUI can mark those as Purple or something to say that other tests must be passing before this one runs.
I realize this opens the door for serious abuse of dependent testing, but maybe you could shed some light on it for me or recommend a better way of testing :) How can I ensure that my tests are atomic and singular, but also leverage the code I've written to provide even more robust tests?
Hi Roy, great post as per usual.
I have recently trended towards smaller, more targetted unit tests myself. Whilst I find that this makes tests easier to read and failed tests easier to rectify, I find that writing them is more burdensome.
When you get a chance, would you mind blogging a bit about alternatives to implementing unit tests in C# / VB / whatever. Are there any unit test-specific CLR languages out there that would make unit tests easier to write, read and maintain?
I do not agree with the part of having to know which one of the asserts failed. As long as the whole test fails it fails. Sure it would be easier to find the concrete assert just by looking at the code, but ... I preffer less test code overall than less code in one method, but that is my opinion.
And for your second argument. If you expect your method to run differently after each call you should also test that it does it in a correct, intended way and write your tests with this in mind.
When I'm using UT, I usually have more than one assert per test.
Why? Simple: when an assert is successful you have a perfect consistency of the object state and using messages you can easily determine what was going wrong.
Plus, sometimes you need to test more "aspects" of a feature and doing several tests instead of one covering more aspects is dispersive in the task switching.
That said, I'm not advocating one test method per class, rather I'm advocating one test method per logical block inside the class.
For example: if I have a class that renders an ul HTML tag and various li's and then I add a property to the li class like "useAnchor" and an "AnchorUrl" one, then it's likely I'll want to test those in the li tag generation rather than in another test which would inherently be burdensome to write.
I think the main reason (that the first assert fails and the others don't run) is a valid reason to have single assert per test, but I think if that was mitigated it would largely become a matter of preference.
You mention that you would extract the setup code to a private method, but you now run this on every test. So if you setup code creates 5 new records in the DB, you know have to do that 10 times instead of one. This is a problem we have on our current project, we have so many tests and so much startup code that it takes forever to run all of our unit tests.
I tried to think of an instance of where I have written an assert that changes the state of an object and I couldnt think of one... could you provide some examples?
Once again, you hit the nail right on the head, Roy. Nice job.
How are things going, by the way? Drop me a line when you have a chance....
I hate it when I get a Nullexcetion with Assert.IsTrue(addressList != null,) because my list is null, I've much rather have an Assert.IsNotNull(addressList) fail on the line before, to give me a better idea what went wrong. I realize the idea is you would have 2 test, and they both would fail, but the problem is one would fail because of the assert, and the other would fail because of a null exception, thus hiding the real error.