0% found this document useful (0 votes)
3 views11 pages

Unit 2

Structural Testing is a software testing approach focused on evaluating the internal design and code structure using white box testing techniques. It includes methods like Mutation Testing, Data Flow Testing, and Slice-Based Testing, each targeting specific aspects of code functionality and coverage. Test coverage metrics are also discussed, highlighting their advantages and limitations in ensuring comprehensive testing and identifying untested code segments.

Uploaded by

knlostindreams00
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views11 pages

Unit 2

Structural Testing is a software testing approach focused on evaluating the internal design and code structure using white box testing techniques. It includes methods like Mutation Testing, Data Flow Testing, and Slice-Based Testing, each targeting specific aspects of code functionality and coverage. Test coverage metrics are also discussed, highlighting their advantages and limitations in ensuring comprehensive testing and identifying untested code segments.

Uploaded by

knlostindreams00
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Structural Testing

Structural Testing is a type of software testing. This testing is used to test the internal design
of the software or the structure of the coding for the particular software. Structural testing
uses white box testing techniques. The structural testing is concentrated on how the system is
doing rather than the functionality of the system. Most of the time structural testing is also
referred to as 'White Box Testing' and also as open, transparent, or glass testing based on the
code.
Types of Structural Testing
1. Mutation Testing

Mutation testing is structural testing that is performed to design new software tests
and also evaluate the quality of tests. It is related to the modification of a program in
small ways.

It is a structural testing technique, which uses the structure of the code to guide the
testing process. Mutation testing has the following three types:

• Value Mutation
• Decision Mutation
• Statement Mutation
Let us understand this using examples.

Value Mutation: It is mutation testing that changes the values of constants to detect
errors. Let us see a simple example to understand it. The following is the initial code
snippet:

Initial code for value mutation

int a=10;

int b=20;

int c= a*b;

Now let us change the value of constant,

Changed co for value mutation

int a=5;
int b=20;

int c=a*b;

Value of integer 'a' has been changed to 5 and the output is directed to observe if
there exist any errors in the code.

Decision Mutation: It is a type of testing that changes the logical or arithmetic


operations to detect any errors. Let us understand this using simple coding snippet.

//Initial Code for decision mutation

int a=10;

int b=2;

if(a%2==0)

printf("hello")

Now the condition statement in the if is changed to see if it raises an


error

//Changed Code for decision mutation

int a=10;

int b=2;

if(a/b==0)

printf("hello")

}
Statement Mutation: A statement mutation either deletes a statement or replaces
the statement to check for errors.

//initial code for statement mutation

int a=10;

int b=5;

int c= a*b;

Now the statement(s) of the code is changed to see if it arises any errors.

//Changed code for statement mutation

int a=10;

int b=5;

float x=a/b;

2. Data Flow Testing

Data Flow testing is structural testing it is used to find the test paths of a program
according to the values. It is used to analyze the flow of data in the program. These
are mainly concerned with

• Statements where variables receive values,

• Where these values are being used or referenced.


The basic idea behind this testing is to reveal the coding errors, mistakes, and
improper usage of data such as whether all the data variables are initialized or not
and initialized data is priorly used or not. It is used to fill the gaps between path testing
and branch testing.

Let us understand this using an example

1. read a,b

2. if a>b
3. c=a-b

4. else

5. c=b-a

6. print(c)

This is the control flow graph of the above example

So now let us see how we use and define the variables

**Variables Defined at node Used at node**

a 1 2,3,5

b 1 2,3,5

c 3,5 6
Basis path testing is a type of white-box testing that tests all possible independent paths in the
control flow graph of a program.

Note:

• A path is the route of nodes in the control flow graph that a program takes from one
point to another.
• An independent path is a path that adds at least one node in the already defined
independent paths. In other words, the independent paths of a program are all unique.

Steps for basis path testing

To conduct basis path testing of a program, follow the steps below:

1. Draw the control flow graph of the program.


2. Calculate the cyclomatic complexity of the control flow graph. This will be the
maximum number of independent paths in the graph.
3. Identify independent paths in the control flow graph.
4. Design test cases based on the independent paths identified so that the test cases
execute all independent paths.

Advantages of basis path testing

The advantages of conducting basis path testing are:

• Basis path testing reduces the number of redundant tests.


• All program statements are executed and tested at least once.
• It guarantees complete branch coverage.

Test coverage

Test coverage is defined as a metric in Software Testing that measures the amount of testing
performed by a set of test. It will include gathering information about which parts of a program
are executed when running the test suite to determine which branches of conditional statements
have been taken.

