“Unit testing” is often referred to as “white box testing.” Although there may be slight differences in how these concepts are defined in terms of testing objects and methods within the industry, there is no fundamental difference between them. Unit testing involves testing and verifying the smallest testable units or logical relationships between units within software. For example, testing a function, class, or a small set of functions in C/C++ code, or a small functional module, typically falls under the category of unit testing.
Unit testing involves designing input parameters for the unit under test and verifying its output values, associated values, or execution process to validate the robustness and correctness of the unit under test. Robustness depends on whether the unit under test operates normally under various types or extreme input conditions; correctness is verified by determining whether the code's execution logic aligns with the original design requirements. The effectiveness of unit testing depends on the test cases, i.e., whether the external input parameters are reasonable and sufficient. These input parameters primarily need to be designed by testers based on the business logic requirements of the unit under test, so there is no universal “silver bullet” that can replace all unit testing work.
• Unit testing for a single function. Based on the design requirements of the function, design external input conditions such as input values, stub functions, and global variables. After the test is executed, determine whether the actual output values meet the expected values, which serves as the basis for determining whether the unit test case passes or fails. As shown in the figure below:
• Testing multiple units, which can also be understood as integration testing between units, as the testing focus remains at the underlying function level. This is a common testing scenario in unit testing work. Testing multiple units can verify the output values after consecutive calls and executions of multiple units, and can also be used to test the interdependent logic between multiple units.
Because traditional system functional testing (also known as “black-box testing”) cannot adequately detect errors in software branches, modules, and module interactions within a limited timeframe due to the complexity of the system after integration. Additionally, the cost of fixing bugs during the system testing phase is often high. Therefore, for systems requiring high reliability and security, software testing needs to be “shifted left” to an earlier stage of the project development process, verifying lower-level code lines, functions, classes, and submodules to achieve earlier and more thorough testing of the software. Additionally, since fixing bugs at an early stage is relatively easier, the overall development costs of the project can also be reduced – this is the original purpose of unit testing.
In other words, the purpose of unit testing is to test for bugs in functions or submodules based on lower-level requirements before system integration, thereby reducing the pressure on later system integration testing, ultimately achieving more thorough testing of the software, improving quality, and reducing costs.
Different paths, same goal: Regarding functional safety ASIL, SIL certification standards such as ISO 26262, IEC 61508, EN 50128, IEC 62304, or GJB-5000A, explicitly require unit testing during the software development process. The underlying rationale is to mitigate safety risks caused by insufficient testing by mandating more thorough testing at lower levels, thereby ensuring the safety and reliability of systems with extremely low tolerance for accidents, such as those in automotive, industrial, rail transportation, medical devices, and defense industries.
Demands and Challenges
Unit testing is time-consuming and labor-intensive. Each step—preparing the test environment, writing driver code, designing test cases, evaluating results, managing test cases, and performing regression and coverage analysis—requires tedious work. For a project containing hundreds, thousands, or even tens of thousands of function units, the amount of work required to rigorously complete unit testing manually is comparable to the entire software development process.
The lack of lower-level requirements documentation and testing experience creates barriers to the implementation of unit testing. In legacy projects, it is very common for function-level design requirements documentation to be insufficient or unstandardized. Relying solely on a small number of testers to interpret the code for unit testing makes testing work extremely difficult.
Unit testing of embedded software is more difficult to prepare and execute test cases due to its involvement in the cross-compilation process and compatibility with the target machine.
The analysis of changes, regression execution, and reuse of a massive unit test case library places high demands on test case management methods.
Unit test coverage statistics are almost impossible to compile manually.
Solutions
The unit test environment automatically generated by VectorCAST natively supports most mainstream host environment compilers and embedded cross-compilers, avoiding the need for significant code modifications or refactoring, or even changing compilers for testing purposes.
VectorCAST supports industry-leading intelligent, automated batch generation of unit test cases, typically achieving 50% to 80% or even higher test coverage.
Automatically parses code structure and provides a convenient and diversified graphical test design platform, greatly simplifying the design of unit test cases.
Organic management of test cases makes collaboration, maintenance, and reuse of test cases very easy.
VectorCAST offers a wide range of third-party integrations, seamlessly integrating upstream and downstream development tool chains and management platforms in the development process, such as requirements management, continuous integration, model development, and static analysis tools.
True embedded unit testing, with test cases seamlessly integrated into embedded target boards or simulators for execution.
Multiple report formats to meet different unit test usage scenarios and third-party certification audit requirements.
RELATED RESOURCES
Download Request