0% found this document useful (0 votes)
147 views

ST Lab File PDF

The document describes an experiment to generate test cases for a program that finds the maximum of three input numbers using the robust testing technique. It involves generating test cases that cover minimum, maximum, nominal and boundary values, as well as values just inside and outside the boundaries. The program, test case classes, and functions to generate test cases based on variable ranges are defined. The test cases are then generated, run against the program, and the results are printed. The experiment aims to learn how to generate robust test cases to thoroughly test the program.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
147 views

ST Lab File PDF

The document describes an experiment to generate test cases for a program that finds the maximum of three input numbers using the robust testing technique. It involves generating test cases that cover minimum, maximum, nominal and boundary values, as well as values just inside and outside the boundaries. The program, test case classes, and functions to generate test cases based on variable ranges are defined. The test cases are then generated, run against the program, and the results are printed. The experiment aims to learn how to generate robust test cases to thoroughly test the program.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 91

Experiment No: 1

Aim
Write a program to find the maximum in three numbers input by the user and generate test
cases for the program using Boundary Value Analysis.

Related Theory
It is a type of functional testing. It concentrates on minimum value, just above minimum,
maximum, just blow maximum and nominal value. Total no of Test cases= 4*n+1 where
n:total no of inputs

Algorithm
1. Identify the testing technique that is to be performed.
2. Identify the input variables.
3. Check whether that technique obeys Single Fault Assumption.
4. Write down the test cases.
5. Test the program.

Program

#include<iostream>
#include<vector>
#include<cstring>

using namespace std;

// Function to be tested
int find_min(int nums[] , int len){
int max = -99999999;

for (int i = 0; i < len; ++i)


{
if (nums[i] > max)
{
max = nums[i];
}
}

return max;
}

// Class for Single Testcase


struct Testcase {
int num_vars,*variables;
int eo;

Testcase(int num_vars , int* variables){


this->num_vars = num_vars;
this->variables = new int[num_vars];

memcpy(this->variables,variables,sizeof(int)*num_vars);
}

void run(){
this->eo = find_min(variables,num_vars);
}

void print_result(){
// Print the testcase
cout<<"Variables : ";
for (int i = 0; i < num_vars; ++i)
{
cout<<variables[i]<<" ";
}

cout<<"Expected Output : "<<eo<<endl;


}
};

// Class for TestSuite


struct Testsuite {
int num_cases;
std::vector<Testcase> cases;

Testsuite(){
num_cases = 0;
}

void add_testcase(Testcase testcase){


this->num_cases++;
this->cases.push_back(testcase);
}

void add_all(std::vector<Testcase> v){

num_cases += v.size();
for (std::vector<Testcase>::iterator i = v.begin(); i != v.end(); ++i)
{
this->cases.push_back(*i);
}

void run(){
for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)
{
(*i).run();
}
}

void print_results(){

cout<<"Number of Testcases : "<<this->num_cases<<endl;

for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)


{
(*i).print_result();
}

}
};

Testcase get_nominal_testcase(int num_vars, pair<int,int> ranges[]){


int variables[num_vars];
for (int i = 0; i < num_vars; ++i)
{
variables[i] = (ranges[i].second - ranges[i].first)/2;
}

return Testcase(num_vars,variables);
}

// Function to generate testcases


Testsuite generate_testcases(int num_vars , pair<int,int> ranges[])
{
Testsuite suite;

// Loop through all the variables one at a time


for (int i = 0; i < num_vars; ++i)
{
int variables[num_vars];
// Generate nominal values for the rest of the variables
for (int j = 0; j < num_vars; ++j)
{
if (i!=j)
{
variables[j] = (ranges[j].second - ranges[j].first)/2;
}
}

// Add values for the selected variable


std::vector<Testcase> v;

// 1. Minimum
variables[i] = ranges[i].first;
v.push_back(Testcase(num_vars,variables));
// 2. Minimum + 1
variables[i] = ranges[i].first + 1;
v.push_back(Testcase(num_vars,variables));

// 3. Maximum - 1
variables[i] = ranges[i].second-1;
v.push_back(Testcase(num_vars,variables));

// 4. Maximum
variables[i] = ranges[i].second;
v.push_back(Testcase(num_vars,variables));

suite.add_all(v);
}

// Add a nominal testcase


suite.add_testcase(get_nominal_testcase(num_vars,ranges));

return suite;
}

// Driver function
int main(int argc, char const *argv[])
{
int num_vars = 0;
cout<<"Enter number of variables : ";
cin>>num_vars;

pair<int,int> ranges[num_vars];
for (int i = 0; i < num_vars; ++i)
{
cout<<"Enter minimum and maximum value of variable "<<i+1<<" : ";
cin>>ranges[i].first>>ranges[i].second;
}

// Get the test suite


Testsuite suite = generate_testcases(num_vars , ranges);

// Run the test suite


suite.run();
suite.print_results();
return 0;
}
Output

Results and Discussions


We successfully generated the testcases for the given program using boundary value analysis.
Boundary value analysis is popular functional testing technique. In this technique, we
concentrate on input values and design test cases with input values that are on or close to
boundary values.

Learning and findings


In this experiment we learned how to generate testcases by using boundary value analysis
technique.
Experiment No: 2
Aim
Write a program to find the maximum in three numbers input by the user and generate test
cases for the program using Robust Approach.

Theory
It is a type of functional testing. It concentrates on minimum value, just above minimum,
maximum, just below maximum, nominal, just below minimum and just above maximum
value. Total no of Test cases= 6*n+1 where n:total no of inputs

Algorithm
1. Identify the testing technique that is to be performed .
2. Identify the input variables.
3. Check whther that technique obeys Single Fault Assumption.
4. Write down the test cases.
5. Test the program.

Program
#include<iostream>
#include<vector>
#include<cstring>

using namespace std;

// Function to be tested
int find_min(int nums[] , int len){
int max = -99999999;

for (int i = 0; i < len; ++i)


{
if (nums[i] > max)
{
max = nums[i];
}
}

return max;
}

// Class for Single Testcase


struct Testcase {
int num_vars,*variables;
int eo;

Testcase(int num_vars , int* variables){


this->num_vars = num_vars;
this->variables = new int[num_vars];

memcpy(this->variables,variables,sizeof(int)*num_vars);
}
void run(){
this->eo = find_min(variables,num_vars);
}

void print_result(){
// Print the testcase
cout<<"Variables : ";
for (int i = 0; i < num_vars; ++i)
{
cout<<variables[i]<<" ";
}

cout<<"Expected Output : "<<eo<<endl;


}
};

// Class for TestSuite


struct Testsuite {
int num_cases;
std::vector<Testcase> cases;

Testsuite(){
num_cases = 0;
}

void add_testcase(Testcase testcase){


this->num_cases++;
this->cases.push_back(testcase);
}

void add_all(std::vector<Testcase> v){

num_cases += v.size();
for (std::vector<Testcase>::iterator i = v.begin(); i != v.end(); ++i)
{
this->cases.push_back(*i);
}

void run(){
for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)
{
(*i).run();
}
}

void print_results(){

cout<<"Number of Testcases : "<<this->num_cases<<endl;

for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)


{
(*i).print_result();
}

}
};
Testcase get_nominal_testcase(int num_vars, pair<int,int> ranges[]){
int variables[num_vars];
for (int i = 0; i < num_vars; ++i)
{
variables[i] = (ranges[i].second - ranges[i].first)/2;
}

return Testcase(num_vars,variables);
}

// Function to generate testcases


Testsuite generate_testcases(int num_vars , pair<int,int> ranges[])
{
Testsuite suite;

// Loop through all the variables one at a time


for (int i = 0; i < num_vars; ++i)
{
int variables[num_vars];
// Generate nominal values for the rest of the variables
for (int j = 0; j < num_vars; ++j)
{
if (i!=j)
{
variables[j] = (ranges[j].second - ranges[j].first)/2;
}
}

// Add values for the selected variable


std::vector<Testcase> v;

// 1. Minimum - 1
variables[i] = ranges[i].first-1;
v.push_back(Testcase(num_vars,variables));

// 2. Minimum
variables[i] = ranges[i].first;
v.push_back(Testcase(num_vars,variables));

// 2. Minimum + 1
variables[i] = ranges[i].first + 1;
v.push_back(Testcase(num_vars,variables));

// 3. Maximum - 1
variables[i] = ranges[i].second-1;
v.push_back(Testcase(num_vars,variables));

// 4. Maximum
variables[i] = ranges[i].second;
v.push_back(Testcase(num_vars,variables));

// 5. Maximum + 1
variables[i] = ranges[i].second+1;
v.push_back(Testcase(num_vars,variables));

suite.add_all(v);
}

// Add a nominal testcase


suite.add_testcase(get_nominal_testcase(num_vars,ranges));
return suite;
}

// Driver function
int main(int argc, char const *argv[])
{
int num_vars = 0;
cout<<"Enter number of variables : ";
cin>>num_vars;

pair<int,int> ranges[num_vars];
for (int i = 0; i < num_vars; ++i)
{
cout<<"Enter minimum and maximum value of variable "<<i+1<<" : ";
cin>>ranges[i].first>>ranges[i].second;
}

// Get the test suite


Testsuite suite = generate_testcases(num_vars , ranges);

// Run the test suite


suite.run();
suite.print_results();
return 0;
}

Output

Results and discussions


We successfully generated the testcases for the given program using robust approach. This is
the extension of boundary value analysis. In this case we also consider invalid values. Invalid
values are also important to check the behaviour of the program. The total test cases in
robustness testing are 6n+1.

Learning and findings


In this experiment we learned how to generate testcases by using robust testing.
Experiment No: 3
Aim
Write a program to find the maximum in three numbers input by the user and generate test
cases for the program using Worst Boundary Value Analysis.

Theory
It is a type of functional testing. It concentrates on minimum value, just above minimum,
maximum, just below maximum and nominal value for each input variable. It does not obey
Single Fault Assumption. Total no of Test cases= 5n where n:total no of input

Algorithm
1. Identify the testing technique that is to be performed .
2. Identify the input variables.
3. Check whther that technique obeys Single Fault Assumption.
4. Write down the test cases.
5. Test the program.

Program

#include<iostream>
#include<vector>
#include<cstring>

using namespace std;

// Function to be tested
int find_min(int nums[] , int len){
int max = -99999999;

for (int i = 0; i < len; ++i)


{
if (nums[i] > max)
{
max = nums[i];
}
}

return max;
}

// Class for Single Testcase


struct Testcase {
int num_vars,*variables;
int eo;

Testcase(int num_vars , int* variables){


this->num_vars = num_vars;
this->variables = new int[num_vars];

memcpy(this->variables,variables,sizeof(int)*num_vars);
}

void run(){
this->eo = find_min(variables,num_vars);
}

void print_result(){
// Print the testcase
cout<<"Variables : ";
for (int i = 0; i < num_vars; ++i)
{
cout<<variables[i]<<" ";
}

cout<<"Expected Output : "<<eo<<endl;


}
};

// Class for TestSuite


struct Testsuite {
int num_cases;
std::vector<Testcase> cases;

Testsuite(){
num_cases = 0;
}

void add_testcase(Testcase testcase){


this->num_cases++;
this->cases.push_back(testcase);
}

void add_all(std::vector<Testcase> v){

num_cases += v.size();
for (std::vector<Testcase>::iterator i = v.begin(); i != v.end(); ++i)
{
this->cases.push_back(*i);
}

void run(){
for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)
{
(*i).run();
}
}

void print_results(){

cout<<"Number of Testcases : "<<this->num_cases<<endl;

for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)


{
(*i).print_result();
}

}
};

// Function to generate testcases


Testsuite generate_testcases(int num_vars , pair<int,int> ranges[] , int variables[], int i,
Testsuite &suite)
{
// Base Case
if (i == num_vars)
{
suite.add_testcase(Testcase(num_vars,variables));
return suite;
}

// 2. Minimum
variables[i] = ranges[i].first;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 3. Minimum + 1
variables[i] = ranges[i].first + 1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 4. Nominal
variables[i] = (ranges[i].second - ranges[i].first)/2;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 5. Maximum - 1
variables[i] = ranges[i].second-1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 6. Maximum
variables[i] = ranges[i].second;
generate_testcases(num_vars,ranges,variables,i+1,suite);

return suite;
}
// Driver function
int main(int argc, char const *argv[])
{
int num_vars = 0;
cout<<"Enter number of variables : ";
cin>>num_vars;

pair<int,int> ranges[num_vars];
for (int i = 0; i < num_vars; ++i)
{
cout<<"Enter minimum and maximum value of variable "<<i+1<<" : ";
cin>>ranges[i].first>>ranges[i].second;
}

// Get the test suite


Testsuite suite;
int variables[num_vars];

suite = generate_testcases(num_vars , ranges ,variables, 0, suite);

// Run the test suite


suite.run();
suite.print_results();
return 0;
}
Output

