Download as pdf or txt
Download as pdf or txt
You are on page 1of 24

Question

Procedure Average:
i = 1;
total.input = total.valid = 0;
sum = 0;
DO WHILE value[i] <> -999 AND total.input < 100
increment total.input by 1;
IF value[i] >= minimum AND value[i] <= maximum
THEN increment total.valid by 1;
sum = sum + value[i];
ELSE skip
ENDIF
increment i by 1;
ENDDO
IF total.valid > 0
THEN average = sum/total.valid;
ELSE average = -999;
ENDIF
END Average;

Answer
Procedure Average:
i = 1; (1)
total.input = total.valid = 0;
sum = 0;
WHILE value[i] <> -999 (2) AND total.input < 100 (3)
increment total.input by 1; (4)
IF value[i] >= minimum (5) AND value[i] <= maximum (6)
THEN increment total.valid by 1; (7)
sum = sum + value[i];
ELSE skip
ENDIF (8)
increment i by 1;
ENDDO (9)
IF total.valid > 0 (10)
THEN average = sum/total.valid; (11)
ELSE average = -999; (12)
ENDIF (13)
END Average;
V(G) = 6 regions
V(G) = 17 edges - 13 nodes + 2 = 6
V(G) = 5 predicate nodes + 1 = 6

Path 1: 1-2-10-11-13
Path 2: 1-2-10-12-13
Path 3: 1-2-3-10-11-13
Path 4: 1-2-3-4-5-8-9-2-. . .
Path 5: 1-2-3-4-5-6-8-9-2-. . .
Path 6: 1-2-3-4-5-6-7-8-9-2-. . .
The ellipsis (. . .) following paths 4, 5, and 6 indicates that any path through the remainder of the
control structure is acceptable.

Q-1)
begin
int a, b, power; 1
float c; 2
input (a, b); 3
if (b < 0) 4
power = -b; 5
else
power = b; 6
c = 1; 7
while (power != 0) 8
{
c = c * a; 9
power = power – 1; 10
}
if (b < 0) 11
c = 1/c; 12
output(c); 13
end
V(G) = No of regions = 4
V(G) = No. of predicate nodes + 1 = 3 + 1 = 4
V(G) = E – N + 2 = 15 – 13 + 2 = 4

Path 1 : 1 – 2 – 3 – 4 – 5 – 7 – 8 – 9 – 10 – 8 – 11 – 12 – 13 – 14
Path 2 : 1 – 2 – 3 – 4 – 6 – 7 – 8 – 9 – 10 – 8 – 11 – 12 – 13 – 14
Path 3 : 1 – 2 – 3 – 4 – 6 – 7 – 8 – 11 – 12 – 13 – 14
Path 4 : 1 – 2 – 3 – 4 – 6 – 7 – 8 – 11 – 13 – 14

Q-2)
int binsearch(int X, int V[ ], int n) { 1
int low, high, mid; 2
low = 0; 3
high = n - 1; 4
while (low <= high) { 5
mid = (low + high)/2; 6
if (X < V[mid]) 7
high = mid - 1; 8
else if (X > V[mid]) 9
low = mid + 1; 10
else
return mid; 11
} 12
return -1; 13
}
Q-3)
1 begin
2 int staff_dis, markedPrice, amount, discountPrice, finalPrice
3 staff_dis = 0.1
4 markedPrice = 0
5 read (finalPrice)
6 while (finalPrice != -1) do
7 markedPrice = markedPrice + finalPrice
8 read (finalPrice)
9 end do while
10 print (markedPrice)
11 if (markedPrice > 25.00) then
12 discountPrice = (staff_dis * markedPrice) + 0.75
13 else
14 discountPrice = staff_dis * markedPrice
15 end if
16 print (discountPrice)
17 amount = totalPrice - discountPrice
18 print (amount)
19 end

V(G) = No of regions = 3
V(G) = No of predicate nodes + 1 = 2 + 1 = 3
V(G) = E – N + 2 = 19 = 19 – 18 + 2 = 3

Data Flow Testing [part of Control Structure Testing]


