Saturday, April 14, 2012

xUnit Theory, the Data Driven Unit Test

Update: I have also written a post about NUnit's Data Driven TestCaseAttribute.

Do you like copying and pasting code? Neither do I.

A good set of unit tests often end up reusing the same code with varied inputs. Rather than copy and paste that test code over and over, we can use the pattern of data driven unit tests to help streamline our test fixtures. This is the practice of having a single test definition be invoked and count as multiple tests at run time. This also enables us to do other dynamic things, such as configuring our unit tests from external sources. :)

I frequently use MSTest, but it's data driven tests inconveniently require you to define a DataSource. (Updated) Come to find out NUnit does offer data driven unit tests with their TestCaseSource attribute. Meanwhile xUnit offers several lightweight and simple options for defining data driven tests, which it refers to as theories.

Let's take a look at some of xUnit's Theory data sources:

InlineData Example

public class StringTests1
{
    [Theory,
    InlineData("goodnight moon", "moon", true),
    InlineData("hello world", "hi", false)]
    public void Contains(string input, string sub, bool expected)
    {
        var actual = input.Contains(sub);
        Assert.Equal(expected, actual);
    }
}

PropertyData Example

public class StringTests2
{
    [Theory, PropertyData("SplitCountData")]
    public void SplitCount(string input, int expectedCount)
    {
        var actualCount = input.Split(' ').Count();
        Assert.Equal(expectedCount, actualCount);
    }
 
    public static IEnumerable<object[]> SplitCountData
    {
        get
        {
            // Or this could read from a file. :)
            return new[]
            {
                new object[] { "xUnit", 1 },
                new object[] { "is fun", 2 },
                new object[] { "to test with", 3 }
            };
        }
    }
}

ClassData Example

public class StringTests3
{
    [Theory, ClassData(typeof(IndexOfData))]
    public void IndexOf(string input, char letter, int expected)
    {
        var actual = input.IndexOf(letter);
        Assert.Equal(expected, actual);
    }
}
 
public class IndexOfData : IEnumerable<object[]>
{
    private readonly List<object[]> _data = new List<object[]>
    {
        new object[] { "hello world", 'w', 6 },
        new object[] { "goodnight moon", 'w', -1 }
    };
 
    public IEnumerator<object[]> GetEnumerator()
    { return _data.GetEnumerator(); }
 
    IEnumerator IEnumerable.GetEnumerator()
    { return GetEnumerator(); }
}
kick it on DotNetKicks.com

Happy testing!
Tom

Sunday, April 8, 2012

Migrating from NUnit to xUnit

I recently started using xUnit, and I have been really enjoying it!

If you are currently using NUnit to write your unit tests, then it is not at all difficult to migrate to using xUnit. The philosophical difference between the two is simply this: with xUnit you need to think of your tests as objects, rather than of methods. Or if you prefer acronyms: put some more OOP into your TDD. *bu-dum, tish!*

Anyway, here is a visual representation of equivalent commands between NUnit and xUnit:

xUnit

NUnit

[NUnit.Framework.TestFixture]
public class TestFixture
{
  [NUnit.Framework.TestFixtureSetUp]
  public void TestFixtureSetUp()
  {
    // 1) Set up test fixture  -------->
  }
  [NUnit.Framework.TestFixtureTearDown]
  public void TestFixtureTearDown()
  {
    // 8) Tear down test fixture  ----->
  }
 
 
 
  [NUnit.Framework.SetUp]
  public void SetUp()
  {
    // 2) Set up TestA  --------------->
    // 5) Set up TestB  --------------->
  }
  [NUnit.Framework.Test]
  public void TestA()
  {
    // 3) Run TestA  ------------------>
  }
  [NUnit.Framework.Test]
  public void TestB()
  {
    // 6) Run TestB.  ----------------->
  }
  [NUnit.Framework.TearDown]
  public void TearDown()
  {
    // 4) Tear down TestA  ------------>
    // 7) Tear down TestB  ------------>
  }
}
 
public class TestData : IDisposable
{
 
  public TestData()
  {
    // 1) Set up test fixture
  }
 
  public void Dispose()
  {
    // 8) Tear down test fixture
  }
}
public class TestClass
  : IDisposable, Xunit.IUseFixture
{
  public TestClass()
  {
    // 2) Set up TestA
    // 5) Set up TestB
  }
  [Xunit.Fact]
  public void TestA()
  {
    // 3) Run TestA
  }
  [Xunit.Fact]
  public void TestB()
  {
    // 6) Run TestB
  }
 
  public void Dispose()
  {
    // 4) Tear down TestA
    // 7) Tear down TestB
  }
  public TestData TestData { get; set; }
  public void SetFixture(TestData data)
  {
    // 2.5) Set fixture data for TestA
    // 5.5) Set fixture data for TestB
    TestData = data;
  }
}
kick it on DotNetKicks.com