Results and Discussions


We successfully generated the testcases for the given program using Worst-Case testing. This
is a special form of boundary value analysis where we don’t consider the ‘single fault’
assumption theory of reliability. The no of testcases will be 5n.

Learning and findings


In this experiment we learned how to generate testcases by using worst case testing
technique.
Experiment No: 4
Aim
Write a program to find the maximum in three numbers input by the user and generate test
cases for the program using Worst Robust Approach.

Theory
It is a type of functional testing. It concentrates on minimum value, just above minimum,
maximum, just below maximum, nominal, just below minimum and just above maximum
value for each input variable. It does not obey Single Fault Assumption. Total no of Test
cases= 7n where n:total no of input

Algorithm
1. Identify the testing technique that is to be performed .
2. Identify the input variables.
3. Check whther that technique obeys Single Fault Assumption.
4. Write down the test cases.
5. Test the program.

Program
#include<iostream>
#include<vector>
#include<cstring>

using namespace std;

// Function to be tested
int find_min(int nums[] , int len){
int max = -99999999;

for (int i = 0; i < len; ++i)


{
if (nums[i] > max)
{
max = nums[i];
}
}

return max;
}

// Class for Single Testcase


struct Testcase {
int num_vars,*variables;
int eo;

Testcase(int num_vars , int* variables){


this->num_vars = num_vars;
this->variables = new int[num_vars];

memcpy(this->variables,variables,sizeof(int)*num_vars);
}

void run(){
this->eo = find_min(variables,num_vars);
}

void print_result(){
// Print the testcase
cout<<"Variables : ";
for (int i = 0; i < num_vars; ++i)
{
cout<<variables[i]<<" ";
}

cout<<"Expected Output : "<<eo<<endl;


}
};

// Class for TestSuite


struct Testsuite {
int num_cases;
std::vector<Testcase> cases;

Testsuite(){
num_cases = 0;
}

void add_testcase(Testcase testcase){


this->num_cases++;
this->cases.push_back(testcase);
}

void add_all(std::vector<Testcase> v){

num_cases += v.size();
for (std::vector<Testcase>::iterator i = v.begin(); i != v.end(); ++i)
{
this->cases.push_back(*i);
}

void run(){
for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)
{
(*i).run();
}
}

void print_results(){

cout<<"Number of Testcases : "<<this->num_cases<<endl;

for (std::vector<Testcase>::iterator i = cases.begin(); i != cases.end(); ++i)


{
(*i).print_result();
}

}
};

// Function to generate testcases


Testsuite generate_testcases(int num_vars , pair<int,int> ranges[] , int variables[], int i,
Testsuite &suite)
{
// Base Case
if (i == num_vars)
{
suite.add_testcase(Testcase(num_vars,variables));
return suite;
}

// 1. Minimum - 1
variables[i] = ranges[i].first-1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 2. Minimum
variables[i] = ranges[i].first;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 3. Minimum + 1
variables[i] = ranges[i].first + 1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 4. Nominal
variables[i] = (ranges[i].second - ranges[i].first)/2;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 5. Maximum - 1
variables[i] = ranges[i].second-1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

// 6. Maximum
variables[i] = ranges[i].second;
generate_testcases(num_vars,ranges,variables,i+1,suite);
// 7. Maximum + 1
variables[i] = ranges[i].second+1;
generate_testcases(num_vars,ranges,variables,i+1,suite);

return suite;
}

// Driver function
int main(int argc, char const *argv[])
{
int num_vars = 0;
cout<<"Enter number of variables : ";
cin>>num_vars;

pair<int,int> ranges[num_vars];
for (int i = 0; i < num_vars; ++i)
{
cout<<"Enter minimum and maximum value of variable "<<i+1<<" : ";
cin>>ranges[i].first>>ranges[i].second;
}

// Get the test suite


Testsuite suite;
int variables[num_vars];

suite = generate_testcases(num_vars , ranges ,variables, 0, suite);

// Run the test suite


suite.run();
suite.print_results();
return 0;
}
Output

Results and Discussions


We successfully generated the testcases for the given program using Robust worst-case
testing. In this technique we added two more states i.e. just below minimum value and just
above maximum value. We also considered invalid inputs. The no of test case generated is 7n.

Learning and findings


In this experiment we learned how to generate testcases by using Robus Worst-Case Testing
technique.
Experiment No: 5
Aim
Write a program to find the type of the triangle on the basis of sides input by the user and
generate test cases to test the program using Equivalance Class Testing.

Theory
It is a type of functional testing. The input domain is divided into various categories with
some relationship and it is expected that every test case from a category exhibits the same
behaviour. Each category is called an Equivalence class.

Algorithm
1. Identify the input domain and output domain.
2. Write the equivalence classes for both input and output domain.
3. Test the program using these equivalence classes.

Program
#include<iostream>
#include<conio.h>

using namespace std;

/* Function to check the type of the triangle


Input: 3 vertices
Output:
-1 - Inavlid input
0 - Equilateral triangle
1 - Isoscles triangle
2 - Scalene triangle
3 - Not a triangle
*/

int triangle(int a[3], int min[3], int max[3])


{
for(int i=0;i<3;i++)
if(a[i]<min[i] || a[i]>max[i])
return -1;

if(a[0]+a[1]>a[2] && a[1]+a[2]>a[0] && a[2]+a[0]>a[1])


{
if(a[0]==a[1] && a[1]==a[2] && a[2]==a[0])
return 0;
else if(a[0]==a[1] || a[1]==a[2] || a[2]==a[0])
return 1;
else
return 2;
}
else
return 3;
}

string inputClass[20], outputClass[4];


void generateClasses()
{
inputClass[0] = "{x : x<xmin}";
inputClass[1] = "{x : x>xmax}";
inputClass[2] = "{x : xmin<x<xmax}";
inputClass[3] = "{y : y<ymin}";
inputClass[4] = "{y : y>ymax}";
inputClass[5] = "{y : ymin<y<ymax}";
inputClass[6] = "{z : z<zmin}";
inputClass[7] = "{z : z>zmax}";
inputClass[8] = "{z : zmin<z<zmax}";
inputClass[9] = "{x,y,z : x=y=z}";
inputClass[10] = "{x,y,z : x=y,x!=z}";
inputClass[11] = "{x,y,z : x=z,x!=y}";
inputClass[12] = "{x,y,z : y=z,x!=y}";
inputClass[13] = "{x,y,z : x!=y!=z}";
inputClass[14] = "{x,y,z : x=y+z}";
inputClass[15] = "{x,y,z : x>y+z}";
inputClass[16] = "{x,y,z : y=x+z}";
inputClass[17] = "{x,y,z : y>x+z}";
inputClass[18] = "{x,y,z : z=x+y}";
inputClass[19] = "{x,y,z : z>x+y}";

outputClass[0] = "Equilateral Triangle";


outputClass[1] = "Isoscles Triangle";
outputClass[2] = "Scalene Triangle";
outputClass[3] = "Not a Triangle";
}

void equivalenceTesting(int min[3], int max[3])


{
int expOut[24], testCases[24][3], i=0, x=0, y=0, z=0;

generateClasses();

cout<<"\nInput Classes...";
for(i=0;i<20;i++)
cout<<"\nI"<<i<<": "<<inputClass[i];

cout<<"\n\nOutput Classes...";
for(i=0;i<4;i++)
cout<<"\nO"<<i<<": "<<outputClass[i];

//for input equivalance class


for(i=0;i<20;i++)
{
switch(i)
{
case 0: x=min[0]-1; y=(min[1]+max[1])/2; z=(min[2]+max[2])/2;
break;
case 1: x=max[0]+1; y=(min[1]+max[1])/2; z=(min[2]+max[2])/2;
break;
case 2: x=(min[0]+max[0])/2; y=(min[1]+max[1])/2; z=(min[2]+max[2])/2;
break;
case 3: y=min[1]-1; x=(min[0]+max[0])/2; z=(min[2]+max[2])/2;
break;
case 4: y=max[1]+1; x=(min[0]+max[0])/2; z=(min[2]+max[2])/2;
break;
case 5: y=(min[1]+max[1])/2; x=(min[0]+max[0])/2; z=(min[2]+max[2])/2;
break;
case 6: z=min[0]-1; y=(min[1]+max[1])/2; x=(min[0]+max[0])/2;
break;
case 7: z=max[0]+1; y=(min[1]+max[1])/2; x=(min[0]+max[0])/2;
break;
case 8: z=(min[2]+max[2])/2; y=(min[1]+max[1])/2; x=(min[0]+max[0])/2;
break;
case 9: x=y=z=60;
break;
case 10: x=y=60; z=(min[2]+max[2])/2;
break;
case 11: x=z=60; y=(min[1]+max[1])/2;
break;
case 12: y=z=60; z=(min[0]+max[0])/2;
break;
case 13: x=40; y=60; z=80;
break;
case 14: y=(min[1]+max[1])/2; z=(min[2]+max[2])/2; x=y+z;
break;
case 15: y=(min[1]+max[1])/2; z=(min[2]+max[2])/2; x=y+z+1;
break;
case 16: x=(min[0]+max[0])/2; z=(min[2]+max[2])/2; y=x+z;
break;
case 17: x=(min[0]+max[0])/2; z=(min[2]+max[2])/2; y=x+z+1;
break;
case 18: y=(min[1]+max[1])/2; x=(min[0]+max[0])/2; z=x+y;
break;
case 19: y=(min[1]+max[1])/2; x=(min[0]+max[0])/2; z=x+y+1;
break;
}
testCases[i][0]=x; testCases[i][1]=y; testCases[i][2]=z;
}

//for output equivalance class


for( ;i<24;i++)
{
switch(i-20)
{
case 0: x=y=z=60;
break;
case 1: x=y=60; z=70;
break;
case 2: x=50; y=60; z=70;
break;
case 3: x=20; y=60; z=100;
break;
}
testCases[i][0]=x; testCases[i][1]=y; testCases[i][2]=z;
}

cout<<"\n\nTest Cases...";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";
cout<<"\n|\t\t Input\t\t\t| Expected\t\t|";
cout<<"\n|\ta\t\tb\t\tc\t| Output\t\t|";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+\n";
for(int i=0;i<24;i++)
{
for(int j=0;j<3;j++)
{
if(j==0) cout<<"|";
cout<<"\t"<<testCases[i][j]<<"\t|";
}
int expOut=triangle(testCases[i],min,max);
if(expOut<0)
cout<<" Invalid input\t";
else cout<<" "<<outputClass[expOut];
cout<<"\t|"<<endl;
}
cout<<"+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";
cout<<"\n>>No. of Test Cases = "<<sizeof(inputClass)/sizeof(inputClass[0]) +
sizeof(outputClass)/sizeof(outputClass[0]);
}

int main()
{
int min[3], max[3];

for(int i=0;i<3;i++)
{
cout<<"Enter min & max value of vertex "<<i+1<<" : ";
cin>>min[i]>>max[i];
}
equivalenceTesting(min,max);
return 0;
}

Output
Enter min & max value of vertex 1 : 1 100
Enter min & max value of vertex 2 : 2 80
Enter min & max value of vertex 3 : 1 50

Input Classes...
I0: {x : x<xmin}
I1: {x : x>xmax}
I2: {x : xmin<x<xmax}
I3: {y : y<ymin}
I4: {y : y>ymax}
I5: {y : ymin<y<ymax}
I6: {z : z<zmin}
I7: {z : z>zmax}
I8: {z : zmin<z<zmax}
I9: {x,y,z : x=y=z}
I10: {x,y,z : x=y,x!=z}
I11: {x,y,z : x=z,x!=y}
I12: {x,y,z : y=z,x!=y}
I13: {x,y,z : x!=y!=z}
I14: {x,y,z : x=y+z}
I15: {x,y,z : x>y+z}
I16: {x,y,z : y=x+z}
I17: {x,y,z : y>x+z}
I18: {x,y,z : z=x+y}
I19: {x,y,z : z>x+y}

Output Classes...
O0: Equilateral Triangle
O1: Isoscles Triangle
O2: Scalene Triangle
O3: Not a Triangle

Test Cases...
+-----------------------------------------------------------------------+
| Input | Expected |
| a b c | Output |
+-----------------------------------------------------------------------+
| 0 | 41 | 25 | Invalid input |
| 101 | 41 | 25 | Invalid input |
| 50 | 41 | 25 | Scalene Triangle |
| 50 | 1 | 25 | Invalid input |
| 50 | 81 | 25 | Invalid input |
| 50 | 41 | 25 | Scalene Triangle |
| 50 | 41 | 0 | Invalid input |
| 50 | 41 | 101 | Invalid input |
| 50 | 41 | 25 | Scalene Triangle |
| 60 | 60 | 60 | Invalid input |
| 60 | 60 | 25 | Isoscles Triangle |
| 60 | 41 | 60 | Invalid input |
| 60 | 60 | 50 | Isoscles Triangle |
| 40 | 60 | 80 | Invalid input |
| 66 | 41 | 25 | Not a Triangle |
| 67 | 41 | 25 | Not a Triangle |
| 50 | 75 | 25 | Not a Triangle |
| 50 | 76 | 25 | Not a Triangle |
| 50 | 41 | 91 | Invalid input |
| 50 | 41 | 92 | Invalid input |
| 60 | 60 | 60 | Invalid input |
| 60 | 60 | 70 | Invalid input |
| 50 | 60 | 70 | Invalid input |
| 20 | 60 | 100 | Invalid input |
+-----------------------------------------------------------------------+
>>No. of Test Cases = 24

