.. _JUnit:
.. raw:: html
.. |--| unicode:: U+2013 .. en dash
.. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace
:trim:
.. This file is part of the OpenDSA eTextbook project. See
.. http://algoviz.org/OpenDSA for more details.
.. Copyright (c) 2012-2013 by the OpenDSA Project Contributors, and
.. distributed under an MIT open source license.
.. avmetadata::
:author: Cliff Shaffer
=============
JUnit Testing
=============
Testing
~~~~~~~
What is the difference between testing and debugging?
How much time have you already spent on this project
testing/debugging your code?
JUnit testing and code coverage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* It is a true art to be able to think in your head all the
possible ways that your program could go wrong.
* One thing that you can get from proper JUnit testing is an
indication of what lines are not covered.
* This indicates situations that you have not yet thought to test.
* Sort of an automatic test generator!
Philosophy
~~~~~~~~~~
* Essential rule: Anything that you do in a test must be
followed with assertions to verify that what you
did is correct.
* Every unit test does two things:
#. Changes the state of the program. You can assert that these
changes are correct.
#. Covers (possibly new) lines of code
You want these two to be in alignment.
A Bad test (1)
~~~~~~~~~~~~~~
* I see many tests like this::
public void testMInit() {
Memman mem = new Memman();
assertNotNull(mem);
Memman.main(new String[] {"25", "20", "P1SampleInput.txt"});
}
A Bad test (2)
~~~~~~~~~~~~~~
Why is this so bad?
* It violates our essential rule.
* There is no testing of what running the program on
input DID. Pretty much your only conclusion is that the
program did not crash.
* But worse: Lots of lines of code are "covered". So you don't
even know what paths have NOT been tested.
WARNING: Project 2 will be unforgiving of this sort of thing.
Full test of output
~~~~~~~~~~~~~~~~~~~
::
public void testSampleInput() throws Exception {
String[] args = new String[3];
args[0]= "10"; args[1]= "32"; args[2]= "P1sampleInput.txt";
Memman.main(args);
assertFuzzyEquals( systemOut().getHistory(),
"|When Summer's Through| " +
"does not exist in the song database.\n" +
"(0,32)\n" +
...
"|Watermelon Man| is added to the song database.\n" +
"(44,11) -> (121,4) -> (319,1)\n");
}
Selective Testing of Output
~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
public void testEmpty()
throws Exception {
String[] args = new String[3];
args[0] = "10";
args[1] = "32";
args[2] = "EmptyTest.txt";
System.out.println("Empty test");
Memman.main(args);
assertTrue(systemOut().getHistory().endsWith("(17,47)\n"));
}
What would be good testing for Project 1?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
?
Models
~~~~~~
* JUnit testing compares a model of what the program should do
against what your program does do.
* Executing commands puts your program into a certain state
(expressed by the output).
* The assertions define characterstics of what you expect from that
state. This is the model.
* The test then compares what state YOUR program is in (expressed
by the output) against the model (assertions).
What if your model is wrong?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* If you have a model in your head, and you write the program to
that model, and you test to that model, a "properly working"
program will meet that model.
* What if your model does not match reality?
* In this program, that most often happens when:
* Your output text is not what is expected. BUT you should have
used the sample output file to write your tests.
* You have the wrong model about how probing works. BUT you
should then see that you pass your tests, and fail the (one)
Web-CAT test. Then you should be suspicious about your model
if they tell you different things.
Regression testing
~~~~~~~~~~~~~~~~~~
* This means running all of your old tests on the program to make
sure that any new changes don't break anything.
* Students sometimes add print statements to help them debug, and
then forget to remove them. Then Web-CAT tells them they failed a
bunch of tests.
* Your unit tests should warn you about this.
* If you find a bug, and your tests all pass, then update the tests
to trigger on the bug.