20CSE71A - ST - MODULE 2 - White Box Testing
20CSE71A - ST - MODULE 2 - White Box Testing
20CSE71A - ST - MODULE 2 - White Box Testing
By
Chempavathy.B
MODULE 2
White Box and Black Box Testing:
White box testing, static testing, static analysis tools, Structural
testing: Module/Code functional testing, Code coverage testing,
Code complexity testing,
Black Box testing, Requirements based testing, Boundary value
analysis, Equivalence partitioning, state/ graph based testing,
Model based testing and model checking, Differences between
white box and Black box testing.
WHAT IS WHITE BOX TESTING?
• White box testing is a way of testing the external
functionality of the code by examining and testing the
program code that realizes the external functionality. This
is also known as clear box, or glass box or open box
testing.
• White box testing takes into account the program code,
code structure, and internal design flow.
• A number of defects come about because of incorrect
translation of requirements and design into program code.
Some other defects are created by programming errors and
programming language idiosyncrasies.
Classification of white box testing.
STATIC TESTING
• Static testing is a type of testing which requires only the
source code of the product, not the binaries or
executables. Static testing does not involve executing
the programs on computers but involves select people
going through the code to find out whether
The code works according to the functional
requirement;
The code has been written in accordance with the design
developed earlier in the project life cycle;
The code for any functionality has been missed out;
The code handles errors properly. Static testing can be
done by humans or with the help of specialized tools.
Static Analysis Tools
• There are several static analysis tools available in the market that
can reduce the manual work and perform analysis of the code to
find out errors such as those listed below.
1. Whether there are unreachable codes (usage of GOTO
statements sometimes creates this situation; there could be
other reasons too)
2. Variables declared but not used
3. Mismatch in definition and assignment of values to variables
4. Illegal or error prone typecasting of variables
5. Use of non-portable or architecture-dependent programming
constructs
6. Memory allocated but not having corresponding statements for
freeing them up memory
7. Calculation of cyclomatic complexity
• These static analysis tools can also be considered as
an extension of compilers as they use the same
concepts and implementation to locate errors. A
good compiler is also a static analysis tool.
• Some of the static analysis tools can also check
compliance for coding standards as prescribed by
standards such as POSIX. These tools can also check
for consistency in coding guidelines (for example,
naming conventions, allowed data types,
permissible programming constructs, and so on).
• While following any of the methods of human
checking-desk checking, walkthroughs, or formal
inspections-it is useful to have a code review
checklist. Every organization should develop its own
code review checklist. The checklist should be kept
current with new learning as they come about.
• In a multi-product organization, the checklist may
be at two levels-first, an organization-wide checklist
that will include issues such as organizational coding
standards, documentation standards, and so on;
second, a productor project-specific checklist that
addresses issues specific to the product or project.
CODE REVIEW CHECKLIST
• Data Item Declaration related
• Data Usage related
• Control Flow related
• Standard related
• Style related
• Miscellaneous
• Documentation related
STRUCTURAL TESTING
• Structural testing takes into account the code, code structure,
internal design, and how they are coded. The fundamental
difference between structural testing and static testing is that in
structural testing tests are actually run by the computer on the
built product, whereas in static testing, the product is tested by
humans using just the source code and not the executables or
binaries.
• Structural testing entails running the actual product against
some predesigned test cases to exercise as much of the code as
possible or necessary. A given portion of the code is exercised if
a test case causes the program to execute that portion of the
code when running the test.
Unit/Code Functional Testing
• This initial part of structural testing corresponds to some quick checks that a developer
performs before subjecting the code to more extensive code coverage testing or code
complexity testing. This can happen by several methods
Initially, the developer can perform certain obvious tests, knowing the input variables and the
corresponding expected output variables. This can be a quick test that checks out any obvious
mistakes. By repeating these tests for multiple values of input variables, the confidence level of
the developer to go to the next level increases. This can even be done prior to formal reviews of
static testing so that the review mechanism does not waste time catching obvious errors.
For modules with complex logic or conditions, the developer can build a “debug version” of the
product by putting intermediate print statements and making sure the program is passing
through the right loops and iterations the right number of times. It is important to remove the
intermediate print statements after the defects are fixed.
Another approach to do the initial test is to run the product under a debugger or an Integrated
Development Environment (IDE).These tools allow single stepping of instructions (allowing the
developer to stop at the end of each instruction, view or modify the contents of variables, and
so on), setting break points at any function or instruction, and viewing the various system
parameters or program variable values.
Code Coverage Testing
• Code coverage testing involves designing and
executing test cases and finding out the percentage
of code that is covered by testing. The percentage of
code covered by a test is found by adopting a
technique called instrumentation of code.
• Code coverage testing is made up of the following
types of coverage.
1. Statement coverage
2. Path coverage
3. Condition coverage
4. Function coverage
Statement coverage
• Program constructs in most conventional
programming languages can be classified as
1. Sequential control flow
2. Two-way decision statements like if then else
3. Multi-way decision statements like Switch
4. Loops like while do, repeat until and for
• Statement Coverage=(Total statements exercised/Total number of
executable statements in program)*100
• Statement coverage refers to writing test cases that execute each
of the program statements. One can start with the assumption
that more the code covered, the better is the testing of the
functionality, as the code realizes the functionality.
• For a section of code that consists of statements that are
sequentially executed (that is, with no conditional branches), test
cases can be designed to run through from top to bottom. A test
case that starts at the top would generally have to go through the
full section till the bottom of the section.
• When we consider a two-way decision construct like the if
statement, then to cover all the statements, we should also cover
the then and else parts of the if statement. This means we should
have, for each if then else, (at least) one test case to test the
Then part and (at least) one test case to test the e1se part.
• The multi-way decision construct such as a Switch statement can
be reduced to multiple two-way if statements. Thus, to cover all
possible switch cases, there would be multiple test cases.
• A good percentage of the defects in programs come about
because of loops that do not function properly. More often, loops
fail in what are called "boundary conditions."
• In order to make sure that there is better statement
coverage for statements within a loop, there should be test
cases that
1. Skip the loop completely, so that the situation of the
termination condition being true before starting the loop
is tested.
2. Exercise the loop between once and the maximum
number of times, to check all possible "normal"
operations of the loop.
3. Try covering the loop, around the "boundary" of n-that is,
just below n, n, and just above n.
Example
• consider the following program.
Total = O; /* set total to zero */
if (code == "M") {
Stmt1;
Stmt2;
Stmt3;
Stmt4;
Stmt5;
Stmt6;
Stmt7;
else percent = value/Total*100; /* divide by zero */
In the above program, when we test with code = "M," we will get 80 percent code
coverage. But if the data distribution in the real world is such that 90 percent of the time,
the value of code is not = "M," then, the program will fail 90 percent of the time (because of
the divide by zero in the highlighted line).
Path coverage
• In path coverage , we split a program into a number
of distinct paths. A program (or a part of a program)
can start from the beginning and take any of the
paths to its completion.
• Let us take an example of a date validation routine.
The date is accepted as three fields mm, dd and yyyy.
We have assumed that prior to entering this routine,
the values are checked to be numeric.
• Path Coverage=(Total Paths exercised / Total number
of paths in program)*100
Flowchart for a date validation routine
There are different paths that can be taken through
the program.
• A
• B-D-G
• B-D-H
• B-C-E-G
• B-C-E-H
• B-C-F-G
• B-C-F-H
Condition coverage
• In the above example, even if we have covered all the paths possible, it would not
mean that the program is fully tested. For example, we can make the program
take the path A by giving a value less than 1 (for example, 0) to mm and find that
we have covered the path A and the program has detected that the month is
invalid.
• But, the program may still not be correctly testing for the other condition namely
mm > 12.
• It is necessary to have test cases that exercise each Boolean expression and have
test cases test produce the TRUE as well as FALSE paths.
• Condition Coverage = (Total decisions exercised / Total number of decisions in
program ) * 100
• The condition coverage, as defined by the formula along side in the margin gives
an indication of the percentage of conditions covered by a set of test cases.
Condition coverage is a much stronger criteria than path coverage, which in turn
is a much stronger criteria than statement coverage.
Function coverage
• This is a new addition to structural testing to identify how many program functions
• Function Coverage = (Total functions exercised / Total number of functions in program)
* 100
• The advantages that function coverage provides over the other types of coverage are as
follows.
1. Functions are easier to identify in a program and hence it is easier to write test cases
to provide function coverage.
2. Since functions are at a much higher level of abstraction than code, it is easier to
achieve 100 percent function coverage than 100 percent coverage in any of the earlier
methods.
3. Functions have a more logical mapping to requirements and hence can provide a
more direct correlation to the test coverage of the product.
4. Since functions are a means of realizing requirements, the importance of functions
can be prioritized based on the importance of the requirements they realize. Thus, it
would be easier to prioritize the functions for testing. This is not necessarily the case
with the earlier methods of coverage.
5. Function coverage provides a natural transition to black box testing.
Code Complexity Testing
• Different types of coverage that can be provided to test a
program. Two questions that come to mind while using these
coverage are:
1. Which of the paths are independent? If two paths are not
independent, then we may be able to minimize the number of
tests.
2. Is there an upper bound on the number of tests that must be
run to ensure that all the statements have been executed at
least once?
• Cyclomatic complexity is a metric that quantifies the complexity
of a program and thus provides answers to the above questions.
• A program is represented in the form of a flow graph. A flow graph consists of nodes
and edges. In order to convert a standard flow chart into a flow graph to compute
cyclomatic complexity, the following steps can be taken.
1. Identify the predicates or decision points (typically the Boolean conditions or
conditional statements) in the program.
2. Ensure that the predicates are simple (that is, no and/or, and so on in each predicate).
If there are loop constructs, break the loop termination checks into simple predicates.
3. Combine all sequential statements into a single node. The reasoning here is that these
statements all get executed, once started.
4. When a set of sequential statements are followed by a simple predicate (as simplified
in (2) above), combine all the sequential statements and the predicate check into one
node and have two edges emanating from this one node. Such nodes with two edges
emanating from them are called predicate nodes.
5. Make sure that all the edges terminate at some node; add a node to represent all the
sets of sequential statements at the end of the program
Flow graph translation of an OR to a simple
predicate.
Converting a conventional flow chart to a
flow graph.
A hypothetical program with no decision
node.
This graph has no predicate nodes because there are no decision points. Hence, the
cyclomatic complexity is also equal to the number of predicate nodes (0) + 1.
Note that in this flow graph, the edges (E) = 1; nodes (N) = 2. The cyclomatic
complexity is also equal to 1 = 1 + 2 – 2 = E – N + 2.
Adding one decision node
• Test Cases for Valid partition value, Invalid partition value and exact
boundary value
• Test Cases 1: Consider password length less than 8.
• Test Cases 2: Consider password of length exactly 8.
• Test Cases 3: Consider password of length between 9 and 11.
• Test Cases 4: Consider password of length exactly 12.
• Test Cases 5: Consider password of length more than 12.
EXAMPLE 2 FOR BVA
• Test cases for the application whose input box accepts numbers between
1-1000
- Valid range 1-1000
- Invalid range 0 and
- Invalid range 1001 or more
• Test Cases for Valid partition value, Invalid partition value and exact boundary
value.
• Test Cases 1: Consider test data exactly as the input boundaries of
input domain i.e. values 1 and 1000
• Test Cases 2: Consider test data with values just below the extreme
edges of input domains i.e. values 0 and 999
• Test Cases 3: Consider test data with values just above the extreme edges of
input domain i.e. values 2 and 1001
• SINGLE FAULT ASSUMPTION
Assumes the ‘single fault’ or “independence of input
variables.”
• In addition to the 5 BVA values of variables includes, add values slightly greater
than the maximum (max+) and a value slightly less than the minimum (min-)
– Min – 1
– Min
– Min +1
– Nom Number of TC = 6n+1
– Max -1 6 Values
– Max n Number of Variables
1 Nom (Average Value)
– Max +1
• In some strongly typed languages values beyond the predefined range will cause a
run-time error
ROBUSTNESS TEST CASES FOR A FUNCTION
OF TWO VARIABLES
Min = 1
Min+ = 2
Nom = 100
Max- = 199
Max = 200
Min
Min+
Nom
Max-
Max
TEST CASE FOR NEXT DATE FUNCTION
Min
Min+
Nom
Max-
Max
Min
Min+
Nom
Max-
Max
EQUIVALENCE CLASS TESTING
CONS OF BVA
• Boundary Value Testing derives test cases with
Serious gaps
Massive redundancy
• Motivations for equivalence class testing are
Complete testing
Avoid redundancy
• Black Box Technique
• Utilizes a subset of data which is representative of a
larger class
• Equivalence partitioning involves partitioning of the
input domain of a software system into several
equivalent classes in a manner that the testing of
one particular representative from a class is
equivalent to the testing of some different value from
the subject class
• Applicability
– Program is a function from input to output
– Input and/or output variables have well defined intervals
DIFFERENCE BETWEEN BVA AND
EQUIVALENCE PARTITIONING
• The idea of equivalence class testing is to identify test
cases by using one element from each equivalence class
• If the equivalence classes are chosen wisely, the
potential redundancy among test cases can be reduced
• [ Closed Interval Includes end-points
• ) Open Interval Does not include end-points
20
For ( X2, X1 )
10 we have:
(24, 2)
(15, 8 )
1 ( 4, 13)
X1 (23, 17)
1 5 10 15 20
X2
30
10
1
X1
1 5 10 15 20
X2
30
We have covered
20 everyone of the 5
equivalence classes for
input X.
10
1
X1
1 5 10 15 20
30
We have covered everyone of
the 5 x 6 Cartesian product of
equivalence classes (including
20 invalid inputs)
10
1
Y
1 5 10 15 20
Four weak normal equivalence class test cases, chosen arbitrarily from each
class.No subintervals exist for a,b,c so WN=SN
WEAK ROBUST TEST CASES
The invalid
values could be
- Zero (0)
- Any Negative
Number (-ve)
- Any number
>200
D6 will become:
D6’={<a,b,c>:a=b+c}
D6”={<a,b,c>:a>b+c}