Results and Discussions


We successfully generated the testcases for the given program using equivalence class
testing. In this case we divide input domain into various categories with some relationship
and expect that every test case from a category exhibits the same behaviour. Each category is
called an equivalence class and type of testing is called equivalence class testing.

Learning and findings


In this experiment we learned how to generate testcases by using Equivalance class testing.
Experiment No: 6
Aim: Write a program to find the type of the triangle on the basis of sides input by the user
and generate test cases to test the program using Decision Table Testing.

Related Theory :

The techniques of equivalence partitioning and boundary value analysis are often applied to
specific situations or inputs. However, if different combinations of inputs result in different
actions being taken, this can be more difficult to show using equivalence partitioning and
boundary value analysis, which tend to be more focused on the user interface. Decision tables
are used in many engineering disciplines to represent complex logical relationships. An
output may be dependent on many input conditions and decision tables give a pictorial view
of various combinations of input conditions

The four parts of the decision table are given as:

Condition Stubs: All the conditions are represented in this upper left section of the decision
table. These conditions are used to determine a particular action or set of actions.

Action Stubs: All possible actions are listed in this lower left portion of the decision table.

Condition Entries: In the condition entries portion of the decision table, we have a number of
columns and each column represents a rule. Values entered in this upper right portion of the
table are known as inputs

Action Entries: Each entry in the action entries portion has some associated action or set of
actions in this lower right portion of the table. These values are known as outputs and are
dependent upon the functionality of the program.

Algorithm:

1) The first task is to identify a suitable function or subsystem which reacts according to
a combination of inputs or events. That is we have to identify the conditions and
actions.
2) The next step is to find the action corresponding to the various possible causes and
mark it to show that this action will be performed when the corresponding conditions
are satisfied.

Source Code :

#include<iostream>
#include<conio.h>
#include<stdlib.h>
#include<math.h>

using namespace std;

/* Function to check the type of the triangle


Input: 3 vertices
Output:
-1 - Inavlid input
0 - Not a triangle
1 - Equilateral triangle
2 - Isoscles triangle
3 - Scalene triangle
*/

int triangle(int a[3], int min[3], int max[3])


{
for(int i=0;i<3;i++)
if(a[i]<min[i] || a[i]>max[i])
return -1;

if(a[0]+a[1]>a[2] && a[1]+a[2]>a[0] && a[2]+a[0]>a[1])


{
if(a[0]==a[1] && a[1]==a[2] && a[2]==a[0])
return 1;
else if(a[0]==a[1] || a[1]==a[2] || a[2]==a[0])
return 2;
else
return 3;
}
else
return 0;
}

string conditionStub[6];
string actionStub[5];
char conditionEntries[6][11];
char actionEntries[6][11];
void generateStubAndEntries()
{
conditionStub[0] = "a<b+c?";
conditionStub[1] = "b<c+a?";
conditionStub[2] = "c<a+b?";
conditionStub[3] = "a=b?";
conditionStub[4] = "b=c?";
conditionStub[5] = "c=a?";

actionStub[0] = "Not a triangle";


actionStub[1] = "Equilateral triangle";
actionStub[2] = "Isoscles triangle";
actionStub[3] = "Scalene triangle";
actionStub[4] = "Impossible";

//generating Condition Entries


//for a<b+c?
int i=0;
conditionEntries[0][i]='F';
for(i=1;i<11;i++)
conditionEntries[0][i]='T';

//for b<c+a?
i=0; conditionEntries[1][i]='-';
i=1; conditionEntries[1][i]='F';
for(i=2;i<11;i++)
conditionEntries[1][i]='T';

//for c<a+b?
i=0; conditionEntries[2][i]='-';
i=1; conditionEntries[2][i]='-';
i=2; conditionEntries[2][i]='F';
for(i=3;i<11;i++)
conditionEntries[2][i]='T';

//for a=b?
for(i=0;i<3;i++)
conditionEntries[3][i]='-';
for(i=3;i<11;i++)
if(i<7)
conditionEntries[3][i]='T';
else
conditionEntries[3][i]='F';

//for a=c?
for(i=0;i<3;i++)
conditionEntries[4][i]='-';
for(i=3;i<11;i++)
if(i<5 || (i>7&&i<9))
conditionEntries[4][i]='T';
else
conditionEntries[4][i]='F';

//for b=c?
for(i=0;i<3;i++)
conditionEntries[5][i]='-';
for(i=3;i<11;i++)
if(i%2)
conditionEntries[5][i]='T';
else
conditionEntries[5][i]='F';

//generating Action Entries


for(i=0;i<5;i++)
for(int j=0;j<11;j++)
actionEntries[i][j]=' ';

actionEntries[0][0]='x';
actionEntries[0][1]='x';
actionEntries[0][2]='x';
actionEntries[3][3]='x';
actionEntries[4][4]='x';
actionEntries[4][5]='x';
actionEntries[2][6]='x';
actionEntries[4][7]='x';
actionEntries[2][8]='x';
actionEntries[2][9]='x';
actionEntries[1][10]='x';

cout<<"\nDecision Table...";
cout<<"+"; for(i=0;i<67;i++) cout<<"-"; cout<<"+\n";
for(i=0;i<6;i++)
{
cout<<"| "<<conditionStub[i]<<"\t\t";
if(i>=3) cout<<"\t";
cout<<"| ";
for(int j=0;j<11;j++)
{
cout<<conditionEntries[i][j]<<" | ";
}
cout<<endl;
}
cout<<"+"; for(i=0;i<67;i++) cout<<"-"; cout<<"+\n";
for(i=0;i<5;i++)
{
cout<<"| "<<actionStub[i]<<"\t";
if(i==4) cout<<"\t";
cout<<"| ";
for(int j=0;j<11;j++)
{
cout<<actionEntries[i][j]<<" | ";
}
cout<<endl;
}
cout<<"+"; for(i=0;i<67;i++) cout<<"-"; cout<<"+\n";
}

void decisionTableTesting(int min[3], int max[3])


{
int expOut[11], testCases[11][3], i=0, x=0, y=0, z=0;

generateStubAndEntries();
for(i=0;i<11;i++)
{
switch(i)
{
case 0: x=100; y=60; z=20;
break;
case 1: x=60; y=100; z=20;
break;
case 2: x=20; y=60; z=100;
break;
case 3: x=y=z=60;
break;
case 4: x=y=z=-1;
break;
case 5: x=y=z=-1;
break;
case 6: x=y=60; z=70;
break;
case 7: x=y=z=-1;
break;
case 8: x=z=60; y=70;
break;
case 9: y=z=60; x=70;
break;
case 10: x=50; y=60; z=70;
break;
}
testCases[i][0]=x; testCases[i][1]=y; testCases[i][2]=z;
}
cout<<"\nTest Cases...";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";
cout<<"\n|\t\t Input\t\t\t| Expected\t\t|";
cout<<"\n|\ta\t\tb\t\tc\t| Output\t\t|";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+\n";
for(int i=0;i<11;i++)
{
for(int j=0;j<3;j++)
{
if(j==0) cout<<"|";
cout<<"\t"<<testCases[i][j]<<"\t|";
}
int expOut=triangle(testCases[i],min,max);
if(expOut<0)
cout<<" Invalid input\t";
else cout<<" "<<actionStub[expOut];
cout<<"\t|"<<endl;
}
cout<<"+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";
cout<<"\n>>No. of Test Cases = 11";
}

int main()
{
int min[3], max[3];

for(int i=0;i<3;i++)
{
cout<<"Enter min & max value of vertex "<<i+1<<" : ";
cin>>min[i]>>max[i];
}
decisionTableTesting(min,max);
return 0;
}

Output :

Enter min & max value of vertex 1 : 1 100


Enter min & max value of vertex 2 : 1 100
Enter min & max value of vertex 3 : 1 100

Decision Table...
+-------------------------------------------------------------------+
| a<b+c? |F|T|T|T|T|T|T|T|T|T|T|
| b<c+a? |-|F|T|T|T|T|T|T|T|T|T|
| c<a+b? |-|-|F|T|T|T|T|T|T|T|T|
| a=b? |-|-|-|T|T|T|T|F|F|F|F|
| b=c? |-|-|-|T|T|F|F|F|T|F|F|
| c=a? |-|-|-|T|F|T|F|T|F|T|F|
+-------------------------------------------------------------------+
| Not a triangle |x|x|x| | | | | | | | |
| Equilateral triangle | | | | | | | | | | | x |
| Isoscles triangle | | | | | | | x | | x | x | |
| Scalene triangle | | | |x| | | | | | | |
| Impossible | | | | |x|x| |x| | | |
+-------------------------------------------------------------------+

Test Cases...
+-----------------------------------------------------------------------+
| Input | Expected |
| a b c | Output |
+-----------------------------------------------------------------------+
| 100 | 60 | 20 | Not a triangle |
| 60 | 100 | 20 | Not a triangle |
| 20 | 60 | 100 | Not a triangle |
| 60 | 60 | 60 | Equilateral triangle |
| -1 | -1 | -1 | Invalid input |
| -1 | -1 | -1 | Invalid input |
| 60 | 60 | 70 | Isoscles triangle |
| -1 | -1 | -1 | Invalid input |
| 60 | 70 | 60 | Isoscles triangle |
| 70 | 60 | 60 | Isoscles triangle |
| 50 | 60 | 70 | Scalene triangle |
+-----------------------------------------------------------------------+
>>No. of Test Cases = 11

Discussion :

We successfully generated the test cases for the given program using Decision table based
testing. Decision tables are popular in circumstances where an output is dependent on many
conditions and a large number of decision are required to be taken. This technique is applied
easily at unit level only.

Learning and Finding :

In this experiment we learned how to generate test cases by using Decision table based
testing technique.
Experiment No: 7
Aim : Write a program to find Cyclomatic complexity of a program.

Related Theory :

Cyclomatic complexity is a software metric (measurement), used to indicate


the complexity of a program. It is a quantitative measure of the number of linearly
independent paths through a program's source code.

Algorithm:

McCabe introduced this concept and gave three methods to calculate cyclomatic complexity.

(i) V(G) = e – n + 2P

where V(G) = Cyclomatic complexity

G : program graph

n : number of nodes

e : number of edges

P : number of connected components

The program graph (G) is a directed graph with single entry node and single exit node. A
connected graph is a program graph where all nodes are reachable from entry node, and exit
node is also reachable from all nodes. Such a program graph will have connected component
(P) value equal to one. If there are parts of the program graph, the value will be the number of
parts of the program graph where one part may represent the main program and other parts
may represent sub-programs.

(ii) Cyclomatic complexity is equal to the number of regions of the program graph.

(iii) Cyclomatic complexity

V(G) = π + 1

Where π is the number of predicate nodes contained in the program graph (G).

Source Code :
#include<fstream>
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

using namespace std;

main()
{
fstream testFile;
testFile.open("test.txt",ios::in);
int i=0, cyclo=0, len=0;
char a[1000];

if(testFile.is_open())
{
while(testFile)
{
a[i]=testFile.get();
cout<<a[i++];
}
len=strlen(a);
}

for(i=0;i<len-3;i++)
{
if(a[i]=='i')
{
i++;
if(a[i]=='f')
{
i++;
if(a[i]=='(')
cyclo++;
}
}
else if(a[i]=='w')
{
i++;
if(a[i]=='h')
{
i++;
if(a[i]=='i')
{
i++;
if(a[i]=='l')
{
i++;
if(a[i]=='e')
{
i++;
if(a[i]=='(')
cyclo++;
}
}
}}
}
}
cout<<"\n\nCyclomatic complexity: "<<cyclo+1;
testFile.close();
return 0;
}
Output :

Discussion :

Cyclomatic complexity is a software metric (measurement), used to indicate the complexity


of a program. It is a quantitative measure of the number of linearly independent paths through
a program's source code. It was developed by Thomas J. McCabe, Sr. in 1976.
Cyclomatic complexity is computed using the control flow graph of the program: the nodes
of the graph correspond to indivisible groups of commands of a program, and a directed edge
connects two nodes if the second command might be executed immediately after the first
command.
Cyclometic complexity is applied to individual functions, modules, methods or classes within
a program.
Following table gives overview on the complexity number and corresponding meaning of v
(G):

