When most people get behind the wheel of a car, they don’t worry about the brakes failing. They also don’t worry about injuries from a malfunction when their child gets a new toy. In fact, most people don’t worry about system malfunctions at all as they go through their daily lives.
That’s because a software developer or a quality control engineer like you has addressed quality issues. If the goal is to deliver high-quality, reliable software systems, then tests must be conducted. Quality issues won’t go away without testing because the more reliable the product is, the safer it is.
One of the processes we use for testing quality and reliability is called robustness testing, the degree to which a system operates correctly in the presence of exceptional inputs or stressful environmental conditions. If you’re new to this kind of testing, buckle up.
Quality assurance engineers will take the fall for a system failure, or worse if that failure causes an injury. But that doesn’t let developers off the hook. Developers should build and test for robustness along with the other tests they perform during the validation process such as benchmark testing.
Embedded software safety and security-critical systems require thorough testing at each phase of the software development life cycle, from the system and high-level design to unit tests and integration testing.
When robustness in software testing comes up, it generally means that the system deployed or still under development, is operating well under normal or ordinary conditions. Robust testing is about improving reliability and finding those corner cases by inputting data that mimics extreme environmental conditions to help determine whether or not the system is robust enough to deliver.
Testing robustness is more focused than dependability benchmarking. Robust testing is about whether or not we can kick the software around and it’s able to handle the abuse and operate correctly. It’s not about those sunny day scenarios where everything runs perfectly. We perform robustness testing to find out what the other tests are missing. Our objective is to create test environments that can assess a software system’s robustness. It’s important to track software test metrics to measure the effectiveness of your testing.
In computer science, programmers are accustomed to creating algorithms that make computer systems work. We’re not used to creating algorithms to break things so robustness testing may seem counter-intuitive to some. It’s necessary when verifying the robustness of the computer systems we build no matter the programming language’s semantics. This is particularly true when there are multiple dependencies.
When we conduct robustness testing, we’re looking for the scenarios that can cause the software to fail. Robustness testing is an end-to-end testing solution for embedded systems. It’s carried out by passing valid input and invalid input to check the reliability of the software. The software can fail for many reasons so we also test for changes that affect the hardware, changes in the environment, or external and independent software.
Safety and reliability are clear benefits of robustness testing. It saves lives and lessens the risk of injury or costly lawsuits. Some industries must test to strict regulatory and compliance standards more than others.
The airline industry with its many embedded aviation systems is an excellent example of the importance of safety and reliability. People’s lives are at stake. You better believe they think about the corner case when testing.
With such a high number of flights over the past sixteen years and the relatively low number of civil airline crashes since 1945, the airline industry has an extremely high success rate. Even with that kind of success, there are unfortunately fatalities, injuries, and lawsuits, but it serves as an effective argument for the effectiveness of robustness testing.
Automated test generation is important to speed up testing. Some robustness testing solutions offer automatic generation of test cases that improve quality and help verify and validate software components right on the target hardware, which is a requirement within the most stringent safety integrity levels, such as DAL A in the DO-178C process standard.
Security is yet another example where developers and engineers cannot afford to get it wrong. Financial institutions, credit card processing companies, and the defense industry are just a few that must meet very rigorous compliance requirements. It’s possible to integrate compliance into existing development processes and ecosystems, from requirements management and source control to IDEs and CI/CD. By automating compliance against functional safety and security-critical standards, organizations can save time and money.
No matter the industry or the application, robustness testing helps organizations achieve and automate compliance and deliver quality software. Good ROI is also achieved, which reduces the cost of delivery for embedded software.
While there are many robustness testing techniques and tools, fuzz is probably the most widely used test method because it’s been around for decades. Fuzz tests have proven to be very effective and it’s a relatively simple method where you create test cases with multiple variations of unexpected inputs and monitor them for exceptions. After exhaustive testing, if it doesn’t crash, fail built-in code assertions, or have potential memory leaks, then you’ve achieved a high degree of software robustness.
Another robustness testing technique is black-box testing. This is where the QA testers or the software engineering team, pretend they are the end users or stakeholders of the product or application to test real-world scenarios. The user only cares whether or not the software system works as intended. It’s the human or user-level testing for functionality and dependability. If the correct output or behavior is generated by the system under stressful environmental conditions and the system operates correctly or works as it was designed, it’s robust.
Other types of robustness testing approaches include classical fault injection testing and mutation testing. The goal of classical fault injection testing is to determine the robustness of the system’s code during runtime by injecting corrupt data types or hardware faults to determine if the system crashes or is unsafe. If it tolerates the faults, it’s robust. The goal of mutation testing is to evaluate the effectiveness of the test case to find a bug. In this test, you put a bug into the code to see if it’s detected. If it is, your test case is thorough.
Tip! If you are a developer working with Java, exception handling is a test method you can deploy to handle the runtime errors so that the normal flow of the application can be maintained.
Automation testing is used to automate repetitive tasks and other testing tasks which are difficult to perform manually. It compares the actual outcome with the expected outcome. Test cases are built to achieve a particular testing objective. Robustness testing can be automated when conducting regression testing, another approach to robustness testing.
Regression testing is a test of the whole application to determine whether there are any ill effect modifications in any module or the functionality of the software. Automation is necessary when conducting regression testing because it’s almost impossible to conduct system testing manually. Automation reduces labor and runtime which testing methodology is used for robust testing.
With automated testing tools, you can also auto-generate test cases to support fuzz testing or symbolic execution which performs min, mid, max, and other value range testing. Some test cases will also test outside the value boundaries to determine whether your software components can handle those values as well.
Automated testing tools with user-friendly graphical interfaces can make things even easier with unit testing by abstracting the code into a visual table allowing the user to fill in fields, like input values and expected results. Generation of the test case from the table can then take place. Stubbing may also be applied for testing even though other software functionality may not be available. There’s also the simplified ability to modify or update test cases and track which test cases need to change if the code changes. Better yet, QA teams can manage test suits with all of the thousands of test cases created.
For organizations that must meet IEEE standards, robustness testing is mandatory, but it can be excessive for non-safety-critical applications so it may not be justified for some organizations. Some tests, such as mutation tests, require an existing test case and inserting realistic bugs, which can be difficult to do.
Unfortunately, time is not always a friend of robustness testing because of the additional time and labor it consumes. But if robustness software testing will help your organization meet its goal to deliver higher software quality, and safe and secure software, with good ROI, and reduce the cost of delivery, then you may need to consider automation tools that can provide the speed and capabilities you need to perform robustness testing.
It’s important to have a good understanding of robustness testing. So much so that the International Symposium on On-Line Testing and Robust System Design (IOLTS) has presented data on it for the IEEE. The IEEE has also specified a family of standards for maintaining compatibility
Additionally, the Association for Computing Machinery (ACM) has presented case studies about robustness testing in the ACM journal.
To learn more about robustness testing, check out our whitepaper, “Optimizing Unit & Regression Testing for Embedded Systems.”
A Sr. Technical Product Marketing Manager for Parasoft’s embedded testing solutions, Ricardo has expertise in the SDLC and test automation of embedded real-time, safety, and security-critical applications, and software compliance to industry standards.