Data flow testing or analysis makes use of control flow graph to find unexpected things that
can happen to data (data flow anomalies). Data flow anomalies are detected based on
associations between values and variables. The declaration, initialization and usage of variables
play major role in data flow analysis.

Some terminologies used in data flow analysis are as follows:

 An occurrence of a variable in a program is a definition of the variable if its value is


bound to the variable at that occurrence. For example, statements like “read y” or
“y=10” are defining nodes for y.
 An occurrence of a variable in the program is a use of the variable if its value is referred
at that occurrence. For example, statements like “print x” and “b = 10 + x” will be usage
nodes for variable x.
 A use of a variable is a predicate use (p-use) if the variable is in a predicate and its
value is used to decide an execution path. For example, for a variable x, a statement
like if x > 10.
 A use of a variable is a computation use (c-use) if its value is used to compute a value
for defining another variable or as an output value i.e. used in a computation. For
example, for a variable x, a statement like c = 5 + x.
 A use of a variable is a location use (l-use) if its value is used in location index. For
example, to determine the array index, like arr[x] with respect to variable x.
 A use of a variable is an iteration use (i-use) if its value is used in controlling the number
of times loop is iterated. For example, for (x = 0; x < 10; x++) with respect to variable
x.
 A path (a, n1, n2, …, nm, b) is a definition clear path (dc-path) for a variable x from a to
b if n1 through nm do not contain a definition of x. Only at node a, defining node of x is
present.
 A path (a, n1, n2, …, nm, b) is a definition usage path (du-path) for a variable x from a
to b if n1 through nm do not contain a definition of x. Only at node a, defining node of
x is present and at later nodes, x is a usage node. Hence, for definition usage path to
occur, first it should be definition clear path.

Let us
1 begin
2 int staff_dis, markedPrice, amount, discountPrice, finalPrice
3 staff_dis = 0.1
4 markedPrice = 0
5 read (finalPrice)
6 while (finalPrice != -1) do
7 markedPrice = markedPrice + finalPrice
8 read (finalPrice)
9 end do while
10 print (markedPrice)
11 if (markedPrice > 25.00) then
12 discountPrice = (staff_dis * markedPrice) + 0.75
13 else
14 discountPrice = staff_dis * markedPrice
15 end if
16 print (discountPrice)
17 amount = totalPrice - discountPrice
18 print (amount)
19 end
understand with an example. Consider following algorithm:
Corresponding CFG would be as shown in Fig.3.12:

Figure 3.12 Control Flow Graph for Algorithm 2.

With respect to finalPrice variable, defining nodes will be (finalPrice, 5) and (finalPrice, 8).
Usage nodes will be (finalPrice, 6) and (finalPrice, 7).
Hence, definition usage paths will be DU (5, 6) , DU (5, 6, 7) , DU (8, 9, 6) and DU (8, 9, 6,
7). Definition clear paths will be the same as definition usage paths.

What is Code coverage?


Code coverage is a measure which describes the degree of which the source
code of the program has been tested. It is one form of white box testing which
finds the areas of the program not exercised by a set of test cases. It also
creates some test cases to increase coverage and determining a quantitative
measure of code coverage.

In most cases, code coverage system gathers information about the running
program. It also combines that with source code information to generate a
report about the test suite's code coverage.

Why use Code Coverage?


Here, are some prime reasons for using code coverage:
 It helps you to measure the efficiency of test implementation
 It offers a quantitative measurement.
 It defines the degree to which the source code has been tested.

Code Coverage Methods


Following are major code coverage methods

 Statement Coverage
 Condition Coverage
 Branch Coverage
 Condition Coverage

Statement Coverage
What is Statement Coverage?

Statement coverage is a white box test design technique which involves


execution of all the executable statements in the source code at least once.
It is used to calculate and measure the number of statements in the source
code which can be executed given the requirements.

Statement coverage is used to derive scenario based upon the structure of


the code under test.

In White Box Testing, the tester is concentrating on how the software works.
In other words, the tester will be concentrating on the internal working of
source code concerning control flow graphs or flow charts.

