You have been provided StudentDirectory for Lab 01. However, when provided code, you should always inspect it to understand the functionality, learn new things about programming, and possibly find bugs. Additionally, you were provided some unit tests for StudentDirectory, but not enough to meet the 80% statement coverage threshold for StudentDirectory. You will write additional unit tests to fully cover StudentDirectory.
StudentDirectory represents a list of Student records in our system. In this section, you will read through the provided StudentDirectory code to understand how it works, and then write unit tests to verify it meets the requirements. The method descriptions below describe what each method should do. You will write unit/integration tests to ensure that the methods do these things correctly. If you find any bugs in StudentDirectory (it is possible, but hopefully unlikely), please let the teaching staff know. That way we can share with the rest of the class so everyone moves forward with bug free code!
There are several resources provided for writing tests, including sample test code:
- Testing Packet
- Dr. Heckman’s Testing Lecture Notes
- Seasons Test Example
- Dr. Heckman’s Coverage and Static Analysis Lecture Notes
- Guided Project 1 CourseTest.java
Note that the tests for StudentDirectory are similar to the tests for WolfScheduler in Guided Project 1. You may use those tests as examples and reference!
Testing Strategies
Your goal is to achieve at least 80% statement coverage by writing high quality tests that exercise most of the paths in StudentDirectory. Note: Line/statement coverage is the primary metric used for grading. There is 1 point of extra credit for exceeding 90% statement coverage, an additional point for obtaining at least 96% statement coverage, and a third point of extra credit for achieving 100% condition/branch coverage!
Make sure you are frequently running your tests! If you find a bug in StudentDirectory (it is possible, but hopefully unlikely), please let the teaching staff know so that we can share the information with the rest of the class. You should fix the bug.
You will need to use similar strategies for handling hashed passwords that you used when testing StudentRecordIO.
By this point you should have enough practice with testing to start thinking of your own tests for each of these methods!
Understanding StudentDirectory
Before writing tests, read through the provided StudentDirectory code to understand what each method does. The descriptions below explain the intended behavior.
StudentDirectory State
StudentDirectory has an ArrayList of Students that represent the student directory for the university.
There is also a constant value for the hash algorithm used to hash the passwords when adding a new Student. We’re using SHA-256. By providing the hash algorithm as a constant, we reduce the chance of throwing a NoSuchAlgorithmException due to a mistype.
StudentDirectory Constructor
The StudentDirectory constructor initializes the studentDirectory field by calling the newStudentDirectory() method.
newStudentDirectory()
This method supports the functionality for a new student directory described in [Use Case 2: Create Student Directory]. studentDirectory is updated to refer to a new ArrayList of Students (which is then empty).
loadStudentsFromFile()
This method supports the functionality for loading a list of student records from a file as described in [Use Case 3: Load Student Directory]. If the call to StudentRecordIO.readStudentRecords() throws a FileNotFoundException, a new IllegalArgumentException is thrown. The provided message may be used in a dialog as described in [Invalid File].
You will need to use similar strategies for handling hashed passwords that you used when testing StudentRecordIO.
saveStudentDirectory()
This method saves the studentDirectory to the given file as described in [Use Case 4: Save Student Directory]. If StudentRecordIO.writeStudentRecords() throws an IOException, a new IllegalArgumentException is thrown. The provided message may be used in a dialog as described in [UC4]. Use the same strategy to cause an IOException that you used when testing StudentRecordIO.writeStudentRecords() for full coverage.
addStudent()
This method supports the functionality for adding a Student to the list of students as described in [Use Case 5: Add Student to Student Directory]. The method also covers several Alternative Flows for Use Case 5. The first grouping of error messages come from IllegalArgumentExceptions thrown during construction of Student or when checking the password and repeatPassword parameters.
The first few lines in the method ensure that there are values for the password and repeatPassword parameters. If there are values, then these values are hashed. We use the private helper method hashString() to hash the provided passwords with SHA-256, then encode the output using Base64 so that the binary data of the hashed password is represented in ASCII format. Do NOT change the hashString() method!
After hashing the passwords, checks are done to ensure that the student can be successfully added to the StudentDirectory.
By returning false, the method triggers the [Non-unique ID] behavior in the GUI.
An error related to “Cannot hash password” should hopefully never happen, but an exception with an error message is provided in case it ever does. You will NOT be expected to write a test to cover this exception. If this is the only uncovered line in StudentDirectory, you will receive full extra credit.
removeStudent()
This method supports the functionality for removing a Student from the list of students as described in [Use Case 6: Remove Student from Student Directory].
getStudentDirectory()
This method returns a 2D array, where each row is a Student and the columns are for the firstName, lastName, and id. The 2D array is required so that the information can be displayed in the table used in the GUI.
You will need to use similar strategies for handling hashed passwords that you used when testing StudentRecordIO.
Write Tests for StudentDirectory
A partial set of unit tests for StudentDirectory has been provided in the starting project. These will help you with some initial debugging, but do not cover all possible scenarios outlined by the requirements.
Examine the provided StudentDirectoryTest class, then add additional tests to cover all the behavior described in the method descriptions above. Think about testing valid inputs, invalid inputs, boundary conditions, and the alternative flows described in the requirements.
Some test scenarios to consider:
- Constructing a
StudentDirectoryresults in an empty directory newStudentDirectory()clears an existing list of studentsloadStudentsFromFile()with a valid file loads the expected students in orderaddStudent()with all valid inputs returnstrueand adds the studentaddStudent()with a duplicate ID returnsfalseand does not add the studentaddStudent()with invalid input (null/empty password, mismatched passwords, invalid field) throwsIllegalArgumentExceptionremoveStudent()returnstruefor a student that exists and removes themremoveStudent()returnsfalsefor a student that does not existgetStudentDirectory()returns the correct 2D array of student informationsaveStudentDirectory()writes the expected output filesaveStudentDirectory()with an invalid file path throwsIllegalArgumentException
Javadoc your Code
Make sure that you Javadoc the StudentDirectoryTest class and methods.
StudentDirectory is already fully Javadoced, but if you would like to clarify the documentation to help your understanding of the code, do so.
Run CheckStyle to ensure that your Javadoc has all elements.
GitHub Resources:
Push to GitHub
Push your PackScheduler project to GitHub
- Add the unstaged changes to the index.
- Commit and push changes. Remember to use a meaningful commit message describing how you have changed the code.
Check the following items on Jenkins for your last build and use the results to estimate your grade:
Check Jenkins
At this point your project should build on Jenkins, hopefully with a green ball! If not, work through Jenkins’s feedback to fix any errors. All tests should be passing before you walk through the GUI.
