Charlie Poole, lead developer of NUnit, had some interesting things to say – level 100

It’s an old interview, but timeless tips.  Roy Osherove interviews Charlie Poole, who is the lead deverloper of the NUnit testing framework.  This was a very interesting interview.  Some points that stood out in my mind were:



  • The next version of NUnit will be 2.4 in order to skip 2.3 so that version collisions won’t happen with the version released with Test-Driven.Net

  • When describing development methods to management, there’s no reason to “ask permission” to refactor.  Just like you wouldn’t ask permission to use a particular type of exception handling, you are responsible for deliverables, so just use the best practices you know.

  • Charlie recommends phasing developers into TDD.  He says that first get them to write automated tests, then unit tests, then introduce driving development with these tests.  Each of these are big jumps by themselves.

I’d recommend a listen if you have time – I listen in the gym while working out.

TDD topc on MSDN will be corrected – level 100

Rob Caron has stated that the Guidelines for Test-Driven Development posts on MSDN is erroneous and will be corrected and that Microsoft has no intention of “redefining” TDD.


We’re aware of the issue and are taking steps to rectify it. An error in a help topic is no different than a coding error – it’s a bug and we’re fixing it. Because of the process involved in publishing product documentation on MSDN, it takes a little bit of time to get updated files in place.


So far the MSDN article has been rated by over 350 people and has an average rating of 1.13 on a scale from 1 to 9.


 

Vanpool to TDD workshop from Austin to Houston Nov 29th – level 100

We’re having a vanpool from Austin to Houston on Nov 29th for the TDD workshop.  We’ll meet at 4:30 and leaving promptly at 5AM for Houston.  We’ll return around 9PM.  Meet in the parking lot on the SW corner of 183 and Burnet.  Here’s a satellite picture of the area.


http://maps.google.com/maps?ll=30.372135,-97.726994&spn=0.006446,0.009560&t=h&hl=en


Check out the AgileATX Yahoo group for more info.

Quickly documenting public APIs using GhostDoc – level 200

Along with Resharper, the following class was created using a minimum number of keystrokes.  Basically, I typed the names of the fields, and shortcut the rest.  Consider the following class that I might want to have Xml documentation for:



public class Person


{


    private string _firstName;


    private string _lastName;


    private string _phoneNumber;


    private int _age;


 


    public string LastName


    {


        get { return _lastName; }


        set { _lastName = value; }


    }


 


    public string PhoneNumber


    {


        get { return _phoneNumber; }


        set { _phoneNumber = value; }


    }


 


    public int Age


    {


        get { return _age; }


        set { _age = value; }


    }


 


    public string FirstName


    {


        get { return _firstName; }


        set { _firstName = value; }


    }


 


    public Person(string firstName, string lastName, string phoneNumber, int age)


    {


        _firstName = firstName;


        _lastName = lastName;


        _phoneNumber = phoneNumber;


        _age = age;


    }


}


I could type all the Xml comments myself, but that would be considerable effort, and there isn’t anything special about this class.  Most people could guess what this API does, so why not have a tool help with the Xml comments.  I press CTRL + Q (my GhostDoc shortcut key) on each of my properties as well as the constructor, and I immediately have the following:



public class Person


{


    private string _firstName;


    private string _lastName;


    private string _phoneNumber;


    private int _age;


 


    /// <summary>


    /// Gets or sets the name of the last.


    /// </summary>


    /// <value>The name of the last.</value>


    public string LastName


    {


        get { return _lastName; }


        set { _lastName = value; }


    }


 


    /// <summary>


    /// Gets or sets the phone number.


    /// </summary>


    /// <value>The phone number.</value>


    public string PhoneNumber


    {


        get { return _phoneNumber; }


        set { _phoneNumber = value; }


    }


 


    /// <summary>


    /// Gets or sets the age.


    /// </summary>


    /// <value>The age.</value>


    public int Age


    {


        get { return _age; }


        set { _age = value; }


    }


 


    /// <summary>


    /// Gets or sets the name of the first.


    /// </summary>


    /// <value>The name of the first.</value>


    public string FirstName