Generally in any software, if we look at the source code, there will be a wide
variety of elements like operators, functions, looping, exceptional handlers,
etc. Based on the input to the program, some of the code statements may
not be executed. The goal of Statement coverage is to cover all the possible
path's, line, and statement in the code.

Let's understand this with an example, how to calculate statement coverage.

Scenario to calculate Statement Coverage for given source code. Here we


are taking two different scenarios to check the percentage of statement
coverage for each scenario.
Source Code:

Prints (int a, int b) { ------------ Printsum is a function


int result = a+ b;
If (result> 0)
Print ("Positive", result)
Else
Print ("Negative", result)
} ----------- End of the source code

Scenario 1:

If A = 3, B = 9

The statements marked in yellow color are those which are executed as
per the scenario

Number of executed statements = 5, Total number of statements = 7

Statement Coverage: 5/7 = 71%

Likewise we will see scenario 2,

Scenario 2:

If A = -3, B = -9
The statements marked in yellow color are those which are executed as
per the scenario.

Number of executed statements = 6

Total number of statements = 7

Statement Coverage: 6/7 = 85%

But overall if you see, all the statements are being covered by 2nd scenario's
considered. So we can conclude that overall statement coverage is 100%.

What is covered by Statement Coverage?

1. Unused Statements
2. Dead Code
3. Unused Branches

Decision Coverage
Decision coverage reports the true or false outcomes of each Boolean
expression. In this coverage, expressions can sometimes get complicated.
Therefore, it is very hard to achieve 100% coverage.
That's why there are many different methods of reporting this metric. All
these methods focus on covering the most important combinations. It is very
much similar to decision coverage, but it offers better sensitivity to control
flow.

Example of decision coverage


Consider the following code-

Demo(int a) {
If (a> 5)
a=a*3
Print (a)
}

Scenario 1:

Value of a is 2

The code highlighted in yellow will be executed. Here the "No" outcome of
the decision If (a>5) is checked.

Decision Coverage = 50%

Scenario 2:

Value of a is 6
The code highlighted in yellow will be executed. Here the "Yes" outcome of
the decision If (a>5) is checked.

Decision Coverage = 50%

Test Case Value of A Output Decision Coverage

1 2 2 50%

2 6 18 50%

Branch Coverage
In the branch coverage, every outcome from a code module is tested. For
example, if the outcomes are binary, you need to test both True and False
outcomes.

It helps you to ensure that every possible branch from each decision
condition is executed at least a single time.

By using Branch coverage method, you can also measure the fraction of
independent code segments. It also helps you to find out which is sections
of code don't have any branches.

The formula to calculate Branch Coverage:

Example of Branch Coverage


To learn branch coverage, let's consider the same example used earlier
Consider the following code

Demo(int a) {
If (a> 5)
a=a*3
Print (a)
}

Branch Coverage will consider unconditional branch as well

Test Case Value of A Output Decision Coverage Branch Coverage

1 2 2 50% 33%

2 6 18 50% 67%

Advantages of Branch coverage:

Branch coverage Testing offers the following advantages:

 Allows you to validate-all the branches in the code


 Helps you to ensure that no branched lead to any abnormality of the
program's operation
 Branch coverage method removes issues which happen because of
statement coverage testing
 Allows you to find those areas which are not tested by other testing
methods
 It allows you to find a quantitative measure of code coverage
 Branch coverage ignores branches inside the Boolean expressions

Condition Coverage
Conditional coverage or expression coverage will reveal how the variables
or subexpressions in the conditional statement are evaluated. In this
coverage expressions with logical operands are only considered.

For example, if an expression has Boolean operations like AND, OR, XOR,
which indicated total possibilities.

Conditional coverage offers better sensitivity to the control flow than decision
coverage. Condition coverage does not give a guarantee about full decision
coverage

The formula to calculate Condition Coverage:

Example:

For the above expression, we have 4 possible combinations

 TT
 FF
 TF
 FT

Consider the following input

X=3 (x<y) TRUE Condition Coverage is ¼ = 25%

