Testing: File Input and Output
Paychecks Requirements
Raleigh’s Parks and Recreation Department hires landscapers to care for and maintain the city’s parks.
Skill Level
An employee has one of three skill levels; each with a hourly pay rate:
| Skill Level | Hourly Pay Rate ($) |
|---|---|
| Level 1 | $19.00 |
| Level 2 | $22.50 |
| Level 3 | $25.75 |
Deductions
All employees may opt in for insurance, which results in a deduction from their pay check.
| Deduction | Weekly Cost ($) |
|---|---|
| Option 1 - Medical Insurance | $24.50 |
| Option 2 - Dental Insurance | $15.30 |
| Option 3 - Vision Insurance | $5.25 |
Employees at skill level 3 may also opt to place up to 6% of their gross pay into a retirement account.
This version of the program inputs employee information through a file and outputs results to a file and error messages to the console. Error messages that are printed to the console can include input files that do not exist, improperly formatted/structured input files, invalid input values for employees, and invalid net pay values. Each file can contain information for multiple employees. Each line of the file will represent a single employee.
Input
The Paycheck program prompts the user input filename and output filename. If the filenames are invalid, the user will be reprompted.
for information about each Employee, including the name, level (1, 2, or 3), hours worked, retirement percent, and whether he or she has medical, dental, and vision insurances. This version of the program has extensive error checking and loops to allow for processing more than one paycheck at a time. The user is prompted for the number of paychecks and stores paycheck information.
Each line is structured in a tab delimited manner:
1
name<TAB>level<TAB>hours worked<TAB>medical<TAB>dental<TAB>vision<TAB>retirement %
Such that medical, dental, and vision are boolean values that represent whether the employee has the given type of insurance.
Output
The following information is printed to output file about each employee’s pay check:
- employee’s name
- hours worked for a week
- hourly pay rate
- regular pay for up to 40 hours worked
- overtime pay (1.5 pay rate) for hours over 40 worked
- gross pay (regular + overtime)
- total deductions
- net pay (gross pay – total deductions).
If the net pay is negative, meaning the deductions exceeds the gross pay, then an error is printed.
System Testing
For System Testing with file input and file output, we create test input files along with expected output files. We test valid and invalid input.
The test files should be in the test-tiles directory. There are input files and expected output files. The input files contain valid or invalid values and the expected output files record the expected results of the execution. You can compare the actual results of execution with the expected results visually, or the diff command may be used to compare the actual results and expected results. If there are any differences, they will be printed to the console. If there are no differences, the prompt will appear and there will be no output.
1
2
3
4
5
$ java -cp bin Paychecks
Input File: test-files/input_level01.txt
Output File: test-files/output_act_level01.txt
$ diff test-files/output_exp_level01.txt test-files/output_act_level01.txt
$
Unit and Integration Testing
If a method returns a non-null object, such as Scanner or PrintWriter, we would want to use the assertNotNull() method.
Testing that Objects Are Not Null
The JUnit library includes many different types of assert methods. We discussed many methods in the Unit and Integration Testing section. If a method returns a non-null object, such as Scanner or PrintWriter, we would want to use the assertNotNull() method.
| Method | Description |
|---|---|
assertNotNull(Object actual, String message) |
Assert that actual is not null. Fails with the supplied failure message. |
Paychecks.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Processes input file of paychecks.
*
* @param fileScanner Scanner to read file with paycheck information
* @param printWriter PrintWriter to write paycheck information to
*/
public static void processFile(Scanner fileScanner,
PrintWriter printWriter) {
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
try {
printWriter.println(processLine(line));
} catch (IllegalArgumentException e) {
System.out.println("Error reading line: " + line);
}
}
}
PaychecksTest.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* Testing contents of scanner
*
* @param expected expected scanner
* @param actual actual scanner
* @param message message for test
*/
public void testFileContents(Scanner expected, Scanner actual,
String message) {
int line = 0;
while (expected.hasNextLine()) {
line++;
if (actual.hasNextLine()) {
assertEquals(expected.nextLine(), actual.nextLine(),
message + ": Testing line " + line);
} else {
fail(message + ": Too few lines: line " + line);
}
}
if (actual.hasNextLine()) {
fail(message + ": Too many lines");
}
}
/**
* Test the Paychecks.processFile() method.
*
* @throws FileNotFoundException if file stream cannot be constructed
*/
@Test
public void testProcessFile() throws FileNotFoundException {
// TEST 1
String message = "Testing file of multiple invalid";
String inputFile = "test-files/input_MULTIPLE_INVALID.txt";
String expectedFile = "test-files/UNIT-output_exp_MULTIPLE_INVALID.txt";
String outputFile = "test-files/UNIT-output_act_MULTIPLE_INVALID.txt";
Scanner in = new Scanner(new FileInputStream(inputFile));
PrintWriter out = new PrintWriter(new FileOutputStream(outputFile));
Paychecks.processFile(in, out);
in.close();
out.close();
Scanner actual = new Scanner(new FileInputStream(outputFile));
Scanner expected = new Scanner(new FileInputStream(expectedFile));
testFileContents(expected, actual, message);
expected.close();
actual.close();
}
