Translate

Monday 25 August 2014

What to Unit test?

Going by the book is not really encouraged in today's wildly advancing technology world. If you, do, it will most probably leave you staring at the behinds of many. :)

Best way to keep yourself ahead is to be really good in your skill set; if it is a programming language, be on top by participating in discussion forums and communities. This will help knowing about scenarios that may never appear in your own project or lifetime.

Close to what I am getting at is this definition of unit tests by Martin Fowler -
Like most software development terminology, however, it's very ill-defined, and I see confusion can often occur when people think that it's more tightly defined than it actually is. 
First and foremost,  what to unit test depends on your commitment to testing. If you are very committed then chances are that your code coverage will be good. But over and above this,  you also need the skill with the unit test tool. For instance, the most common statement possibly used by almost all programmers across the world is the if (!fileExists) or within a try...catch block.

Is this statement testable? Should it be tested? To answer the second question first, the reason the answer is 'Yes' is because the line of code is expected to throw many exceptions -  DirectoryNotFoundException, FileNotFoundException and (yes) etc...So, the first question becomes important - is it testable?

Again, the answer is 'Yes' (left out italicizing it to make it more interesting! :)) but if you really do not know any syntax of existing unit test tool, how to write the test?

This question has always seemed important to me (to make a programmer move from the "Code-first syndrome" to a "Test-first-and-let-the-test-tell-you-what-code-to-write avatar") and so, I decided to list (well, sharing just one technique now (how to get and test a list of files from the file system in a unit test)...will share more later) here some of these common scenarios.

Aside from helping the code achieve the necessary quality benchmarks, unit tests should also be efficient and lean so that it does not weigh down the overall build or CI framework.

So, to write a unit test in the 'file exists' scenario,

1. If not file exists

Scenarios - as many as there are files (wild possibilities! :)) in a specified directory.

So, the unit test will want a list of files against which to test for some criteria.

The code will be something like this -

using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace NUnit_Tests
{
    public class ClassUnderTest
    {            
        public List getListOfFiles()
        {
            string[] filePaths=null;
            filePaths = Directory.GetFiles(@"c:\cambridge\");
            return filePaths.ToList();
        }
    }
}

In  NUnit, here is an example of how to test the method most efficiently and ALSO in such a way that maximum scenarios can be tested with this approach !!

using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace NUnit_Tests
{
    [TestFixture]
    public class TestClass
    {
        ClassUnderTest objInstance;
        string[] filesToExist = { "abc.jpg", "a.htm" };
        [Category("LongRunning")]
        [Test]
        public void LongRunningTest([ValueSource("Files")] string filePath)
        {
            Assert.That(Files.ToList().LastOrDefault(),Is.EqualTo("zzz.jpg"));
        }

        private IEnumerable Files
        {          
            get
            {
                objInstance = new ClassUnderTest();
                return objInstance.getListOfFiles();
            }
        }
    }
}

The snapshot below (before refactoring class names) shows the number of scenarios (equivalent of unit tests / asserts in NUnit or unit testing tools) that are now possible with this approach.



For example, you could test if the path is returned correctly with Is.SamePath or can test the number of files existing or if a particular file has a required extension and the possibilities are endless.



No comments: