23 May 2011

Data driven test in NUnit with csv source data

I wanted to test a date parser across a large range of values so wanted a simple test harness to test all the values.

The test framework options around c# / .net seem to be:
  • MSTest - can do csv via jet, but can't do inline test data which is something I also want.
  • NUnit - can do inline data driven test data (with the TestCase(data...) attribute), and has support for extending this via the TestCaseSource attribute.
  • xUnit - confusing (aka flexible), doesn't seem to get me to my end result any faster after a bit of searching around.
I've used NUnit and combined TestCaseSource with a simple wrapper class around the csv parsing library

To get this to work:
  • Save your csv file in your test project
  • add the file to your project (in visual studio 2008 in this case)
  • right-click on the csv file in solution explorer, click properties, change "Copy to Output Directory" to "Copy Always"
  • download the binaries (dlls) for csv reader from code project, add a reference to this in your test project
  • add a private method to your test class for reading the csv file and returning an enumarable (see code below)
  • add the TestCaseSource attribute to your test method(s) that you want to use the csv data, referencing your new IEnumerable method (see code below)


using System.Collections.Generic;
using System.IO;
using LumenWorks.Framework.IO.Csv;
using NUnit.Framework;

namespace mytests
{
    class MegaTests
    {
        [Test, TestCaseSource("GetTestData")]
        public void MyExample_Test(int data1, int data2, int expectedOutput)
        {
            var methodOutput = MethodUnderTest(data2, data1);
            Assert.AreEqual(expectedOutput, methodOutput, string.Format("Method failed for data1: {0}, data2: {1}", data1, data2));
        }

        private int MethodUnderTest(int data2, int data1)
        {
            return 42; //todo: real implementation
        }

        private IEnumerable<int[]> GetTestData()
        {
            using (var csv = new CsvReader(new StreamReader("test-data.csv"), true))
            {
                while (csv.ReadNextRecord())
                {
                    int data1 = int.Parse(csv[0]);
                    int data2 = int.Parse(csv[1]);
                    int expectedOutput = int.Parse(csv[2]);
                    yield return new[] { data1, data2, expectedOutput };
                }
            }
        }
    }
}


references:

18 May 2011

Reliable javascript checkbox events


Some sites have checkboxes which show/hide another element when you click them. This a handy feature, but not all sites take into account the fact that firefox remembers the contents of a form when you reload the page (this is a good thing).

So here's how you avoid that with jQuery:

<script type="text/javascript">
$(function() {
// initialise show/hide to match the checkbox value
$('.targetelements').toggle($('#mycheckbox').attr('checked'));
// attach click handler for show/hide to checkbox
$('#mycheckbox').click(function(){ $('.targetelements').toggle(this.checked);})
});
</script>

Simples!

You could use the same principle without jQuery if you need to. Simply read the value of the checkbox with javascript the old fashioned way before deciding whether to hide when you initialise you page.