Printer Friendly

Software testing: early testing benefits consumer electronics.

Although consumer-electronics products do not demand the high reliability and availability of, say, communication switches, they still require a high level of testing. And today's short product life cycles require developers to test thoroughly, but in less time.

Often, testing an embedded system presents a unique challenge. Developers must write and test code on a host system that differs from the target hardware in a product. Several reasons could cause this disconnect: Engineers may not yet have target hardware, hardware may cost too much to give software developers access to it, and so on.


Unit Testing Helps Developers

Developers can effectively test software for an embedded system by running unit tests, or more generally, application program interface (API) tests, on the host system or on a simulator. This approach lets testing begin earlier in a design cycle, often concurrent with target-hardware development.

A premise of unit testing holds that tests occur in isolation from the rest of the system, which stub functions emulate. (A stub function, or stub, simulates the action of hardware or software components not yet available.) In this fashion, developers can verify that their code operates properly independent of the rest of the system. This type of testing gives developers two benefits.

First, unit testing lets developers start to test code before they have any target hardware, and they can run tests on the same host system used to develop code. Early testing gives code-development teams more time to find and repair defects. In addition, early testing distributes test efforts across the product-development cycle and helps avoid the 11th-hour testing rush.

Second, unit testing offers a "divide-and-conquer" strategy that lets developers partition complex systems so they can test quasi-independent modules. Test tools manage any module-to-module software dependencies and use stubs to simulate them (Figure 1).

Protect Code Integrity as Applications Evolve

Developers of complex systems often worry that a change to code in one section of the application program could "break" or unexpectedly change the operation of other code. To address this concern, developers produce unit tests for each portion of code they add to the overall system. These unit tests form a series of tests, called a regression suite, for regression testing. As developers add new code to their application program, they automatically execute the regression suite to ensure their added or changed code does not alter the operation of code somewhere else. Because unit tests can test parts of the system's code in isolation, developers can continuously execute a regression suite without having access to the target hardware. This type of testing does not exclude separate application regression tests, which test the overall application.

A comprehensive automated test suite lets the development team proceed safely and predictably with engineering changes, without the fear of "breaking" good code as they fix bugs. As new target hardware becomes available, developers should "re-target" their host-based tests to validate that their code will operate properly on the target hardware under realistic conditions. Running the regression suite on a host system does not diminish the need to automate the system tests on the target hardware to the equivalent degree.

Verify Error Handling

The need to reliably handle errors in consumer products can complicate system testing because designers cannot foresee every sequence of user actions. As a result, designers must produce code that will handle and recover from a broad range of incorrect and unexpected inputs.

By using unit testing with stubs, developers can simplify error testing. In general, testing error conditions at the application level can consume much time because designers must put an application into the "proper state of error." Doing so may require that they prepare a complicated set of input data and put the application into one specific state out of a large number of possible states.

In contrast, developers can easily test error handling in a function by using an "error simulation" approach. In the code shown in Example 1, developers can test the call to handle_bad_data() in context because they can provide signal, noise and mode data directly to the SignalToNoiseRatio function:

More often, however, developers cannot directly control conditions from a function interface. Instead, they depend on a specific system state, as shown in Example 2. Forcing the system into the error state that produces the error message may require complicated steps and may involve polling the status of a device interface. So, designers must simulate this error condition in a test case. In Example 2, testing the error handler requires the stub for uploadingData() to have at least one case that returns a true condition.

By using advanced test tools that support "smart stubs," unit testing for complex error conditions becomes-no more difficult than that shown in Example 1. Smart stubs allow code execution for the original function, as well as for implementation of specific behavior necessary for testing.

Although the application being tested is not in the error state, code invokes the specific function being tested as if the specific application error actually occurred, hence the term "error simulation."

Choose Software Tools with Care

Testing on a host system may imply the compiler used to build the code differs from the compiler used to produce code for the target hardware. If the cross-compiler vendor also supplies a compiler for the development plat-form, for example, the native compilers from Green Hills Software take this route. Alternatively, developers can freely use the GNU Compiler Collection (GCC) available for many host systems. Although keeping the code portable between the host and target compilers may slightly increase the software-maintenance cost, the benefits of early testing outweigh this expense.

Unit testing is unlikely to uncover error conditions caused by synchronization errors at the application level or errors that occur at the interfaces with real devices. However, in the development of embedded software, unit testing lets developers find many types of defects much earlier, thus improving the overall efficiency of their system development and removing test bottlenecks.

Sergei Sokolov has worked as a senior member of the Professional Services team at Parasoft for two years. He has more than 10 years of experience in developing large software systems in C and C++ in the electronic design automation (EDA) industry. Sergei has two Masters degrees and was awarded a patent for a new EDA technology. For more information, contact Parasoft, 101 E. Huntington Dr., Monrovia, CA 91016; (888) 305-0041;;

by Sergei Sokolov, Product Manager of C/C++ Solutions, Parasoft
float signalToNoiseRatio (float signal, float noise,
                          MODE mode)
        if (MODE_MEASUREMENT == mode)
                 if (signal < 0 || noise < 0)

Example 1

float shutDown()
        if  (uploadingData())
            userMessage("Cannot execute shutdown
                        while uploading data");
                  // shut down indeed
Example 2
COPYRIGHT 2006 Advantage Business Media
No portion of this article can be reproduced without the express written permission from the copyright holder.
Copyright 2006 Gale, Cengage Learning. All rights reserved.

Article Details
Printer friendly Cite/link Email Feedback
Author:Sokolov, Sergei
Publication:ECN-Electronic Component News
Date:Nov 15, 2006
Previous Article:ESD protection.
Next Article:Parameters of MOSFETs in automotive applications: motor drives in bridge configurations.

Terms of use | Copyright © 2018 Farlex, Inc. | Feedback | For webmasters