In simple terms, it is a technique to ensure that your tests are testing your code or how much
of your code you exercised by running the test.

There are several types of test coverage metrics, each focusing on different aspects of the code:

1. Statement Coverage: Statement coverage measures the percentage of executable


statements in the code that have been executed by the test cases. It indicates whether
each statement in the code has been reached and evaluated during the testing process.
Statement coverage is calculated by dividing the number of executed statements by the
total number of statements in the code.
2. Branch Coverage: Branch coverage, also known as decision coverage, measures the
percentage of decision points or branches in the code that have been exercised by the
test cases. It assesses whether each possible branch outcome (e.g., true or false) has
been tested. Branch coverage is calculated by dividing the number of executed branches
by the total number of branches in the code.
3. Path Coverage: Path coverage measures the percentage of unique paths through the
code that have been executed by the test cases. It aims to test every possible
combination of branches and decision points in the code, ensuring comprehensive
testing coverage. Path coverage is challenging to achieve and often impractical for
large, complex systems due to the exponential number of possible paths.
4. Function Coverage: Function coverage measures the percentage of functions or
subroutines in the code that have been invoked or called by the test cases. It assesses
whether all functions in the code have been exercised during testing.
5. Condition Coverage: Condition coverage focuses on the evaluation of logical
conditions within the code, ensuring that all possible condition outcomes (e.g., true,
false) have been tested. It helps identify potential logic errors or inconsistencies in the
code.
6. Loop Coverage: Loop coverage assesses whether all possible loop iterations have been
tested, ensuring that the code behaves correctly under different loop conditions and
termination criteria.

Test coverage metrics provide valuable insights into the quality and reliability of the software
under test. However, achieving 100% test coverage does not guarantee the absence of defects
or errors in the code. It is essential to prioritize test coverage based on criticality, complexity,
and risk factors associated with different code segments. Additionally, test coverage should be
complemented with other testing techniques such as boundary testing, equivalence partitioning,
and error guessing to ensure comprehensive validation of the software.

Advantages:

1. Objective Measurement: Test coverage metrics provide an objective and quantifiable


measure of the extent to which the code has been exercised by the test cases. This allows
teams to track testing progress and identify areas of the code that require additional
testing.
2. Identification of Untested Code: Test coverage metrics help identify sections of the
code that have not been executed by the test cases. This allows testers to focus their
efforts on testing critical or high-risk areas of the code that may contain defects or
errors.
3. Enhanced Confidence: Achieving high test coverage instills confidence in the quality
and reliability of the software. It indicates that the code has undergone thorough testing
and validation, reducing the likelihood of undiscovered defects or bugs in production.
4. Early Detection of Defects: Test coverage metrics facilitate early detection of defects
by highlighting untested code segments. This allows developers to address issues
promptly during the development cycle, minimizing the cost and effort associated with
fixing defects later in the process.
5. Quality Improvement: Test coverage metrics encourage developers to write testable
and modular code by emphasizing the importance of comprehensive testing. This
promotes good coding practices and ultimately leads to improved software quality.
Disadvantages:

1. Limited Scope: Test coverage metrics provide insights into the extent of code
execution but do not guarantee the absence of defects or errors. Achieving 100% test
coverage does not guarantee the correctness or robustness of the software as it may still
contain logic errors or integration issues.
2. Focus on Quantity over Quality: Focusing solely on achieving high test coverage may
lead to a false sense of security, where the emphasis is placed on the quantity of tests
rather than their quality. It is essential to complement test coverage metrics with other
testing techniques to ensure thorough validation of the software.
3. Complexity: Achieving 100% test coverage, especially for large and complex systems,
can be challenging and impractical. Path coverage, in particular, is often difficult to
achieve due to the exponential number of possible execution paths through the code.
4. Maintenance Overhead: Test coverage metrics require ongoing maintenance and
monitoring to ensure that they remain relevant and effective. As the codebase evolves
over time, test cases may need to be updated or modified to reflect changes in the
software.
5. False Sense of Completion: Relying solely on test coverage metrics may lead to a false
sense of completion, where teams believe that achieving high test coverage is sufficient
to ensure software quality. It is essential to supplement test coverage metrics with other
quality assurance practices such as code reviews, static analysis, and user acceptance
testing.

Slice-Based Testing

Slice-Based Testing is a structural testing technique used to identify and test subsets or "slices"
of a software program's functionality. It focuses on selecting and testing portions of the code
that are relevant to specific requirements or features, rather than testing the entire program as
a whole. This approach allows testers to achieve better test coverage and efficiency by targeting
critical areas of the codebase.