Complexity Number Meaning

1-10 Structured and well written code

High Testability

Cost and Effort is less

10-20 Complex Code

Medium Testability

Cost and effort is Medium

20-40 Very complex Code

Low Testability

Cost and Effort are high

>40 Not at all testable

Very high Cost and Effort

Learning and Findings :

Cyclomatic Complexity can prove to be very helpful in

3) Helps developers and testers to determine independent path executions


4) Developers can assure that all the paths have been tested atleast once
5) Helps us to focus more on the uncovered paths
6) Improve code coverage
7) Evaluate the risk associated with the application or program
8) Using these metrics early in the cycle reduces more risk of the program
Experiment No : 8
Aim: Write a program to input graph matrix and find the independent paths.

Related Theory:

A graph matrix is a square matrix with one row and one column for every node of the graph.
The size of the matrix (number of rows and number of columns) is the number of nodes of
the
graph. Graph matrix is the tabular representation of a program graph.

Calculating number of independent paths from the graph matrix :

If we assign weight for every entry in the table, then this may be used for the identification of
independent paths. The simplest weight is 1, if there is a connection and 0 if there is no
connection. Each row with more than one entry represents a predicate node and cyclomatic
complexity is predicate nodes plus one ( +1).

Source Code:

#include<iostream>
#define MAX 10

using namespace std;

int main()
{
int row, col, i, j, edges=0, nodes=0;
char ch;
int matrix[MAX][MAX];

cout<<"Enter the number of rows: ";


cin>>row;
cout<<"Enter the number of columns: ";
cin>>col;
cout<<"\nEnter the adjacency matrix is.. \n";
for(i=0;i<row;i++)
for(j=0;j<col;j++)
cin>>matrix[i][j];

nodes = row;
cout<<"\nNumber of nodes = "<<nodes;

for(i=0;i<=row;i++)
for(j=0;j<=col;j++)
if(matrix[i][j]==1)
edges++;

cout<<"\nNumber of edges = "<<edges;


cout<<"\n\nCyclomatic Complexity of graph = edges-nodes+2p\n";
cout<<"\t\t\t\t= "<<edges<<" - "<<nodes<<" + 2";
cout<<"\n\t\t\t\t= "<<edges-nodes+2;
return 0;
}
Output:
Enter the number of rows: 4
Enter the number of columns: 4

Enter the adjacency matrix is..


0110
0101
1100
1101

Number of nodes = 4
Number of edges = 9

Cyclomatic Complexity of graph = edges-nodes+2p


=9-4+2
=7

Discussion :

Graph matrices is a mathematical concept which is used in software testing to trace all possible paths in a graph,
at least once, and calculates the cyclomatic complexity. It converts a flow graph into matrix and each node
corresponds to particular row & column, by applying step by step process to get desired paths with its calculated
values. It represents a crucial relationship between nodes. It represents complex graphs in matrix form, and
applies multiple operations in matrices to trace a path. Each node in a graph holds particular value. Sometimes,
path can be traced twice which occurs redundancy or can be missed. These misconception and tracing errors
generate interruptions and leads us to confusion.

Learning and Finding :

As we know, each graph matrix expresses a direct link between nodes. If we take the square
of the matrix, it shows 2-links relationships via one intermediate node. Hence, square matrix
represents all paths of two links long. The Kth power of matrix represents all paths of K links
long.
Program No: 9
Aim: Perform an experiment on Mutation Testing.

Related Theory:
It is a popular technique to assess the effectiveness of a test suite. We may have a large
number of test cases for any program. We neither have time nor resources to execute all of
them. We may select a few test cases using any testing technique and prepare a test suite.
Hence, assessing the effectiveness and quality of a test suite is very important. Mutation
testing may help us to assess the effectiveness of a test suite and may also enhance the test
suite, if it is not adequate for a program.

When we execute a mutant using a test suite, we may have any of the following outcomes:
(i) The results of the program are affected by the change and any test case of the test suite
detects it. If this happens, then the mutant is called a killed mutant.
(ii) The results of the program are not affected by the change and any test case of the test
suite does not detect the mutation. The mutant is called a live mutant.
The mutation score associated with a test suite and its mutants is calculated as:

The total number of mutants is equal to the number of killed mutants plus the number of
live mutants. The mutation score measures how sensitive the program is to the changes and
how accurate the test suite is. A mutation score is always between 0 and 1. A higher value of
mutation score indicates the effectiveness of the test suite although effectiveness also depends
on the types of faults that the mutation operators are designed to represent.

Algorithm: 1) Mutants are introduced in the program.


2) The Test Suite is used to check the modified program to assess its
effectiveness.
3) If the output of the Test Suite for original and modified program is same
then mutant is alive, mutant is killed.
4) We calculate the Mutation Score for the Test Suite.

Program:
-->Mutations performed:
9) Change the access modifier from private to public
10) Change static modifier
11) Change argument modifier
12) Change the operator
13) Change the numeric value of operands
14) Calculate the mutation score

#include<iostream>
#include<conio.h>
#include<math.h>
using namespace std;

class Rectangle
{
int length;
int breadth;
static int count;
public:
Rectangle();
int getLength();
int getBreadth();
void storeData(int , int );
int calculateArea(int , int );
int objectCount();
};

int Rectangle :: count = 0;

Rectangle :: Rectangle()
{ count++;
length = 0;
breadth = 0;
}
int Rectangle :: getLength()
{ return length;
}

int Rectangle :: getBreadth()


{ return breadth;
}

void Rectangle :: storeData(int l, int b)


{ length = l;
breadth = b;
}

int Rectangle :: calculateArea(int length, int breadth)


{ return length * breadth;
}

int Rectangle :: objectCount()


{ return count;
}

main()
{
char ch='y';
do{
Rectangle R;

int l, b;
cout<<"\nEnter the dimensions of the rectangle...\n";
cout<<"Length = ";
cin>>l;
cout<<"Breadth = ";
cin>>b;
R.storeData(l,b);

cout<<"Area of the rectangle = "<<R.calculateArea(R.getLength(),R.getBreadth());


cout<<"\n\nDo you want to calculate more? (y/n): ";
cin>>ch;
if(ch=='n' || ch=='N')
cout<<"\nObject count = "<<R.objectCount();
}while(ch=='y' || ch=='Y');

return 0;
}
Mutated Statements:

Mutant Line
Original Line Modified Line
No. No.
M1 13 public: private:
M2 11 static int count; int count;
41 void Rectangle :: storeData(int l, void Rectangle :: storeData(int b,
M3
int b) int l)
M4 49 return length * breadth; return length + breadth;
M5 27 length = 0; length = 10;

Mutant M1:
Test Cases length breadth Expected Output Actual Output
1 2 2 4 Compilation Error
2 3 5 15 Compilation Error

Output:

Mutant M2:
Test Cases length breadth Expected Output Actual Output
1 2 2 4 Compilation Error
2 3 5 15 Compilation Error
Output:

Mutant M3:
Test Cases length breadth Expected Output Actual Output
1 2 2 4 4
2 3 5 15 15

Output:

Mutant M4:
Test Cases length breadth Expected Output Actual Output
1 2 2 4 4
2 3 5 15 8

Output:

Mutant M5:
Test Cases length breadth Expected Output Actual Output
1 2 2 4 4
2 3 5 15 15

Output:
Calculation of Mutation Score:
No. of killed mutants = 3
No. of live mutants = 2
Total no. of mutants = 5
Mutation Score = No. of killed mutants / Total no. of mutants
= 3/5
= 0.6

Discussion: Mutation testing is a structural testing technique, which uses the structure of the
code to guide the testing process. On a very high level, it is the process of rewriting the
source code in small ways in order to remove the redundancies in the source code
These ambiguities might cause failures in the software if not fixed and can easily pass
through testing phase undetected. Mutation testing helps us in assessing the effectiveness of
the test suite. It helps us in identifying which of the test suite is effective in finding errors in
the program.

Learning: The purpose of mutation testing is not only to assess the capability of a test suite
but also to enhance the test suite. Therefore it is effective for selecting test suite for a required
program.
Experiment No: 10
Aim
Write a program to generate test cases using cause effect graph technique.

Theory
This technique is a popular technique for small programs and considers the combinations of
various inputs which were not available in earlier discussed techniques like boundary value
analysis and equivalence class testing. Such techniques do not allow combinations of inputs
and consider all inputs as independent inputs. Two new terms are used here and these are
causes and effects, which are nothing but inputs and outputs respectively.

FlowChart

Program
#include<iostream>
#include<conio.h>

using namespace std;

/* Function to check the type of the triangle


Input: 3 vertices
Output:
-1 - Invalid input
0 - Right angled triangle
1 - Obtuse triangle
2 - Acute triangle
3 - Not a triangle
*/
bool cause[6]={0};
bool effect[5]={0};
void triangle(int a[3], int min[3], int max[3])
{
for(int i=0;i<3;i++)
if(a[i]<min[i] || a[i]>max[i])
return;

if(a[0]+a[1]>a[2] && a[1]+a[2]>a[0] && a[2]+a[0]>a[1])


{
cause[0]=1;
cause[1]=1;
cause[2]=1;
if((a[0]^2)==((a[1]^2)+(a[2]^2)))
{
cause[3]=1;
cause[4]=0;
cause[5]=0;
}
else if(a[0]^2>a[1]^2+a[2]^2)
{
cause[3]=0;
cause[5]=0;
cause[4]=1;
}
else
{
cause[3]=0;
cause[4]=0;
cause[5]=1;
}
}
else
{
if(a[0]>=a[1]+a[2])
cause[0]=0;
else if(a[1]>=a[0]+a[2])
cause[1]=0;
else
cause[2]=0;
}
effect[0]=(!cause[0])||(!cause[1])||(!cause[2]);
effect[1]=cause[0]&&cause[1]&&cause[2]&&cause[3];
effect[2]=cause[0]&&cause[1]&&cause[2]&&cause[4];
effect[3]=cause[0]&&cause[1]&&cause[2]&&cause[5];

}
string c[6],e[5];
void generateCauseEffect()
{
c[0]="a < b+c";
c[1]="b < a+c";
c[2]="c < a+b";
c[3]="a^2 = b^2 + c^2";
c[4]="a^2 > b^2 + c^2";
c[5]="a^2 < b^2 + c^2";
e[0]="Invalid Triangle";
e[1]="Right Angle Triangle";
e[2]="Obtuse Angle Triangle";
e[3]="Acute Angle Triangle";
e[4]="Impossible";
}
void causeEffectTesting(int min[3],int max[3])
{
int expOut[6],i=0,x=0,y=0,z=0,testCases[6][3];
testCases[0][0]=3;
testCases[0][1]=2;
testCases[0][2]=1;
testCases[1][0]=2;
testCases[1][1]=3;
testCases[1][2]=1;
testCases[2][0]=2;
testCases[2][1]=1;
testCases[2][2]=3;
testCases[3][0]=5;
testCases[3][1]=4;
testCases[3][2]=3;
testCases[4][0]=5;
testCases[4][1]=4;
testCases[4][2]=2;
testCases[5][0]=5;
testCases[5][1]=5;
testCases[5][2]=5;
cout<<"\n\nTest Cases...";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";
cout<<"\n|\t\t Input\t\t\t| Expected\t\t|";
cout<<"\n|\ta\t\tb\t\tc\t| Output\t\t|";
cout<<"\n+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+\n";
for(int i=0;i<6;i++)
{
for(int j=0;j<3;j++)
{
if(j==0) cout<<"|";
cout<<"\t"<<testCases[i][j]<<"\t|";
}
triangle(testCases[i],min,max);
if(expOut<0)
cout<<" Invalid input\t";
else
{
int k;
for(int i=0;i<5;i++)
{
if(effect[i]==1)
{
k=i;
break;
}

}
cout<<" "<<e[k];
}
cout<<"\t|"<<endl;
}
cout<<"+"; for(int i=0;i<71;i++) cout<<"-"; cout<<"+";

}
void decisionTable()
{
generateCauseEffect();
cout<<"\nCauses...";
for(int i=0;i<6;i++)
{
cout<<"\nc"<<i+1<<":"<<c[i];
}
cout<<"\nEffects...";
for(int i=0;i<5;i++)
{
cout<<"\ne"<<i+1<<":"<<e[i];
}
cout<<"\n\nDecision Table\n";
cout<<"Conditions\n--------------------------------------------------------------------------\n";
cout<<"c1:"<<c[0]<<"\t\t\t0 1 1 1 1 1 1 1 1 1 1\n";
cout<<"c2:"<<c[1]<<"\t\t\tX 0 1 1 1 1 1 1 1 1 1\n";
cout<<"c3:"<<c[2]<<"\t\t\tX X 0 1 1 1 1 1 1 1 1\n";
cout<<"c4:"<<c[3]<<"\t\tX X X 1 1 1 1 0 0 0 0\n";
cout<<"c5:"<<c[4]<<"\t\tX X X 1 1 0 0 1 1 0 0\n";
cout<<"c6:"<<c[5]<<"\t\tX X X 1 0 1 0 1 0 1 0\n";
cout<<"--------------------------------------------------------------------------\n";
cout<<"e1:"<<e[0]<<"\t\t1 1 1\n";
cout<<"e2:"<<e[1]<<"\t 1\n";
cout<<"e3:"<<e[2]<<"\t 1\n";
cout<<"e4:"<<e[3]<<"\t 1\n";
cout<<"e5:"<<e[4]<<"\t\t\t 1 1 1 1 1\n";
cout<<"\n\n";
}
int main()
{
int min[3],max[3];
for(int i=0;i<3;i++)
{
cout<<"Enter min and max value of vertex"<<i+1<<":";
cin>>min[i]>>max[i];
}
decisionTable();
causeEffectTesting(min,max);
}

