A STRATEGIC APPROACH TO SOFTWARE TESTING
1. Effective Technical Reviews:
Crucial for performing effective testing.
Helps eliminate many errors before the actual testing begins.
2. Progressive Testing Approach:
Start at the unit level.
Progressively work outward towards the integration of the entire system.
3. Adaptability of Testing Techniques:
Different techniques are suitable for different software engineering methods.
Techniques vary based on the timeline or stage of development.
4. Who Conducts Testing:
Testing is primarily done by the software's developer.
For larger projects, an independent test group is essential.
5. Distinction Between Testing & Debugging:
These are two distinct activities.
Debugging should be factored into any testing strategy.
1.1 VERIFICATION AND VALIDATION (V&V)
Definition:
Software testing is a subset of the broader domain known as V&V.
Verification:
Focuses on tasks ensuring the software implements specific functions correctly.
As Boehm put it: "Are we building the product right?"
Validation:
Deals with tasks ensuring the built software is aligned with customer requirements.
Boehm's perspective: "Are we building the right product?"
Scope of V&V:
V&V comprises a wide spectrum of Software Quality Assurance (SQA) activities including,
but not limited to:
1. Technical reviews.
2. Quality and configuration audits.
3. Performance monitoring.
4. Simulation.
5. Feasibility study.
6. Documentation review.
7. Database review.
8. Algorithm analysis.
9. Development testing.
10. Usability testing.
11. Qualification testing.
12. Acceptance testing.
13. Installation testing.
1.2 ORGANIZING FOR SOFTWARE TESTING
Conflict of Interest in Testing:
A conflict arises when developers are asked to test their own software. It's akin to self-
assessment, which can be inherently biased.
Developers' Role in Testing:
Developers are primarily responsible for:
1. Unit Testing: Testing individual components or units of the program to ensure each
functions correctly.
2. Integration Testing: This step involves constructing and testing the complete software
architecture. It's often done after unit tests and before independent tests.
Independent Test Group (ITG):
Purpose: To alleviate the issues tied with developers testing their own software.
Role: Ensure that testing is unbiased and comprehensive.
Collaboration: Developers and ITG collaborate closely. Developers remain involved to
rectify any uncovered errors during the testing phase.
1.3 SOFTWARE TESTING STRATEGY—THE BIG PICTURE
Software Process Visualization:
The process can be depicted as a spiral.
Phases of the Spiral:
1. System Engineering: Defines the role of software.
2. Software Requirements Analysis: Establishes various criteria and features like the
information domain, functionality, behaviour, performance, constraints, and validation
metrics for the software.
Spiral Movement:
Moving inward (counterclockwise) along the spiral, the levels of abstraction decrease with
each turn. This journey commences from broader system understanding and funnels down
towards detailed coding.
Testing strategy
Software testing steps
Testing
SOFTWARE TESTING STRATEGY IN THE CONTEXT OF THE SPIRAL
Unit Testing:
Location: Begins at the centre (vortex) of the spiral.
Focus: Each unit/component of the software as realized in source code.
Purpose: Ensure each component functions properly in isolation.
Techniques: Emphasizes specific paths within a component's control structure for
complete coverage and maximum error detection.
Integration Testing:
Location: Moving outward from the centre of the spiral.
Focus: Design and construction of the overall software architecture.
Purpose: Addresses the issues of verification and overall software construction.
Techniques: Often leans towards test case designs that focus on inputs and outputs.
However, methods that stress particular program paths can be utilized to ensure coverage
of major control paths.
Validation Testing:
Location: Further outward on the spiral.
Focus: Validation against established requirements during the requirements modelling
phase.
Purpose: Provides assurance that the software meets all established criteria, including
informational, functional, behavioural, and performance requirements.
System Testing:
Location: At the outermost edge of the spiral.
Focus: The entire system, which includes the software and other related system elements
(hardware, people, databases).
Purpose: Verifies the seamless integration and functioning of all system elements,
ensuring overall system function/performance is achieved.
Context: Goes beyond just software engineering and enters the realm of computer system
engineering.
SUMMARY:
The process of software testing, as framed within software engineering, consists of a
sequential series of steps. This starts from a granular focus on individual components (unit
testing) and progressively widens to embrace the system as a whole (system testing).
1.4 CRITERIA FOR COMPLETION OF TESTING
The Elusive End:
A common query in software testing is, "When are we done testing?" Regrettably, there's
no absolute answer.
Continuous Testing by Users:
One viewpoint is that testing is a perpetual process. After the software engineer's testing
ends, the end user essentially takes over. Every time a user operates the software, it
undergoes a new form of testing.
Need for Rigorous Criteria:
While many would agree with the idea of perpetual testing by users, a more solid criterion
is essential to determine the adequacy of testing in a formal software development setting.
Clean Room Software Engineering:
This approach introduces statistical methods.
Tests are run based on a statistical sample of all conceivable software runs across all
potential users within the target demographic. This offers a more systematic and
probabilistic assessment of software's readiness.
Utilizing Metrics and Reliability Models:
Gathering metrics during testing and leveraging existing software reliability models can
provide more clarity.
By analysing these metrics in the context of reliability models, it's feasible to devise
practical guidelines that help address the fundamental question of testing completion.
In Summary:
While the notion of "complete testing" remains somewhat abstract, combining empirical
data, reliability models, and statistical methods can offer meaningful benchmarks. It's
about striking a balance between pragmatism and thoroughness.
3.1 Unit Testing
1. Definition and Focus:
Unit testing is concentrated on the smallest piece of software design, often referred to as
a unit or component.
It emphasizes the internal logic, processing, and data structures of the component without
concerning its interactions with other components.
2. Parallel Testing Possibility:
Multiple components can undergo unit testing simultaneously, thus speeding up the
testing phase.
3. Key Considerations of Unit Testing:
a. Module Interface Testing:
Ensures smooth flow of information in and out of the unit.
b. Local Data Structure Examination:
Verifies that temporary data maintains its integrity throughout the algorithm's execution.
c. Independent Path Testing:
Ensures every statement in the module is executed at least once.
d. Boundary Condition Testing:
Confirms the module's operation at established processing limits or restrictions.
e. Error Handling Path Testing:
Validates the paths intended to handle errors.
4. Execution Path Testing:
It's crucial to selectively test execution paths to discover errors related to computations,
comparisons, or control flows.
5. Importance of Boundary Testing:
Software commonly encounters errors at its boundaries
6. Antibugging & Error Handling:
Antibugging anticipates error conditions, establishing paths to handle these errors.
Potential error handling issues to test include:
1. Unclear error descriptions.
2. Mismatch between reported and encountered errors.
3. System intervention before error handling.
4. Incorrect processing of exception conditions.
5. Insufficient information in error descriptions to pinpoint the error source.
7. Unit Test Procedures and Timing:
Unit testing can be an extension of the coding phase.
Designing unit tests can happen either before or after the coding process.
8. Unit Test Environment:
a. Drivers:
These are akin to main programs. They accept test case data, pass it to the unit for testing,
and display the results.
b. Stubs:
These are temporary replacements for modules that the unit being tested might invoke.
9. Simplification via Cohesion:
Unit testing becomes simpler when the component exhibits high cohesion.
A highly cohesive component, which addresses only one function, reduces the number of
required test cases and makes error identification easier.
This organized, pointwise breakdown offers a clear and detailed understanding of unit
testing, its considerations, and its procedures.
3.2 Integration Testing
1. Definition and Purpose:
Integration testing is focused on combining unattested components and constructing the
software's overall architecture.
It aims to uncover errors specifically related to interfacing between the components.
2. Non Incremental (Big Bang) Integration:
All components are combined and tested as a whole.
This approach can lead to challenges in isolating and correcting errors due to the
complexity of the entire system. It can end up in an ongoing cycle of identifying and fixing
errors.
3. Incremental Integration:
Opposite to the "big bang" approach.
Software is constructed and tested in smaller increments, facilitating easier error isolation
and correction.
This approach ensures comprehensive interface testing and enables a systematic test
process.
4. Incremental Integration Strategies:
There are two main strategies:
a. Top Down Integration:
It's an incremental approach that builds the software architecture from the top module
down through its hierarchy.
Modules are integrated in a depth first or breadth first manner.
I. Depth First Integration:
Integrates components on a major control path of the program structure sequentially,
moving down that path.
For example, if you had components M1, M2, and M5 on one path, you'd integrate these
first before moving on to other paths.
ii. Breadth First Integration:
Incorporates all components at the same hierarchy level before moving to the next level.
For instance, if M2, M3, and M4 are at the same level, they are integrated simultaneously
before integrating modules at subsequent levels.
b. Steps for Top Down Integration:
1. Utilize the main control module as a test driver, and use stubs for all modules directly
under it.
2. Depending on the chosen integration method (depth first or breadth first), replace stubs
anyone with the actual modules.
3. Conduct tests for each integrated component.
4. After each test set, another stub is substituted with its actual module.
5. Once integration is complete, perform regression testing to ensure no new errors have
emerged.
5. Regression Testing:
Done after integrating each component to ensure that the recent changes or additions
haven't introduced new errors into the existing system.
This breakdown offers a structured, pointwise overview of integration testing, its types,
and the steps involved in the top down integration process.
Bottom Up Integration Testing
Bottom up integration testing is a method of integration testing where testing begins with
the most basic components or units of a software program. It progresses upwards,
integrating and testing higher level components one at a time.
Steps Involved:
1. Low-level Components Clustering
Begin by combining low-level components to form clusters, also known as builds.
These clusters are designed to perform a specific software subfunction.
2. Writing a Driver
A driver, which is essentially a control program for testing, is written to manage the test
case input and output.
3. Testing the Cluster
The cluster, formed by integrating various components, is then thoroughly tested.
4. Removal of Drivers and Upward Integration
After testing, the drivers are removed.
The clusters are then integrated with higher level modules or components.
Integration continues upwards in the software's program structure.
Illustrative Integration Pattern:
Clusters 1, 2, and 3 are formed by combining components.
Each cluster is tested with its respective driver (D1, D2, D3).
Post testing, the drivers are removed and the clusters are integrated with main
components, for instance, Ma and Mb.
As the integration process progresses upwards, the need for individual drivers decreases.
If integration for the top levels is done top down, the overall number of drivers needed
can be significantly reduced.
Regression Testing
Regression testing is the process of testing a software application to ensure that new
changes or modifications haven't introduced any unintended errors or affected existing
functionalities.
Key Points:
1. Purpose of Regression Testing
Ensure that recent code changes haven't caused unexpected issues or side effects.
Confirm that the modified code still complies with the specified requirements.
2. Methods of Conducting Regression Testing
It can be conducted manually by executing a select subset of all the test cases.
Automated capture/playback tools can be used. These tools capture test cases and results
for later playback and comparison.
3. Regression Test Suite
The test suite contains a subset of tests to be executed during regression testing. The suite
comprises:
A representative sample of tests for all software functions.
Additional tests focusing on software functions potentially affected by recent changes.
Tests targeting the software components that were modified.
4. Growing Number of Regression Tests
As integration testing proceeds and the software evolves, the regression test suite can
expand considerably. Proper management and selection of test cases are crucial to ensure
efficient regression testing.
Smoke Testing
Smoke testing is a preliminary form of integration testing that helps assess if the primary
functionalities of a software product work correctly. It serves as an early detection system
for severe issues that might become major problems later in the development cycle.
Definition and Purpose:
1. What is Smoke Testing?
It's an integration testing technique predominantly used during the software development
process.
Aimed at pacing time critical projects, it allows the software team to regularly evaluate the
project's status.
2. Key Activities in Smoke Testing:
a. Building the Software:
Components that have been coded are assembled into a build.
This build contains all necessary files, libraries, reusable modules, and components
needed for one or more functionalities.
b. Designing Test Series:
These tests aim to discover critical errors preventing the build from functioning correctly.
The primary goal is to detect "showstopper" errors that can significantly derail the
project's timeline.
c. Daily Integration and Testing:
Each build is integrated with others, and the entire current version of the product
undergoes smoke testing daily.
The integration process can be top down or bottom up.
3. McConnell's Description of Smoke Test:
The test should involve the entire system from start to finish.
While it doesn't need to be exhaustive, it must detect major issues.
If a build passes the smoke test, it's deemed stable enough for deeper, more thorough
testing.
Benefits of Smoke Testing:
1. Minimization of Integration Risk:
Conducting smoke tests daily uncovers severe incompatibilities and issues early on,
which helps avoid significant timeline disruptions later.
2. Enhanced Product Quality:
Being an integration focused approach, smoke testing can highlight functional,
architectural, and component level design errors.
Addressing these errors early on ensures a higher quality end product.
3. Simplified Error Diagnosis and Correction:
Errors identified during smoke testing often relate to the most recent software additions.
Pinpointing errors in these "new software increments" simplifies the diagnostic and
correction processes.
4. Clearer Progress Assessment:
With daily integration and testing, more of the software gets validated as functional.
This regular validation boosts team morale and provides managers with tangible evidence
of progress.
Testability in Software Development
Importance: When software is built with testability in mind, it eases the process of
verifying and validating the software, ensuring it meets the intended requirements and is
free of critical errors.
Metrics: Metrics like code complexity, cohesion, and coupling can provide insight into the
software's testability.
Characteristics of Testable Software
1. Operability: If the software functions well, it becomes easier to spot when something
goes wrong.
2. Observability: To verify a test's outcome, it's crucial to have observable outputs. If you
can't observe it, you can't test it.
3. Controllability: Being able to control the software's behaviour ensures that specific
conditions and states can be tested.
4. Decomposability: By breaking the software into smaller parts, you can isolate tests,
which makes defect detection faster.
5. Simplicity: A simpler design is easier to understand and, thus, easier to test.
6. Stability: Constant changes can disrupt the testing process. Stable software ensures that
tests remain valid for longer durations.
7. Understandability: If testers understand the software, they can design better tests and
detect anomalies more effectively.
Attributes of a Good Test
Value: Every test should add value in terms of finding potential errors. A test that doesn't
have the potential to reveal new information is of little value.
Purpose: Each test should have a clear purpose. It should not replicate the intent of
another test.
Optimality: Among similar tests, the one that's most effective should be chosen.
Simplicity: While thoroughness is critical, overcomplicating a test can introduce its own
set of problems.
BlackBox vs. Whitebox Testing
BlackBox Testing: Here, the tester doesn't need to know the internal workings of the
application. The tests are based on the software requirements and functionality.
Advantages: Focuses on the system as a whole. It often identifies discrepancies in the
specifications.
Examples: Functional testing, acceptance testing.
Whitebox Testing: In this approach, the tester has knowledge of the internal workings of
the application and designs tests based on it.
Advantages: Can identify issues that might be overlooked in Blackbox testing, like logic
errors, dead code, and condition testing.
Examples: Statement coverage, path testing.
BlackBox Testing
Blackbox testing is a crucial method in the software testing landscape. Here’s an expansion
and elaboration on the topic:
Overview
Functional vs. Nonfunctional: While Blackbox testing majorly concentrates on the
functional aspects (how the software performs its intended functions), it can also be used
to validate nonfunctional requirements like performance, usability, and reliability.
Importance: The strength of Blackbox testing lies in its focus on the software's intended
behaviour and its insulation from the internal complexities. This means you're testing the
software as a user would experience it.
Errors Targeted by BlackBox Testing
Incorrect or Missing Functions: Verifying that all specified functions are present and
work as expected.
Interface Errors: Ensuring smooth interactions between different software components,
as well as between the software and external systems.
Data Structure Errors: Validating that data structures or external database access work
correctly.
Performance Errors: Checking if the software performs tasks within an acceptable
timeframe and responds quickly to user interactions.
Initialization and Termination Errors: Ensuring that the software starts and ends
sessions correctly.
Designing BlackBox Test Cases
The aim is to design tests that:
1. Efficiency: Reduce the total number of tests required to ensure comprehensive testing.
2. Broad Error Detection: Detect classes of errors, not just specific instances. For
instance, if an error is detected in one part of a data input range, similar issues may be
present in other parts.
Graph Based Testing Methods
Graph Representation: Using a graph for software testing involves creating nodes (which
represent entities or states) and links (which represent relationships or transitions).
Types of Links:
Directed Link: Indicates a one-way relationship.
Undirected (or Symmetric) Link: Represents a two-way relationship.
Parallel Links: Used when multiple relationships exist between nodes.
Behavioural Testing Methods Using Graphs
Transaction Flow Modelling: Nodes depict various stages in a transaction (e.g., stages
in an online purchase), and links indicate the sequence or logical connection between
these stages.
Finite State Modelling: Represents software's different states and the transitions between
them. For instance, a music player can have states like "playing," "paused," or "stopped,"
and certain actions will transition between these states.
Data Flow Modelling: Focuses on data and transformations. For example, raw data might
undergo several transformations before it's presented in a report.
Timing Modelling: Concentrates on time dependencies in software execution. It’s
particularly vital for Realtime systems where timing is crucial.
Benefits of Graph Based Testing
Visualization: Helps in visualizing the system's behaviour, which can be especially useful
for complex systems.
Coverage: Ensures that every node (entity or state) and every link (relationship or
transition) is tested.
Systematic Approach: Provides a structured method, ensuring that critical paths or
functionalities aren't missed.
5.2 Equivalence Partitioning
Equivalence partitioning is premised on the notion that if a software works correctly for a
value in an equivalence class, it will work for all the values in that class. It's a way of
optimizing testing efforts.
Example:
For a software that accepts age between 18 to 65:
One valid equivalence class: 18 to 65
Two invalid equivalence classes: < 18 and > 65
By just picking a value from each class (e.g., 20, 10, and 70), we can determine the
software's behaviour across the entire input domain.
5.3 Boundary Value Analysis
While equivalence partitioning tests within ranges or classes, BVA tests at the extremes or
boundaries. Many software defects tend to reside at these extremes.
Example:
For the same age acceptance software:
Values to test: 17 (just below 18), 18, 65, 66 (just above 65)
This means, instead of testing every value between 18 and 65, you're focusing on the
edges, which are more prone to defects.
5.4 Orthogonal Array Testing
Orthogonal Array Testing (OAT) is a systematic, statistical way of testing. It's used for
systems with multiple input combinations but where testing every combination is not
feasible.
Purpose: To test multiple parameters with different values in as few test cases as possible.
How it Works: OAT uses a matrix to determine which combinations of inputs to test. Each
row represents a test case, and each column represents a variable or parameter. The goal
is to ensure that each combination of inputs is tested at least once.
Example:
If you have two features, each with three possible settings:
Without OAT: You'd have 3 x 3 = 9 test cases to cover all combinations.
With OAT: You might cover all combinations in just 3 test cases.
Benefits:
1. Efficiency: Provides maximum coverage with fewer test cases.
2. Defect Detection: Due to its systematic approach, OAT often uncovers defects that may
be missed by other methods.
3. Cost Effective: Requires fewer resources and less time compared to exhaustive testing.
Orthogonal Array Testing (OAT)
OAT is a systematic and statistical way of testing which can be used to efficiently test
multiparameter systems. It's based on the principle that defects are caused by the
combination of parameters. By testing only a subset of these combinations, OAT aims to
detect most of the defects in the system.
Illustration with L9 Orthogonal Array
Let’s consider the fax application’s send function. The function has four parameters (P1,
P2, P3, and P4) and each parameter can have three distinct values. The example for P1
denotes sending times:
P1 1: Send it now
P1 2: Send it one hour later
P1 3: Send it after midnight
Similarly, P2, P3, and P4 signify other functionalities with values 1 to 3 representing various
options.
Traditional "One Input Item at a Time" Testing
If one were to test using a one factor at a time method, the sequence would be:
(1, 1, 1, 1)
(2, 1, 1, 1)
(3, 1, 1, 1)
...
(1, 1, 1, 3)
This method focuses on altering one parameter while keeping others constant. The
problem with this method is that it does not account for interactions between parameters.
So while it can detect errors caused by a single parameter's specific value, it won't catch
errors that arise when specific combinations of parameters are used.
If you were to do exhaustive testing, you'd need 3^4 = 81 test cases. This is thorough but
can be labour intensive and time consuming.
Using the L9 Orthogonal Array
The L9 Orthogonal Array reduces the number of tests by focusing on parameter
combinations that have the highest likelihood of finding defects. The benefits are:
1. Detecting Single Mode Faults: If there's a consistent issue with any parameter's
specific value, OAT will find it. For example, if the parameter P1 with value 1 consistently
causes a problem, the tests will reveal this.
2. Detecting Double Mode Faults: If a problem consistently appears when two
parameters take on specific values together, OAT will identify this. For instance, if a
problem only arises when P1 is set to 1 and P2 is set to 3, then this method will catch that
interaction.
3. Multimode Faults: The primary design of the L9 array (or similar orthogonal arrays)
assures detection of single and double mode faults. However, they may also detect some
higher level interaction faults, but not all.
Conclusion
Orthogonal Array Testing is an efficient way to test systems with multiple parameters. By
focusing on specific parameter combinations instead of testing every possible
combination, OAT can significantly reduce the number of required tests while still
detecting a high number of defects.
6. White Box Testing
Whitebox testing focuses on the internal logic and structure of the code. Unlike Blackbox
testing, which is centred around the functionality and requirements, Whitebox testing is
concerned with how the application works internally.
Key Features of White Box Testing:
1. Independent Path Execution: It ensures every path in the software is tested at least
once. This is essential for uncovering path based errors which might remain hidden during
functional tests.
2. Logical Decisions: Both the true and false conditions of logical decisions must be tested
to ensure that they both work as expected.
3. Loop Boundaries: It's common for errors to be found at the boundaries of loops (like at
the start and end). Whitebox testing mandates testing these boundaries and the
operational bounds within.
4. Data Structures: The internal data structures like lists, arrays, and queues should be
verified for their integrity.
6.1 Basic Path Testing
This is a method to ensure that each path in the software has been tested at least once.
Concept: Introduced by Tom McCabe, basic path testing focuses on the cyclomatic
complexity of a program to determine the number of linearly independent paths and then
creates test cases for each path. This ensures that all paths, including potential edge cases,
are tested.
6.1.1 Flow Graph Notation
Flow graphs are visual representations that depict the control flow of a program. They're
useful tools in white box testing as they visually break down the program's structure.
Nodes: These are circles in the flow graph. Each node represents one or more procedural
statements. It can be simple statements or conditions.
Edges/Links: These are the arrows connecting the nodes. They represent the flow of
control. For example, in an if else condition, there will be two edges emerging from the
node (one for true and one for false).
Regions: These are areas enclosed within nodes and edges. Including the area outside
the graph, the total number of regions can also represent the cyclomatic complexity of the
graph.
Predicate Nodes: These are the nodes that have conditions. They will have two or more
edges emerging from them based on the conditions they have.
Example: If there's a simple if else condition, the flow graph will have one predicate node
(the condition) with two edges coming out of it. One will represent the 'true' path, and the
other will represent the 'false' path.
6.1.2 Independent Program Paths
In Whitebox testing, it's crucial to identify and test every unique path through the software
to ensure all code has been executed. An independent path introduces either a new set of
processing statements or a new condition. By focusing on edges or links in the flow graph
that haven't been traversed, testers can ensure all logic and conditions in the code are
evaluated.
The sequence of paths illustrated:
Path 1: This path goes directly from the start to the end.
Path 2: This path introduces the evaluation of the parameters P2, P3, and P4.
Path 3 & 4: They provide different routes through the logic, ensuring all conditions and
statements are evaluated.
Cyclomatic Complexity:
Cyclomatic complexity is a measure of the software's complexity, and it's used to
determine the number of independent paths. This metric can be calculated in three
primary ways:
1. Regions: The number of regions in the flow graph.
2. Edges and Nodes: V(G) = E – N + 2
3. Predicate Nodes: V(G) = P + 1
This complexity value, therefore, provides a quantitative measure to guide testers on the
number of tests required.
6.1.3 Deriving Test Cases
To derive test cases using basis path testing:
1. Flow Graph Creation: This graph represents the program's control flow.
2. Complexity Calculation: By calculating the cyclomatic complexity, we determine the
number of test cases needed.
3. Path Identification: From the flow graph, identify a basis set of independent paths.
4. Test Case Preparation: Design test cases to ensure each path in the basis set is
executed.
6.1.4 Graph Matrices
Automating the basis path testing process is possible through graph matrices, which
provide a tabular representation of the flow graph. Each entry in the graph matrix
represents a connection between nodes. Adding weights to these entries, called link
weights, can provide valuable information like:
Probability: The likelihood of an edge being executed.
Processing Time: The time taken to traverse an edge.
Memory Usage: Memory consumed while traversing an edge.
Resources: Other resources used while following a link.
6.2 Control Structure Testing
Control structure testing aims to ensure that all logical paths of the software are fully
exercised. This type of testing covers different aspects of the code's control flow, such as
conditions, loops, and data flows.
6.2.1 Condition Testing
Condition testing revolves around testing the conditions in the software. This could be
simple conditions, compound conditions, or complex logical structures.
Simple Condition: This involves testing a basic condition, which could be a Boolean
variable or a relational expression. Testing for incorrect, missing, or extra Boolean
operators is key here.
Compound Condition: This involves conditions with multiple Boolean operations. Testing
ensures that the entire logic and its combinations are evaluated.
Errors can occur in many ways in conditions, and this technique aims to identify them,
ensuring the program reacts correctly to all possible inputs.
6.2.2 Data Flow Testing
Data flow testing focuses on the paths that data takes as it moves through the program. By
understanding how variables are defined, used, and where they're used, you can design
tests that ensure the program's logic in relation to these data paths is correct.
6.2.3 Loop Testing
Loop testing specifically targets loops in the software. Loops are common sources of
errors, and this method ensures all loops work as expected. There are four main types of
loops:
Simple Loops: Testing should ensure the loop can be skipped entirely, executed once,
multiple times, and to its maximum limit.
Nested Loops: For nested loops, starting testing from the innermost loop and
progressively moving outwards is recommended. Testing should ensure each loop is
evaluated within the context of its surrounding loops.
Concatenated Loops: If loops follow each other (but aren't nested), they can be tested like
simple loops if they're independent. If they're dependent, they should be tested like
nested loops.
Unstructured Loops: These should be avoided. If found, they should be refactored to
structured loops before testing.
Example: Deriving Test Cases
To derive test cases using white box testing:
1. Flow Graph Creation: Create a visual representation of the software's flow. This will help
in understanding the software's paths and decision points.
2. Complexity Calculation: Calculate the cyclomatic complexity, which gives an indication
of the number of independent paths in the software. This will give a hint of the number of
test cases needed.
3. Path Identification: Identify independent paths in the software based on the flow graph.
Each path represents a unique route through the software, and all of them should be tested.
4. Test Case Creation: For each identified path, create a test case. This test case should
force the software to traverse the path, ensuring all logic on the path is executed and
validated.
• 4. Prepare test cases that will force execution of each path in the basis
• set.