What Is Unit Testing?
Unit testing is a software testing technique for verifying the functionality of individual components, or units, of a program in isolation from the rest of the application.
A “unit” typically refers to the smallest testable part of a program, such as a function, method, class, or script. By breaking down complex scripts or algorithms into these smaller units, precise and targeted tests can be developed to validate the functionality of each component.
Why Is Unit Testing Important?
By performing unit testing on the individual units early, you can catch and fix errors, resulting in more reliable code and less complicated and time-consuming debugging projects. It also supports the development of modular and maintainable software, which, in turn, improves code quality.
Advantages and Challenges of Unit Testing
Unit testing provides several benefits:
- Unit tests are often easier to write and faster to run than whole-system or more comprehensive tests.
- It’s likely easier to identify and isolate bugs at an early stage.
- It may help you identify issues with other parts of the software, keeping the number of subsystem interactions to a minimum.
- You can start testing at early development stages, without waiting for the entire application to be completed.
However, one challenge is that testing individual units in isolation may not detect all problems.
When to Perform Unit Testing
To ensure code quality and catch impacts of coding changes, unit testing should be done throughout the development process:
- During development: Write unit tests alongside the development of new features. This approach ensures each component works as intended from the start.
- When refactoring: Use unit tests to ensure that refactoring does not alter the expected behavior of the code.
- After bug fixes: Implement unit tests for bugs that have been resolved to prevent them from recurring in the future and to ensure the fixes didn’t negatively impact other software functionality.
- Before and during integration: Conduct unit tests before merging changes into the main code and incorporating them into your continuous integration (CI) pipeline. This prevents new code from introducing errors and helps maintain a stable codebase.
The Software Testing Pyramid
Performing unit testing early in and throughout the software development process supports better code quality. However, unit testing is just one part of a comprehensive strategy. The software testing pyramid illustrates the different levels of testing—unit testing, integration testing, and system testing—highlighting their granularity and frequency. This pyramid provides a structured approach to managing and prioritizing testing efforts, emphasizing the balance needed to achieve optimal software quality.
Characteristics of these testing types are as follows:
- Unit testing, at the base of the pyramid, is the most granular and is executed frequently. Unit tests are generally small and thus faster and more cost-effective to write and run. They can be implemented early in the development process, providing immediate feedback on the functionality of individual components.
- Integration testing, situated in the middle of the pyramid, focuses on verifying the interactions between different components or systems. Integration tests are slightly more complex and time-consuming than unit tests but are crucial for ensuring that integrated components function together as expected.
- System testing, at the top of the pyramid, evaluates the entire application. System tests are more comprehensive and resource-intensive. They are typically performed later in the development cycle to validate that the complete system meets the specified requirements.
The pyramid emphasizes the importance of having more low-level tests, such as unit tests, and fewer high-level tests. A balanced approach aims for approximately 70% unit tests, 20% integration tests, and 10% system tests by the project’s completion. This strategy ensures a solid foundation of reliable code, reducing the likelihood of issues in higher-level testing stages.
Other Types of Software Testing
In addition to the granularity and frequency of testing represented by the software testing pyramid, there are several types of testing methods, each with specific objectives based on their intended outcomes. One key distinction is between functional and nonfunctional tests:
- Functional tests focus on verifying the correct functionality and behavior of the software. Examples include smoke testing, which checks for basic functionality, and regression testing, which ensures that new code changes do not adversely affect existing features.
- Nonfunctional tests evaluate other critical aspects of the software, such as usability, security, and stability. Performance testing, the most common type of nonfunctional testing, assesses how well the software operates under specific conditions, such as load and stress.
Leveraging both functional and nonfunctional tests ensures that software performs correctly and meets quality standards.
Unit Testing with MATLAB
Testing code is an integral part of developing quality software. MATLAB® provides a robust, built-in unit testing framework that enables you to write unit tests and monitor for regressions in code functionality. The framework supports writing tests using classes, enabling you to structure your tests logically. Additionally, you can run and analyze test results.
Class-Based Unit Tests
In this approach, you define tests as methods within a class. MATLAB can generate a generic template for you, and MATLAB Test™ can generate a specific test for your code. This approach enables you to test scripts and functions within your test methods, combining the advantage of object-oriented programming with the flexibility to test various code types. This example demonstrates writing class-based unit tests.
Running Tests
After saving the test file, you can run the test from the MATLAB toolstrip. You can also use the runtests
function or the MATLAB Test Browser app to execute tests, view results, and debug failures interactively.
Analyzing Test Results
MATLAB provides summaries, detailed reports, and code coverage to analyze your source code.
For more advanced capabilities, MATLAB Test offers additional features to enhance the testing process, such as automated test generation, enhanced test management, integration with CI/CD systems, advanced code coverage, and a quality dashboard. Learn more about analyzing test results.
Example of Unit Testing in MATLAB
This example demonstrates how to perform unit testing on a simple fibonacci
function. This function computes the Fibonacci sequence up to a specified number (n). To validate its correctness, we provide sample inputs, and the unit test checks whether the computed output matches the expected output for the given input. If the outputs match, the test passes; otherwise, it fails.
function x = fibonacci (n) % Generate the first n Fibonacci numbers n=6; x = ones (1,n); for ii = 3:n; x(ii) = x(ii - 1) + x(ii - 2); end end
% This is an autogenerated sample test for file fibonacci.m classdef test fibonacci < matlab.unittest.TestCase methods (Test) function test_fibonacci (testCase) % Specify the input (s) of % fibonacci n = 6; % Specify the expected output(s) of % fibonacci expected_x = [1, 1, 2, 3, 5, 8]; % Exercise the function fibonacci actual_x = fibonacci(n); testCase.verifyEqual(actual_x,expected_x); end end end
Examples and How To
Software Reference
See also: MATLAB Test, software testing