Output

Results and Discussions


We successfully generated the test cases for the given program using cause effect graph
method. This technique is a popular technique for small programs and considers the
combinations of various inputs which were not available in many earlier techniques like
boundary value analysis and equivalence class testing. Two new terms used in this case cause
and effects, which are nothing but inputs and outputs respectively.

Learning and findings


In this experiment we learned how to generate test cases by using cause effect graph
technique.
Experiment No: 11
Aim: Execute static analysis tool cppcheck

Related Theory :

We have to execute the static analysis tool to analsye its functioning. Here we consider
cppcheck as the static analysis tool .

Introduction:

Cppcheck is an analysis tool for C/C++ code. Unlike C/C++ compilers and many other
analysis tools, it doesn’t detect syntax errors. Cppcheck only detects the types of bugs that the
compilers normally fail to detect. The goal is no false positives.

Supported code and platforms:

• You can check non-standard code that includes various compiler extensions, inline
assembly code, etc.

• Cppcheck should be compilable by any C++ compiler that handles the latest C++ standard.

• Cppcheck should work on any platform that has sufficient CPU and memory.

Algorithm :

 Write the C/C++ program in an editor and save it.


 Open the cppcheck GUI for testing the program.
 Select the Check menu , then select files option and choose the file which is to be
analysed.
 If there is an error , result will be displayed as a list.
 Else a pop up showing no errors will be displayed.

Program and Corresponding Outputs:

Program 1:
#include<iostream>
using namespace std;
int main(){
int a[10];
for(int i=10;i>0;i++)
cin>>a[i];
return 0;
}
Output :

Program 2:
/*Program to compute day of the week*/
/*Header Files*/
#include<stdio.h>
#include<conio.h>
void main()
{
int day,month,year,century,Y,y1,M,date,validDate=0,leap=0;
//clrscr();
printf("Enter day:");
scanf("%d",&day);
printf("Enter month:");
scanf("%d",&month);
printf("Enter year (between 1900 and 2058):");
scan("%d",&year);
/*Check whether the date is valid or not*/
if(year>=1900&&year<=2058) {
if(year%4==0) { /*Check for leap year*/
leap=1;
if((year%100)==0&&(year%400)!=0) {
leap=0;
}
}
if(month==4||month==6||month==9||month==11){
if(day>=1&&day<=30) {
validDate=1;
}
else {
validDate=0;
}
}
else if(month==2){
if(leap==1&&(day>=1&&day<=29)) {
validDate=1;
}
else if(day>=1&&day<=28) {
validDate=1;
}
else {
validDate=0;
}
}
else if((month>=1&&month<=12)&&(day>=1&&day<=31)){
validDate=1;
}
else {
validDate=0;
}
}
if(validDate) { /*Calculation of Day in the week*/
if(year>=1900&&year<2000){
century=0;
y1=year-1900;
}
else {
century=6;
y1=year-2000;
}
Y=y1+(y1/4);
if(month==1) {
if(leap==0) {
M=0; /*for non-leap year*/
}
else {
M=6; /*for leap year*/
}
}
else if(month==2){
if(leap==0) {
M=3; /*for non-leap year*/
}
else {
M=2; //for leap year
}
}
else if((month==3)||(month==11)) {
M=3;
}
else if((month==4)||(month==7)) {
M=6;
}
else if(month==5) {
M=1;
}
else if(month==6) {
M=4;
}
else if(month==8) {
M=2;
}
else if((month==9)||(month==12)) {
M=5;
}
else {
M=0;
}
date=(century+Y+M+day)%7;
if(date==0) { /*Determine the day of the week*/
printf("Day of the week for [%d:%d:%d] is Sunday",day,month,year);
}
else if(date==1) {
printf("Day of the week for [%d:%d:%d] is Monday",day,month,year);
}
else if(date==2) {
printf("Day of the week for [%d:%d:%d] is Tuesday",day,month,year);
}
else if(date==3) {
printf("Day of the week for [%d:%d:%d] is Wednesday",day,month,year);
}
else if(date==4) {
printf("Day of the week for [%d:%d:%d] is Thursday",day,month,year);
}
else if(date==5) {
printf("Day of the week for [%d:%d:%d] is Friday",day,month,year);
}
else {
printf("Day of the week for [%d:%d:%d] is Saturday",day,month,year);
}
}
else {
printf("The date entered [%d:%d:%d] is invalid",day,month,year);
}
getch();
}
Output :

Program 3:
#include <stdio.h>
#include<iostream.h>
int *p;
int a(int sz)
{
delete [] p;
if (sz <= 0)
throw std::runtime_error("size <= 0");
p = new int[sz];
}

Output :

Program 4:
int main(void)
{
char *str1 = "abcdefghijklmnop";
char *str2 = malloc(100);
strcpy(str2, str1);
char x[16];
x[16] = 10;
return 0;
}
Output :

Program 5:
/*Program to classify whether a triangle is acute, obtuse or right angled given the sides of
the triangle*/
//Header Files
#include<stdio.h>
#include<conio.h>
#include<math.h>
void main() //Main Begins
{
double a,b,c;
double a1,a2,a3;
int valid=0;
clrscr();
printf("Enter first side of the triangle:"); /*Enter the sides of Triangle*/
sprintf("%lf",&a);
printf("Enter second side of the triangle:");
scanf("%lf",&b);
printf("Enter third side of the triangle:");
scanf("%lf",&c);
/*Checks whether a triangle is valid or not*/
if(a>0&&a<=100&&b>0&&b<=100&&c>0&&c<=100) {
if((a+b)>c&&(b+c)>a&&(c+a)>b) {
valid=1;
}
else {
valid=-1;
}
}
if(valid==-1) {
a1=(a*a+b*b)/(0);
a2=(b*b+c*c)/(a*a);
a3=(c*c+a*a)/(b*b);
if(a1<1||a2<1||a3<1) {
printf("Obtuse angled triangle");
}
else if(a1==1||a2==1||a3==1) {
printf("Right angled triangle");
}
else {
printf("Acute angled triangle");
}
}
else if(valid==-1) {
printf("\nInvalid Triangle");
}
else {
printf("\nInput Values are Out of Range");
}
getch();
}
Output :

Discussion :

As we executed the programs we noted that the syntax errors were not detected by this tool
which was according to what the tool did.

The bugs other that syntax errors were detected by the tool and it also showed us some
improvements which can be made in the code like reducing the scope of the variables
according to its usage.
Hence this can be used for finding bugs.

Learning and Finding :

There are limits of Cppcheck. Cppcheck is rarely wrong about reported errors. But there are
many bugs that it doesn’t detect. More bugs can be found in the software by testing it
carefully, than by using Cppcheck.More bugs can be found in the software by instrumenting
the software, than by using Cppcheck. But Cppcheck can still detect some of the bugs that
one may miss when testing and instrumenting your software.
Experiment No: 12
Aim
Write a program for generating Control Flow Graph and DD Path Graph

Theory
What is Control Flow Path?
A control flow path is a graphical representation of all paths that might be traversed through a
program during its execution. Most representations are of two types of blocks. Viz - An entry
block through which control enters into the flow graph and the exit block through which all
control flow leaves.
By this representation, we can also calculate cyclomatic complexity. It also enables us to
verify reachability, relationship with other nodes, edges and loops effectively.

What is DD Path Graph?


A decision-to-decision path is defined as path in a program's flowchart such that all the
following hold (quoting from the paper):
 its first constituent edge emanates either from an entry node or a decision box;
 its last constituent edge terminates either at a decision box or at an exit node; and
 there
Triangle program
are noDD-paths
decision boxes on the path except those at both ends

Nodes Path Case Nodes Path Case


1 First 1 10 H 4
2,3 A 5 11 I 3
4 B 3 12 J 4
5 C 4 13 K 4
6 D 4 14 L 3
7 E 3 15 M 3
8 F 3 16 N 4
9 G 3 17 Last 2

PT–14
Flow Chart

Program
#include<iostream>
#include<fstream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>

using namespace std;

// constants
const int NOTYPE=0 ,
TYPE_REGULAR=1,TYPE_IF=2,TYPE_ELSE=3,TYPE_IF_CLOSE=4,TYPE_ELSE_CLOSE=5;
const string IF_STRING="if(", ELSE_STRING="else" , CLOSE_STRING="}";

class Node
{

public:

int num;
static int node_count;

// list of ptrs to next nodes


vector<Node*> next;

static Node* create_new_node(){

Node* new_node = new Node();


new_node->num = Node::node_count++;

return new_node;
}
};

int Node::node_count = 1;

class Stack_Node{
public:
Node* ptr;
int type;

Stack_Node(){
this->ptr = NULL;
this->type = NOTYPE;
}

Stack_Node(Node* ptr, int type){


this->ptr = ptr;
this->type = type;
}
};

stack<Stack_Node> mStack;

class Graph {
public:
Node* head;

void printGraph(){

queue<Node*> q;
q.push(head);

while(!q.empty()){

Node* travel_ptr = q.front();


q.pop();

cout<<travel_ptr->num<<" : ";

for (std::vector<Node*>::iterator i = travel_ptr->next.begin(); i != travel_ptr-


>next.end(); ++i)
{
cout<<(*i)->num<<" ";
q.push((*i));
}
cout<<endl;
}
}
};

void process_line(string line, Graph* g){

Node* current_node = NULL;


// if the line is not empty create a new node for this line
if (line.find_first_not_of(' ')!=string::npos)
{
current_node = Node::create_new_node();
}

if (g->head == NULL)
{
g->head = current_node;

Stack_Node new_node(current_node,TYPE_REGULAR);
mStack.push(new_node);

return;
}

// ------------------------------ ATTACHMENT CODE -------------------------------------------------


/*
Check if the top of the stack is an 'ELSE_CLOSE' node , if so then attach the current node to the else
tail and pop the 'ELSE CLOSE AND ELSE' nodes from the stack. Then attach the IF CLOSE to the
current node and pop the IF CLOSE AND IF nodes from the stack */
if (mStack.top().type == TYPE_ELSE_CLOSE)
{
// Attach to the else node
mStack.top().ptr->next.push_back(current_node);

// Pop ELSE CLOSE


mStack.pop();

// Pop ELSE
mStack.pop();

// Attach IF_CLOSE
mStack.top().ptr->next.push_back(current_node);

// Pop IF_CLOSE
mStack.pop();

// Pop IF
mStack.pop();

}
else {

// if the current node is not an else node Attach like normal


if (line.find(ELSE_STRING) == string::npos){
mStack.top().ptr->next.push_back(current_node);
}
}

// ----------------------------------- PROCESSING CODE --------------------------------------

// if line contains 'if' then


// we push the if node to the stack
if(line.find(IF_STRING) != string::npos){
// Push the if node to the stack
Stack_Node new_node(current_node,TYPE_IF);
mStack.push(new_node);
}

// if the line contains 'else' we push the


// else node to the stack
else if (line.find(ELSE_STRING) != string::npos){
// Attach the current node to the last if

Stack_Node node_if_close = mStack.top();


mStack.pop();
mStack.top().ptr->next.push_back(current_node);
mStack.push(node_if_close);

Stack_Node new_node(current_node,TYPE_ELSE);
mStack.push(new_node);
}

// if the line contains a '}' we check if it is a IF_CLOSE or an


// ELSE_CLOSE
else if (line.find(CLOSE_STRING) != string::npos){

// Check if the top of the stack is a regular node


if (mStack.top().type == TYPE_REGULAR){
mStack.pop();
if (!mStack.empty() && mStack.top().type == TYPE_IF){
Stack_Node new_node(current_node,TYPE_IF_CLOSE);
mStack.push(new_node);
}else if(!mStack.empty() && mStack.top().type == TYPE_ELSE){
Stack_Node new_node(current_node,TYPE_ELSE_CLOSE);
mStack.push(new_node);
}else{
Stack_Node new_node(current_node , TYPE_REGULAR);
mStack.push(new_node);
}
}else{

if (mStack.top().type == TYPE_IF)
{
Stack_Node new_node(current_node,TYPE_IF_CLOSE);
mStack.push(new_node);
}else if(mStack.top().type == TYPE_ELSE){
Stack_Node new_node(current_node,TYPE_ELSE_CLOSE);
mStack.push(new_node);
}

}
}

// if the line is a regular line we see if the top is a regular line and pop it and push this line
// else if the top node is IF_TYPE or ELSE_TYPE we simply push it
else {

if (mStack.top().type == TYPE_REGULAR){
mStack.pop();

Stack_Node new_node(current_node,TYPE_REGULAR);
mStack.push(new_node);
}
else if(mStack.top().type == TYPE_IF || mStack.top().type == TYPE_ELSE){

Stack_Node new_node(current_node,TYPE_REGULAR);
mStack.push(new_node);
}
}
}

