freecol/test/TEST-HOWTO

140 lines
4.8 KiB
Plaintext

!---------------------------------------------!
! Unit Testing Guide !
! !
! to run the tests: 'ant testall' !
!---------------------------------------------!
1. What is unit testing?
Writing code that will check whether a small unit of code works is called unit testing.
Example:
If we encode directions like this
protected static final int N = 0, NE = 1, E = 2, SE = 3, S = 4, SW = 5, W = 6, NW = 7;
and we want to write a function that returns the opposite direction. Usually we would
write the implementation
public static int getOppositeDirection(int direction) {
return (direction < 4) ? direction + 4 : direction - 4;
}
and then manually check that the method works correctly by either testing the compiled code
within the application itself (in FreeCol this would mean verifying that each direction is
properly made opposite via the GUI output) or for a console-based application performing a
series of calls to the System.out.println function to output whether or not each case worked
properly.
Instead we can write source code that verifies whether the function behaves correctly:
public void testGetOppositeDirection() throws FreeColException {
assertEquals(Map.S, Map.getOppositeDirection(Map.N));
assertEquals(Map.N, Map.getOppositeDirection(Map.S));
assertEquals(Map.E, Map.getOppositeDirection(Map.W));
assertEquals(Map.W, Map.getOppositeDirection(Map.E));
assertEquals(Map.NE, Map.getOppositeDirection(Map.SW));
assertEquals(Map.NW, Map.getOppositeDirection(Map.SE));
assertEquals(Map.SW, Map.getOppositeDirection(Map.NE));
assertEquals(Map.SE, Map.getOppositeDirection(Map.NW));
}
Each assert statement will check whether the given condition holds true. If all assert
statements succeed, the test passes (this may be indicated by a green bar in some IDEs)
otherwise the test fails (this may be indicated with a red bar), telling you which line
did not pass the assertion.
2. Why write tests?
* Verify that code works as expected in certain situations.
* To describe a bug to other developers, a test which fails can be cited as an example.
3. What are the benefits?
* Be able to run all the tests after a change to see if one broke existing functionality
("regression test"), thus after enough tests have been written, it is easier to be
confident about changing the code.
* A test describes what a piece of code is supposed to do and often can help to understand
how it is supposed to be used.
* Since the test is written in source code it is much faster to run than manual tests in
the application.
4. Drawbacks?
* Writing test cases can be a lot of work.
* Testing of GUIs is especially difficult.
* One needs a lot of tests to get benefits like the regression checking.
5. How do I write test cases?
* Create a new class in the test/src folder that extends the class TestCase (import org.junit.*).
All methods in this class that have a name that starts in "test...." will be executed.
* To check basic conditions use assertEquals, assertTrue, assertFalse, assertNotNull, etc...
* To check for exceptions to occur use the following construction:
try {
// code that should throw exception
...
fail()
} catch (FreeColException e){
// Exception throws, thus okay
}
* To fail if an exception is thrown, just declare it:
public void testGetOppositeDirection() throws FreeColException {
6. How to run a test case?
a.) In Eclipse to run a test case:
Right click the Test class -> Run As... -> JUnit Test
b.) On the command line the main directory (replace the text between $ $):
java -cp $classpath for the class files from both src/ and test/src$;test/lib/junit.jar junit.swingui.TestRunnerorg $fully qualified name of the test class$
For instance if bin is your target directory and you want to run all tests
java -cp bin;test/lib/junit.jar junit.swingui.TestRunner net.sf.freecol.AllTests
c.) Using ant run:
If you have Apache Ant 1.7 or higher you can just run
ant testall
Otherwise:
ant -lib test/lib/junit.jar -Dtest=$qualified name of test class but ommitting net.sf.freecol$ test
for instance
ant -lib test/lib/junit.jar -Dtest=AllTests test
7. FAQ
Q: What is the difference between unit and integration testing?
A: In unit testing the goal is to test small units in relative isolation, while integration
testing tries to figure out whether parts of the system work if put together. Both approaches
have their purpose and their strengths. In general one should try to first test code that has little
dependencies to other code or remove the dependencies by using mock objects and later see
whether the code integrates with the rest of the system.
8. References:
[1] JUnit Test Infected: Programmers Love Writing Tests
http://junit.sourceforge.net/doc/testinfected/testing.htm
[2] JUnit Homepage
http://junit.org