    {


        get { return _firstName; }


        set { _firstName = value; }


    }


 


    /// <summary>


    /// Initializes a new instance of the <see cref=”Person”/> class.


    /// </summary>


    /// <param name=”firstName”>Name of the first.</param>


    /// <param name=”lastName”>Name of the last.</param>


    /// <param name=”phoneNumber”>The phone number.</param>


    /// <param name=”age”>The age.</param>


    public Person(string firstName, string lastName, string phoneNumber, int age)


    {


        _firstName = firstName;


        _lastName = lastName;


        _phoneNumber = phoneNumber;


        _age = age;


    }


}


Most of the work is done.  There is no way GhostDoc can read my mind, so I might have to make a few adjustments to the comments, but they are minimal.  Note that GhostDoc got confused on firstName and lastName, but that’s understandable.  It hits the rest dead-on:



public class Person


{


    private string _firstName;


    private string _lastName;


    private string _phoneNumber;


    private int _age;


 


    /// <summary>


    /// Gets or sets the last name.


    /// </summary>


    /// <value>The last name.</value>


    public string LastName


    {


        get { return _lastName; }


        set { _lastName = value; }


    }


 


    /// <summary>


    /// Gets or sets the phone number.


    /// </summary>


    /// <value>The phone number.</value>


    public string PhoneNumber


    {


        get { return _phoneNumber; }


        set { _phoneNumber = value; }


    }


 


    /// <summary>


    /// Gets or sets the age.


    /// </summary>


    /// <value>The age.</value>


    public int Age


    {


        get { return _age; }


        set { _age = value; }


    }


 


    /// <summary>


    /// Gets or sets the first name.


    /// </summary>


    /// <value>The first name.</value>


    public string FirstName


    {


        get { return _firstName; }


        set { _firstName = value; }


    }


 


    /// <summary>


    /// Initializes a new instance of the <see cref=”Person”/> class.


    /// </summary>


    /// <param name=”firstName”>First name.</param>


    /// <param name=”lastName”>Last name.</param>


    /// <param name=”phoneNumber”>The phone number.</param>


    /// <param name=”age”>The age.</param>


    public Person(string firstName, string lastName, string phoneNumber, int age)


    {


        _firstName = firstName;


        _lastName = lastName;


        _phoneNumber = phoneNumber;


        _age = age;


    }


}


Microsoft’s guidance for unit testing actually describes integration testing – level 200

I commend Microsoft for putting a big emphasis on automated testing.  This is a big step for the software industry as a whole to embrace automated testing.  The hardware industry has already discovered this and has a built-in self-test in almost every device.  Likewise, software should have built-in self-tests to ensure that everything is working.


Microsoft has provided Unit Testing and Generating Source Code for Unit Test Frameworks Using Visual Studio 2005 Team System.  In this article they describe how to unit test some code using Team System’s automated testing features.  The problem is that what is actually described is integration testing.  The tests call a BankAccount object and exercise some methods.  There is no mocking(stubbing) of BankAccount’s dependencies, so this cannot be a unit test.  If BankAccount actually works, it will have to communicate with some dependency unless this BankAccount keeps everything in memory.