int main(int argc, char const *argv[])


{
char filename[100];
string line;

// input the filename


cout<<"Enter the filename : ";
cin>>filename;

Graph* g = new Graph();

ifstream file(filename);

if (file.is_open())
{
// start reading the file
while(getline(file,line))
{
process_line(line,g);
}
}

g->printGraph();

return 0;
}

Output
Sample.txt

Output Graph
Discussion
Graphs that represent the control flow of programs have been studied since many years and are known
under the names of control flow graphs or program graphs. There are mainly two types of such
graphs: one that associates one node with each statement in programs, see, for example, where control
flow graphs are applied to optimization or for the application in software engineering; and the other
that replaces maximal sets of consecutive nodes with a single entry and a single exit called blocks or
segments, by single nodes. Blocks can be derived from the control flow graphs of the first type or
constructed directly from the programs. Both types capture the control flow by abstraction from the
program details.
Since the control flow through programs is determined by the decisions, for example, the if-then-else-
constructs, based on the data and the conditions in such constructs, it is promising to keep in graphical
representations of programs only the decisions and the control flow between them and thus defining a
reduction of control flow graphs that preserves the branching structure.

Learning and Finding


We derived decision graphs from directed graphs such that the branching structure is preserved. It can
be shown that the branches in a graph without unconditional loops correspond to the edges in the
decision graph. One useful application is the modeling of programs with control flow graphs.
Decision graphs form an abstraction from control flow graphs that display only the decisions, for
example, if-then-else-constructs and the paths between decisions to the programmer. With this
approach, we compared different definitions of branch covering in software testing that already
existed and showed the differences. When we exclude unconditional loops, branch coverage based on
the edges in decision graphs subsumes edge coverage of the control flow graph and decision
coverage. Control flow graphs are not only popular in software modeling but also popular in different
other fields. Therefore, it seems promising to apply decision graphs to other domains and exploit their
advantages
Experiment No: 13
Aim : Write a program for generating Graph Matrix and computing the number of
independent paths

Related Theory :

Graph Matrices :

A graph matrix is a square matrix with one row and one column for every node of the graph.
The size of the matrix (number of rows and number of columns) is the number of nodes of
the
graph. Graph matrix is the tabular representation of a program graph. An example of program
graph and its graph matrix is given below :

Calculating number of independent paths from the graph matrix :

If we assign weight for every entry in the table, then this may be used for the identification of
independent paths. The simplest weight is 1, if there is a connection and 0 if there is no
connection. Each row with more than one entry represents a predicate node and cyclomatic
complexity is predicate nodes plus one ( +1).

Source Code :

#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

class vertex{

public:
int in_deg;
vector<int> e_list;
int line_num;
vertex(){
in_deg = 0;
}
vertex(const vertex & v){
in_deg = v.in_deg;
for (int i=0;i<v.e_list.size();i++)
e_list.push_back(v.e_list[i]);
line_num = v.line_num;
}
};

struct graph{
int num_vertex;
vector<vertex> v_list;

void insert(const vertex & v){


vertex v2 = v;
num_vertex ++;
v2.line_num = num_vertex;
v_list.push_back(v2);
}

void erase(int i){


num_vertex--;
v_list.erase(v_list.begin() + i);
}
graph(const graph & cfg){
num_vertex = cfg.num_vertex;
for (int i=0;i<num_vertex;i++)
v_list.push_back(cfg.v_list[i]);
}

graph(){
num_vertex = 0;
}
};
int buildDDHelper(graph & dd, int index, int & deleted){

int i,prev_val;
for (i=index;i<dd.num_vertex;){
if (dd.v_list[i].in_deg == 1 &&
dd.v_list[i].e_list.size() == 1){
prev_val = i;
i++;

while (dd.v_list[i].in_deg == 1 &&


dd.v_list[i].e_list.size() == 1){

int val = dd.v_list[i].e_list[0] - deleted - 2;


dd.erase(i);
deleted++;

i = val;
}

dd.v_list[prev_val].e_list[0] = i + deleted + 1;
}

if (dd.v_list[i].e_list.size() > 1){


buildDDHelper(dd,dd.v_list[i].e_list[0] - deleted - 1, deleted);
i = buildDDHelper(dd,dd.v_list[i].e_list[1] - deleted - 1,deleted);
}
else
break;
}

return i;
}
void buildDD(graph & dd){

int deleted = 0;

for (int i=0;i<dd.num_vertex;){


if (dd.v_list[i].in_deg == 1 &&
dd.v_list[i].e_list.size() == 1){
i++;

while (dd.v_list[i].in_deg == 1 &&


dd.v_list[i].e_list.size() == 1){
dd.erase(i);
deleted ++;
}
dd.v_list[i-1].e_list[0] = dd.v_list[i].line_num;
}

if (dd.v_list[i].e_list.size() > 1){


buildDDHelper(dd,dd.v_list[i].e_list[0] - deleted - 1,deleted);
i = buildDDHelper(dd,dd.v_list[i].e_list[1] - deleted - 1,deleted);
}
else
i++;
}
}
void buildCFG(graph & cfg, ifstream & fin){
char ar[100];
do{
fin.getline(ar,100);

string str(ar);
int pos = str.find_first_not_of(' ');

if (pos == string::npos)
continue;

int prev_pos = cfg.num_vertex - 1;


if (str.substr(pos,2) == "if"){
vertex v;
v.in_deg = 1;
cfg.insert(v);

p1:
cfg.v_list[prev_pos].e_list.push_back(cfg.num_vertex);
buildCFG(cfg,fin);

int prev_pos2 = cfg.num_vertex - 1;


do{
fin.getline(ar,100);
string str(ar);
int pos = str.find_first_not_of(' ');

if (pos == string::npos)
continue;

if (str.substr(pos,4) == "else"){
vertex v;
v.in_deg = 1;
cfg.insert(v);

cfg.v_list[prev_pos + 1].e_list.push_back(cfg.num_vertex);
buildCFG(cfg,fin);

do{
fin.getline(ar,100);
string str(ar);
int pos = str.find_first_not_of(' ');

if (pos == string::npos)
continue;

vertex v2;
v2.in_deg = 2;

cfg.insert(v2);

cfg.v_list[cfg.num_vertex -2].e_list.push_back(cfg.num_vertex);
cfg.v_list[prev_pos2].e_list.push_back(cfg.num_vertex);

if (str[pos] == '}')
return;

break;
}
while (true);
}
else{
vertex v2;
v2.in_deg = 2;
cfg.insert(v2);
cfg.v_list[cfg.num_vertex -2].e_list.push_back(cfg.num_vertex);
cfg.v_list[prev_pos2 - 2].e_list.push_back(cfg.num_vertex);
if (str.substr(pos,2) == "if")
goto p1;
else if (str[pos] == '}')
return;
}

break;
}
while (true);

else{
vertex v;
v.in_deg = 1;
cfg.insert(v);

cfg.v_list[prev_pos].e_list.push_back(cfg.num_vertex);
if (str[pos] == '}')
break;
}
}while (true);
}

void printGraph(const graph & cfg){


for (int i=0;i<cfg.num_vertex;i++){
cout << cfg.v_list[i].line_num << ": Indegree: "<<cfg.v_list[i].in_deg<<" Edge List-> ";

int size_edge = cfg.v_list[i].e_list.size();


for (int j=0;j<size_edge;j++)
cout << cfg.v_list[i].e_list[j] << " ";

cout << endl;


}
}

void graph_matrix(const graph & cfg){


int size = cfg.num_vertex;
int i,j,k,num;
int ar1[size];
int arr[size][size];
for(i=0;i<size;i++){
ar1[i] = cfg.v_list[i].line_num;
}
for(i=0;i<size;i++){
for(j=0;j<size;j++){
arr[i][j]=0;
}
}
for(i=0;i<size;i++){
int size_edge = cfg.v_list[i].e_list.size();
for (int j=0;j<size_edge;j++){
num= cfg.v_list[i].e_list[j];
for(k=0;k<size;k++){
if(ar1[k]==num){
arr[i][k]=1;
break;
}
}
}
}

for(i=0;i<size;i++){
if(i==0)
printf(" %d ",ar1[i]);
else
printf("%d ",ar1[i]);
}
int count=2;
printf("\n");
for(i=0;i<size;i++){
printf("%d ",ar1[i]);
for(j=0;j<size;j++){
printf("%d ",arr[i][j]);
if(arr[i][j]==1)
count++;
}
count--;
printf("\n");
}
printf("\n Number of Independent Path : %d",count);
}
int main(){

char file_name[100];

cout << "ENTER THE NAME OF THE FILE TO BE ANALYSED: ";


cin.getline(file_name,100);
ifstream fin(file_name);

if (!fin){
cerr << "FILE NOT FOUND!\n";
}
else{
char ar[100];
bool terminate = false;
while (!terminate){
fin.getline(ar,100 - 1);

string str(ar);
int pos = str.find_first_not_of(' ');

if (str[pos] == '#')
continue;

if (str.find("main()") != string::npos){
graph cfg;
vertex v;
cfg.insert(v);

buildCFG(cfg,fin);

cout << "\nTHE GRAPH MATRIX IS AS FOLLOWS: \n";


graph dd(cfg);
buildDD(dd);

graph_matrix(dd);

terminate = true;
}
}
}
Output :

Discussion :

Graph matrices is a mathematical concept which is used in software testing to trace all possible paths in a
graph, at least once, and calculates the cyclomatic complexity. It converts a flow graph into matrix and each
node corresponds to particular row & column, by applying step by step process to get desired paths with its
calculated values. It represents a crucial relationship between nodes. It represents complex graphs in matrix
form, and applies multiple operations in matrices to trace a path. Each node in a graph holds particular value.
Sometimes, path can be traced twice which occurs redundancy or can be missed. These misconception and
tracing errors generate interruptions and leads us to confusion.
Learning and Finding :

As we know, each graph matrix expresses a direct link between nodes. If we take the square
of the matrix, it shows 2-links relationships via one intermediate node. Hence, square matrix
represents all paths of two links long. The Kth power of matrix represents all paths of K links
long.
Program No: 14
Aim: Security Testing of a Website

Theory :

Security is the procedure used to protect information from various threats. It is very important
to protect sensitive and critical information and data while communicating over the network.
The user wants implementation of a safeguard to protect personal, sensitive and financial
information. We want data to be accurate, reliable and protected against unauthorized access.

The primary requirement of security includes:

(i) Authentication: Is the information sent from an authenticated user?

(ii) Access Control: Is data protected from unauthorized users?

(iii) Integrity: Does the user receive exactly what is sent?

(iv) Delivery: Is the information delivered to the intended user?

(v) Reliability: What is the frequency of a failure? How much time does the network take

to recover from a failure? What measures are taken to counter catastrophic failure?

(vi) Non-repudiation: Is the receiver able to prove that the data received came from a

specific sender?

A web application must fulfil the above mentioned primary security requirements. Testing

the threats and vulnerabilities in a web application is an important activity. The tester must

check the web application against all known internet threats.

Algorithm:

1) Prepare a list of questionnaires.


2) Answer the questionnaire to review the security breaches involved in the website.
Questionnaire:

S. Description Yes/
No No
Authentication, Access control and privacy

1 Are unauthorized users restricted from viewing private data? Yes

2 Is sensitive organization information restricted from public access? Yes

3 Are users aware of the privacy polices? Yes

4 Are legal consequences of policies known to the user? Yes

5 Are authentication mechanisms adequate to prevent malicious intrusion to the Yes


application?
6 Does the web application ask for login id and password? Yes

7 Does the web server lock the users who try to access the website multiple Yes
times with invalid login ids/passwords?
8 Have you tested the combinations of invalid and valid login ids/passwords? Yes

9 Is there any provision for forget/change password? Yes

10 Are levels of authentication defined? Yes

Firewall

11 Does the firewall properly implement all the security policies of the Yes
company?
12 Are firewalls’ adequacy tested? Yes

13 Is the ‘security in charge’ aware of the known faults in the firewalls Yes

14 Is the location of the firewall effective? Yes

15 Is any penetration possible in the security boundaries created by a firewall? Yes