Happy testing!
~Tom

Saturday, March 31, 2012

Configuring Bundles in MVC 4

We write a lot of JavaScript.

Thus the bundling, compression, and minification of JavaScript is important to the speed and performance of modern websites. This is why I love and have been a big advocate of tools like Combres, and also why I was so excited to hear that such features were (finally) coming built in to ASP.NET MVC 4.

Introducing MvcBundleConfig

MvcBundleConfig is a very simple minimalist project I wrote to add configuration and debugging features to MVC 4's bundling framework, and achieves all 6 six of the goals listed below. It requires only MVC4 to run, and you need only add one config file to your project, one line of code to your application start, and you are off and running.

NuGet Package: https://nuget.org/packages/MvcBundleConfig/

Source on GitHub: https://github.com/tdupont750/MvcBundleConfig

Before we get to the demonstration at the bottom, let's review the needs and wants of a good minification framework.

What I NEED in a minification tool:

  1. Compress resources into single files.
    • Multiple request take time and resources, neither of which are things that any of us have to spare. By compressing resources into single requests and can limit the overhead and load time on both our clients and our servers.
  2. Minify JavaScript and CSS content.
    • Minification removes as many unnecessary white spaces and characters as possible from your resource files, reducing file size by up to 80% on average. When then compounded with gzip, we can reduce the file size another 50%. This means that our web applications can be brought down to clients 90% faster.
  3. Make use of both client and server side caching.
    • Making 90% less requests is nice, and making those requests 90% smaller is even better, but only ever having to request or serve them once is the key to true performance. Unfortunately client and server caching can be a bit complex due to quirks of different technologies and browsers. A good minification framework should abstract these concerns away from us.
  4. Ability to turn off during debugging.
    • As fantastic as everything that we have listed about is for a production website, it is a nightmare for a development website. Debugging JavaScript is no less complicated or time consuming than debugging C#, and we need to be able to use a debuggers and other client side tools that are inhibited by minification. A good minification framework must expose a debugging mode that skips compression pipeline.

What I WANT in a minification tool:

  1. Simple and dynamic configuration.
    • I hate hardcoded configuration. It bloats my code, and it requires bin drops to deploy. Meanwhile I really like the ability to add simple configuration files to my site as often as I can. Config files are explicit, abstract, and can be updated at any time. Win.
  2. Take a few dependencies as possible.
    • I mentioned above that I like Combres and it has a reasonably sized code base, unfortunately the fact that it's NuGet package pulls down half a dozen additional dependencies makes it feel quite heavy. The fewer dependencies a framework takes the better.

MvcBundleConfig Examples

Bundles.config

<?xml version="1.0"?>
<bundleConfig ignoreIfDebug="true" ignoreIfLocal="true">
  <cssBundles>
    <add bundlePath="~/css/shared">
      <directories>
        <add directoryPath="~/content/" searchPattern="*.css" />
      </directories>
    </add>
  </cssBundles>
  <jsBundles>
    <add bundlePath="~/js/shared" minify="false">
      <files>
        <add filePath="~/scripts/jscript1.js" />
        <add filePath="~/scripts/jscript2.js" />
      </files>
    </add>
  </jsBundles>
</bundleConfig>

Global.asax.cs

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    BundleTable.Bundles.RegisterTemplateBundles();
 
    // Only code required for MvcBundleConfig wire up
    BundleTable.Bundles.RegisterConfigurationBundles();
}

_Layout.cshtml

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width" />
        <title>@ViewBag.Title</title>
 
        @* Call bundle helpers from MvcBundleConfig *@
        @Html.CssBundle("~/css/shared")
        @Html.JsBundle("~/js/shared")
    </head>
    <body>
        @RenderBody()
    </body>
</html>

In the Browser

NuGet Package: https://nuget.org/packages/MvcBundleConfig/

Source on GitHub: https://github.com/tdupont750/MvcBundleConfig

kick it on DotNetKicks.com

Enjoy,
Tom

Sunday, March 11, 2012

Converting SNES Soundtracks to MP3

Do you like video game soundtracks from the Super Nintendo Entertainment System? Do all of your media devices use the MP3 format? Well then you are in luck!