Y=4

A=3 (a>b) FALSE

B=4

Which Type of Code Coverage to Choose


This is certainly the most difficult answer to give. The higher the probability
that defects will cause costly production failures, the more severe the level
of coverage you need to choose.
Advantages of Using Code Coverage
 Helpful to evaluate a quantitative measure of code coverage
 It allows you to create extra test cases to increase coverage
 It allows you to find the areas of a program which is not exercised by
a set of test cases

Disadvantages of Using Code Coverage


 Even when any specific feature is not implemented in design, code
coverage still report 100% coverage.
 It is not possible to determine whether we tested all possible values
of a feature with the help of code coverage
 Code coverage is also not telling how much and how well you have
covered your logic
 In the case when the specified function hasn't implemented, or a not
included from the specification, then structure-based techniques

Program Slicing
Program slicing is a technique which allows the programmer/tester to focus on only relevant
part of the source code that does a specific computation or needs focus of testing. Hence, from
the entire source, slice the code which should be tested for a behaviour, to make the focus
smaller rather than dealing the entire source code which might have irrelevant statements with
respect to the test cases. In this way, the sliced code will be a subset of the actual source code.
For example, your source code computes wrong value of a variable y at some line number 200,
though the statement at line 200 is correct. How can you minimize the number of statements to
investigate?
Solution is only focus of computation of statements that influence the value of variable y and
skip the rest.

Program slicing is a technique of debugging, testing and software maintenance. Two different
types of program slicing are: Static slicing and dynamic slicing.

 Static slicing: Static slicing is done for a statically available information only. Static
slicing on a program consists of all executable statements in program that affects the
variable value in a statement s for any possible input. It is defined as slicing criteria, C
= (s, v) where s is a statement in program P and v is a variable in s. Static slices are
computed by backtracking the dependencies. In order to compute the static slice for (s,
v), we need to find all the program statements that directly affects the value of v before
encountering statement s. Recursively, each statement si with a variable vi that
transitively affects the value of variable v will also be added in the slice.

For example, consider the following algorithm:


1 read (no)
2 i=1
3 add = 0
4 prod = 1
5 while (i < = no) do
6 add = add + i
7 prod = prod * i
8 i=i+1
9 end do
10 write (add)
11 write (prod)

Algorithm 3.4

Now, let’s consider, we want to compute slice for C = (write (prod), prod) i.e. C = (11,
prod). Line number 4 and 7 are directly affecting the value of prod. And variable i and no are
indirectly affecting the value of prod. Hence, the slice for C = (write (prod), prod) will be as
follows:

1 read (no) This will be under the classification of backward


2 i=1 slicing as we are backtracking the statements that
4 prod = 1 affect the value of prod from line number 11. So,
5 while (i < = no) do backward slice of S contains all the statements that
7 prod = prod * i S would transitively depend upon.
8 i=i+1
9 end do
11 write (prod)

Consider another example where we want to compute slice for C = (3, add). This will be under
the classification of forward slicing as add present in line number 3 will be affected by which
statements in future. So, forward slice of S contains all the statements that transitively depend
on S.

 Dynamic slicing: A dynamic slice contains all executable statements at a program point
p for a particular execution e of the program that actually affects the value of a variable
v rather than all statements that may have affected the variable value at a program point
p for any arbitrary execution of the program.

Slicing criterion, here will be, C = (i, v, p) where i is input, v is a variable and p is a
program point. The slicing uses the execution history of the program for an input i.
Consider the following algorithm:
1 read (n)
2 for i = 1 to n do
3 x = 10
4 if condition1 then
5 if condition2 then
6 x = 20
7 else
8 x = 30
9 result = x
10 write (result)

Algorithm 3.5

Let’s compute dynamic slice for criterion C = (1, result, 101)


where 1 is input (i.e. value of n)
10 being line number i.e. write (result)
result being the variable that is getting affected
101 means line number 10 with variable result with input value n = 1

