Unit Testing, Agile Development, Leadership & .NET - By Roy Osherove
Interesting, so how would you recommend fixing this test?
Ben
@Ben_Hall
When u talk about create manual mocks an stubs, do you mean create an entire class that "emulate" the behavior of a given class because this is a third party sealed class for example? Or do u mean to set the behavior of a given class with some mock framewrk like typemock, (in typemock's case you set the outcome with a method named "will return" that missused could lead to potential test issues)
"for example"?
It looks you forgot to cut&paste the example.
Totally agree. This is something I always point out in code reviews because it's very, very bad!
It also makes the test code less declarative -- instead of just saying what the result is meant to be, you are also saying _how_ to get the result.
I can't really agree with this rule. While I do understand the reasoning, I don't agree with the conclusion. Shying away from specifying domain logic in the test leads to magic numbers or strings that may seem unrelated to each other.
That leads to Obscure Tests.
I'm not saying that a test should reproduce a complete algorithm because that could obviously lead to bugs in the tests, but the key is to chop up complex business rules into constituent parts and only test one part per test.
I wrote about this overall principle a while back: blog.ploeh.dk/.../DerivedValuesEnsureExecutableSpecification.aspx
As a rule of thumb, I find Derived Values much more communicative than magic values. Not always, but most of the time.
Mark:
that's where the name of the test, as well as other factors (how simple is the test, how simple is the input\expected output) come in to play.
for example, you could name the expected 42 value in your post to a variable name that explains what the result means.
@Emilio
remove line 8 and chane line 9 to
Assert.AreEqual("hello user",result);
in this way you remove the logic bit from the test
Well, I never liked those rigid test name rules. Things change and stuff gets refactored and suddently, the class or method under test gets renamed, yet the test name remains the same.
For that reason I consider the test code the primary specification, and the name as secondary. I still prefer helpful test names, but I don't rely on them.
@smnbss: In your example, you would need two or more tests just to make sure the code didn't always return "Hello User" rather than the paramter. Would the following be better
var stringPrefix = "Hello ";
Assert.IsTrue(result.StartsWith(stringPrefix, result);
Assert.IsTrue(result.EndsWith(string.Format(" {0}", user), result);
Assert.AreEqual(stringPrefix.Length + userName.Length, result.Length);
Paul: Or just add another test that calls:
> cut.SayHello("bill");
and asserts again without logic