Static Code Analysis, Data Flow Analysis, Unit Testing, and Code Review
Software verification techniques such as pattern-based static code analysis, flow analysis, unit testing, and application-level testing are all valuable techniques for finding bugs in .NET software. On its own, each technique can help you find specific types of errors. However, if you restrict yourself to applying just one or some of these techniques in isolation, you risk having bugs that slip through the cracks. A safer, more effective strategy is to use all of these complementary techniques in concert. This establishes a bulletproof framework that helps you find bugs which are likely to evade specific techniques. It also creates an environment that helps you find functional problems, which can be the most critical and difficult to detect.
This paper will explain how automated techniques such as pattern-based static code analysis, testing (both unit testing and application-level testing, which includes manually-run tests as well as automatic tests), and flow analysis can be used together to find bugs in a .NET application. These techniques will be demonstrated using Parasoft .TEST, an integrated solution for automating a broad range of best practices proven to improve software development team productivity and software quality.
As you read this paperand whenever you think about finding bugsits important to keep sight of the big picture. Automatically detecting bugs such as memory corruption and deadlocks is undoubtedly a vital activity for any development team and can point out problems that are hard to detect by other means. However, the most deadly bugs are functional errors, which often cannot be found automatically. Well briefly discuss techniques for finding these bugs at the conclusion of this paper.
Introducing the Scenario
To provide a concrete example, we will introduce and demonstrate the recommended bug-finding strategies in the context of a real application: a version of the open source Paint.Net application.
Although the application typically works very well, it throws serialization exceptions under some conditions that are difficult to reproduce. The nature of the problem makes it hard to get a reproducible test case...which in turn makes it hard to use a debugger. We are left with a few choices on how to tackle the problem: review the code with any possible hints we can get from the stack traces (if available) or perform static analysis to see if we can get any hints as to what might be causing the issue.
Given that reviewing the code for this purpose is like to searching in the dark, the obvious first choice is to use available automatic techniques and then go to review as a last resort. Then, if the automatic techniques provide a solution, we can use these results to guide any further code review efforts.
Pattern-Based Static Code Analysis
Pattern-based static analysis checks for known anti-patterns in source code constructs and reports each occurrence of a match. Pattern-based static analysis can be done quickly and is guaranteed to find all cases of code that match a pattern. Avoiding certain software anti-patterns is a great way to eliminate categories of defects from the project.
In the case discussed above, we are in luck; we perform pattern-based static analysis with .TEST, and this reveals the exact problem: The class FileType, which is the base class of the Serializable class PdnFileType, is not marked as Serializable.
Marking the class FileType with the Serializable attribute should fix the problem. However, we are not able to reproduce the problem easily by running the application because the problem occurs only under circumstances that require serialization. We need a reliable way to determine whether this was indeed the problem and if soif it actually was resolved. One solution is to verify the problem and the fix via unit testing. In the next section, we discuss how to achieve this goal...
To read more, download the complete Integrated Error-Detection Techniques Find More Bugs in .NET Applications paper as a PDF.