You can download any SNES sound track and convert all of it's tracks to MP3 for free.

Step 1: Setup the Tools

Step 2: Go get some music

SNESMusic.org is a very nearly complete archive of all SNES soundtracks. Go there, find something you like, and download the RSN file. These RSN files are actually archives contains all of the individual tracks in SPC format.

Open the RSN file using WinRAR and extract the SPCs. If you have properly installed the foo_gep component, you should now be able to open and play these files in Foobar.

(Having a hard time deciding what to get? Check out VGMuseum's top SNES Soundtracks.)

Step 3: Convert to MP3

Create a playlist in Foobar of all the tracks that you wish to convert. Select them, right click, and select convert.

Set the output format to "MP3 Lame". Update your destination settings, I recommend specifying an output folder, and setting a multi-track file pattern of "%album%\%album% - %title%". There is no need to update the processing or other settings unless you wish to.

Click convert and the program will ask you to specify the file path of the LAME MP3 Encoder that you downloaded in step 1. Just put in the path and select lame.exe

Step 4: Rock out!

Foobar should now be converting your SPC files to MP3s. :)

Enjoy,
Tom

Monday, February 20, 2012

Browser Specific TestFixtures Sharing Tests

I will get to WebDrivers running in parallel next week, for now something even more fun: How to share Tests across browser specific TestFixtures with WebDriver.

When writing a unit test to test a webpage, you will want to duplicate that test against multiple browsers. How do we do accomplish this feat? Inheritance!

Step 1: SetUpFixture

First we need to create a SetUpFixture that will manage our WebDrivers. This will be largest and most complex class of our demonstration.

[SetUpFixture]
public class SetUpFixture
{
    private static IWebDriver _internetExplorerDriver;
    private static IWebDriver _chromeDriver;
 
    public static IWebDriver InternetExplorerDriver
    {
        get
        {
            if (_internetExplorerDriver == null)
            {
                DisposeDrivers();
                _internetExplorerDriver = new InternetExplorerDriver();
            }
            return _internetExplorerDriver;
        }
    }
 
    public static IWebDriver ChromeDriver
    {
        get
        {
            if (_chromeDriver == null)
            {
                DisposeDrivers();
                var dir = ConfigurationManager.AppSettings["chrome"];
                _chromeDriver = new ChromeDriver(dir);
            }
            return _chromeDriver;
        }
    }
 
    private static void DisposeDrivers()
    {
        if (_internetExplorerDriver != null)
        {
            _internetExplorerDriver.Close();
            _internetExplorerDriver.Dispose();
            _internetExplorerDriver = null;
        }
        if (_chromeDriver != null)
        {
            _chromeDriver.Close();
            _chromeDriver.Dispose();
            _chromeDriver= null;
        }
    }
 
    [TearDown]
    public void TearDown()
    {
        DisposeDrivers();
    }
}

Step 2: Base Class

Second we create an abstract base class that will go select our WebDriver from the SetUpFixture via an abstract property.

[TestFixture]
public abstract class TestFixtureBase
{
    public abstract IWebDriver WebDriver { get; }
 
    [SetUp]
    public void SetUp()
    {
        WebDriver.Url = "about:blank";
    }
}

Step 3: Tests

Write your tests in abstract classes that inherit from the base class.

public abstract class TestFixtureA : TestFixtureBase
{
    [Test]
    public void Test1()
    {
        WebDriver.Url = "http://www.phandroid.com/";
        Assert.IsTrue(WebDriver.Title.StartsWith("Android Phone"));
    }
 
    [Test]
    public void Test2()
    {
        WebDriver.Url = "http://www.reddit.com/";
        Assert.IsTrue(WebDriver.Title.StartsWith("reddit"));
    }
}

Step 4: Driver Specific TestFixtures

Create a test fixture for each permutation of browser and test class.

public class ChromeTestFixtureA : TestFixtureA
{
    public override IWebDriver WebDriver
    {
        get { return SetUpFixture.ChromeDriver; }
    }
}
 
public class InternetExplorerTestFixtureA : TestFixtureA
{
    public override IWebDriver WebDriver
    {
        get { return SetUpFixture.InternetExplorerDriver; }
    }
}

Step 5: Run!

Okay, next week I'll actually talk about running WebDrivers in parallel. :)

kick it on DotNetKicks.com

Enjoy,
Tom

Saturday, February 11, 2012

Sharing a WebDriver across TestFixtures

I absolutely love WebDriver.