Assuming condition1 and condition2 both are true, the execution history will be all the
statements that are getting executed for the value of n = 1, which are line 1, 2, 3, 4, 5, 6, 9 and
later goes back to line 2 where value of i will be incremented to 2 which fails the condition (i
< n) for loop, hence, execution history jumps to line 10 directly.

Now, out of the execution history, which lines actually affect the value of variable result will
be a part of dynamic slice.

1 read (n)
2 for i = 1 to n do
4 if condition1 then
5 if condition2 then
6 x = 20
9 result = x
10 write (result)

Difference between static slicing and dynamic slicing:


As clearly seen in example, considering if and else block, static slicing will not check the
execution of the program (whether if or else) and will take all the program statements that
affects the value of a variable v (from both if as well as else). Whereas in case of dynamic
slicing, it takes into consideration the execution of the program and only considers affected
statement from that execution (either from if or else as per the execution flow).
To clearly understand, let us consider the Algorithm 3.5 with input n = 1 and assuming
condition1 and condition2 are true, let’s compute static as well as dynamic slices.
Static slice, C = (10, result) Dynamic slice, C = (1, result, 101)

1 read (n) 1 read (n)


2 for i = 1 to n do 2 for i = 1 to n do
3 x = 10 4 if condition1 then
4 if condition1 then 5 if condition2 then
5 if condition2 then 6 x = 20
6 x = 20 9 result = x
7 else 10 write (result)
8 x = 30
9 result = x
10 write (result)

Hence, this reduces the time of the developer/tester to execute the test cases by constricting the
focus of analysis.

BLACK BOX TESTING

Boundary Value Analysis & Equivalence Partitioning


with Examples
What is Boundary Testing?

Boundary testing is the process of testing between extreme ends or boundaries


between partitions of the input values.

 So these extreme ends like Start- End, Lower- Upper, Maximum-Minimum, Just
Inside-Just Outside values are called boundary values and the testing is called
"boundary testing".
 The basic idea in boundary value testing is to select input variable values at
their:

1. Minimum
2. Just above the minimum
3. A nominal value
4. Just below the maximum
5. Maximum
 In Boundary Testing, Equivalence Class Partitioning plays a good role
 Boundary Testing comes after the Equivalence Class Partitioning.

What is Equivalent Class Partitioning?

Equivalent Class Partitioning is a black box technique (code is not visible to tester)
which can be applied to all levels of testing like unit, integration, system, etc. In this
technique, you divide the set of test condition into a partition that can be considered
the same.

 It divides the input data of software into different equivalence data classes.
 You can apply this technique, where there is a range in the input field.

Example 1: Equivalence and Boundary Value

 Let's consider the behavior of Order Pizza Text Box Below


 Pizza values 1 to 10 is considered valid. A success message is shown.
 While value 11 to 99 are considered invalid for order and an error message
will appear, "Only 10 Pizza can be ordered"

Submit
Order Pizza:

Here is the test condition

1. Any Number greater than 10 entered in the Order Pizza field(let say 11) is
considered invalid.
2. Any Number less than 1 that is 0 or below, then it is considered invalid.
3. Numbers 1 to 10 are considered valid
4. Any 3 Digit Number say -100 is invalid.

We cannot test all the possible values because if done, the number of test cases will
be more than 100. To address this problem, we use equivalence partitioning
hypothesis where we divide the possible values of tickets into groups or sets as
shown below where the system behavior can be considered the same.
The divided sets are called Equivalence Partitions or Equivalence Classes. Then we
pick only one value from each partition for testing. The hypothesis behind this
technique is that if one condition/value in a partition passes all others will also
pass. Likewise, if one condition in a partition fails, all other conditions in that
partition will fail.

Boundary Value Analysis- in Boundary Value Analysis, you test boundaries


between equivalence partitions

In our earlier example instead of checking, one value for each partition you will check
the values at the partitions like 0, 1, 10, 11 and so on. As you may observe, you test
values at both valid and invalid boundaries. Boundary Value Analysis is also
called range checking.

Equivalence partitioning and boundary value analysis(BVA) are closely related and
can be used together at all levels of testing.

Example 2: Equivalence and Boundary Value


