Chess TDD 11: Tying Up Loose Ends

Now that all of the pieces are implemented, I decided to change it up a little and get rid of a few yellow items in one fell swoop. I thought it would also be a good time to
Here’s what I accomplish in this clip:

  • Move Knight into it’s own class.
  • Separated test and production into their own assemblies.
  • Got rid of the DefaultBoardSize constant that had been defined in many test classes by consolidating it into one place.
  • Went back to earlier test classes and implemented “MovesFromXX” pattern that I had settled on.

Here are some lessons to take away:

  • If Ctrl-M, O stops working (or any normal VS shortcut), it might be because some other process has claimed part or all of the sequence and is preempting Studio.  Kill processes or reboot.
  • If you have some mundane but necessary tasks (e.g. moving a bunch of classes into a new namespace), this can be a good way to “warm up” when you haven’t looked at a code base in a while.  Generally speaking, look for tasks that can ease you back into the code base while being productive.
  • Even duplication that is seemingly mundane should be avoided.  The DRY principle states that systems should have a single point of definition for all pieces of knowledge, and that includes things like database schemas, config files, and yes, even your unit test classes.  You need to maintain your unit tests, and duplication creates maintenance pain.
  • Pay attention to your test method names as you’re making changes.  These are documentation as to how your code should behave, so if you change the behavior, make sure to change the names to reflect those changes.
  • “Lean on the compiler” to help you with your refactorings.  If you’re getting rid of a bunch of references to a variable, delete the definition of the variable and the compiler will then force you to get rid of all references.  If you do it in the opposite order, you might miss references and waste time.  As a more general rule, you should always favor failing early and doing things in such a way that mistakes will result in non-compiling.
  • When you do large refactorings, it might not hurt to run all of the unit tests explicitly in the test runner instead of relying on the dots in NCrunch (or any continuous testing tool that you’re using).

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1664

  • sten

    Yes! Another part! I could not wait for next part so I’ve started ahead and trying to be more TDD! Now I can enjoy seeing that I did some things right!

    Question:
    I’d like to to use 2 tests that are common for all pieces, e.g “GetMovesFrom.Returns_No_InvaliBoard_Coordinates_From_1_1″ and “GetMovesFrom.Does_Not_Return_Starting_Position”

    Is it possible to introduce a base test class of some kind? How will that work with the nested test class structure?

  • sten

    Ohh one more thing. The item on the list “Implement Equals on BoardCoordinate”.

    Isn’t that unnecessary since structs that doesn’t contain reference type members does a byte-by-byte in-memory comparison as default Equals implementation? Or are you planning on using the == operator?

  • http://www.daedtech.com/blog Erik Dietrich

    Certainly, it’s possible to have a test class for a base class — even an abstract one. Depending on your mocking framework, you can create a mock of the base that defaults to the defined method behavior for non-abstract members on the base class. Now, what you’re proposing is a little more complicated than that, though, since you want to express some kind of invariant that applies to all of inheritors (even those not yet defined). This is an interesting proposition, by the way.

    Here are two ways I can think to do it. First, you can use what I’m talking about and define a method in the base class that does the filtering (either the GetMovesFrom() method or some other method) and have all child implementers invoke it. This is still pretty manual, though. Another thought would be to use reflection to instantiate all Piece inheritors and call their GetMovesFrom to assert that nothing invalid is returned. This has the upside of being a broad invariant and not requiring you to do anything to the test as you add new pieces. It has the downside of probably being a bit ugly from a test suite performance perspective. I’d be interested to hear how it went. If you go that route, I’d just define a Piece test class and probably a GetMovesFrom test class nested in it.

    In response to your second comment, I think I’m going to write a blog post on this subject. The short answer is that I don’t recall the default Equals behavior of structs off the top of my head and that I’d just kind of find out how it worked as I wrote the tests (if I get it out of the box, it’ll be easy to check off my list :) )

  • Pingback: Recall, Retrieval, and the Scientific Method | DaedTech