CompSci 307
Fall 2022
Software Design and Implementation

Practice Exercise: Unit Testing the Model

This exercise is intended to help you practice creating automated test suites that can be run as often as needed to test the Model side of the program, not just the most recent version of the code.

JUnit, the most common automated framework for Java, focuses on testing individual methods and it has inspired similar frameworks in almost every other modern language and is built in to all major IDEs, including IntelliJ. It has even been important in changing developers habits, by practicing of test-driven development (TDD), so they produce tests along with their code features (and, better yet, before writing their code) instead of waiting until the code is complete.

Submitting your Work

At the end of lab, use Gitlab's Merge Request from your forked repository's master branch back to the original organization repository's master branch to submit your refactored code. You only need to create one Merge Request, no matter how many commits you make, and you do not worry about potential conflicts since your request will not be approved (it is just an easy way for us to see what changes you made).

Make sure the Title of your Merge Request is of the form "lab_unittest - participating NETIDs".

Resources

Workflow

Here is a review of the steps you will use to work with GIT during lab (as distinct from assigned team projects):

  1. On Gitlab, one person should fork the original project lab_unittest into their own repository to allow pushing your group's changes
    • On the resulting project web page, go to Settings -> Members to add your partner so both people in the group can access the same repository
    • Search for your partner's name and give them a Maintainer role in the project and choose Add to Project
  2. In Terminal, all students should use git clone to copy the one forked repository to their individual machines so they can work on their own separate copies
  3. In IntelliJ, all students should Open the cloned folder to create a new project on their personal machine
  4. As a group, discuss useful tests for the current code and study what tests currently exist
  5. In IntelliJ, write new tests for (and, as needed, debug) the code using Pair Programming, making sure each person gets to write a variety of tests and that every few tests, you add, commit, and push your changes
    Write as many tests as you can think of to verify the code and, in the process, find any bugs or other issues with the code using these steps:
    1. Add a new JUnit test to verify whether or not the code works as intended
    2. Run all the tests to verify they all continue to pass (both the old and new tests show green)
    3. If you find a bug: (i.e., a test fails by showing red)
      1. Comment out the buggy code
      2. Write a comment telling the cause of the error
      3. Write the correct code that fixes the error
    4. Again, run all the tests to verify they all continue to pass

Specifications

Consider the following questions as you try to come up with useful scenarios to test the program:

  1. What would be the most simple data you could make to test the program does something reasonable?
  2. What "special cases" does the program check for (or not)?
  3. What "categories" does program behavior naturally fall into? What data shows the boundaries of those categories?
  4. What "bad" data values you can think of and what checks would you add to the code to make it more robust from failure or a nonsensical answer?

Resist the urge to simply create a lot of "random" tests (i.e., the shotgun approach) and focus on making each test as useful as possible (i.e., the sniper approach).

Each test should be:

You can also check which lines of code are not executed by your tests.

Buggy Programs

When you are done testing these projects, both the original tests and your new tests should pass.

Bins

This is the refactored version of the Bins program (imagine trying to test its original version!)

Several tests are already written for this project, so try to think about unusual data values, odd situations, and actual errors that may not be covered in the existing code. This should result in needing to write new code for either class and, of course, tests for that new code. Tests can be in the form of input data files, strings to represent example data, or constructing an exact collection to that verify every line of code written works as intended.

Container

This is a very buggy example in a few lines of code, even though the given tests all pass!

There are at least 5 errors in the code. Update the JUnit code by writing only new tests to verify the existing bugs. How you fix the bugs is entirely up to you, but fix one at a time to emphasize thinking about different strategies for what to test (e.g., do not simply change the implementation to an ArrayList and fix all the compilation errors since that will likely fix most of the bugs without you having to think about tests for each).

Pair Programming

Labs in this course expect you to work either in pairs or with your project team.

Professionally, this practice is called Pair Programming: working closely with another programmer, sharing a "single computer" that we will simulate using a shared computer, shared repository or use IntelliJ's new Code With Me feature. To ensure both people do some coding, you will switch which person actually writes the code every 10-15 minutes (in industry this switch happens only 1-3 times per day). The person who is not actively coding can be advising, suggesting better names, looking up documentation, or searching the Internet for solutions to small problems you are likely to face, but not multi-tasking (i.e., doing their own work or socializing).