Sunday, February 21, 2016

What is the Business Value of Unit Testing? Part 1

Part 2
Part 1 you are here

We've been doing a lot more concentration on unit testing at work lately, and a question has come up. What value do automated unit tests provide?

The text book(ish) answer is: if you're unit testing your code with relevant asserts, with good enough code coverage, the less likely there will be bugs. Sounds great! Why isn't everyone doing it? Unit testing does require a certain style of coding, loose dependencies, and a certain amount of planning. Here's a good SO answer that goes into some detail on how/why unit testing is great - but I like examples.

Requirements change. It's a fact of (programming) life. Something that held true today, might not be true months or years down the road. One of the great things about unit tests and code coverage is that when considered together, you can really get a feel for if your code is working correctly, even create requirements based on your unit tests! On to the example - we're going to build a super important piece of business logic based on this requirement:

>  As a user, I need a way to enter a number.  Once the number has been entered,  I need it to be printed back to me.

Well that sounds easy.  Going to start a new github repo to track progress.

So based on our requirement.  I'm going to create a console application that takes a user's entry, and then prints it back to them.. This is probably the most useful business logic in the history of the universe.

Based on the requirement, I've created a class and method:

    /// <summary>
    /// This class is used to return a number.
    /// </summary>
    public class NumberReturner
    {
 
        /// <summary>
        /// Return the provided number as a string
        /// </summary>
        /// <param name="numberToReturn">The number to return</param>
        /// <returns>The number as string</returns>
        public string ReturnNumberAsString(int numberToReturn)
        {
            return numberToReturn.ToString();
        }
 
    }

The above method is extremely easy to test as there is only a single branch.  It should be no problem getting 100% code coverage, with a completely relevant assert.

/// <summary>
    /// Tests for NumberReturner
    /// </summary>
    [TestClass]
    public class NumberReturnerTests
    {
 
        /// <summary>
        /// Ensure ReturnNumberAsString has appropriate return type
        /// </summary>
        [TestMethod]
        public void NumberReturner_ReturnNumberAsString_CorrectReturnTypeIsString()
        {
            // Arrange
            int expected = 42;
            NumberReturner biz = new NumberReturner();
 
            // Act
            var results = biz.ReturnNumberAsString(expected);
 
            // Assert
            Assert.IsInstanceOfType(results, typeof(string));
        }
 
        /// <summary>
        /// When ReturnNumberAsString is provided a number, the number is returned as a string
        /// </summary>
        [TestMethod]
        public void NumberReturner_ReturnNumberAsString_ReturnsNumberThatWasProvided()
        {
            // Arrange
            int expected = 42;
            NumberReturner biz = new NumberReturner();
 
            // Act
            var results = biz.ReturnNumberAsString(expected);
 
            // Assert
            Assert.AreEqual(expected.ToString(), results);
        }
 
    }

And our code coverage:


With the above test and code coverage, we can safely say we have thoroughly tested our code.  Our requirement is extremely simple as of now, but next time we'll expand our requirements by a bit, while still keeping focus on our unit tests and code coverage.  Here's the repo as of this post: https://github.com/Kritner/UnitTestingBusinessValue/tree/f8b21a5bde31635c2f37d530130d8bd393eee23e

On to part 2

No comments:

Post a Comment