Date post: | 28-Dec-2015 |
Category: |
Documents |
Upload: | alexander-parks |
View: | 227 times |
Download: | 2 times |
Testing To The Rescue
Before we start coding, write solid set of tests Best, worst, & average cases examined in
tests Includes tests for all possible boundary
conditions Tests drive the code & set pace of the
coding Code only written to be good enough to
pass tests Debugging simplified using the simple
failed cases Once system can pass all tests, we’re
golden
Testing To The Rescue
Before we start coding, write solid set of tests Best, worst, & average cases examined in
tests Includes tests for all possible boundary
conditions Tests drive the code & set pace of the
coding Code only written to be good enough to
pass tests Debugging simplified using the simple
failed cases Once system can pass all tests, we’re
golden
Testing To The Rescue
Before we start coding, write solid set of tests Best, worst, & average cases examined in
tests Includes tests for all possible boundary
conditions Tests drive the code & set pace of the
coding Code only written to be good enough to
pass tests Debugging simplified using the simple
failed cases Once system can pass all tests, we’re
golden
Oops…
Design we created has lots of side effects Results printed out at the end of void
methods Other methods just update values of
object’s fields Add special methods that allow field
access Not a big deal & needed to test affect on
fields' values
OOPS… Stuck with BIG issue: how to check I/O
correct? How to test screen to verify warning are
printed? How to insure file has correct values before
& after?
OOPS… Stuck with BIG issue: how to check I/O
correct? How to test screen to verify warning are
printed? How to insure file has correct values before
& after? Cannot skip tests since correctness
important Always want to be correct, but cannot test
online
OOPS… Stuck with BIG issue: how to check I/O
correct? How to test screen to verify warning are
printed? How to insure file has correct values before
& after? Cannot skip tests since correctness
important Always want to be correct, but cannot test
online
And it monitors a nuclear reactor
Laziness Depends on Design
Well-planned design makes testable methods
Testable methods leads to good tests
Good tests leads to easy coding & debugging
Easy coding & debugging leads to free time
Free time leads to laziness
Design Methods For Testing
Start by defining method for each calculation Method returns result once it is calculated As needed, create other methods to output
results Easy to test & debug methods with
observable results
Design Methods For Testing
Start by defining method for each calculation Method returns result once it is calculated As needed, create other methods to output
results Easy to test & debug methods with
observable results
versus
Mock Objects To Win
Some things just cannot be tested with JUnit
Failed nuclear plant tests a bit of a problem Some times its impossible to access or use
classes File or network I/O required, but cannot test
offline These situations leave limited options
Whine about it being unfair Leave code untested and say "oops" a lot Prove correctness mathematically Create stand-ins called mock objects
Getting Ready for Mocks
Use interfaces in place of hard-to-use classes Interface defines minimum number of
methods Update old class to implement this interface
Must modify code when hard-to-use class alloc'd Pass instance to method & eliminate new
command If instance was field, set using constructor's
parameter
Original Example
public class ThreeMileIsland {private NuclearReactor reactor;
public ThreeMileIsland() { reactor = new NuclearReactor("SNPP");}
public boolean checkForBreach() { if (!reactor.withinLimits()) { return reactor.alarmSounding(); } return false;}
}
New Interface
public interface NRInterface {public boolean withinLimits();public boolean alarmSounding();
}
public class ThreeMileIsland {// More code went herepublic boolean checkForBreach() { if (!reactor.withinLimits()) { return reactor.alarmSounding(); } return false;}
}
Rewrite From This…
public class ThreeMileIsland {private NuclearReactor reactor;
public ThreeMileIsland() { reactor = new NuclearReactor("SNPP");}
public boolean checkForBreach() { if (!reactor.withinLimits()) { return reactor.alarmSounding(); } return false;}
}
Rewrite …To This
public class ThreeMileIsland {private NRInterface reactor;
public ThreeMileIsland(NRInterface nm) { reactor = nm;}
public boolean checkForBreach() { if (!reactor.withinLimits()) { return reactor.alarmSounding(); } return false;}
}
Create Mock Class
Write classes needed to test code fully Testing ThreeMileIsland not NuclearReactor
ONLY purpose is testing other classes code May hard-code values; write as simply as
possible Store parameters in Sequences to check
calls correct Do not use files or network, mock to avoid
these needs Duct tape & mock classes are similar
Useful & pretty, but not the real thing
Writing Mock Class
public interface NRInterface {public boolean withinLimits();public boolean alarmSounding();
}
public class MeltdownMock implements NRInterface{public boolean withinLimits() { return false; }public boolean alarmSounding() { return true; }
}
Using Mock Class
Now run original method in two different ways Provide and use mock objects when testing
code Actual classes during execution so still
works Remember:
Testing ThreeMileIsland not mock class
Writing Mock Class
public class MeltdownMock implements NRInterface {public boolean withinLimits() { return false; }public boolean alarmSounding() { return true; }
}
@Testpublic void testTMI() {
NRInterface mltdn = new MeltdownMock();ThreeMileIsland tmi = new ThreeMileIsland(mltdn);assertTrue(tmi.checkForBreach());
}
Mock Class Coding Review
Use interfaces in place of hard-to-use classes Interface defines minimum number of
methods Update old class to implement this interface
Must modify code when hard-to-use class alloc'd Pass instance to method & eliminate new
command If instance was field, set using constructor's
parameter Test original using specially written
mock classes Mock classes should be simple, often return
a constant Not testing mocking, but if class can handle
its result
Testing Printing To Screen
Java already thought of this & created solution Only need to set static field in System
class System.setOut(PrintStream) does this
for us Instance passed as parameter will be sent
all output No new classes required for this to
work Can add code to method run before each
test @Before method needed to contain this
code
Writing Code to Test Output
import java.io.PrintStream;public class TestCode {
private OutputStream os;String nl = System.getProperty("line.separator");
@Beforepublic void setUp() { os = new ByteArrayOutputStream(); System.setOut(new PrintStream(os));}
@Testpublic void testPrintln() { callMethodWith_println_Hi(); assertEquals(os.toString(), "Hi" + nl);}
Writing Code to Test Output
import java.io.PrintStream;public class TestCode {
private OutputStream os;String nl = System.getProperty("line.separator");
@Beforepublic void setUp() { os = new ByteArrayOutputStream(); System.setOut(new PrintStream(os));}
@Testpublic void testPrintln() { callMethodWith_println_Hi(); assertEquals(os.toString(), "Hi" + nl);}
Writing Code to Test Output
import java.io.PrintStream;public class TestCode {
private OutputStream os;String nl = System.getProperty("line.separator");
@Beforepublic void setUp() { os = new ByteArrayOutputStream(); System.setOut(new PrintStream(os));}
@Testpublic void testPrintln() { callMethodWith_println_Hi(); assertEquals(os.toString(), "Hi" + nl);}
For Next Lecture
Next weekly assignment available online Due as usual tomorrow at 5PM Give me notes on reading to delay this due
date
Reading on event-driven programming How to code if we do not know what will
happen? What error is found most starting GUI
programs? How can I make my code finish within my
lifetime? (Design notes for ActionListener okay for
extension)