TDD Teaser #1 - Do you know the answer?

Published Wednesday, October 6, 2004 8:04 PM

I recently concluded a TDD with ASP.NET presentation in Cleveland with several TDD Teaser problems for the audience.  The idea proved to be a lot of fun so I decided to repost the problems on my blog.

The Rules:

  1. Prize (a Thycotic keyring light) to be mailed to the first comment with the correct answer on this blog post with valid contact information.
  2. My definition of the problem is the correct one. :)  Other answers might be right but won't win the prize.
  3. I will post the answer within a few days.

What is wrong with the following code?

1using NUnit.Framework; 
2
3namespace UnitTests.BadCode
4{
5 [TestFixture]
6 public class Problem1
7 {
8 [Test]
9 public virtual void TestSomething()
10 {
11 MyClass a = new MyClass();
12 TestAmount(a);
13 }
14
15 public virtual void TestAmount(MyClass a)
16 {
17 Assert.AreEqual(2500, a.Amount);
18 }
19 }
20}
Winner: Roy Osherove

Answer & Discussion (click and drag your mouse to see the answer)
Kirk - you are right. It doesn't compile the return type on TestAmount should have been void (Note to self: make sure your teaser compiles!). Unfortunately that wasn't the one I was looking for. I have changed the return type to void as it should have been.

Dean - virtual methods and inheritance can be quite useful in tests - you should refactor your tests as judiciously as your production code and this may result in inherited tests. I often use inheritance when writing validity checks for different scenarios. I agree with your comments about TestAmount being poorly designed.

Answer:
NUnit, for backwards compatibility to 1.0, will identify TestAmount as a test due to the "Test" prefix on the method name. This results in an error since Tests may not have parameters. Why did NUnit 1.0 look for the Test prefix rather than use attributes? - because it was ported from JUnit which uses naming conventions since Java doesn't have attributes.

Well done Roy! (your keyring light is on its way)

Thanks to everyone for participating! :-)

Comments

# Kirk Marple said on Wednesday, October 6, 2004 8:50 PM

TestAmount is supposed to be returning a string but all it does is Assert. it shouldn't even compile.

Kirk
kirk<nospam>@agnostic-media.com

# Dean Harding said on Wednesday, October 6, 2004 9:43 PM

I can see two things at first glance:

First is the fact that all methods are virtual. The class should be probably be sealed to start with - test cases are not meant to be extended in that manner.

Second, you've separated your test case into two methods. What happens if you change one method and not the other? At the very least your TestAmount method should have an "expected" parameter which it uses instead of the hard-coded 2500. The TestSomething method can pass in the expected value when it calls TestAmount. What I'm trying to say here is that TestSomething knows what the state of "a" should be, but TestAmount does not necessarily know.

dean.blogger@codeka.com

# Roy Osherove said on Wednesday, October 6, 2004 10:37 PM

TestAmount is public and begins with "Test". because of backwards compatibility issues Nunit will run that method as well thinking it is a test. However, it accepts parameters which means it will won't run and you'll get a nice error.
Right?

# Roy Osherove said on Wednesday, October 6, 2004 10:38 PM

oh yeah - Roy at osherove dot com is my email :)

# Roy Osherove said on Wednesday, October 6, 2004 10:41 PM

other ideas:
if you *are* going to use a separate verification method, it should at least be named "VerifyXX" and be private. You also didint' specify an error message on failure (the third missing parameter in the assert) and that's usually a no-no.

# Ron Krauter said on Thursday, October 7, 2004 12:02 AM

Assert.AreEqual(2500, a.Amount) will never run since the method does not have the [Test] attribute?

# Matt Berther said on Thursday, October 7, 2004 12:02 AM

Roy: I thought that that was the issue as well, but after thinking about it, I think that the backwards compatability with methods that begin with "Test" also requires the method to return void and accept no parameters.

# Haacked said on Thursday, October 7, 2004 12:28 AM

Kirk is correct in that it won't compile.

Assuming you correct that by changing TestAmount to return void, you end up with two test methods in NUnit.

One that correctly runs the assertion and one that displays the method TestAmount and says it must not have parameters.

haacked@yahoo.com

# Roy Osherove said on Thursday, October 7, 2004 5:16 AM

dang - it won't compile.

This Blog

Syndication