33
LECTURE 6: DO I HAVE TO TEST IT? WHY? CSC 213 – Large Scale Programming

Lecture 6: Do I HAVE TO Test IT? Why ?

Embed Size (px)

DESCRIPTION

CSC 213 – Large Scale Programming. Lecture 6: Do I HAVE TO Test IT? Why ?. Why Do We Test?. But the Problem Is…. Can We Get Best Of Both?. Can We Get Best Of Both?. Testing To The Rescue. Before we start coding, write solid set of tests Best, worst, & average cases examined in tests - PowerPoint PPT Presentation

Citation preview

LECTURE 6:DO I HAVE TO TEST IT? WHY?

CSC 213 – Large Scale Programming

Why Do We Test?

But the Problem Is…

Can We Get Best Of Both?

Can We Get Best Of Both?

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

OOPS…

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;}

}

Why We Write Mock Classes!

Testing ThreeMileIsland

not NuclearReactor

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)