Unit Testing
Tags: Unit Testing, Testing, QA, Unit Testing Tools, Unittest

What is Unit Testing?

Unit Testing is a type of software testing where individual units or components of the software are tested. The purpose is to validate that each unit of the software code performs as expected. Unit Testing is done during the development (coding phase) of an application by the developers. Unit Tests isolate a section of code and verify its correctness. A unit may be an individual function, method, procedure, module, or object.

In SDLC, STLC, V Model, Unit testing is the first level of testing done before integration testing. Unit testing is a WhiteBox testing technique that is usually performed by the developer. Though, in a practical world due to the time crunch or reluctance of developers to tests, QA engineers also do unit testing.

Why Unit Testing?

Unit Testing is important because software developers sometimes try saving time doing minimal unit testing and this is a myth because inappropriate unit testing leads to high-cost. Defect fixing during System Testing, Integration Testing and even Beta Testing after application is built. If proper unit testing is done in early development, then it saves time and money in the end.

Here, are the key reasons to perform unit testing :

Unit tests help to fix bugs early in the development cycle and save costs. It helps the developers to understand the code base and enables them to make changes quickly Good unit tests serve as project documentation Unit tests help with code re-use. Migrate both your code and your tests to your new project. Tweak the code until the tests run again.

How to do Unit Testing

In order to do Unit Testing, developers write a section of code to test a specific function in the software application. Developers can also isolate this function to test more rigorously which reveals unnecessary dependencies between the function being tested and other units so the dependencies can be eliminated. Developers generally use the UnitTest framework to develop automated test cases for unit testing.

Unit Testing is of two types

Manual

Automated

Unit testing is commonly automated but may still be performed manually. Software Engineering does not favor one over the other but automation is preferred. A manual approach to unit testing may employ a step-by-step instructional document.

Under the automated approach-

A developer writes a section of code in the application just to test the function. They would later comment out and finally remove the test code when the application is deployed.

A developer could also isolate the function to test it more rigorously. This is a more thorough unit testing practice that involves copy and paste of code to its own testing environment than its natural environment. Isolating the code helps in revealing unnecessary dependencies between the code being tested and other units or data spaces in the product. These dependencies can then be eliminated.

A coder generally uses a UnitTest Framework to develop automated test cases. Using an automation framework, the developer codes criteria into the test to verify the correctness of the code. During the execution of the test cases, the framework logs failing test cases. Many frameworks will also automatically flag and report, in summary, these failed test cases. Depending on the severity of a failure, the framework may halt subsequent testing.

The workflow of Unit Testing is 1) Create Test Cases 2) Review/Rework 3) Baseline 4) Execute Test Cases.

How to write Unit tests

Map your program into units. The key aspect of a good unit test is that it checks just one portion of a program. Whether you are looking to test an existing program or planning tests for a program that isn’t written yet, you’ll need to break it down into discrete parts (“units”). You’ll then write a unit test for each one.

The definition of a “unit” varies widely depending on the type of program you are developing. A unit could be a class, but also a single function or procedure.

2. Determine if you need state-based or interaction-based testing. A unit test can be used to check two kinds of scenarios. State-based testing is used to see if a program unit produces proper or expected results. Interaction-based testing, on the other hand, is used to see if a unit sets anticipated methods into action. To write a good test, you’ll need to identify what you are trying to test for, so keep one of these approaches in mind as a model.

3. Plan simple and readable tests. Keep in mind that you’ll need to write lots and lots of unit tests. You’ll want to run a unit test for every portion of your program. Keeping your tests simple will have several benefits:

Simple tests will help ensure that you really are testing only one unit at a time.

The tests’ code will be reliable. If you have complex test code, it will be more prone to problems, making it just that harder to see bugs in the code of the program you are testing.

The tests will be faster, decreasing the overall amount of time it takes to do the testing.

A simple test will be readable, meaning you may see some potential problems just by looking at the code itself.

4. Differentiate unit tests from integration tests. Seasoned developers know that there are different ways to test a program. Unit tests are narrow, specific, and look at only one portion of a program. Integration tests, on the other hand, look at the whole program in a real environment. In other words, unit testing ensures that the individual parts of a program work, while integration testing verifies that the parts work together.

Integration tests also usually require external elements, such as web servers or a database. To keep unit tests controlled, write them so that they don’t require external elements.

Unit Testing Tools

There are several automated tools available to assist with unit testing. We will provide a few examples below:

Junit: Junit is a free to use testing tool used for Java programming language. It provides assertions to identify test methods. This tool test data first and then inserted in the piece of code. NUnit: NUnit is a widely used unit-testing framework use for all .net languages. It is an open-source tool that allows writing scripts manually. It supports data-driven tests that can run in parallel. JMockit: JMockit is an open-source Unit testing tool. It is a code coverage tool with line and path metrics. It allows mocking API with recording and verification syntax. This tool offers Line coverage, Path Coverage, and Data Coverage. EMMA: EMMA is an open-source toolkit for analyzing and reporting code written in Java language. Emma support coverage types like method, line, basic block. It is Java-based so it is without external library dependencies and can access the source code. PHPUnit: PHPUnit is a unit testing tool for PHP programmers. It takes small portions of code which is called units and test each of them separately. The tool also allows developers to use pre-define assertion methods to assert that a system behaves in a certain manner.

Those are just a few of the available unit testing tools. There are lots more, especially for C languages and Java, but you are sure to find a unit testing tool for your programming needs regardless of the language you use.

Test-Driven Development (TDD) & Unit Testing

Unit testing in TDD involves extensive use of testing frameworks. A unit test framework is used in order to create automated unit tests. Unit testing frameworks are not unique to TDD, but they are essential to it. Below we look at some of what TDD brings to the world of unit testing:

Tests are written before the code

Rely heavily on testing frameworks

All classes in the applications are tested

Quick and easy integration is made possible

Advantages

Developers looking to learn what functionality is provided by a unit and how to use it can look at the unit tests to gain a basic understanding of the unit API.

Unit testing allows the programmer to refactor code at a later date, and make sure the module still works correctly (i.e. Regression testing). The procedure is to write test cases for all functions and methods so that whenever a change causes a fault, it can be quickly identified and fixed.

Due to the modular nature of the unit testing, we can test parts of the project without waiting for others to be completed.

Disadvantages

Unit testing can’t be expected to catch every error in a program. It is not possible to evaluate all execution paths even in the most trivial programs

Unit testing by its very nature focuses on a unit of code. Hence it can’t catch integration errors or broad system-level errors.

It’s recommended unit testing be used in conjunction with other testing activities.

Best Practices

Unit Test cases should be independent. In case of any enhancements or change in requirements, unit test cases should not be affected.

Test only one code at a time.

Follow clear and consistent naming conventions for your unit tests

In case of a change in code in any module, ensure there is a corresponding unit Test Case for the module, and the module passes the tests before changing the implementation

Bugs identified during unit testing must be fixed before proceeding to the next phase in SDLC

Adopt a “test as your code” approach. The more code you write without testing, the more paths you have to check for errors.

Benefits

Unit testing provides numerous benefits including finding software bugs early, facilitating change, simplifying integration, providing a source of documentation, and many others, which we will look right now with more detail.

1. Makes the Process Agile

One of the main benefits of unit testing is that it makes the coding process more Agile. When you add more and more features to the software, you sometimes need to change old design and code. However, changing the already-tested code is both risky and costly. If we have unit tests in place, then we can proceed for refactoring confidently.

Unit testing really goes hand-in-hand with agile programming of all flavors because it builds in tests that allow you to make changes more easily. In other words, unit tests facilitate safe refactoring.

2. Quality of Code

Unit testing improves the quality of the code. It identifies every defect that may have come up before code is sent further for integration testing. Writing tests before actual coding makes you think harder about the problem. It exposes the edge cases and makes you write better code.

3. Finds Software Bugs Early

Issues are found at an early stage. Since unit testing is carried out by developers who test individual code before integration, issues can be found very early and can be resolved then and there without impacting the other pieces of the code. This includes both bugs in the programmer’s implementation and flaws or missing parts of the specification for the unit.

4. Facilitates Changes and Simplifies Integration

Unit testing allows the programmer to refactor code or upgrade system libraries at a later date and make sure the module still works correctly. Unit tests detect changes that may break a design contract. They help with maintaining and changing the code.

Unit testing reduces defects in the newly developed features or reduces bugs when changing the existing functionality.

Unit testing verifies the accuracy of each unit. Afterward, the units are integrated into an application by testing parts of the application via unit testing. Later testing of the application during the integration process is easier due to the verification of the individual units.

5. Provides Documentation

Unit testing provides documentation of the system. Developers looking to learn what functionality is provided by a unit and how to use it can look at the unit tests to gain a basic understanding of the unit’s interface (API).

6. Debugging Process

Unit testing helps simplify the debugging process. If a test fails, then only the latest changes made in the code need to be debugged.

7. Design

Writing the test first forces you to think through your design and what it must accomplish before you write the code. This not only keeps you focused; it makes you create better designs. Testing a piece of code forces you to define what that code is responsible for. If you can do this easily, that means the code’s responsibility is well-defined and therefore that it has high cohesion.

8. Reduce Costs

Since the bugs are found early, unit testing helps reduce the cost of bug fixes. Just imagine the cost of a bug found during the later stages of development, like during system testing or during acceptance testing. Of course, bugs detected earlier are easier to fix because bugs detected later are usually the result of many changes, and you don’t really know which one caused the bug.

Closing Quote