In: Computer Science
What is the purpose of the following code and a detailed testing scope that can be made by looking at the following code to check for bugs or software testing measures such as statement coverage or branch coverage checks in the code.
import java.io.*;
public class Cal
{
public static int cal (int month1, int day1, int month2,
int day2, int year)
{
//***********************************************************
// Calculate the number of Days between the two given days in
// the same year.
// preconditions : day1 and day2 must be in same year
// 1 <= month1, month2 <= 12
// 1 <= day1, day2 <= 31
// month1 <= month2
// The range for year: 1 ... 10000
//***********************************************************
int numDays;
if (month2 == month1) // in the same month
numDays = day2 - day1;
else
{
// Skip month 0.
int daysIn[] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30,
31};
// Are we in a leap year?
int m4 = year % 4;
int m100 = year % 100;
int m400 = year % 400;
if ((m4 != 0) || ((m100 == 0) && (m400 != 0)))
daysIn[2] = 28;
else
daysIn[2] = 29;
// start with days in the two months
numDays = day2 + (daysIn[month1] - day1);
// add the days in the intervening months
for (int i = month1 + 1; i <= month2-1; i++)
numDays = daysIn[i] + numDays;
}
return (numDays);
}
public static void main (String[] argv)
{ // Driver program for cal
int month1, day1, month2, day2, year;
int T;
System.out.println ("Enter month1: ");
month1 = getN();
System.out.println ("Enter day1: ");
day1 = getN();
System.out.println ("Enter month2: ");
month2 = getN();
System.out.println ("Enter day2: ");
day2 = getN();
System.out.println ("Enter year: ");
year = getN();
// preconditions : day1 and day2 must be in same year
// 1 <= month1, month2 <= 12
// 1 <= day1, day2 <= 31
// month1 <= month2
// The range for year: 1 ... 10000
if ( (month1 < 1) || (month1 > 12) )
{
month1 = 1;
System.out.println ("invalid month1, choosing 1.");
}
if ( (month2 < 1) || (month2 > 12) )
{
month2 = 1;
System.out.println ("invalid month2, choosing 1.");
}
if ( (day1 < 1) || (day1 > 31) )
{
day1 = 1;
System.out.println ("invalid day1, choosing 1.");
}
if ( (day2 < 1) || (day2 > 31) )
{
day2 = 1;
System.out.println ("invalid day2, choosing 1.");
}
while ( month1 > month2 )
{
System.out.println ("month1 must be prior or equals to
month2");
System.out.println ("Enter month1: ");
month1 = getN();
System.out.println ("Enter month2: ");
month2 = getN();
}
if ( (year < 1) || (year > 10000) )
{
year = 1;
System.out.println ("invalid year, choosing 1.");
}
T = cal (month1, day1, month2, day2, year);
System.out.println ("Result is: " + T);
}
// ====================================
// Read (or choose) an integer
private static int getN ()
{
int inputInt = 1;
BufferedReader in = new BufferedReader (new InputStreamReader
(System.in));
String inStr;
try
{
inStr = in.readLine ();
inputInt = Integer.parseInt(inStr);
}
catch (IOException e)
{
System.out.println ("Could not read input, choosing 1.");
}
catch (NumberFormatException e)
{
System.out.println ("Entry must be a number, choosing 1.");
}
return (inputInt);
} // end getN
}
The purpose of the program is to calculate the number of days between the two given days in the same year. The program would take all considerations of leap year or non-leap year while calculating these number of days between any two days of the year.
The preconditions are:
i) day1 and day2 must be in the same year
ii) 1 <= month1, month2 <= 12
iii) 1 <= day1, day2 <= 31
iv) month1 <= month2
v) range for year: 1 ... 10000
100% statement coverage ensures all lines of code are executed at least once for all the test cases and 100% branch coverage ensures all conditions of an if-else block are covered.
A detailed testing scope includes testing:
1) If the year is leap year or not.
In the Gregorian calendar, a normal year consists of 365 days. The actual length of a year is 365.2425 days. Therefore, a "leap year" of 366 days is used once every four years. So 2004, 2008, and 2012 are leap years, as all these years are evenly divisible by 4.
However, according to the Gregorian calendar, every year that is evenly divisible by 100 (for example, 1900) is a leap year if and only if it is also evenly divisible by 400.
The following years are leap years: 1200, 1600, 2000, 2400
This is because they are evenly divisible by both 100 and 400.
However, the following years are not leap years:
1300, 1500, 1700, 1800, 1900, 2100, 2200, 2300, 2500, 2600
This is because they are evenly divisible by 100 but not by 400.
Example of such a sample test case:
Here, the answer result in the program is correct since 1900 is not a leap year. You have to also test with another non-leap year like 2019 for 100% branch coverage. You have to also test with the same day1, month1, day2, and month2 values in a leap year like 2020. You will get the answer as 9.
2) If day1 and day2 are in the same month
If day1 and day2 are in the same month, the result of the program should be correct. Here, there is a bug in the program as it always considers no. of days in a particular month as 31, whereas it maybe 28, 29, 30, or 31. A sample test case can be:
Here, the answer is wrong. The day2 entered is invalid since we have tried to find the no. of days between 10th Feb and 30th Feb in the year 2020.
3) If day1 and day2 are in different months
If day1 and day2 are in different months, the result of the program should be correct. The program should consider all the intervening months in between the two given months. A sample test case can be:
Here, the answer is correct as we are trying to find the no. of days between 15th January and 15th May, 2019 which is 16+28+31+30+15 = 120.
4) Testing the pre-conditions
For 100% branch coverage, you need to test all anomalies in entering month1, month2, day1, and day2 values. You need to enter test cases where
i) month1 is 0. (month1<1)
ii) month1 is 13. (month1>12)
iii) month2 is 0. (month2<1)
iv) month2 is 13. (month2>12)
v) day1 is 0. (day1<1)
vi) day1 is 32. (day1>31)
vii) day2 is 0. (day2<1)
viii) day2 is 32. (day2>31)
ix) month1 > month2 (Ex. month1 is 10 & month2 is 5)
x) year is 0. (year<1)
xi) year is 10001. (year>10000)
5) Testing code inside catch block
For 100% statement coverage, we need to test the code inside catch block. NumberFormatException can be easily reached if we do not enter integers for any of the inputs for month1, month2, day1, day2, or year. A sample test case can be:
Here, code inside the catch NumberFormatException exception is reached.
One good example of IOException is EOFException which will be thrown if you try to read characters from a file but you have hit the end of the file. In this way, the code inside the IOException is reached.