Run the tests and read a failure: knowing your work is right before you push
Week 0 onboarding. About 15 minutes to read, then about 10 minutes to run the tests on your own lab once. Your lab comes with a set of tests already written. Running them is how you know your code is right before you push, the same way the course grader will check it after the deadline. This lesson shows the one command that runs them and, more importantly, how to read the result when a test fails, because a failing test is not a scolding. It is a precise to-do list. Every command below was run on the real course project, and the output blocks are copied from those real runs, trimmed to the lines that matter, so this matches what you will see.
The one promise of this lesson. By the end you can run your lab's tests from the terminal, tell a pass from a fail at a glance, and read a failure well enough to know exactly which method to fix next. That single skill, run and read and fix, is the loop you live in for every lab.
Before you start
You should be able to tick each of these. If one is shaky, do the matching Week 0 onboarding lesson first.
- [ ] I have accepted a lab on Canvas and cloned the repository to my machine.
- [ ] I can open a terminal in my project folder.
- [ ] I know that the course grader runs on my pushed repository after the deadline.
Why run the tests yourself, when the grader runs them anyway
The grader runs once, after the deadline, on your final commit. If that were the only time your code got checked, you would be flying blind all week and finding out your score when it is too late to change it. The tests in your repository are the same kind of check, and you can run them as often as you like, for free, before you push. That is the professional habit this trains: you decide your work is ready by testing it yourself, the way you will on the job, instead of pushing and hoping. The tests are written for you in Week 0 labs; from Lab 1 on, some of them are yours to make pass.
Atom 1: the one command that runs the tests
From your project folder, run the project's test task:
./gradlew test
gradlew is the gradle wrapper, a small script in your repository that runs the build for you, so you do not
have to install anything. test is the task that compiles your code and runs every test. The first run takes
a few seconds while it starts up; later runs are faster.
Check yourself. You are not sure whether you are in the right folder. What file should you see sitting
right next to your src folder that tells you ./gradlew will work here?
Atom 2: what passing looks like
When your code is right, every test passes and gradle ends with success:
> Task :test
BUILD SUCCESSFUL in 8s
BUILD SUCCESSFUL is the whole message: it compiled, and every test passed. One thing that surprises people:
if you run ./gradlew test again without changing anything, gradle prints UP-TO-DATE next to the tasks and
does not re-run them, because nothing changed since the last green run. That is gradle being efficient, not a
problem. Change a file, and it runs them again.
Check yourself. You run ./gradlew test, get BUILD SUCCESSFUL, then immediately run it again and see
UP-TO-DATE and no test output. Did your tests stop running?
Atom 3: reading a failure (this is the real skill)
Here is a real failing run, from the course project with compareTo left as an unwritten stub that just
returns 0. Look at it before reading the explanation:
> Task :test FAILED
CourseTest > identity: equals and hashCode (Week 1, yours to write) > same code, section, and term are equal PASSED
CourseTest > natural order: compareTo (Week 1, yours to write) > orders by course code first FAILED
org.opentest4j.AssertionFailedError at CourseTest.java:79
CourseTest > natural order: compareTo (Week 1, yours to write) > breaks ties on section, then term FAILED
org.opentest4j.AssertionFailedError at CourseTest.java:88
CourseTest > natural order: compareTo (Week 1, yours to write) > a TreeSet keeps two sections that differ only by section number FAILED
org.opentest4j.AssertionFailedError at CourseTest.java:99
14 tests completed, 5 failed
> There were failing tests. See the report at:
file:///.../build/reports/tests/test/index.html
BUILD FAILED in 3s
Read it from the bottom up. BUILD FAILED and 14 tests completed, 5 failed is the headline: most tests
pass, five do not. Now read which five. Every failing line names the test, and the names were written to tell
you what is missing: orders by course code first, breaks ties on section, then term, a TreeSet keeps two
sections. They are all under compareTo, and the equals tests passed. That is the failure telling you,
precisely, that your compareTo is the thing to write next, and nothing else. The line at CourseTest.java:79
is the exact assertion that failed, so you can open the test and see what it expected.
A failing test is a to-do list with line numbers, not a judgment. The report link opens a page that shows the expected value next to the actual value for each failure, which is the fastest way to see how your output differs from what the test wanted.
Check yourself. Your run says 12 tests completed, 3 failed, and all three failing names are under
fromCsvRow, while every compareTo test passed. Which method do you work on, and which one do you leave
alone?
Atom 4: the red-to-green loop
The whole job is to turn red into green, one failure at a time. The loop is small and you run it constantly:
- Run
./gradlew testand read the first failure. - Open the named method and the named test line, and make that one test pass.
- Run
./gradlew testagain. One fewer failure, or a new clue. - Repeat until
BUILD SUCCESSFUL.
Commit each time a test goes from red to green, so each commit is a real step forward you can return to. This is the single most important habit in the course, and it is exactly how professionals work: small change, run the tests, small change, run the tests.
Check yourself. You fix one method and your failures drop from five to two, but one of the two is a test that passed a minute ago. What does that tell you?
If it goes wrong
Gradle cannot find Java, or uses the wrong version
If the first run complains it cannot find a JDK or names a Java version older than the one the course uses, the
fix is to make sure the course JDK is installed and selected. The exact JDK setup is covered in the JDK
onboarding lesson; come back here once ./gradlew test starts compiling.
It says "compileJava FAILED", not a test failure
A compile error is different from a test failure. If you see Task :compileJava FAILED with a message about a
symbol or a semicolon, your code does not compile yet, so the tests never got to run. Fix the compile error
first; the message names the file and line. Once it compiles, the tests run and you are back to reading
pass-and-fail.
The terminal seems stuck on the first run
The very first ./gradlew run can pause while it sets up, and a slow network makes that longer. Give it a
minute. When you see the task lines appear, it is working.
The same thing in IntelliJ (coming with screenshots)
IntelliJ has a button to run these same tests and a panel that shows the results. The verified, click-by-click
version, with a real screenshot of the run panel, is being captured from the installed IntelliJ and will be
added here. Until then, ./gradlew test in the terminal runs the identical tests and gives you the identical
pass-and-fail, so you can work today without waiting.
Show what you can do
Make this small artifact, then write the reflection.
- Artifact. In your own lab repository, run
./gradlew test. Copy the headline line that says how many tests passed and failed. If anything fails, write the name of one failing test and the method it points you to. - Reflection ("I can ..."). Write one line for each, in your own words: I can run my lab's tests with one command; I can tell a pass from a fail and read how many of each; I can read a failing test name and say which method to fix; I can tell a compile error apart from a test failure. Then name one thing the tests told you that you would not have noticed by just reading your own code.
Where this goes next
Lab 1 has tests under compareTo, equals, and fromCsvRow that start red and turn green as you write the
methods, so you will run this loop for real. The professional git workflow lesson is the other half: once your
tests pass, you commit, push, and open a pull request. The IntelliJ visual walkthrough adds the green run
arrows and the click-to-the-failure panel on top of the command you now understand.