Data security

16 Are the data validations tested? Yes

17 Is sensitive information (such as password, credit card number) displayed in Yes


text field?
18 Are privileges to access data enforced? Yes

19 Are file download permissions established? Yes

20 Is sensitive and important data kept at secure locations? Yes

Encryption

21 Are encryption standards enforced? Yes

22 Is there any procedure followed to identify what is to be encrypted? Yes

23 Is sensitive and critical information (such as password, credit card number, Yes
company’s financial sheets) encrypted?
24 Is Security Socket Layer (SSL) used to provide encryption of sensitive Yes
elements?
25 Does the enforcement of encryption standard affect the speed of the web Yes
page?
Virus

26 Are mechanisms used to identify and remove viruses? Yes

27 Are anti-virus softwares scheduled for periodical updates? Yes

28 Does the anti-virus software identify the unprotected sites? Yes

29 Are viruses sent for analysis to the anti-virus software company? Yes

30 Are users trained for virus prevention and recovery procedures? Yes

31 Is the procedure for handling a virus attack adequate? Yes

32 Are users alerted from downloading insecure items? Yes

33 Is legitimate anti-virus software installed on the client’s machine? Yes

34 Is virus scan scheduled periodically? Yes

35 Is spyware removal software installed and run periodically? Yes

Failure Management and Recovery

36 Are backups schedules at defined intervals? Yes

37 Does the recovery take a long time? Yes

38 In case of site crash, is there any provision to route to another server? Yes
39 Have recovery mechanisms been defined and tested? Yes

40 Is any criteria followed to ensure the completion and correction of recovery Yes
procedures?
Yes

General

41 Are any warning messages issued when the user enters or leaves the secured Yes
website?
42 Is the user allowed to login with the same account from different machines Yes
(simultaneously)?
43 Are unauthorised external sites identified and screened? Yes

44 Can the previous page be accessed after signing out from the website? Yes

45 Is the user able to access restricted pages after the session is timed out? Yes

46 Is auditing performed periodically in order to keep a record of all the Yes


operations?
47 Are all payment methods tested thoroughly? Yes

48 Are enough security mechanisms enforced, if customer registration is Yes


compulsory on your website?
49 Does the source code reveal any critical information? Yes

50 Does the application use digital signature to sign a file? Yes

Discussion: It is a process to determine that an information system protects data and


maintains functionality as intended. The security testing is performed to check whether there
is any information leakage in the sense by encrypting the application or using wide range of
software’s and hardware’s and firewall etc. Software security is about making software
behave in the presence of a malicious attack.

Result: It is necessary to perform Security Testing before the deployment of the website to
maintain its integrity. Thus it should be taken care to perform security testing to protect the
website from the attack of malicious users.
Program No: 15
Aim: Generate test cases for a shopping website using compatibility, navigational form
based ,usability and load testing techniques.

Theory: The main challenge of testing a web application is not only to find common
software errors, but also to test associated quality related risks that are specific to a web
application. We should know the architecture and key areas of web application to effectively
plan and execute the testing. Web applications are difficult and complex as compared to
traditional client-server applications. They are required to be tested on different browsers and
varied platforms. It is important and critical to identify the areas that need special focus while
testing a web application. A web application needs to be tested for:

(i) Functionality

(ii) Usability

(iii) Browser compatibility

(iv) Security

(v) Load and stress

(vi) Storage and Database

There are numerous issues that need to be considered that are specific to web application,
hence, only a sub-set of conventional testing techniques are applicable for testing a web
application.

Test Cases:

TEST CASE ID DESCRIPTION INPUT EXPECTED


OUTPUT

TC1 Search the product Search string List of items


gallery to decide searched are
which items to displayed.
purchase
TC2 Register on the Login id, password, If the information
website to place an confirm password, entered is valid the
order shipping details and user is registered
billing details. successfully, other-
wise appropriate
error is displayed.
TC3 1. Log into the 1.Login id, Item is successfully
website password added in the
2. Select item to be 2.item number ,item shopping cart.
purchased and its name ,quantity
quantity. 3.-
3. Add selected item
to the shopping cart.
TC4 1.Log into the 1.Login id, Item is not added in
website password the shopping cart.
2. Select item to be 2.item number ,item
purchased and its name ,quantity
quantity. 3.-
3. Do Not Add
selected item to the
shopping cart.
TC5 1. Log into the 1.Login id, Item are
website password successfully added
2. Select item to be 2.item number ,item in the shopping cart.
purchased and its name ,quantity
quantity. 3. item number
3. Add selected item ,item name ,quantity
to the shopping cart. 4. item number
4. Select some more ,item name ,quantity
items and add them
to the shopping cart.
TC6 1.Log into the 1.Login id, If deletion is
website password confirmed item is
2. Select item to be 2.item number ,item successfully deleted
purchased and its name ,quantity from the shopping
quantity. 3. item number cart.
3. Add selected item ,item name ,quantity
to the shopping cart. 4. item number
4. Delete one item
from the shopping
cart.
TC7 1.Log into the 1.Login id, If update is
website password confirmed quantity
2. Select item to be 2.item number ,item is successfully
purchased and its name ,quantity updated.
quantity. 3. item number
3. Add selected item ,item name ,quantity
to the shopping cart. 4. Quantity
4. Update quantity
of one item from the
shopping cart.
TC8 1.Log into the 1.Login id, User checks outs
website password from the shopping
2. Select item to be 2.item number ,item cart and total bill of
purchased and its name ,quantity the purchased items
quantity. 3. item number is displayed.
3. Add selected item ,item name ,quantity
to the shopping cart.
4.Checkout

TC9 1.Log into the 1.Login id, After authentication,


website password amount is
2. Select item to be 2.item number ,item transferred and
purchased and its name ,quantity items are delivered
quantity. 3. item number successfully.
3. Add selected item ,item name ,quantity
to the shopping cart. 4.
4. Checkout. 5. Bank name, credit
5. Enter valid credit card type, credit
card information. card number

TC10 1.Log into the 1.Login id, Appropriate error


website password message is
2. Select item to be 2.item number ,item displayed.
purchased and its name ,quantity
quantity. 3. item number
3. Add selected item ,item name ,quantity
to the shopping cart. 4.
4. Checkout. 5. Bank name, credit
5. Enter invalid card type, credit
credit card card number
information.

Compatibility testing:

Browser Firefox chrome IE-8 opera safari UC torch


Browser
Audio X X X X X
Video X X X X X X
Text X X X X X X X
Platforms:
Windows X X X X X X X
10: X X X X X X X
Windows 8: X X X X
Linux: X X X X X
Android:

Form X X X X X
Navigational testing:

Test case id Description Inputs Expected output


Tc1 Check all the links Link1=home Appropriate web
on the web page Link2=about us page is opened with
Link3=product respect to each
gallery other.
Link4=contact us
Link5=registration
Link6=shopping cart
Link7=order status
Link8=feedback
Tc2 Click on the all link Link1=home Appropriate
on each web page to Link2=about us horizontal and
test the appearance Link3=product vertical scroll bars
of content on each gallery are present and the
web page Link4=contact us user can view the
Link5=registration page content
Link6=shopping cart properly.
Link7=order status
Link8=feedback
Tc3 Search for items in Search string The user is able to
the available product navigate across
gallery multiple search
pages successfully
Tc4 Click back link - The appropriate web
present on each web page is displayed.
page

Form based testing:

Test case id Description Inputs Expected output


Tc1 Navigate using ta - The user follows the
from one field to correct sequence
another in other while navigating
form from one field to
another.
Tc2 Check max and min Login id, password, If the char are
length of all length confirm password, entered within the
of all fields in the shipping details and range, the
form billing details information is added
successfully;
otherwise an
appropriate error
message is
displayed.
Tc3 Check data Login id, password, If the char are
validations of all confirm password, entered valid, the
fields in the form. shipping details and information is added
billing details successfully;
otherwise an
appropriate error
message is
displayed.
Tc4 Check whether all Login id, password, If the required fields
the mandatory fields confirm password, are entered
are entered in the shipping details and successfully, the
form billing details information is added
successfully;
otherwise an
appropriate error
message is
displayed.

Load testing:

Usability testing :

Introduction
1. Do all the labels and yes
hyperlinks display a
meaningful title
2. Does any internal or external No
link provide incorrect details
3. Are appropriate error yes
messages displayed
wherever required
4. Do you frequently encounter Less
problems in the application
or not
Efficiency
5. How easily are features and Easy
updates downloadable
6. How easily are common task Very easy
performed
7. How frequently are errors Less
encountered while
navigating through the web
application
8. Is the response time a cause No
of frustration
9. How many pages are <3
accessed to complete a Task
10. How quickly does the web Fast
app recover from an error
Completeness
11. Are some features missing No
from the web app?
12. Are any additional control No
required
13. To what degree are you High
satisfied with web app
14. Are web pages well Yes
designed
15. Does the online help and Yes
documentation provide
enough info
Learnability
16. How easily is the user able Very easy
to learn the features of the
web page
17. Are the links menus and lists Very easy
are easily understandable
18. How often is the search High
feature used
19. How easily is it to return to Very easy
homepage
20. Can the features be used Yes
without any help and
assistance
Clarity and accuracy of
online and written
documentation
21 Is the terminology well Yes
understood
22. How easily are the topics Easy
found in the online help
23. Are the topic content No
sufficient in the help
24. How frequently was the Less
required topic found in the
help
25. Is online help useful when Yes
error message are
encountered
26. Do menus lists hyperlinks Yes
toolbars and tables operate
as stated
27. Are the steps to complete a Yes
task correctly stated
28. How helpful is the content Very useful
related to topics
General

29. How easily is the Very easy


information available in the
various sections
30. In context to other Difficult
competitive apps the given
web app was found to be
31. Would you like to use this Very high
web app frequently
32. Is correcting the mistakes Difficult
easy or difficult
33. How will you overall rate Good
this web app
Result: It is necessary to perform web based testing on web applications to ensure their
proper functioning
Program No: 16
Aim: Conduct a survey of different testing tools available. Prepare a presentation of
their advantages and disadvantages.

6. SELENIUM

Selenium is a set of different software tools each with a different approach to supporting test
automation. Most Selenium QA Engineers focus on the one or two tools that most meet the
needs of their project, however learning all the tools will give you many different options for
approaching different test automation problems. The entire suite of tools results in a rich set
of testing functions specifically geared to the needs of testing of web applications of all types.
These operations are highly flexible, allowing many options for locating UI elements and
comparing expected test results against actual application behavior. One of Selenium’s key
features is the support for executing one’s tests on multiple browser platforms.

Selenium first came to life in 2004 when Jason Huggins was testing an internal application at
ThoughtWorks. Being a smart guy, he realized there were better uses of his time than
manually stepping through the same tests with every change he made. He developed a
Javascript library that could drive interactions with the page, allowing him to automatically
rerun tests against multiple browsers. That library eventually became Selenium Core, which
underlies all the functionality of Selenium Remote Control (RC) and Selenium IDE.
Selenium RC was ground-breaking because no other product allowed you to control a
browser from a language of your choice.

Advantages:

1. Selenium is pure open source, freeware and portable tool.


2. Selenium supports variety of languages that include Java, Perl, Python, C#, Ruby, Groovy,
Java Script, and VB Script. etc.
3. Selenium supports many operating systems like Windows, Macintosh, Linux, Unix etc.
4. Selenium supports many browsers like Internet explorer, Chrome, Firefox, Opera, Safari
etc.
5. Selenium can be integrated with ANT or Maven kind of framework for source code
compilation.
6. Selenium can be integrated with TestNG testing framework for testing our applications
and generating reports.
7. Selenium can be integrated with Jenkins or Hudson for continuous integration.
8. Selenium can be integrated with other open source tools for supporting other features.
9. Selenium can be used for Android, IPhone, Blackberry etc. based application testing.
10. Selenium supports very less CPU and RAM consumption for script execution.
11. Selenium comes with different component to provide support to its parent which is
Selenium IDE, Selenium Grid and Selenium Remote Control (RC).

Disadvantages:

1. Selenium needs very much expertise resources. The resource should also be very well
versed in framework architecture.
2. Selenium only supports web based application and does not support windows based
application.
3. It is difficult to test Image based application.
4. Selenium need outside support for report generation activity like dependence on TestNG or
Jenkins.
5. Selenium does not support built in add-ins support.
6. Selenium user lacks online support for the problems they face.
7. Selenium does not provide any built in IDE for script generation and it need other IDE like
Eclipse for writing scripts.
8. Selenium Automation Engineers are bit in scarcity these days.
9. Selenium script creation time is bit high.
10. Selenium does not support file upload facility.
11. Selenium partially supports for Dialog boxes.

7. FitNesse:

