CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Karl Seguin

developer @ Fuel Industries ottawa, ontario

July 2007 - Posts

  • The secret to unit testing: the unit

    After spending time in some of my old code this weekend, I've come to the conclusion that developers new to unit testing are likely to bloat their tests.
    Since your test has set up some type of state, it's very tempting to test the complete state, rather than the specific behaviour you're looking to validate.

    For example, we might have a Save method who's interaction we want to test, so let's start off with a simple test:

    [Test]
    public void SavingANewUserCallsDataStore()
    {
       //todo move to SetUp
       MockRepository mock = new MockRepository();
       IDataStore dataStore = mock.CreateMock<IDataStore>();

       User user = User.CreateNewUser();  
       Expect.Call(dataStore.SaveUser(user)).Returns(39);
       mock.ReplayAll();

       user.Save();
       //todo move to teardown
       mock.VerifyAll();
    }

    Great, the test does exactly what it says it will: it validates that our datastore's SaveUser method is called. While we're at it, why don't we make sure that calling user.Save() did a couple other things? So we add:

    Assert.AreEqual(39, user.UserId);
    Assert.AreEqual(UserStatus.Normal, user.Status);

    The change might seem pretty useful, but we've actually taken a step back. Our test is now doing a lot more than it advertises, which not only makes it less useful as documentation, but also harder to maintain. If either of the two new behaviours we are testing (that the UserId gets set or that the status changes) change, our test will break.

    What's worse is that these trivial extras have a tendency to get repeated over and over again, while at the same time never having a dedicated test for the specific behaviour (why bother, we've tested that the userId gets set in 4 other Save tests).

    I've read once or twice that unit test should never have more than a single assert. I certainly don't agree with that as a rule, but I understand the spirit in which it was said. I've redoubled my efforts to focus on the specific unit while unit testing, and I'm already seeing the effort pay off. My tests are far more maintainble and understanble. That my friends is a recipe for success.

  • Stored Procedures: Going…going…gone?

    For years now, I’ve been a fan and advocate of stored procedures. I’ve used them in almost every system I’ve worked on. Recently I even used them almost exclusively for a large system with a MySQL Cluster back-end (which was an interest project in many respects). At some point, like many others, I woke up and found out that it wasn’t cool to use stored procedures anymore. So I became a closet-sproc-lover.

    The last couple weeks, I’ve started doing some preliminary work on two small projects. In both cases, I’ve found myself completely abandoning stored procedures.

     
    One of the systems is a reporting application, and like it or not, I’m stuck doing very ugly dynamic SQL (like dynamic table/column names and such). For such a case, C# and VB.NET are infinitely better. I mean string formatting, concatenation and manipulation is just easier and far cleaner (hence maintainable). Security is equally problematic in both cases. As for performance, well, it’s a highly indexed and de-normalized system….I don’t have enough data to test yet, but I’m positive I wouldn’t be able to measure any difference.

     
    The other system though is a more typical web-app, and I surprised myself when I started to write SELECT statements in-code. I was annoyed because I had multiple stored procedures to pull one or more rows from a Users table….say:

     
    User_GetFromCredentials(@userName, @password)
    User_GetFromId(@userId)
    User_GetAllForCompany(@companyId)

     
    And whenever I added data to my User class/Table definition I’d need to hunt down all the places where I had the same select (but different wheres) and update them. This was a problem I had faced before, and more or less gotten around by doing some whacky thing with an XML data type, but it was really frustrating. So for fun, I ended up trying something like:

     
    private string _userSelect = “SELECT UserId, UserName, FirstName, LastName, Email FROM Users”:

     
    And I haven’t really looked back.

     
    I found an old post by Jeff Atwood that actually sold me on this entire inline-SQL (here for anyone interested). He’s right on all three points, but most importantly that using a stored procedure only for performance IS a micro-optimization. I’ve never EVER registered a significant performance gain by moving to a stored procedure (you get significant performance gains by properly indexing and modeling and not using datasets.)

    Who knows how it’ll go. We’ll see. And who knows, maybe my next step is O/R Mapper land.

More Posts