What is one assert?
One of the thing that you would hear TDDer say is "one assert per test". The problem is, what is one assert? Does it mean one Assert.Something() call? I don't agree with this. To me, this is a single assert:
Assert.AreEqual(3, rows.Count); Assert.AreEqual("ALFKI", rows[0]["Id"]); Assert.AreEqual("Wrong id", rows[0]["Name"]) Assert.AreEqual("BUMP", rows[1]["Id"]); Assert.AreEqual("Goose", rows[1]["Name"]); Assert.AreEqual("Lump", rows[2]["Id"]); Assert.AreEqual("Of Rock", rows[2]["Name"]);
I am asserting that the set of rows is the expected set of rows, it simply takes several calls to assert that.
Comments
Agreed!!
I agree, to me the one assert per test is really one assert group.
I know a test smells if i see some logic, then asserts, followed by more code which in turn is followed by more asserts.
Exampl
Logic....
Assert something
More Logic....
More Asserts
...
...
...
Derik
Provided that you have a ctor that accepts key/value pairs on the Row class, I guess you could write the test like this:
Row[] expectedRows=new Row[]
Assert.AreEqual(expectedRows,rows);
How is this different? Just because it has a single assert?
Also, even it would work, I would say that this is less obvious
I think it depends on the scenarios your making the assertion. If you do it more than once, it might be more descriptive to refactor to a expected result. Another option is to write a custom assertion method (this might be the best alternative).
Whether an expected result with one assertion or multiple assertions is better is more or less a matter of taste imho.
This is one of those questions that makes me appreciate the context-oriented approach of RSpec and friends. When IronRuby arrives, you might have something like:
You achieve many of the ideals the single assertion per test (localize failures, continue running assertions after one fails). I've tried this with MbUnit in C# and it works, but it's quite heavy syntactically (one TestFixture per context) and that obscures the related nature of the multiple contexts your class under test can exist in.
In looking forward to Ruby and .NET, one of the most appealing and interesting things to me is using Ruby as a language for my testing my C# code.
Cheers from NYC,
Luke
I agree, for me the term "Single Assert" means Test a single functionality of the code, if the functionality means write a lot of Assert instruction I have no problem.
Usually when a programmer does heavvy Mock Testing he write a lot of expectation for each mock object, since every expectation is an assert actually I'm doing more than one assert instruction per test, but for me is fine if it is needed to test a single scenario.
The important things to do are write a meaningful string for each assert so the error is clear and is clear why the test is failing.
Alk.
I agree completely.
As Anders suggests I find refactoring these sorts of assertions into a well named cutom assertion method is often a good idea.
Hello...
I just recently added your Blog to my reader, so I have to comment this a little bit later then the rest of the Folks here...
I must disagree with all those that agree... ;)
I think you are loosing one important feature of TDD if you have more then one Assert per test! In NUnit an Assert will throw an exception when it is invalid. That means if i have made a change in my code, that managed to break more then one of the asserts in my test, then I will have to do more then one itteration to "find" all bugs
Example: I managed to break 3 fields in a class after a db shema change... If I have only one assert for one testcase, then I would see EXACTLY that I have 3 fields that I need to fix.
If I have 1 testmethod that has 15 Asserts to validate all the fields, then I would have to fix the -ONE- reported error, only to get one more. If I dont "notice" that the Assert exception Message changed from
"Expected that something should be this but i got nada"
to
"Expected that something should be that but i got nada"
Then I might think the fix which I just did -successfully- was invalid. Ill roll it back and try something else...
With one assert per test, I will see after the 1st Fix that I actually made progress! It will only report -2- more errors instead of -3- and I am feeling emotionaly better, since i made progress ;)
Also, for a simple mapping test like that, I would use an Implicit setup/teardown so all my testmethods would ONLY contain one assert, since all will run against the same object under test.
Example:
[Test]
public void ShouldContainExactly3Rows()
{
Assert.AreEqual(3, rows.Count);
}
[Test]
public void FirstRowShouldBeAlFki()
{
Assert.AreEqual("ALFKI", rows[0]["Id"]);
}
Also I would not validate all 6 Fields of the 3 rows, but only the IDs (Test for checking the mapping of the Row itself are in another test class, so I know they work)
So the Number of test in the example would go from 7 to 3-4 and I would still feel that I have a good coverage.
I hope this makes sense ;)
Heiko Hatzfeld
Damn no Edit... I forgot something...
The thing you are loosing with multiple asserts is a good defect location. The Example with Mocks from Gian Maria is different. Here the feedmack gained from the test will include all failures (I admit that i am using NMock... So dont hit me to hard pls) So I can see from a glance that the mock was not correctly excersiced.
The Failure will give me a list of ALL expectation that where violated, and not stop at the 1st one. Thats a crutial difference in the amount of feedback that I get from a single test!
Comment preview