When writing code, most people understand what they are doing – at least at the time – but how clear will it be later, and how understandable is it to others? Is it overly complex? Does it follow prescribed coding standards? Are there subtle errors that could make it vulnerable to hacking? You don’t know unless you check, and that means static analysis.
The foundation for software quality (and often required for qualification or certification) is static analysis: the parsing and examination of the source code. Static analysis provides telling insight into how well the code is written, particularly with reference to quality metrics and adherence to coding standards; it provides the foundation for further assessments including control and data flow analysis and structural coverage analysis; and it provides the basis for artifacts that are both admissible documentation for certification, and tangible evidence of quality.
Static analysis works at the source code level by parsing the code much like a compiler would, while identifying information pertinent to control and data flow such as the whereabouts of conditional branches. The data it collates provides the basis for metrics that help developers better understand the clarity, complexity, and even testability of the code under development. In its simplest form it can flag seemingly minor things like typos that could possibly cause hours of delay before they are found. A more sophisticated static analysis tool can also calculate such metrics as cyclomatic complexity, which is a measure of the number of unique paths through a program or section of code, such as may result from overly high loop density (the number of conditionals nested within loops). A static analysis tool that can give a density score for different sections of a program can guide the developer to provide simpler and clearer paths. This also results in better understandability and improved testability.
Another capability of static analysis is to assure compliance to coding standards, either industry defined, user-defined, or a combination of the two. Standards such as MISRA C, CERT C, CWE, and others are derived from research and industry best practices in developing software that is safe and secure. Static analysis offers protection against even subtle errors and oversights that can cause problems under certain conditions, such as the recent notorious “heartbleed” vulnerability that resulted from not checking the length of a variable. A number of industry functional safety standards such as ISO 26262 in the automotive industry and IEC 62304 for medical devices also call out things to be checked by static analysis, ensuring that (for example) there are no hidden data flows and no unconditional jumps in the interest of code quality and security.
Static analysis helps “map” future analysis
Static analysis develops something of a “brain map” for the code system that can be used as the foundation for dynamic analysis techniques such as detailed structural coverage analysis and automated unit and integration testing. In turn, these generate their own related metrics to reinforce the evidence of a quality development process. Used in tandem with a requirements traceability tool, these tests and their resulting artifacts establish a transparent lifecycle of development by linking the functional, safety, and security requirements to the code, the analysis results, and the test cases and results. In effect, this bidirectional traceability not only provides evidence of the faithful and complete implementation of the requirements. It also enables impact analysis of requirements changes or failed tests as they occur throughout the lifecycle, highlighting all parts of the software system impacted, and hence any analysis and tests that need to be repeated.
Static analysis data provides additional benefits
The usefulness of static analysis to unit test starts with an understanding of the structure of the code. Through static analysis, the data and control aspects of the application can be analyzed, the interfaces can be understood, and the foundation for test case harnesses can be derived. These harnesses are invaluable to requirements related testing, saving time and expense.
From this derived set of data, the test cases themselves can also be automatically generated to exercise the majority of the code and provide evidence of that by means of structural coverage analysis. These automatically generated tests provide an ideal mechanism to augment requirements based testing to arrive at a robust set of test cases that address functional, safety, and security requirements. Requirements traceability, again, can link from the requirements through the test cases that verify the software components and validate the application.
Static analysis, when used throughout the software development lifecycle, can prevent latent errors from persisting to the point where they require significantly more effort and expense to correct. The data from static analysis and the analytical tools that rely on it are vitally necessary for producing the proof of testing and documentation required for certification by a growing variety of governmental and industrial organizations.