FitNesse is a web server, a wiki and an automated testing tool for software. It is based
on Ward Cunningham's Framework for Integrated Test and is designed to support acceptance
testing rather than unit testing in that it facilitates detailed readable description of system
function.
FitNesse allows users of a developed system to enter specially formatted input (its format is
accessible to non-programmers). This input is interpreted and tests are created automatically.
These tests are then executed by the system and output is returned to the user. The advantage
of this approach is very fast feedback from users. The developer of the system to be tested
needs to provide some support (classes named "fixtures", conforming to certain conventions).
FitNesse is written in Java (by Robert C. Martin and others). The program first supported
only Java, but versions for several other languages have been added over time (C++, Python,
Ruby, Delphi, C#, etc.).
FitNesse as a testing tool
Tests are described in Fitnesse as some sort of coupling of inputs and expected output. These
couplings are expressed as some sort of variation of a decision table. The FitNesse tool
supports several of these variations, ranging from literal decision tables to tables that execute
queries to tables that express testing scripts (i.e. a literal ordering of steps that must be
followed to reach a result). The most generic form is a fully free-form table that can be
interpreted in any way the test designers like. All tests are expressed in the shape of some sort
of table, however.
FitNesse is focused entirely on easily creating tests, allowing testers and developers to focus
on creating high-quality tests rather than getting lost in the mechanics of executing a test.
Given the way FitNesse works, creating tests easily involves three factors:

 Creating tables easily.


 Easily translating tables into calls to the system under test.
 Allowing ease and flexibility in documenting tests.

Advantages:
 FitNesse tests can give us feature feedback very early in the project. In fact, the tests
ought to be written first, so programmers can code to the tests.
 FitNesse tests can give us feature feedback very frequently. They can be run
manually or automatically by anyone with web access to the server, as frequently as required.
Every week, every day, every hour in a crunch.
 FitNesse tests are deterministic: they either run green or red. If they run green for a
given requirement, either the requirement is done and we move on to others, or the set of tests
is not yet exactly right, in which case we refine them. Either way, we are successively
refining the system in an orderly way. With each new test running green, we can all see the
system getting better, more valuable, closer to what we need.
 Being based on example data, FitNesse tests exercise more paths through the
business logic. When you use FitNesse, you run less risk of missing important features or
functional behavior.

Disadvantages

6.No capture & replay possible


7.Cannot explicitly test a web frontend
8.Web interface can make setting up expectations time consuming
9.Learning curve to understand the framework is steeper if we have to modify the
framework.
a. WATIR

Watir (Web Application Testing in Ruby, pronounced water), is an open-source (BSD)


family of Ruby libraries for automating web browsers. It drives Internet
Explorer, Firefox, Chrome, Opera and Safari, and is available as a RubyGems gem. Watir
was primarily developed by Bret Pettichord and Paul Rogers.

Functionality
Watir project consists of several smaller projects. The most important ones are watir-classic,
watir-webdriver and watirspec.
Watir-classic

Watir-classic makes use of the fact that Ruby has built in Object Linking and
Embedding (OLE) capabilities. As such it is possible to drive Internet Explorer
programmatically. Watir-classic operates differently than HTTP based test tools, which
operate by simulating a browser. Instead Watir-classic directly drives the browser through the
OLE protocol, which is implemented over the Component Object Model (COM) architecture.
The COM permits interprocess communication (such as between Ruby and Internet Explorer)
and dynamic object creation and manipulation (which is what the Ruby program does to the
Internet Explorer). Microsoft calls this OLE automation, and calls the manipulating program
an automation controller. Technically, the Internet Explorer process is the server and serves
the automation objects, exposing their methods; while the Ruby program then becomes the
client which manipulates the automation objects.

Pros:
1. No external server needed to run a test. Just run "ruby test.rb" and it goes, this
simplifies any scripts you use to execute your tests through continuous integration
servers like Hudson or Bamboo or whatever.
2. GREAT API! this is the kind of API rubyists dream of... its easy and fun and once you
get the basics you can just guess how to write the code without needed alot of
documentation.
3. Tests can often be run through alternative tools... watir-webdriver, webrat, celerity and
more all more-or-less support the watir API. This means that if you write your
framework carefully you are not locked in to watir... its hard to overstate the value of
this.
4. only works in ruby (not jruby), BUT watir-webdriver does work in both ruby and jruby
(see above point)
5. Havent really had much issue dealing with AJAX, watir always seems to know when the
page is "loaded"
6. Typically runs faster than a comparable selenium test.
7. Better support for headless browsers, see Celerity.

Cons:

6. Each browser's implementation is a little bit different, and the driver for each browser is
written independently. This can mean inconsistent test results between browsers, but it
hasnt really been much an issue for me.
7. api is ruby only (but if you use ruby, this is actually an advantage because you get a
truly ruby-esque tool)
8. doesnt seem to be as widely used as selenium, a lil bit harder to find engineers (finding
good ones is pretty much impossible)

b. Quick Test Professional


HP Unified Functional Testing (UFT) software, formerly known as HP QuickTest
Professional (QTP), provides functional and regression test automation for software
applications and environments. HP Unified Functional Testing can be used for enterprise
quality assurance.
HP Unified Functional Testing supports keyword and scripting interfaces and features a
graphical user interface. It uses the Visual Basic Scripting Edition (VBScript) scripting
language to specify a test procedure, and to manipulate the objects and controls of the
application under test.
HP Unified Functional Testing was originally written by Mercury Interactive and called
QuickTest Professional.Mercury Interactive was subsequently acquired by Hewlett
Packard(HP) in 2006. HP Unified Functional Testing 11.5 combined HP QuickTest
Professional and HP Service Test into a single software package, which is currently available
from the HP Software Division. The integrated HP Unified Functional Testing software
allows developers to test from a single console all three layers of a program's operations: the
interface, the service layer and the database layer.
Advantages:

1. QTP has record and playback facility with editing the scripts generated after the recording
is completed. It supports different recording mode i.e. Normal, Analog and Low level which
facilitates to automate different types of applications.
2. QTP supports almost all popular automation frameworks like Linear, Keyword, Data
Driven, Hybrid etc. for automation purpose.
3. QTP is very much user friendly and anyone can start using it very less expertise.
4. QTP has built in IDE associated which is very much easy to use.
5. Its primary scripting language is VB script, thus it does need skilled code to start
automation work. Also this tool is packed with many add-ons which supports it very much.
6. QTP can be integrated with one of the most useful test management tool i.e. Quality Center
(QC). This integration very much supports the testing activity.
7. One of the most important features of QTP is Object Repository which is useful to store
the property of the objects which is being tested.
8. QTP has very excellent Object Identification process.
9. QTP also supports Object Spy mechanism to identify object properties associated.
10. QTP supports many add-ins like Peoplesoft, Java, .Net, Siebel, Visual Basic, Web
Service, SAP, ActiveX, Silver Light, Java etc.
11. QTP supports built in Database testing. It uses excel or Data tables in very expertise
manner.
12. QTP provides very good parameterization, navigation, script edition, result validation etc.
features.
13. QTP has excellent support for reporting to show the test result.
14. QTP also provide online support for their users.

Disadvantages:

1. QTP is used with license and the license cost of using it is very high.
2. For getting online support we need to keep on the license renewal.
3. QTP supports many add-ins, but for using it we need to buy it.
4. QTP takes loads of RAM and CPU and comparatively slow in execution.

c. WebLOAD
WebLOAD is load testing tool, performance testing, stress test web applications. This web
and mobile load testing and analysis tool is from RadView Software. Load testing tool
WebLOAD combines performance, scalability, and integrity as a single process for the
verification of web and mobile applications. It can simulate hundreds of thousands of
concurrent users making it possible to test large loads and report bottlenecks, constraints, and
weak points within an application.
Using its multi-protocol support, WebLOAD simulates traffic of hundreds of thousands of
users and provides analysis data on how the application behaves under load. WebLOAD
monitors and incorporates statistics from the various components of the system under test:
servers, application server, database, network, load-balancer, firewall, etc., and can also
monitor the End User Experience and Service Level Agreement (SLA) compliance in
production environments.
WebLOAD's features include:

6. IDE An integrated development environment for visually recording, editing & debugging
load test scripts. WebLOAD's proxy-based recorder records HTTP activity. Test are
generated in JavaScript and can be enhanced and edited using various tools in the IDE.[7]
7. Correlation Automatic correlation of dynamic values such as Session IDs, enables a
script to be executed dynamically with multiple virtual clients.
8. Load Generation WebLOAD generates load from on-premises machines or from the
cloud.[10]
9. Analytics A set of predefined analysis reports provides performance data, helping users
identify bottlenecks. Reports and analysis data can also be viewed remotely via a
customizable Web Dashboard.[11]
10. PMM Collects server-side statistics during test runs, providing users with additional data
for root-cause analysis.
11. Web Dashboard Analyzing performance test results from any browser or Mobile device.

Advantages:

4. Uses Java script for script programming


5. Allows for session handling, outside of cookies
6. Supports Ajax, SOAP and Web services
7. Has a Forum for Support related question
8. Allows for automated script recording
9. Allows for use of any COM or Java object in the test script
10. Has debugging features of script etc.
11. Supports command line execution and enable a scheduled run
12. Has a separate performance monitoring program
Disadvantages:

1) Some developers complain that Web Load is not an open source in true sense.
Contrary to what their press release and website says, it contains proprietary
components that are released in binary form with no source code
d)HP Unified Functional Testing
HP Unified Functional Testing (UFT) software, formerly known as HP QuickTest
Professional (QTP), provides functional and regression test automation for software
applications and environments. HP Unified Functional Testing can be used for enterprise
quality assurance.
HP Unified Functional Testing supports keyword and scripting interfaces and features a
graphical user interface. It uses the Visual Basic Scripting Edition (VBScript) scripting
language to specify a test procedure, and to manipulate the objects and controls of the
application under test.
HP Unified Functional Testing was originally written by Mercury Interactive and called
QuickTest Professional. Mercury Interactive was subsequently acquired by Hewlett
Packard(HP) in 2006. HP Unified Functional Testing 11.5 combined HP QuickTest
Professional and HP Service Test into a single software package, which is currently available
from the HP Software Division. The integrated HP Unified Functional Testing software
allows developers to test from a single console all three layers of a program's operations: the
interface, the service layer and the database layer.
Advantages:

1. QTP has record and playback facility with editing the scripts generated after the recording
is completed. It supports different recording mode i.e. Normal, Analog and Low level which
facilitates to automate different types of applications.
2. QTP supports almost all popular automation frameworks like Linear, Keyword, Data
Driven, Hybrid etc. for automation purpose.
3. QTP is very much user friendly and anyone can start using it very less expertise.
4. QTP has built in IDE associated which is very much easy to use.
5. Its primary scripting language is VB script, thus it does need skilled code to start
automation work. Also this tool is packed with many add-ins which supports it very much.
6. QTP can be integrated with one of the most useful test management tool i.e. Quality Center
(QC). This integration very much supports the testing activity.
7. One of the most important features of QTP is Object Repository which is useful to store
the property of the objects which is being tested.
8. QTP has very excellent Object Identification process.
9. QTP also supports Object Spy mechanism to identify object properties associated.
10. QTP supports many add-ins like Peoplesoft, Java, .Net, Siebel, Visual Basic, Web
Service, SAP, ActiveX, Silver Light, Java etc.
11. QTP supports built in Database testing. It uses excel or Data tables in very expertise
manner.
12. QTP provides very good parameterization, navigation, script edition, result validation etc.
features.
13. QTP has excellent support for reporting to show the test result.
14. QTP also provide online support for their users.

Disadvantages:

1. QTP is used with license and the license cost of using it is very high.
2. For getting online support we need to keep on the license renewal.
3. QTP supports many add-ins, but for using it we need to buy it.
4. QTP takes loads of RAM and CPU and comparatively slow in execution.
5. QTP supports limited version of browsers for script execution
6. QTP does not support multithreading i.e. running multiple instance of script in different
browsers at same time.
DELHI TECHNOLOGICAL
UNIVERSITY

SOFTWARE TESTING LAB FILE

Submitted by- Tarun verma


2k14/SE/094
INDEX
S. No Aim Date Remarks
1. Generate Testcases using Boundary Value
Analysis

2. Generate Testcases using Robust Testing

3. Generate Testcases using Worst Case BVA

4. Generate Testcases using Worst Case


Robust Testing

5. Generate Testcases using Equivalence


Class Testing

6. Generate Testcases using Decision Table


based Testing

7. Program to find Cyclomatic Complexity of


the program

8. WAP to input graph matrix and find


number of independent paths

9. WAP to perform Mutation Testing

10. Program to perform testing using Cause


Effect Graphing Technique

11. Analyse programs with static analysis tool


CPP check

12. WAP to generate Control Flow Graph and


DD Path graph

13. WAP to generate graph matrix and


compute number of independent paths

14. Security Testing of a website

15. Testcases for shopping website using


functional, navigational, compatibility
testing

16. Conduct a survey of different Testing


Tools

You might also like