test case

Computer Science 209
Testing With JUnit
Why Test?
• I don’t have time, I’ve got a deadline to meet
• The more pressure I feel, the fewer tests I will
write
• Fewer tests lead to less accurate and less stable
code
• Less accurate and less stable code puts more
pressure on me . . .
Integrate Testing and Coding
• Code a little, test a little, code a little, test a
little . . .
• Write test units before coding the pieces to
be tested
• Get immediate feedback and fix bugs as you
code
Tester Programs
• Test individual classes where possible, then
interactions
• Bottom-up approach
• A main method displays expected results
before actual results of running methods
Testing Freecell
public class FreeCellTester{
public static void main(String[] args){
FreeCellModel = new FreeCellModel();
System.out.println(model);
}
// Now what??
}
Lots of things to test!
Smaller pieces (deck, cards, particular types of cells)
should be tested first
Problems With Tester Programs
• Must visually inspect a long output stream
to check results (tedious and error-prone)
• Must create code to produce visually useful
output
• Tests of methods are not modularized: One
long sequence that is hard to maintain
JUnit
• Provides “outside influence” in the form of a
framework for unit testing
• Highly modular, can create a suite of test cases for
each class and add to them incrementally
• Assertion-based: A failed test halts with an error
message, so verification is automated
The Basic Framework
import junit.framework.*;
public class PatronTest extends TestCase{
// Will test the Patron class using JUnit
}
Write a testing class that extends TestCase
TestCase is defined in the junit.framework
package
You should write a similar class for each of the
classes that are unit-tested in your system
Add a Test Case
import junit.framework.*;
public class PatronTest extends TestCase{
public void testIncBooksOut(){
Patron p1 = new Patron("Lambert", "Java");
for (int i = 1; i <= Patron.MAX_BOOKS; i++){
p1.incBooksOut();
assertTrue(i == p1.getBooksOut());
}
}
}
A test case is a method that tests the functionality of another method
testIncBooksOut is the test case for incBooksOut
assertTrue expects true and halts the test if it gets false
Testing equals
import junit.framework.*;
public void testEquals(){
Patron p1 = new Patron("Lambert", "Java");
Patron p2 = new Patron("Levy", "Scheme");
assertEquals(p1, p1);
assertEquals(p1, new Patron("Lambert", "Java"));
assertTrue(! p1.equals(p2));
}
}
assertEquals runs the equals method with its two parameters
Be sure to test all of the possible options of equality
Establish a Fixture
import junit.framework.*;
public class PatronTest extends TestCase{
private Patron p1, p2;
protected void setUp(){
p1 = new Patron("Lambert", "Java");
p2 = new Patron("Levy", "Scheme");
}
}
// Tests for incBooksOut and equals can use p1 and p2
A fixture captures a common context for several test cases
This context consists of a set of objects that can be initialized once
in a setup method and made visible to all test cases
Some fixtures can consist of many objects, so this really saves time
Create a Suite of Test Cases
import junit.framework.*;
public class PatronTest extends TestCase{
// Code for fixture and test cases
public PatronTest(String s){
super(s);
}
public static Test suite(){
TestSuite suite = new TestSuite();
suite.addTest(new PatronTest("testIncBooksOut"));
suite.addTest(new PatronTest("testEquals"));
return suite;
}
public static void main(String[] args){
junit.textui.TestRunner.run(suite());
}
}
Be sure that the names of the test case methods are spelled correctly!
Create an instance
of PatronTest
for each test case
method and pass
the name of the
method to the
constructor
Add each case to a
TestSuite
object
Run the suite in the
main method
Create a Suite of Test Cases
import junit.framework.*;
public class PatronTest extends TestCase{
// Code for fixture and test cases
public PatronTest(String s){
super(s);
}
public static Test suite(){
TestSuite suite = new TestSuite(PatronTest.class);
return suite;
}
public static void main(String[] args){
junit.textui.TestRunner.run(suite());
}
Create an instance
of PatronTest
for each test case
method and pass
the name of the
method to the
constructor
Add each case to a
TestSuite
object
}
Alternatively, pass the class of the test cases to another
Suite constructor
Run the suite in the
main method
Running a Test
For a simple batch-style text interface:
>java PatronTest
For a GUI that allows you to track and run tests for
multiple classes:
>java junit.swingui.TestRunner
Guidelines for Testing
• Write tests as you develop, when you
imagine how the code will run
• Factor the test code to reflect the factoring
of your system
• Keep the old tests running, and always run
all of your tests
Guidelines for Testing
• Avoid writing print statements; write
tests instead
• Focus on tests that are useful
– When you add functionality to the system
– During debugging, write a test that will succeed
if the code works, then debug with it
Guidelines for Testing
• Run every test at least once a day
• Set them up so that you can’t go home
unless they’re all 100%
• You’ll be more aggressive about refactoring
because you won’t fear breaking the code