Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

Create One Unit Test With A Bunch of Data Driven Scenarios: Using DataSource with MSTest

Posted by Keith Elder | Posted in .Net, Visual Studio | Posted on 15-05-2008

When writing unit tests there are a couple of ways to test a bunch of scenarios.  One way is to write a test for each and every case.  That can take forever and as developers we always like to work smarter instead of harder right?  Another way is to create a data file with known expected results and then run a test on the data file.  For example, let’s say you write a regular expression, something a little complex like a regular expression to validate URLs.  How many unit tests would you have to write to cover all the possible scenarios?  One?  Two? Ten?  I know I can think of ten tests I’d want to test easily.  Using the DataSource attribute on tests with MSTest is a great way to play out an unlimited number of test scenarios.  Here’s how to accomplish this.  It is easier than you think!

Sample Solution

To showcase how this is done I created a sample solution in Visual Studio.  I created a C# library with a static class called Validator.cs.  This class will hold my static method to validate a URL with a regular expression.  My favorite place to find regular expressions is http://ww.regexlib.com.  I did a quick search for a URL regular expression and found one written by Brian Bothwell that seemed interesting.

image

It didn’t look too bad and seemed to account for the various things I think a regular expression like this should account for. 

I took Brian’s regular expression and added it to my Validator.cs file as seen here.

        public static bool ValidateURL(string url)
        {
            return Regex.IsMatch(url, @"^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA" 
                +@"-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]"
            +@"{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]"
            +@"{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]"
            +@"|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])"
            +@"|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net"
                +@"|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*"
                +@"(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
        }

With my method in place I added a test project to the solution and generated a test for this method.  My initial test looked like this.

        /// <summary>
        ///A test for ValidateURL
        ///</summary>
        [TestMethod()]
        public void ValidateURLTest()
        {
            string url = "http://keithelder.net"; 
            bool expected = true;
            bool actual;
            actual = Validator.ValidateURL(url);
            Assert.AreEqual(expected, actual);
        }

Running the test we can see it passed.

image

This is great to test one scenario but I want to test this regular expression with a bunch of URLs to make sure this test covers all of my possible scenarios.  Here’s how to convert this one simple test into a data driven test.

Convert Simple Test Into Data Driven Test in Visual Studio

The first thing we need to do to power our test case with data is to create a data file.  Visual Studio supports several data sources:  Database, CSV, and XML.  In my experience I have always found CSV to be the easiest and my recommended choice for creating these types of test.  The data is easy to edit with Excel and can also be easily edited with just a plain text editor.  To add a  CSV file to Visual Studio right click your test project and select add new item.  In the new window select the general category and then the Text File.  Enter the name of your file with a .csv extension as shown here.

image

image

Double click the .CSV file and add two columns.  One called URL and another called Valid.  We’ll use these two columns to store the urls we want to test with our method and the expected outcome we expect of the url in the Valid column.

Here’s a sample file:

URL,Valid
http://www.keithelder.net,true

Now that we have data let’s setup our test to use this file.  To do this is open the Test List Editor or the Test View as seen here.

image

Once the Test List Editor is open you should see all of your tests. 

image

After this screen opens, select the test in the list and press F4 or right click and click on properties.

image

In the properties panel select the ellipses in the “Data Connection String” field.

image

In the next screen select the type of data source you want to use.  Since we setup a .CSV file, the choice should be pretty obvious!

image

Browse to your project location and select your .CSV file.

image

You’ll notice that it will parse the file and display the data in the screen.   Click finish and several attributes will be placed onto the ValidateURLTest().  Here’s what the method looks like with the new attributes.

        /// <summary>
        ///A test for ValidateURL
        ///</summary>
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", 
            "|DataDirectory|\\URLs.csv", 
            "URLs#csv", DataAccessMethod.Sequential), 
        DeploymentItem("TestProject1\\TestProject1\\URLs.csv"), 
        TestMethod()]
        public void ValidateURLTest()
        {
            string url = "http://keithelder.net"; 
            bool expected = true;
            bool actual;
            actual = Validator.ValidateURL(url);
            Assert.AreEqual(expected, actual);
        }

There are two new attributes besides the TestMethod attribute.  The DataSource and the DeploymentItem.   The DeploymentItem attribute is what places the file in the output directory where the tests are run from so it can be found.  The DataSource attribute specifies the type of data source (in this case csv), the name of the file and how it is to be processed.  In this example the data is to be processed sequentially.  Another enumeration option possible is to randomize the data.

Now that we’ve got the ability to pump data into our test to play multiple scenarios we only have to change a few lines to use this data.  In order to do this we’ll use the TestContext class to access the data.  Here is the change.

       /// <summary>
        ///A test for ValidateURL
        ///</summary>
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", 
            "|DataDirectory|\\URLs.csv", 
            "URLs#csv", DataAccessMethod.Sequential), 
        DeploymentItem("TestProject1\\TestProject1\\URLs.csv"), 
        TestMethod()]
        public void ValidateURLTest()
        {
            string url = TestContext.DataRow["URL"] as string;
            bool expected = Boolean.Parse(TestContext.DataRow["Valid"].ToString());
            bool actual;
            actual = Validator.ValidateURL(url);
            Assert.AreEqual(expected, actual);
        }

The data is accessible via TestContext.DataRow.  Notice we use the same names as the names in the columns to access our data row.  Pretty simple.  Running this our test passes.  Great!  Now, let’s add some more URLs to the test data. We’ll add some that we know shouldn’t pass and some that should pass.  Here’s the newly added data below.  Note:  Since you are using a CSV file, I suggest adding another column to the file called “Notes”.  This will help you later on to keep track of why a specific scenario was added and what you are testing for. 

