Test Driven Design
Test driven design, TDD, means writing automated tests for the code before writing the code itself, i.e., designing the how the code's interface by figuring out how to test it. The goal of this process is to create a rhythm of programming where you first write a test, run it, and see it fail (as expected), then you write new code that is focused on making that test pass, run it, and see it pass (as hoped for). Besides helping to regularize your programming sessions, it provides a host of other benefits and even more!
Getting Started
For this lab exercise, it is suggested that you work together with one other person in the class:
- One person should fork the original lab_tdd repository into your own account to provide a place to edit, commit, and push changes
- On the resulting project web page, go to
Settings -> Membersto add your partner so both people in the group can access the same repository - Search for your partner's name and give them a
Maintainerrole in the project and chooseAdd to Project - Both students should clone the one forked repository to their individual machines so they can work on their own separate copies
- Import the project into IntelliJ (
New -> Project From Existing Sources)using the folder you just created (and just accept the defaults for all the options by selectingNext)
- Once the project window appears, you will need to do a few more steps to get it to run:
- Select
File -> Project Structureand then selectLibrarieswithin the dialog that appears - Right click on the
junitlibrary and selectAdd to Modules - Click
OKin the dialog that appears andOKagain to close the Project Settings dialog - Click to expand the folders
src -> debugto find the Java classContainerArrayTest - Right click on this class to run it by selecting "Run ContainerArrayTest"
- Select
- Run the program to verify that your Java installation is working.
If there are compilation errors or it does not run, then the project is not correctly configured.
Unit Testing Debugging
In this exercise, you will write tests to verify existing code works as expected and update it to fix bugs that you discover. Try to establish a rhythm of first verifying a test fails (i.e., you see red) then fixing the bug in the class such that all the tests pass again (i.e., both old and new tests show all green).
Using the classes in the package debug, add to the JUnit code by writing additional tests to cover the that bugs exist within the ContainerArray class (it has at least 5 bugs). You should not modify the existing tests because they represent reasonable situations that all pass and so should continue to pass as you modify the existing code. How you decide to fix the code is up to you (although do not do the trivially simple way that fixes all the bugs by using an ArrayList) but you should not fix all the bugs at once, even if you think it would be easy to do so, because your goal is to first write tests that verify the bug exists so you have confidence each new test has value.
Make Tests of Your Own
Solve the following problem from scratch using TDD to try to establish a coding rhythm:
Write a set of classes to represent hands of cards (5 or 7 are the most common varieties) that can be compared based on their ranking in a Poker game (see rankings of different types of poker hands and odds for those hands). Note, hands that represent multiple types should report only the higher type (i.e., two pair instead of one pair, full house instead of three of a kind or one pair) and if two hands are of the same type, the one with the higher card values is ranked higher. To start, you may assume the Ace always takes on the highest value. Implement as many different hand types as you have time for and, if you have extra time, allow your deck to include jokers (i.e., wild cards).
First, write a test in a separate well named method that shows the intention of the test, annotated with @Test and with its own call to the appropriate kind of JUnit assert statement. Then write the most simple code to make that test pass (i.e., do not write a complex data structure until you need it).
To show you are truly following the TDD process, you should have a lot of GIT commits that go together in pairs (where the first one represents a test that fails and the next one represents code that causes that test to pass). Obviously that is not how you would typically commit your code to the repository but this is just to establish that you are doing the work in the correct order.
In order to see the process more clearly when working as a pair, we strongly suggest that one person writes the test and the other person writes the code that passes the test (so one person writes the first test, the next person writes the code and the next test, then the first person writes the next code and the next test, etc.).
Note, you will not need to write a Main class or main() method or interact with the user for this exercise since the tests should fully exercise the code.
If you are having trouble thinking of how to come up with appropriate tests to follow this process, here is TDD challenge that shows a series of tests in the order you might write them for a different application (and in an older version of JUnit).
Resources
Submission
At the end of class, use Gitlab's Merge Request to submit your code to the original organization repository (note, there is no discussion file for this lab). Make sure your NetID is in the title of your Merge Request and in comments within the main class.