Here are some recommended “unit tests” from the article:


  • Constructor Test—To make sure your object loads properly, with the correct information.
  • PositiveLoadScalarTest—To test the successful Load of a Customer that exists in the database.
  • NegativeLoadScalarTest—To test the unsuccessful Load of a Customer—that is, one that does not exist in the database.
  • PositiveLoadTest—To test the successful load of Customers, based on known data.
  • NegativeLoadTest—To test the unsuccessful load of Customers that do not exist in the database.
  • NegativeValidationTest—To make sure your validation logic is working correctly.

  • Clearly, the assumption is made that a database is in the testing stack.  This disqualifies the tests from being unit tests because they include a dependency and test more code than the “unit” – BankAccount component. 


    Automated testing is very important, but I must clarify some points in this article.  The testing described here is “integration testing”.  This kind of testing is important too, but it’s important to make the distinction.  Unit tests test at the unit level and exclude a database.  Unit tests are fast and can run on any workstation, not just a specially configured development environment.


    Integration tests include multiple components of a system and make sure the pieces work together.  In an integration test, it is appropriate to include multiple components including a database.  For unit testing, including a database is not appropriate.

    How to create a jump-to-page feature to enhance the DataGrid pager – level 200

    When displaying information in a grid on an ASP.NET web page, it’s
    often a good idea to page the information if there is a lot of
    it.  For instance, if you have 10000 rows of information to
    potentially display, it’s unreasonable to expect the user to wait to
    download all of it at one time and scroll forever.  It’s wasteful,
    too.  Instead, page it in smaller chunks (10-50).  Then let
    the user move to different pages of information.  But when there
    is a lot of pages, you don’t want the user to have to click multiple
    times to get to page 15.  If information is sorted, a user will
    often know what page to jump to.  In this
    post, I’ll cover how to add a “jump-to-page” feature to the
    paging mechanism of an ASP.NET DataGrid.
     
    First, let’s cover how to get paging working on a normal, stock
    DataGrid.  I’ve spoofed some data in the form of a string array,
    and I have my basic, numeric pager:
     
    <form id=”Form1″ method=”post” runat=”server”>
      <asp:DataGrid AllowPaging=”True” PagerStyle-Mode=”NumericPages” 
         PagerStyle-PageButtonCount=”10″ ID=”grid” Runat=”server” />
    </form>
     

    using System;

    using System.Web.UI;

    using System.Web.UI.WebControls;

     

    public class WebForm1 : Page

    {

        protected DataGrid grid;

     

        protected override void OnLoad(EventArgs e)

        {

            base.OnLoad(e);

            if (!IsPostBack)

            {

                grid.DataSource = this.GetSource();

                this.BindGrid(0);

            }

        }

     

        protected override void OnInit(EventArgs e)

        {

            base.OnInit(e);

            grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);

        }

     

        private string[] GetSource()

        {

            //just imagine how you would get/cache your data source.

            string[] rows = new string[10000];

            for (int i = 0; i < 10000; i++)

            {

                rows[i] = i.ToString();

            }

            return rows;

        }

     

        private void BindGrid(int currentPageIndex)

        {

            grid.DataSource = this.GetSource();

            grid.CurrentPageIndex = currentPageIndex;

            grid.DataBind();

        }

     

        private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)

        {

            this.BindGrid(e.NewPageIndex);

        }

    }

    This works fine, but I have to click so many times to get to page
    100 (10 clicks).  I would like to be able to punch in a number and
    jump to that page quickly.  Let’s examine the following code and
    how I created some controls to insert into the DataGrid paging
    mechanism.  The DataGrid doesn’t provide a PageTemplate, so we
    have to do a bit of manual control arrangement.  First, we’ll set
    up how we would like it to work:

    Let’s add our jump-to section:

    <form id=”Form1″ method=”post” runat=”server”>
     <asp:DataGrid AllowPaging=”True” PagerStyle-Mode=”NumericPages”
      PagerStyle-PageButtonCount=”10″ ID=”grid” Runat=”server” />
     <asp:Panel ID=”pagerEnhancement” Runat=”server”>
      Jump to page:
      <asp:TextBox id=jumpToText Runat=”server” Width=”25″></asp:TextBox>
      <asp:Button id=jumpToButton Runat=”server” Text=”Go”></asp:Button>
     </asp:Panel>
    </form>

    Notice that we just have a textbox and a button.  We’ve added code to make this affect the DataGrid page:

    using System;

    using System.Web.UI;

    using System.Web.UI.WebControls;

     

    public class WebForm1 : Page

    {

        protected System.Web.UI.WebControls.TextBox jumpToText;

        protected System.Web.UI.WebControls.Button jumpToButton;

        protected System.Web.UI.WebControls.Panel pagerEnhancement;

        protected DataGrid grid;

     

        protected override void OnLoad(EventArgs e)

        {

            base.OnLoad(e);

            if (!IsPostBack)

            {

                grid.DataSource = this.GetSource();

                this.BindGrid(0);

            }

        }

     

        protected override void OnInit(EventArgs e)

        {

            base.OnInit(e);

            grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);

            jumpToButton.Click +=new EventHandler(jumpToButton_Click);

        }

     

        private string[] GetSource()

        {

            //just imagine how you would get/cache your data source.

            string[] rows = new string[10000];

            for (int i = 0; i < 10000; i++)

            {

                rows[i] = i.ToString();

            }

            return rows;

        }

     

        private void BindGrid(int currentPageIndex)

        {

            grid.DataSource = this.GetSource();

            grid.CurrentPageIndex = currentPageIndex;

            grid.DataBind();

        }

     

        private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)

        {

            this.BindGrid(e.NewPageIndex);

        }

     

        private void jumpToButton_Click(object sender, System.EventArgs e)

        {

            int newPage = int.Parse(jumpToText.Text);

            this.BindGrid(newPage – 1); //The DataGrid needs a page index, zero-based.

        }

    }

    This works, but when I make my DataGrid pretty, I don’t want this
    paging attachment left out.  I need it to be inside the DataGrid,
    so let’s write some code to move it from outside the DataGrid to right
    next to the default pager:

    using System;

    using System.Web.UI;

    using System.Web.UI.WebControls;

     

    public class WebForm1 : Page

    {

        protected TextBox jumpToText;

        protected Button jumpToButton;

        protected Panel pagerEnhancement;

        protected DataGrid grid;

     

        protected override void OnLoad(EventArgs e)

        {

            base.OnLoad(e);

            if (!IsPostBack)

            {

                grid.DataSource = this.GetSource();

                this.BindGrid(0);

            }

        }

     

        protected override void OnInit(EventArgs e)

        {

            base.OnInit(e);

            grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);

            jumpToButton.Click += new EventHandler(jumpToButton_Click);

            grid.ItemCreated +=new DataGridItemEventHandler(grid_ItemCreated);

        }

     

        private string[] GetSource()

        {

            //just imagine how you would get/cache your data source.

            string[] rows = new string[10000];

            for (int i = 0; i < 10000; i++)

            {

                rows[i] = i.ToString();

            }

            return rows;

        }

     

        private void BindGrid(int currentPageIndex)

        {

            grid.DataSource = this.GetSource();

            grid.CurrentPageIndex = currentPageIndex;

            grid.DataBind();

        }

     

        private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)

        {

            this.BindGrid(e.NewPageIndex);

        }

     

        private void jumpToButton_Click(object sender, EventArgs e)

        {

            int newPage = int.Parse(jumpToText.Text);

            this.BindGrid(newPage – 1); //The DataGrid needs a page index, zero-based.

        }

     

        private void grid_ItemCreated(object sender, DataGridItemEventArgs e)

        {

            if(e.Item.ItemType == ListItemType.Pager)

            {

                TableCell pagerCell = (TableCell) e.Item.Controls[0];// User Trace to view the

                //control tree and found out how to grab the pager.;

                pagerCell.Controls.Add(pagerEnhancement);

            }

        }

    }

    Notice how I am listening to the ItemCreated event of the DataGrid
    and then moving the control when I’m on the Pager.  I used the
    Trace feature to observe the DataGrid control to see how the Pager was
    laid out.  The DataGrid is rendered as an Html table, so I just
    needed to move my extra paging controls to the appropriate TableCell.

    Obviously, I have simplified this example to demonstrate the basics
    of adding to the default paging mechanism in the DataGrid.  When I
    use this technique, I make the appearance a lot more attractive, and I
    also validate that an actual page number was entered into the
    TextBox.  After all, I have to gracefully handle whatever the user
    types into that box. 

    Test-driven development panel at Innotech – level 000

    At the Innotech conference, there was a TDD panel with Mary Poppendieck and 4 members of the local developer community (2 of them are my coworkers).  Mary clarified that TDD is as old as software development itself.  She relates that when she was coding assembly, she would create a testing framework to simulate the device she was writing for before she wrote any code.  Then, every bit of code was written with automated tests.  Here is a picture of the panel.  From left to right there is Scott Bellware, Jeremy Miller, Jeff Smith, Bret Pettichord, and Mary Poppendieck.