We all want "better" test suites. But what makes for a good test suite? Certainly, test suites ought to aim for good coverage, at least at the statement coverage level. To be useful, test suites should run quickly enough to provide timely feedback.
This talk will investigate a number of other dimensions on which to evaluate test suites. The talk claims that better test suites are more maintainable, more usable (for instance, because they run faster, or use fewer resources), and have fewer unjustified failures. In this talk, I'll present and synthesize facts about 10 open-source test suites (from 8,000 to 246,000 lines of code) and evaluate how they are doing.
4. Basic Test Suite Properties
Benchmark sizes:
30 kLOC (google-visualization) to
495 kLOC (weka)
% of system represented by tests:
5.3% (weka) to 50.4% (joda-time)
22. Test methods with at least 5 asserts
e.g. from Joda-Time:
public void testEquality() {
assertSame(getInstance(TOKYO), getInstance(TOKYO));
assertSame(getInstance(LONDON), getInstance(LONDON));
assertSame(getInstance(PARIS), getInstance(PARIS));
assertSame(getInstanceUTC(), getInstanceUTC());
assertSame(getInstance(), getInstance(LONDON));
}
24. Test Methods with Branches
if (isAllowNullKey() == false) {
try {
assertEquals(null, o.nextKey(null));
} catch (NullPointerException ex) {}
} else {
assertEquals(null, o.nextKey(null));
}
// from apache-cc
25. Test Methods with Loops
counter = 0;
while (this.complexPerm.hasNext()) {
this.complexPerm.getNext();
counter++;
}
assertEquals(maxPermNum, counter);
// from jgrapht
37. Types of reuse (standard Java)
1. test class setUp()/tearDown()
2. inheritance: e.g. in apache-cc,
TestFastHashMap extends AbstractTestMap
3. composition: e.g. in jfreechart,
helper class RendererChangeDetector
41. Helper Classes Example
from poi:
/** Test utility class to get Records
* out of HSSF objects. */
public final class RecordInspector {
public static Record[] getRecords(...) {}
}
43. Test Clone Example
public void testNominalFiltering() {
m_Filter = getFilter(Attribute.NOMINAL);
Instances r = useFilter();
for (int i = 0; i < r.numAttributes(); i++)
assertTrue(r.attribute(i).type() != Attribute.NOMINAL);}
public void testStringFiltering() {
m_Filter = getFilter(Attribute.STRING);
Instances r = useFilter();
for (int i = 0; i < r.numAttributes(); i++)
assertTrue(r.attribute(i).type() != Attribute.STRING);}
46. How to Refactor?
● setUp/tearDown/subclassing
● JUnit 4:
Parametrized Unit Tests
● Test Theories
47. apache-cc: Bulk tests
public BulkTest bulkTestKeySet() {
return new TestSet(makeFullMap().keySet());
}
● runs all tests in the TestSet class
with the object returned from makeFullMap().
keySet()
48. jdom: Generated Test Case Stubs
class ClassGenerator makes e.g.:
class TestDocument {
void test_TCC__List();
void test_TCM__int_hashCode();
}
Developer still needs to populate tests.