Testing



Testing

Create a unit test plan.

Instrument and debug a Windows service, a serviced component, a .NET Remoting object, and an XML Web service.

  • Provide multicultural test data to components and applications.

  • Execute tests.

NOTE

Correctness, Robustness, and Reliability Correctness refers to a program's capability to produce expected results when the program is given a set of valid input data. Robustness is a program's capability to cope with invalid data or operations. Reliability is a program's capability to produce consistent results on every use.


Testing is the process of executing a program with the intention of finding errors (bugs). By error I mean any case in which a program's actual results fail to match the expected results. The criteria of the expected results may not include just the correctness of the program; they may also include other attributes, such as usability, reliability, and robustness. The process of testing may be manual, automated, or a mixture of both techniques.

In this increasingly competitive world, testing is more important than ever. A software company cannot afford to ignore the importance of testing. If a company releases buggy code, not only will it end up spending more time and money fixing and redistributing the corrected code, but it will also lose goodwill. In the Internet world, the competition is not even next door: It is just a click away!

Creating a Test Plan

Create a unit test plan.

A test plan is a document that guides the process of testing. A good test plan should typically include the following information:

  • Which software components need to be tested

  • What parts of a component's specification are to be tested

  • What parts of a component's specification are not to be tested

  • What approach needs to be followed for testing

  • Who will be responsible for each task in the testing process

  • What the schedule is for testing

  • What the criteria are for a test to fail or pass

  • How the test results will be documented and used

Executing Tests

Incremental testing (sometimes also called evolutionary testing) is a modern approach to testing that has proven very useful for rapid application development (RAD). The idea of incremental testing is to test the system as you build it. Three levels of testing are involved in incremental testing:

  • Unit testing— Unit testing involves testing elementary units of the application (usually classes).

  • Integration testing— Integration testing tests the integration of two or more units or the integration between subsystems of those units.

  • Regression testing— Regression testing usually involves the process of repeating the unit and integration tests whenever a bug is fixed, to ensure that the old bugs do not exist and that no new ones have been introduced.

Unit Testing

Units are the smallest building blocks of an application. In Visual C# .NET, these building blocks often refer to components or class definitions. Unit testing involves performing basic tests at the component level to ensure that each unique path in the component behaves exactly as documented in its specifications.

NOTE

NUnit NUnit is a simple framework for writing repeatable tests in any .NET language. For more information, visit http://nunit.sourceforge.net.


Usually, the same person who writes the component also does unit testing for it. Unit testing typically requires that you write special programs that use the component or class being tested. These programs are called test drivers; they are used throughout the testing process, but they are not part of the final product.

The following are some of the major benefits of unit testing:

  • It allows you to test parts of an application without waiting for the other parts to be available.

  • It allows you to test exceptional conditions that are not easily reached by external inputs in a large, integrated system.

  • It simplifies the debugging process by limiting the search for bugs to a small unit rather than to the complete application.

  • It helps you avoid lengthy compile-build-debug cycles when debugging difficult problems.

  • It enables you to detect and remove defects at a much lower cost than with other, later, stages of testing.

Integration Testing

Integration testing verifies that the major subsystems of an application work well with each other. The objective of integration testing is to uncover the errors that might result because of the way units integrate with each other.

Visualize the whole application as a hierarchy of components; integration testing can be performed in any of the following ways:

  • Bottom-up approach— With this approach, the testing progresses from the smallest subsystem and then gradually progresses up in the hierarchy to cover the whole system. This approach may require you to write a number of test-driver programs that test the integration between subsystems.

  • Top-down approach— This approach starts with the top-level system, to test the top-level interfaces, and gradually comes down and tests smaller subsystems. You might be required to write stubs (that is, dummy modules that mimic the interface of a module but have no functionality) for the modules that are not yet ready for testing.

  • Umbrella approach— This approach focuses on testing the modules that have a high degree of user interaction. Normally, stubs are used in place of process-intensive modules. This approach enables you to release a graphical user interface (GUI)–based application early and gradually increase functionality. It is called the umbrella approach because the input/output modules are generally present on the edges, forming an umbrella shape. For example, think of an equipment rental company, whose component hierarchy resembles the hierarchy shown in Figure. Here the input/output modules are represented by solid lines because they are fully implemented, whereas the computational modules are represented by the dotted lines because a stub may be used in their place. In umbrella-approach integration testing, you test the input/output modules, which form the edge of an umbrella-like shape.

    1. The umbrella approach of integration testing focuses on testing the modules that have a high degree of user interaction.

    graphics/09fig01.gif

NOTE

Limitations of Testing Testing can show the presence of errors, but it can never confirm the absence of errors. Various factors such as the complexity of the software, requirements such as interoperability with various software and hardware, and globalization issues such as support for various languages and cultures, can create excessive input data and too many execution paths to be tested. Many companies do their best to capture most of the test cases by using automation (that is, using computer programs to find errors) and beta-testing (that is, involving product enthusiasts to find errors), but errors in final products are still a well-known and acknowledged fact.


Regression Testing

Regression testing should be performed any time a program is modified, either to fix a bug or to add a feature. The process of regression testing involves running all the tests mentioned in the preceding sections, as well as any newly added test cases to test the added functionality. Regression testing has two main goals:

  • Verify that all known bugs are corrected.

  • Verify that the program has no new bugs.

Testing International Applications

Testing an application designed for international usage involves checking the country and language dependencies of each locale for which the application has been designed. When testing international applications, you need to consider the following:

  • You should test the application's data and user interface to make sure that they conform to the standards for date and time, numeric values, currency, list separators, and measurements for the locales and countries in which you plan to sell your product.

  • You should test your application on as many language and culture variants as necessary to cover your entire market for the application. Operating systems such as Windows 2000 and Windows XP support the languages used in more than 120 cultures/locales.

  • You should use Unicode for your applications. Applications that use Unicode run without requiring any changes on Windows 2000 and XP. If an application instead uses Windows code pages, you need to set the culture/locale of the operating system according to the localized version of the application that you are testing. Each such change requires you to reboot the computer.

  • While testing a localized version of an application, you should make sure to use input data in the language that is supported by the localized version. This makes the testing scenario similar to the scenario in which the application actually will be used.

REVIEW BREAK

  • Testing is the process of executing a program with the intention of finding errors. You should design an effective test plan to ensure that your application is free from all likely defects and errors.

  • Unit testing ensures that each unit of an application functions precisely as desired. It is the lowest level of testing.

  • Integration testing ensures that different units of an application function as expected by the test plan after they are integrated.

  • Whenever code is modified or a new feature is added in an application, you should run all the existing test cases, along with a new set of test cases, to check the new feature. This helps you develop robust applications.