Skip to content
SE eBook
Menu

Levels of Testing

Public section
Preferences are saved on this device.

6.2 Testing Strategy

Testing does not happen at a single level. It is carried out in stages, beginning with individual components and gradually progressing to the entire system. Broadly, we can distinguish four main levels of testing:

  1. Unit Testing
  2. Integration Testing
  3. System Testing
  4. Acceptance Testing

In this section, we focus on the first two: unit testing and integration testing.

6.2.1 Unit Testing

Unit testing focuses on verifying individual program units or modules (functions, classes, procedures). It is usually performed by the developer and checks whether each module:

  • Works correctly within its own boundary.
  • Produces correct results for both valid and invalid inputs.

Unit testing often runs in parallel for multiple components, since units can be tested independently. A unit test strategy is illustrated in Figure 47.

Unit Testing Workflow A structured diagram of the Unit Testing workflow. Design and Test Cases serve as inputs. The Unit Under Test is centrally exercised by a Driver and supported by Stubs. Results lead to Defect Reports, which feedback into the Design/Code. Unit Testing Workflow Design & Code (Source Code) Test Cases (Data & Logic) Driver Unit Under Test (Function/Class) Stub(s) Test Results Pass / Fail Defect Report (If Failed) Feedback / Fixes
Figure 47: Unit testing workflow diagram.

Typical checks in unit testing include:

  • Module interface: Verify that parameters and return values are passed correctly, and ensure that data flows properly into and out of the unit.
  • Local data structures: Confirm that temporary data retains integrity and is used correctly throughout the algorithm.
  • Control structure paths: Exercise all independent paths in the unit so that each statement is executed at least once.
  • Boundary conditions: Test extreme and edge values of inputs, noting that many software failures occur at boundaries (for example, minimum/maximum values, empty lists, zero, negative numbers).
  • Error-handling paths: Force error conditions and verify that the module responds as specified (proper messages, safe recovery, no crashes).

If data does not enter or leave a module correctly, there is no point in further testing its internal logic—interface testing is therefore a natural first step.

Well-designed units (high cohesion, low coupling) are easier to test, and unit testing helps detect:

  • Boundary errors
  • Control flow errors
  • Data structure and local variable errors
Drivers and Stubs

Because units are not stand-alone programs, auxiliary driver and stub programs are often needed during unit testing.

  • Driver: A dummy “main” program that calls the unit under test, supplies test data, and records the outputs. Drivers are typically used when we need to test lower-level modules whose callers are not yet implemented.
  • Stub: A dummy subprogram that replaces a called lower-level module. A stub usually performs minimal data manipulation, may print a simple message, and then returns control to the caller. Stubs are commonly used in top-down testing when lower-level modules are not yet available.

Drivers and stubs are part of the testing overhead and should be kept as simple as possible. If suitable drivers or stubs cannot be constructed, full testing of that unit may be postponed until the integration testing stage.

Login to add personal notes and bookmarks.