Following password field accepts minimum 6 characters and maximum 10
characters

That means results for values in partitions 0-5, 6-10, 11-14 should be equivalent

Submit
Enter Password:

Test Scenario # Test Scenario Description Expected Outcome

1 Enter 0 to 5 characters in password field System should not accept

2 Enter 6 to 10 characters in password field System should accept

3 Enter 11 to 14 character in password field System should not accept

Examples 3: Input Box should accept the Number 1 to 10

Here we will see the Boundary Value Test Cases

Test Scenario Description Expected Outcome

Boundary Value = 0 System should NOT accept

Boundary Value = 1 System should accept

Boundary Value = 2 System should accept

Boundary Value = 9 System should accept

Boundary Value = 10 System should accept

Boundary Value = 11 System should NOT accept

Why Equivalence & Boundary Analysis Testing


1. This testing is used to reduce a very large number of test cases to manageable
chunks.
2. Very clear guidelines on determining test cases without compromising on the
effectiveness of testing.
3. Appropriate for calculation-intensive applications with a large number of
variables/inputs

Summary:

 Boundary Analysis testing is used when practically it is impossible to test a large


pool of test cases individually
 Two techniques - Equivalence Partitioning & Boundary Value Analysis testing
techniques are used
 In Equivalence Partitioning, first, you divide a set of test condition into a partition
that can be considered.
 In Boundary Value Analysis you then test boundaries between equivalence
partitions
 Appropriate for calculation-intensive applications with variables that represent
physical quantities

Combinational Test Technique – Orthogonal Array Testing


Technique (OATS)

Combinational test technique, as the name suggests, is a technique of combining the data
/ entities as input parameters for testing, to increase the scope. This technique is beneficial
when we have to test with huge number data having many permutations and
combinations.

The beauty of this technique is that, it maximizes the coverage by comparatively lesser
number of test cases. The pairs of parameters which are identified should be independent
of each other. It’s a black box technique, so like other BB technique; we don’t need to
have the implementation knowledge of the system. The point here is to identify the correct
pair of input parameters.

There are many technique of CTD, where OATS (Orthogonal array testing
technique) is widely used.

How to use OATS?


Implementing OATS technique involves the below steps:

1. Identify the independent variables. These will be referred to as “Factors”


2. Identify the values which each variable will take. These will be referred as “Levels”
3. Search for an orthogonal array that has all the factors from step 1 and all the levels from
step 2
4. Map the factors and levels with your requirement
5. Translate them into the suitable test cases
6. Look out for the left over or special test cases (if any)
Let me demonstrate it with an example:
Orthogonal Array Testing Technique (OATS) example:
Let us consider you have to identify the test cases for a Web Page that has 4 sections:
Headlines, details, references and Comments, that can be displayed or not displayed or
show Error message. You are required to design the test condition to test the interaction
between different sections.

In this case:
1. Number of independent variables (factors) are = 4
2. Value that each variable can take = 3 values (displayed, not displayed and error
message)
3. Orthogonal array would be 34.
4. Google and find an appropriate array for 4 factors and 3 levels. For this example, I am
referencing the bellow table

5. Now, map this array with our requirements as below:


 1 will represent “Is Displayed” value
 2 will represent “not displayed” value
 3 will represent “error message value”
 Factor A will represent “ Headlines” section
 Factor B will represent “Details” section
 Factor C will represent “references ”section
 Factor D will represent “Comment” section.
 Experiment no will represent “Test Cases #”
6. After mapping, the table will look like:

7. Based on the table above, design your test cases. Also look out for the special test
cases / left over test cases.
Conclusion:
None of the testing technique provides a guarantee of 100% coverage. Each technique
has its own way of selecting the test conditions. In the similar lines, there are some
limitations of using this technique:
 Testing will fail if we fail to identify the good pairs.
 Probability of not identifying the most important combination which can result in
losing a defect.
 This technique will fail if we do not know the interactions between the pairs.
 Applying only this technique will not ensure the complete coverage.
 It can find only those defects which arise due to pairs, as input parameters.

You might also like