Author: way0utwest

  • A tSQLt Mistake – Debugging a Test

    While I was working on a test the other day, it kept failing. Not a big surprise, but I couldn’t figure out why. When I looked at tsqlt.testresults, I saw extra rows. Double rows in fact, and that threw me.

    This was my Assemble code.

    -- Assemble
    CREATE TABLE #Expected (
    yearnum int
    , monthnum TINYINT
    , salestotal money
    )


    INSERT INTO #Expected
    ( yearnum
    , monthnum
    , salestotal
    )
    VALUES
    ( 2012, 11, 2500.23 )
    , ( 2012, 12, 2200.15 )
    , ( 2013, 1, 2656.75 )

    SELECT *
    INTO #actual
    FROM #Expected AS e

    EXEC tsqlt.FakeTable @TableName = N'MonthlySales', @SchemaName='dbo';

    INSERT dbo.MonthlySales
    VALUES
    ( 11, 1000.00)
    , ( 11, 1500.23)
    , ( 12, 2200.15)
    , ( 13, 1000.00)
    , ( 13, 1656.00)
    , ( 13, 0000.75);

    Here was the output (ignoring the failure messages):

    [tArticles].[test sum of sales by month for multiple months] failed: (Failure) The calculations are incorrect

    |_m_|yearnum|monthnum|salestotal|

    +—+——-+——–+———-+

    |=  |2012   |11      |2500.2300 |

    |=  |2012   |12      |2200.1500 |

    |=  |2013   |1       |2656.7500 |

    |>  |2013   |1       |2656.7500 |

    |>  |2012   |12      |2200.1500 |

    |>  |2012   |11      |2500.2300 |

     

    Hmmm. What’s going on? Why don’t the rows match? If I run the query, I see the results I expect. Is it the query or test?

    In this case, you read the results as showing that I have 3 rows that are the same in my expected and actual tables (@expected and @actual variables in the assert). However I also have 3 extra rows in the actual table, which appear to be duplicates.

    If I go back to the Assemble, I see a pattern that’s a problem. Some people might think these hassles are a way to give up on testing. Some might build a better pattern. I’ll do the latter.

    In this case I create the expected table and then I insert the expected results. Then I create my actual table from the expected one to keep the schema the same and avoid repeating code. However in this case I have a bug.

    The bug is I’m moving the expected results to actual. If I asserted at this point, I’d pass. However then I run the query and insert the results, which happen to be the same as the expected results (my query works). If the query didn’t work, I might really spend a lot of time debugging it, but here I can tell my test code is buggy.

    I have two choices to fix this.

    1. Add a WHERE clause of WHERE 1 = 0 (no rows inserted)
    2. Move the creation of the actual table.

    My first thought was to adjust the pattern to this:

    CREATE TABLE #Expected (
    yearnum int
    , monthnum TINYINT
    , salestotal money
    )

    SELECT *
    INTO #actual
    FROM #Expected AS e


    INSERT INTO #Expected
    ( yearnum
    , monthnum
    , salestotal
    )
    VALUES
    ( 2012, 11, 2500.23 )
    , ( 2012, 12, 2200.15 )
    , ( 2013, 1, 2656.75 )

    I move the #Actual and #Expected tables together, so that once I get the results set, I immediately create the #Actual copy. I could leave things and do this:

    CREATE TABLE #Expected (
    yearnum int
    , monthnum TINYINT
    , salestotal money
    )


    INSERT INTO #Expected
    ( yearnum
    , monthnum
    , salestotal
    )
    VALUES
    ( 2012, 11, 2500.23 )
    , ( 2012, 12, 2200.15 )
    , ( 2013, 1, 2656.75 )

    SELECT *
    INTO #actual
    FROM #Expected AS e
    WHERE 1 = 0

    EXEC tsqlt.FakeTable @TableName = N'MonthlySales', @SchemaName='dbo';

    Maybe the best thing is to be careful and do this:

    -- Assemble
    CREATE TABLE #Expected (
    yearnum int
    , monthnum TINYINT
    , salestotal money
    )

    SELECT *
    INTO #actual
    FROM #Expected AS e
    WHERE 1 = 0

    INSERT INTO #Expected
    ( yearnum
    , monthnum
    , salestotal
    )
    VALUES
    ( 2012, 11, 2500.23 )
    , ( 2012, 12, 2200.15 )
    , ( 2013, 1, 2656.75 )

    Combine the ideas and keep this insulated from refactoring moving or adding code in there.

    Remember, tests are code. This is why they should fail first, so that you have some confidence in your code working and causing a test to pass.

  • Choosing Your Tasks

    This editorial was originally published on May 13, 2011. It is being re-run as Steve is out of town.

    I have been working for SQLServerCentral for nearly a decade. I started in 2002 and in that time I have had to define my own job most of the time. Early on Andy and Brian had a list of things they thought I should be doing, and there were certain things to get done each week, but it was a general list.

    This Friday I thought this was a topic for a good poll. Answer this question:

    What percentage of your time is self-directed?

    By self-directed I mean the tasks that you choose to do because you think they need to be done for some reason. This is opposed to the specific tasks that someone assigns you and gives you some deadline for finishing. If someone asks you to “tune the server”, I don’t consider that a specific task, and you would have to pick items to work on, and determine how much time you spend on them, that’s a self-directed task.

    Do you have a good amount of self-directed time? When I used to manage a series of production servers, I usually had at least half my time as self-directed time. I could look at poor running queries, contact groups with proactive ideas for improving performance or preventing problems. I even had time to schedule DR testing. That took a lot of investment over time. I had to understand each system, set up monitoring and standards, build in data capture and analysis routines, and of course, plenty of alerting mechanisms.

    I think that a great production DBA will have a lot of self-directed time after 6-12 months on the job. A development DBA, however, will likely be constantly responding to code requests and enhancements, which is one reason I prefer the former job.

    Steve Jones

  • A Long Trip Ahead

    This is my last day at home for a long time. At least long by my standards. I head to the airport tomorrow for a ten day trip, not returning to CO until Saturday, Oct 17. I rarely travel more than 4 or 5 days at the most, so this is one of my longer ones.

    My first stop is Orlando. I’m heading over to help teach a DLM workshop for Redgate Software on Friday. This is our Database Source Control workshop that covers some in depth work with SQL Source Control and version control systems. I’ve done a few of these, so this should be easy for me.

    Saturday is SQL Saturday #442 in Orlando. I haven’t been to a SQL Saturday in Orlando in a long time, so I’m excited to get back to the place where these all started. I’ve got one talk on Saturday, talking Encryption, around which I’ll be hanging out with friends and trying to learn a few SQL things along the way.

    Sunday I travel, though at a relaxed pace. I’ll spend the day making my way to Houston before an overnight flight to London on the Dreamliner. It’s a leisurely day, where I’ll probably spend time catching up on Python work because Monday is crazy.

    Monday is a day I dread a bit. I land in London and immediately drive to Cambridge for a few meetings. I’ve got some SQL in the City rehearsals planned before I turn around and head back to London to catch the fun bus to Bristol for SQL Relay. If you map this out, it seems silly, but that’s what I got myself talked into somehow.

    Tuesday is SQL Relay in Bristol. I’ll be previewing my talk for SQL in the City, so I’ll apologize in advance if things aren’t 100% set. However after a day at the conference, I’ll be heading over to Cardiff where I’ll get dinner and try to fix all the things I did wrong during the talk.

    Wednesday is SQL Relay Cardiff.  A repeat of Tuesday in a new city. I’m not sure if everything is the same, but I’ll be (hopefully) delivering a better talk on Wednesday. Wednesday night Grant and I aren’t doing anything, so it’s a few hours to unwind.

    Thursday morning we make our way back to London. Hopefully we manage the train system fine because we have lunchtime and afternoon meetings with people coming down from Redgate during the day. This is the final SQL in the City prep time, as well as a few other in person events, including seeing my boss for only the 3rd time this year.

    Friday is SQL in the City 2015 London. Redgate puts on a great event, and I’m looking forward to another exciting day. Three times on stage for me, so I’m sure when things wrap up around 5 I’ll be quite tired. However no rest, I head to Heathrow for a night in my 5th hotel on this trip.

    10 days. Orlando, Cambridge, Bristol, Cardiff, London.

    I have the feeling I won’t be doing much on Saturday night or Sunday when I return.

  • Aging Software

    I wrote The Age of Software awhile back and noted that supporting previous versions of software isn’t necessarily a good use of resources for development teams. I especially think this is true of SQL Server. But does that mean we should abandon aging software platforms?

    It’s a tough question. I’ve certainly talked about the case for upgrading, and the reasons why you might not. For any particular instance, however, I think that each of you has to make the case about whether the software works, or it doesn’t.

    If it works, then it seems many of us will live with the old software and keep it running. As late as a few years ago I knew a company running SQL 6.5 with a piece of software built in 1996 and last patched in 2001. However this software ran a building key card system, and there wasn’t a good case to be made for upgrading.

    For a software developer, however, when you look at aging pieces of software, even those that customers may pay for support on, is it worth maintaining skills and support? If you don’t have staff turnover, then perhaps. If you don’t, I do think that it might be time to let the product die.

    I’m torn on the way we deal with software in our world. On one hand, I’d like to see customers given source code for end of life platforms in order to support themselves if they wish. On the other, I understand the IP concerns, and business case to let software die.

    Ultimately I’m mostly OK with the current way most vendors support software. If it works for a decade and support ends, I can continue to use it. Until it doesn’t work, and then I am glad that most vendors have an upgrade for me.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 2.5MB) podcast or subscribe to the feed at iTunes and LibSyn.