Here’s my initial tests I created along with the notes that go with them.

image

Running our ValidateURLTest now runs all of these scenarios at one time in one test.  You might wonder where the foreach loop or for loop is to loop through all the data, but you don’t need it.  The testing framework automatically will play through all of the test scenarios in the file.  Here’s what it looks like after you view the test.

image

As you can see, each row in the CSV file is played through the test.  If a particular row is incorrect you’ll know exactly which row it is.  If one row fails, the whole test fails as seen here.

image

That’s it!  From this point forward just use your imagination and easily convert plain boring tests into more dynamic tests to get better code coverage.  The more pieces of data you throw at your tests the better.  Happy testing!

Witty Twitter ClickOnce Update Now Supports Skins

Posted by Keith Elder | Posted in PC Software | Posted on 11-05-2008

A new version of Witty Twitter has been published via ClickOnce (0.1.8.5).  You can install Witty Twitter by clicking the link below or if you already have it installed, simply launch it from your start menu.

http://keithelder.net/software/witty/witty.application

Witty Twitter Now With Skins

Witty Twitter now supports skins via ClickOnce updates.  Alan checked in the changes this morning around 6:33 AM CST and I picked them up, tested them, fixed some settings / app.config files and then made a new ClickOnce deployment.  Thank you Alan!

Right now there are only three skins:  Aero, AeroCompact and CoolBlue.  The majority of users will probably like the AeroCompact skin the most since it fits more tweets on the screen.  Here are the differences in the three skins. 

Aero

image

AeroCompact

image

CoolBlue

image

To change skins click on options at the top of the application:

image

Click on the appearance button:

image

Select your desired skin:

image

Enjoy and don’t forget to thank Alan!

Speaking at Lansing, MI Day of .Net Thanks To Passing of The Hat

Posted by Keith Elder | Posted in Speaking | Posted on 10-05-2008

A few weeks ago I got an email from Jeff McWherter who runs the Greater Lansing .Net User Group they were going to have a Day of .Net event in June.  The email contained the normal type stuff you’d expect in an announcement for call to speakers.  Dates, times, location, etc.  but Jeff threw in a twist.  At the bottom of the email he listed drive times from the various locations to Lansing, MI.  At the bottom of it was Hattiesburg, MS.  Pretty funny!

image

If you don’t recall, Jeff and I rode with each other to CodeMash in January.  He was kind enough to give me a ride from company head quarters in Livonia, MI to CodeMash 2008 and back.  Great guy and if you attend different events around Michigan, Ohio, Tennessee, Indiana, Iowa, Vermont, and Timbuck Two you will probably run into Jeff.

Being 14 hours and 23 minutes away I knew I had no hope of going, but it was nice Jeff included me anyway.  After I got the email, Jeff pinged me in instant messenger and said, “Hey, I am going to try to find a way for you to come up, can you make it?”.  I checked my schedule and the dates missed my anniversary and my birthday (never travel during those times, the Wife Approval Factor is very low). 

Jeff started passing the hat and beating the bushes and made it happen.  He broke the news to me yesterday.  Jeff, you are awesome!  Thus I am happy to announce I’ll be joining everyone in Lansing, MI for the Day of .Net event on June 21st, 2008.  I have no idea what I’ll be speaking on yet but it’ll be something off my current list.

The last Day of .Net event I did was in Ann Arbor, MI last year so it has been  along time since I’ve done a Day of .Net event.  I am very much looking forward to seeing everyone there.

First .Net User Group in Mississippi Forms in Hattiesburg, MS

Posted by Keith Elder | Posted in .Net | Posted on 07-05-2008

Hattiesburg, MS, locally referred to as the Hub City, is officially forming a .Net User Group called the Hub City Nug for short.  Hattiesburg, voted as one of the top cities to live in in years past, is strategically located near the pan handle in South Mississippi only one hour from the Gulf of Mexico.  Aubrey Cote of http://forteonline.com and myself are forming the group.  Other surrounding states have multiple .Net groups and it is exciting to see such an interest in technology in the Hattiesburg area.  We expect to coordinate some larger events in the up and coming year due to our centralized location near many larger cities including Mobile, AL, Jackson, MS and New Orleans, LA.  The group is in the early stages of organizing but we hope to start having meetings as early as June. 

How To Stay Informed

There are three ways to keep up with the happenings of the Hub City Nug.

  1. A mailing list has been established for the community and anyone that wants to start connecting with the community in the Hub City area is welcomed to join.
  2. You can keep up with the group’s meetings, announcements and more by subscribing to the news feed at:  http://feeds.feedburner.com/hubcitynug
  3. Visit the Hub City Nug web site for the most current information at http://hubcitynug.org.

Witty Twitter 0.1.8.3 Published

Posted by Keith Elder | Posted in PC Software | Posted on 03-05-2008

I just published a new version of Witty Twitter via ClickOnce.  Things have been a little slow lately but some progress has been made.  Everyone has been really busy.  Alan had a baby (congrats!), well Alan didn’t have the baby but he’s a daddy now.  Jon and Scott are still recovering from the MVP Summit in April and Brian just switched jobs and is moving.  As for me I’ve been working on a little something something that I’ll officially announce in a week or two.  Stay tuned!

Here’s a screen shot from the log that covers what’s been done.

image

As you see, we have not resolved the issues with skins getting deployed via ClickOnce yet.  We’ll get it though, don’t worry.

There are several ways to get the latest version.  If you have the app running you can either wait until the auto update alerts you or you can go to the update options screen and click the button to update.  You can get the latest version by clicking this link (make sure Witty isn’t running).

http://keithelder.net/software/witty/witty.application

If this is your first time to install Witty just click the link and enjoy but make sure you have the .Net 3.5 framework installed before doing so.