How Slice-Based Testing Works:

1. Identifying Slices: The first step in slice-based testing is to identify slices of the code
that correspond to specific features, functions, or requirements of the software. Slices
are subsets of the codebase that encapsulate the relevant statements, branches, and
variables related to a particular functionality.
2. Creating Test Cases: Once slices are identified, test cases are designed to exercise the
functionality represented by each slice. Test cases should cover various scenarios, input
combinations, and boundary conditions to ensure comprehensive testing coverage
within each slice.
3. Executing Test Cases: Test cases are executed against the corresponding slices of the
code to verify the correctness and robustness of the implemented functionality. Test
results are recorded, and any discrepancies or failures are analyzed and addressed by
developers.
4. Iterative Process: Slice-based testing is an iterative process that involves refining and
expanding the set of slices and test cases as the software evolves. New slices may be
identified, and existing test cases may be updated or augmented to accommodate
changes in the codebase or requirements.
Advantages of Slice-Based Testing:

1. Focused Testing: Slice-based testing allows testers to focus their efforts on specific
areas of the code that are relevant to the software's requirements or features. This
targeted approach enhances test coverage and effectiveness by prioritizing critical
functionalities.
2. Efficiency: By testing smaller subsets of the code, slice-based testing can be more
efficient compared to testing the entire program. Testers can achieve thorough coverage
of critical functionalities while minimizing the time and resources required for testing.
3. Early Detection of Defects: Slice-based testing facilitates early detection of defects or
errors in the code by enabling testers to focus on individual slices and functionalities.
This allows for prompt resolution of issues before they escalate and impact the overall
quality of the software.
4. Improved Maintainability: By breaking down the codebase into smaller, manageable
slices, slice-based testing enhances the maintainability and scalability of the testing
process. Test cases can be easily maintained, updated, and reused as the software
evolves over time.
5. Enhanced Debugging: Testing individual slices of the code makes it easier to isolate
and debug issues, as the scope of analysis is limited to specific functionalities. This
accelerates the troubleshooting process and improves the overall efficiency of defect
resolution.

Limitations of Slice-Based Testing:

1. Dependency Management: Slice-based testing may encounter challenges related to


managing dependencies between different slices of the code. Changes in one slice may
impact the behavior of other slices, requiring careful coordination and synchronization
of testing efforts.
2. Integration Testing: While slice-based testing focuses on testing individual
functionalities, it may overlook interactions and dependencies between different
components of the software. Integration testing is necessary to validate the behavior of
the system as a whole and ensure seamless interaction between its parts.
3. Complexity: Identifying and defining slices of the code can be complex, especially for
large and intricate software systems. Testers need to carefully analyze the software
requirements and architecture to determine the appropriate slicing strategy and scope.

In summary, slice-based testing is a valuable technique for achieving focused and efficient
testing of software functionalities. By breaking down the codebase into smaller, manageable
slices, testers can achieve thorough coverage and early detection of defects, leading to
improved software quality and reliability. However, it is essential to address challenges related
to dependency management, integration testing, and complexity to maximize the effectiveness
of slice-based testing in real-world scenarios.
A retrospective on structural testing

A retrospective on structural testing with a focus on identifying gaps and redundancies involves
a thorough review of the testing process to uncover areas where testing may have been
insufficient, incomplete, or inefficient. Let's discuss this in detail:

1. Defining Gaps and Redundancies:


• Gaps in structural testing refer to areas of the software that were not adequately
tested or where testing was completely missed. This could include untested code
paths, functionalities, or requirements.
• Redundancies, on the other hand, occur when there is overlap or duplication in
the testing effort. This might involve multiple tests covering the same
functionalities, code paths, or scenarios.
2. Identifying Gaps in Test Coverage:
• During the retrospective, the testing team reviews the scope and objectives of
the structural testing activities conducted during the software development
lifecycle.
• They analyze code coverage metrics to identify areas of the code that were not
adequately exercised by the tests. This could include branches, statements,
conditions, or paths that were not tested.
• Gaps in test coverage could result from incomplete requirements, insufficient
test planning, or limitations in resources or time.
3. Analyzing Redundancies in Testing:
• The team reviews the test suite to identify duplicate or overlapping test cases.
They assess whether multiple tests cover the same functionalities, code paths,
or scenarios.
• Redundant tests can lead to increased maintenance effort, longer test execution
times, and decreased efficiency in the testing process.
• Redundancies may arise due to poor test case management, lack of
communication between testers, or changes in requirements not being properly
updated in the test suite.
4. Understanding Root Causes:
• To address gaps and redundancies effectively, it's essential to understand why
they occurred. This involves analyzing the underlying factors and root causes.
• Gaps in test coverage may result from inadequate requirements analysis,
ambiguous specifications, or incomplete test planning.
• Redundancies may stem from a lack of coordination between testing teams,
legacy test cases that were not retired, or changes in requirements not being
properly communicated.
5. Assessing Impact and Risks:
• The retrospective evaluates the impact of gaps and redundancies on the quality,
reliability, and stability of the software.
• Gaps in test coverage increase the risk of undetected defects and potential issues
in production.
• Redundancies in testing lead to wasted time, effort, and resources, which can
impact project timelines and budgets.
6. Proposing Solutions and Action Items:

Based on the findings of the retrospective, the team proposes actionable
solutions to address gaps and redundancies in structural testing.
• This may involve improving requirements gathering processes, enhancing test
planning and prioritization, or optimizing the test suite for efficiency and
effectiveness.
• Solutions should be prioritized based on their impact on improving test
coverage, reducing redundancies, and enhancing overall testing quality.
7. Emphasizing Continuous Improvement:
• The retrospective emphasizes the importance of continuous improvement in the
testing process.
• It encourages a culture of learning, collaboration, and adaptation within the
testing team.
• Regular reviews and feedback sessions help monitor progress, identify new
improvement opportunities, and ensure that gaps and redundancies are
addressed effectively over time.

In summary, a retrospective on structural testing with a focus on gaps and redundancies


provides valuable insights into the effectiveness and efficiency of the testing process. It helps
identify areas for improvement and guides the implementation of strategies to enhance the
quality and reliability of the software.

Metrics for method evaluation

Metrics for method evaluation in structural testing focus on assessing the effectiveness,
coverage, and quality of the testing process with respect to the internal structure of the software
code. These metrics help evaluate how thoroughly the code has been tested, identify areas of
improvement, and ensure that the testing process meets its objectives. Here's a detailed
discussion on metrics commonly used for evaluating structural testing:

1. Statement Coverage:
• Definition: Statement coverage measures the percentage of executable
statements in the code that have been executed by the test cases.
• Purpose: It indicates the extent to which the code has been exercised during
testing and helps identify untested or unreachable code.
• Example: If a function contains 20 executable statements, and the test cases
cover 16 of them, the statement coverage would be 80%.
2. Branch Coverage:
• Definition: Branch coverage measures the percentage of decision points
(branches) in the code that have been executed by the test cases.
• Purpose: It ensures that all possible outcomes of conditional statements and
loops are tested, helping identify potential logic errors and corner cases.
• Example: If a decision point has two possible outcomes (branches), and the test
cases cover both branches, the branch coverage would be 100%.
3. Path Coverage:
• Definition: Path coverage measures the percentage of all possible execution
paths through the code that have been exercised by the test cases.
• Purpose: It ensures that all possible combinations of conditions and loops are
tested, providing more thorough coverage of the code.
•Example: If a function has multiple conditional statements and loops, each
unique combination of paths through the code represents a separate execution
path.
4. Cyclomatic Complexity:
• Definition: Cyclomatic complexity is a quantitative measure of the complexity
of a program, calculated based on the number of linearly independent paths
through the code.
• Purpose: It helps identify complex areas of the code that may require additional
testing and validation, as higher complexity correlates with increased risk of
defects.
• Example: A function with a cyclomatic complexity of 10 indicates that there
are 10 linearly independent paths through the code.
5. Mutation Score:
• Definition: Mutation testing involves introducing small changes (mutations) to
the code and then running the test suite to see if any of the mutations are
detected.
• Purpose: Mutation score represents the percentage of mutations detected by the
test cases, indicating the effectiveness of the test suite in detecting code changes.
• Example: If 80% of introduced mutations are detected by the test cases, the
mutation score would be 80%.
6. Function and Method Coverage:
• Definition: Function and method coverage measure the percentage of functions
or methods in the codebase that have been executed by the test cases.
• Purpose: It ensures that all functions and methods are tested, helping identify
potential defects and ensuring comprehensive code coverage.
• Example: If the test cases cover 15 out of 20 functions in the codebase, the
function coverage would be 75%.

These metrics provide quantitative measures of the thoroughness and effectiveness of structural
testing methods. By analyzing these metrics, software development teams can identify areas
for improvement, optimize testing strategies, and ensure the reliability and quality of their
software products.

You might also like