WebDriver (also known as Selenium 2.0) is a web testing tool that is both useful and easy, which is a very rare find. If you are doing web development with ASP.NET, you need to take 30 minutes of your time and go try out WebDriver. That is all the time it will take to get you hooked.

WebDriver and NUnit

To launch a browser you need only new up a Driver object for that browser. I used to create a new Driver in my TestFixtureSetup, and then close and dispose of that in the testFixtureTearDown. However now that Firefox does not persist my windows login credentials it can be very frustrating to have to log back in for every test fixture.

A solution to this problem is simply to share a single WebDriver across multiple TestFixtures. Fortunately NUnit's SetUpFixture makes this very easy to do.

Step 1: Create a SetUpFixture

This class's SetUp method will be called once before any TestFixtures run, and then it's TearDown will be called once after all the TestFixtures have completed.

[SetUpFixture]
public class SetUpFixture
{
    public const string ProfileKey = "firefoxprofile";
 
    public static IWebDriver WebDriver { get; private set; }
 
    [SetUp]
    public void SetUp()
    {
        var profileDir = ConfigurationManager.AppSettings[ProfileKey];
        if (String.IsNullOrWhiteSpace(profileDir))
        {
            WebDriver = new FirefoxDriver();
        }
        else
        {
            var profile = new FirefoxProfile(profileDir);
            WebDriver = new FirefoxDriver(profile);
        }
    }
 
    [TearDown]
    public void TearDown()
    {
        if (WebDriver == null)
            return;
 
        WebDriver.Close();
        WebDriver.Dispose();
    }
}

Step 2: Create an abstract base class

This abstract class will use the TestFixtureSetUp to copy the static WebDriver that was initialized by the SetUpFixture. I also like to have a SetUp that will clear the browser, just to make sure you are navigation to a new page from a blank one.

public abstract class TestFixtureBase
{
    public IWebDriver WebDriver { get; private set; }
 
    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
        WebDriver = SetUpFixture.WebDriver;
    }
 
    [SetUp]
    public void SetUp()
    {
        WebDriver.Url = "about:blank";
    }
}

Step 3: Make your TestFixtures inherit the base class

These TestFixtures will now share the static WebDriver.

[TestFixture]
public class TestFixtureA : TestFixtureBase
{
    [Test]
    public void Test1()
    {
        WebDriver.Url = "http://www.phandroid.com/";
        Assert.IsTrue(WebDriver.Title.StartsWith("Android Phone"));
    }
}
 
[TestFixture]
public class TestFixtureB : TestFixtureBase
{
    [Test]
    public void Test1()
    {
        WebDriver.Url = "http://www.reddit.com/";
        Assert.IsTrue(WebDriver.Title.StartsWith("reddit"));
    }
}

Step 4: Run those tests!

If you love .NET 4.0 then stay tuned, because in my next post I'll explore running WebDrivers in PARALLEL! See you next week. :)

kick it on DotNetKicks.com

Enjoy,
Tom

Saturday, January 7, 2012

.NET Collection Runtimes

Each week my department holds a morning tech review. Subjects vary from testing tools, advanced caching mechanisms, to good ol' basic .NET facts. This week the tech review was an "Asymptomatic Analysis of .NET Collections". While most of the material was pretty straight forward, I always find getting back to the basics to be a good thing.

I thought that it was fun to see all of the collection run times aggregated into one table. As several of my coworkers pointed out, it can be a bit of a pain to find all these "simple" facts on the SEO crammed internet...so then why does no one simply blog about it?

In summary: here is some stolen content. Thanks Byron!

List-Like Collections

  List LinkedList SortedList
Add O(1) or O(N) O(1) O(Log N) or O(N)
Remove O(N) O(N) O(N)
Clear O(N) O(1) O(Log N)
Get O(1) O(N) O(Log N)
Find O(N) O(N) O(Log N)
Sort O(N log N) or O(N^2) - Already sorted
Underlying
Data
Structure
Array Dynamically allocated nodes Array

Hash-Like Collections

  Dictionary SortedDictionary HashSet SortedSet
Add O(1)
or O(N)
O(Log N) O(1)
or O(N)
O(log N)
Remove O(1) O(log N) O(1) O(N)
Clear O(N) O(Log N) O(N) O(N)
Get / Find O(1) O(Log N) O(1) O(Log N)
Sort - Already sorted - -
Underlying
Data
Structure
Array + Linked List Dynamically allocated nodes
(Binary Search Tree)
Array + Linked List Dynamically allocated nodes
(Binary Search Tree)

If you would like to see any updates/additions please feel free to leave a comment.

Enjoy,
Tom

Real Time Web Analytics