My favorite form of a “TODO” in code

I tweeted this yesterday, but confused some folks because, well, because it’s Twitter and using 140 character sound bytes is a terrible way to communicate.  I’m working on StoryTeller this morning to finally add a “Delete Test” contextual action to the UI.  The architecture for contextual actions and how they plug into StoryTeller are well established and working, so I just need to flesh out how to do the actual test deletion.  While working on the “ProjectController” class, I realized that I needed a “DeleteTest()” method on another interface “IProject” as specified in this test:

    [TestFixture]

    public class when_deleting_a_test : InteractionContext<ProjectController>

    {

        private Test theTest;

        private Suite theSuite;

 

        protected override void beforeEach()

        {

            theTest = new Test("test 1");

            theSuite = new Suite("suite 1");

 

            theSuite.AddTest(theTest);

 

            ClassUnderTest.HandleMessage(new DeleteTestMessage(theTest));

        }

 

        [Test]

        public void should_invoke_the_inner_project_to_delete_the_test()

        {

            MockFor<IProject>().DeleteFile(theTest);

        }

    }

Don’t worry too much about the “InteractionContext / MockFor<T>()” business, that’s just a little test harness superclass I use for auto mocking.  I’m working on the ProjectController class here, but I’ve basically made an extension to the IProject interface which will have to be implemented at some point for this whole “Delete Test” process to work.  I really don’t want to break my stride on the ProjectController class (because it has other things to do), so I need to drop off some sort of “TODO” to remind myself to come back and implement the “IProject.DeleteFile(Test)” method.  I do that by going into the test fixture for the concrete Project class and doing this:

    [TestFixture]

    public class ProjectTester

    {

 

        [Test]

        public void delete_a_test_file()

        {

            Assert.Fail("Do.");

        }

    }

Now, I can go on and worry about ProjectController without a context switch into the Project file system concerns and be sure that I’ve wrapped up loose ends later because as soon as I start my normal check in dance I’ll get unit test failures gently reminding myself to go back and fill in the blanks.  There is a bunch of “throw NotImplementedException” lines all over the real code too, but I’d have to run the UI a bit to run into these.  Running the unit test suite turns out to be a faster and more thorough way of finding the little TODO land mines because every unit test runs and gives me a complete picture of what isn’t implemented yet.

Last note, these TODO tests aren’t necessarily a complete specification of the missing implementation, just a TODO that bites back at you to tell you there’s missing work.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://igorbrejc.net Igor Brejc

    Not sure which xUnit testing framework you use, but Gallio has [Pending] test method attribute for these kinds of things.

  • rteytry

    rteytry

  • http://ashish.tonse.com Ashish Tonse

    “If you’ve got devs checking in with failing unit tests, you’ve got bigger problems.”

    I’ve got devs that don’t even write tests. Even Bigger problems. :)

  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @secretGeek,

    Nice, but I almost ran away screaming as soon as I saw “PInvoke”

  • http://secretGeek.net secretGeek

    nice one Jeremy.

    For less than gentle reminding, you need a little PInvoke fun…

    [DllImport("kernel32.dll")]
    public static extern bool Beep(int freq,int duration);

  • eviltobz

    I’d like to get into TDD but it is not the way of doing things in my office, so I can’t use this approach. However, I recently found my own way of flagging todo’s in a suitably obnoxious way.

    I create a method something like void LogToDo(string message) which just outputs the todo message to the debug window, but I mark the method with the Obsolete attribute. This means that every call to it generates a compiler warning which can be double clicked to take you straight to the part of the source code that needs to be changed.

    Admittedly setting it as Obsolete isn’t exactly correct, but as it is only there as a temporary measure during development I’m not too concerned about that.

  • ralf

    Reminds me a bit of a thing that Kent Beck or Ward Cunningham once wrote. Along the line of “Ending work in the evening with a failing test”. That way you instantly know on what you need to continue when you come back in the morning.

    r

  • http://www.tigraine.at Tigraine

    I sometimes implement a test for a new feature that will keep failing for quite some time before I manage to implement that at some point.
    So I usually [Ignore] those tests and only write Failing unit tests for real TODO code that has to be fixed in order to check back in.

    greetings Daniel

  • Arielr

    And btw, if you work on a branch per feature mode – checking failing tests is a good idea. Checking in failing integration tests at the start of a feature and “allowing yourself” to merge back when they pass – is even better.

  • Arielr

    :)
    I have tests with
    throw new FeatureNotImplementedException();

  • http://www.squaredroot.com Troy Goode

    Oh I absolutely agree, my concern is that this would somehow be viewed as not _really_ a failing unit test by other devs. Perhaps its a non-issue. I’ll give it a shot at some point and see if it catches on in my org. =)

  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Troy,

    That’s the whole point of the “check in dance.” I do NOT check in with failing tests, period. If you’ve got devs checking in with failing unit tests, you’ve got bigger problems.

  • http://www.squaredroot.com Troy Goode

    This is an interesting idea. My only fear is in the (obviously abuseful) scenario where the Assert.Fails are committed to source control frequently and begin to cloud the CI servers reports. “Is the build failing because it is broken or because there are some TODOs out there that havent been TODONE?”