Unit testing isn’t the sexiest part of software development, but it can make or break your project.
PixelRocket Presents: Unit Testing.
The goal of this blog, aside from making us look credible, is to help other up and coming software developers understand the important concepts and practices that are absolutely necessary to be successful in this brave new world of software development. That being said, not every blog topic will be utilized by every software shop out there. They are just concepts that we at PixelRocket have embraced in our quest to define ourselves as a reliable company. They are also relevant practices that are commonly implemented because of the results they produce.
So if you wonder what awaits in the professional world of programming, you want to brush up on a few important topics before that big interview, or even if you’re just bored and this is the most interesting thing you’ve come across all day, then feel free to join us as we examine important parts of the programming process.
Unit Testing and Test Driven Development.
Unit Testing is a software development practice that has exploded in usage since 2002, when the first Unit Testing book was released. It has revolutionized the way that code is both written AND maintained. Maintenance has always been a notoriously volatile and expensive part of the development process, and it’s because of the massive benefit to this area that unit testing has been embraced with open arms.
A look into the past:
Software contracts were a very iffy process in the early days of computer programming. There was no cohesion (learn this word) between developers and clients, which resulted in software that was out of spec, filled with bugs and delayed for months or even years until release. There was no guarantee of quality and definitely no guarantee of punctuality. The cost of software was often many times the original estimated cost.
The most notoriously difficult part of contracting work was Post-Delivery maintenance, defined as the work that was needed to be put into a program after it has been “delivered”. Adding features, fixing bugs and optimization all fall into the post-delivery maintenance category. Any kind of maintenance was a nightmare for developers who had to change code that had already been written. Poorly written or documented code meant that it took a long time just for developers to familiarize themselves with how the code was supposed to work. Even after developers had undergone the familiarization process it was common for one bug fix to introduce several more bugs. It was sometimes cheaper for companies to contract completely new programs than to maintain old ones.
Introducing the Unit Test.
The unit test is a simple yet dazzlingly effective approach to solving this problem, and here’s how it works:
A unit test is a function that tests a very small portion of source code, known as a unit. Before a unit is even WRITTEN the developer should think of the cases in which this unit should work and not work, and then create the unit tests. After the tests are written the developer then starts writing the code so that it passes the unit tests. This incrementally adds and defines functionality in a very controlled manner.
Follow along with this example (which I will be doing with java syntax):
Say that I am making a basic calculator app. I want the calculator to be able to add two integers. I will use a function called addNumbers, and it will take two integers as parameters. What are some expected inputs? Well, the numbers can be either negative or positive, so we’ll have to take that into account. What about if the numbers are too big? We now should write tests to define how we want the function to behave when these cases happen. The test functions would look something like this:
We’re using this blog post as the standard for naming these tests
So what did I just do? Well for starters I defined the context in which this function should be used. Positive and negative integers are both accepted as inputs by the unit tests, which means this calculator will support the functionality of negative numbers (you’d be surprised). Second, I defined the expected behavior of each context. Look at the last function: testAdd_NumberOverflow_result0. I’m clearly stating in my unit tests that this function should return a value of 0 if the two numbers added together result in an integer overflow exception. This tells both me and future developers that integer overflows are not supported by this calculator.
Why does all this matter?
Unit tests help me as the initial developer by ensuring that I have a clear understanding of my own function. This also prevents the scope creep of a function. Unit tests help enforce the single responsibility rule, which is a rule of thumb saying that “a function should perform one and only one task”. This rule makes code clean and readable, and also makes my code testable. Vice versa, unit tests help me as the developer enforce this rule because as I continue to add unit tests to a function I will be fully aware as to how much this function is actually doing. Because I’m writing the unit tests first I will be able to decide whether or not a unit should support certain functionality or if certain tasks should be refactored into other functions that will in turn be unit tested.
Unit tests also help future developers have a clear and concise understanding of my code, more so than comments and naming conventions ever could. Future developers now have a list of all the expected behaviors and accepted inputs for a function, so now it’s clearly defined without having to sift through hundreds of lines of code. This has the benefits of:
1. Saving the developer time
2. Keeping the developer from changing a function in a way that will make it behave unexpectedly
Point #2 is probably the most important for maintenance. If a developer changes the code of a unit in any way then the unit tests will reflect that change. If any unit tests fail then the developer knows that he has changed the functionality in a way that will most likely affect other parts of the program. Remember, unit tests reflect how a function SHOULD be used, and the rest of the program was written specifically in accordance with that unit test in mind. If a unit test does end up failing then the developer is best off trying to find another way to implement his solution (and reverting the changes he has made until the unit test is passing again).
The Result: Clean, Maintainable Code.
The introduction of these simple yet effective tests has made post-delivery maintenance a breeze. Well, maybe not a breeze but definitely much easier on everyone involved. Code can be understood and maintained quicker and bugs can be caught before they even happen, resulting in a much happier client, a much happier developer and a much happier world. Save lives, write unit tests.
PixelRocket is one of the top mobile app developers in Houston Texas, as well as one of the leading web application and branding firms in the city. We work primarily with nonprofits, startups and enterprise companies as one of the leading app development companies, whether for web or for mobile. Our primary concerns as a software and design company are to exceed the standards of average iPhone application development companies by bringing value to the customer and their goals.
PixelRocket also strives to provide the best in UI/UX design when it comes to the end user experience for web and mobile applications. Our designers are the best in the state and we aim to provide an extraordinary experience with every digital interaction we craft.