31
1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

Embed Size (px)

Citation preview

Page 1: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

1

Object Oriented Programming

Testing with Unit Testing & the JUnit toolBasic Refactoring techniques

Page 2: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

3

Today's Talk

• Testing software– motivation for the importance of testing

• What and how can we test?– what is testable?– is testing and debugging the same?

• The JUnit tool– a tool for Unit testing

Page 3: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

4

Debugging and Testing

• Debugging– fo find out why a program does now work as

intended

• Testing– testing ≠ debugging

• testing revals if a problem exist• debugging is to find out exactly where and why

something goes wrong

Page 4: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

5

found a Bug – sept. 9, 1945

Page 5: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

6

Unit Testing

Page 6: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

7

Real Programmers Need no Testing![citings of a lecture note on testing in SW.Eng at MIT]

• The TOP five bad excuses list

• 5) I want to get this done fast, testing is going to slow me down• 4) I started programming when I was 2. Don’t insult me by

testing my perfect code!• 3) Testing is for incompetent programmers who cannot hack.• 2) We are not Harward students, our code actually works

• 1) ”Most of the functions in Graph.java, as implemented, are one or two line functions that rely solely upon functions in HashMap or HashSet. I am assuming that these functions work perfectly, and thus there is no need to test them.” – excerpt from a students e-mail, SW. Eng. Course at MIT

Page 7: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

8

Testing software• We need to test and verify that our

code functions correctly• Problem: most programs are very

large and complex– Difficult to trace why and where things go

wrong

• How do we test efficiently?– Where do we insert test code?– What parameters do we test on?– Do we cover all significant test cases?

Page 8: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

9

Unit testing

• Large programs are compositions of several units (objects)

• We can reduce testing complexity by testing each component separately

• In Java, a unit test is made at the level of a class, method or interface

Page 9: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

10

Testing Phases

• 1. Unit testing– test each class iteratively during

implementation– assert computed values are correct

according to the expected

• 2. Integration testing– merge tested units to larger

compositions and perform new tests

• 3. System testing– test complete program

Page 10: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

11

What we can and cannot test with Unit tests

• We can test if the implementation match the specification– stable state conditions (the representation invariant)– that computed values (results) are the expected

values– That non-valid input are rejected or taken care of

• Things we cannot test– if lines of code are wrong, and which specific lines– behaviour in non-steady state (monitor variables and

instructions inside functions)• We must use a debugger for this purpose

Page 11: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

12

What should we test and how?

• For each unit, we must define a set of test cases

• The test cases should help us– assert that the representation invariant

holds– assert that computed values match

expected values– faults detected are gracefully managed

• How should we formulate test cases?– We must test both valid and non-valid

input

• In most cases, it is practically impossible to test all cases– a common strategy: check the “boundary”

conditions and a selected set of representative cases

Page 12: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

13

Basic structure of a Unit test

• Basic implementation of unit tests– 1. Create a test class– 2. Instantiate some test objects

– the class which we want to test

– 3. Send some test messages– inputs to the methods we want to test

– 4. Verify the expected output– Using a set of assertions

Page 13: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

14

a tool for Unit testing

• JUnit is a tool (java framework) for unit testing• Why use a tool for unit testing?

– No test clutter the source code!• Test classes generated in separate package

– Automatic generation of• Test case skeletons

– stub methods

• Test runners (a test suite)– Wrapper code for running and hooking test methods in the unit

to test

– Simplifies incremental and iterative testing

Page 14: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

15

The TestCase class

• A JUnit test class must extend the TestCase class

• Mandatory constructor with a string argument – a description of the specific test running

public class RationalTest extends TestCase{ public RationalTest(String testName){ super(testName); }

…}

Page 15: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

16

Implementing test methods

Test message

Test objects

Assert correctness

Expected val.

public void testPlus() { System.out.println("plus"); Rational a = new Rational(2,3); Rational b = new Rational(2,3); /* Test two positive numbers */ Rational expResult = new Rational(4,3); Rational result = Rational.plus(a, b); assertEquals(expResult, result); assertTrue(result.repOk());

Page 16: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

17

Assertions in JUnit(changed in newest release)

• In junit.framework.Assert– assertEquals(*);– assertTrue(*);– assertFalse(*);– assertNotNull(*);– assertNull(*);– assertNotSame(*);– assertSame(*);– fail(*);

Page 17: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

18

Testing of Exceptions

• Many methods throws Exceptions

• In Junit we can test that Exceptions – are thrown when suppossed to– are thrown properly (descriptive message)

• Runtime Exception: ”you are stupid error” ???

• How do we do this?– 1. incorporate try-catch clauses– 2. using the fail() assertion in JUnit

Page 18: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

19

Testing throwables

• The test is ”successful” if a fail ocurrs (”the bomb goes off”)

Rational a = new Rational(1,3);Rational b = new Rational();

Try{Rational.div(a,b);// Should not be reachedfail(”Div by zero should not be

allowed”);}catch(ArithmeticException ae){

// Exception was thrown so do nothing}

Page 19: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

20

Asserting exception messages

• Force the exception message to be implemented as we require:

Rational a = new Rational(1,3); /* 1/3 */Rational b = new Rational(); /* zero */

Try{Rational.div(a,b);fail(”Div by zero should not be allowed”);

}catch(ArithmeticException ae){

assertEquals(”Division by zero”, ae.getMessage());}

Page 20: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

21

Correctness of the test code

• The correctness of the tests are dependent on the correctness of the test methods

• Problem: How do we minimize the risqué for implementing faulty test code?

• Simple and practical guidance– 1. Run tests as soon you have a new method to test

• Do not implement too much before testing– 2. Do incremental testing frequently

• Extend the test class when new methods are completed

Page 21: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

22

Refactoring

Page 22: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

23

Refactoring of Code

• Refactoring is a technique to refine and restructure programs– E.g. factor (move) identical code sections into

generic classes or methods• What do we mean with a ”generic class”?

– classes collecting general functionality, which we can reuse (with or without adaptation)• code used in multiple sections of a program • a general framework useable for many programs

– optimally, they can be reused without need of modifying the code

Page 23: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

24

Refactoring Strategies

• Three basic refactoring strategies:– Refactoring of methods

• at level of single program (code usually specific for a certain program)

– Refactoring by inheritance• at level of single program and framework (code

generalizable for a specific purpose)

– Refactoring by delegation• at level of single program and framework (codes

that are often most generalizable)

Page 24: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

25

Refactoring of methodsClass ComputeThings {

public void computeAnything(){anything();compute1();compute2();compute3();

}public void computeSomething(){

something();compute1();compute2();compute3();

}}

These parts are similar....

Page 25: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

26

Refactoring of methodsclass computeThings {

public void computeMany1(){anything();computeAlot();

}public void computeMany2(){

something();computeAlot();

}public void computeAlot(){

compute1();compute2();compute3();

}}

Page 26: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

27

Refactoring of methods

• What is the purpose of refactoring methods?– reduces lines of code

(redundancy)– changes can be done

more safely • we only have to change in

one location of the program

– tend to make programs ”easier” to read and understand

Page 27: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

28

Refactoring by Inheritance

Class computeStuff1{

superCompute1(){

compute1();

compute2();

compute3();

}

....

}

Class computeStuff2{

somethingElse(){

compute1();

compute2();

compute3();

}

...

}

Both classes implement

identical code sections

Page 28: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

29

Refactoring by Inheritanceclass ComputeStuff1 extends Common{

...superCompute1(){

super.computeAlot();}....

}

class ComputeStuff2 extends Common{

...somethingElse(){

super.computeAlot();}...

}

class Common{...computeAlot(){

compute1();compute2();compute3();

}...

}

Page 29: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

30

Refactoring by Delegation

• Instead of inheriting factorized code– let the the common code be encapsulated in a

separate class

• We can chose to make functions accessible– via an object reference

– by declaring the factorized methods as static • as for example the arithmetics in Rational

• Example: the Sorting and Helper classes in the search engine

Page 30: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

31

Refactoring by Delegation(access by reference)

class ComputeStuff1{

Compute compVar;

superCompute1(){compVar.computeAlot();

}....

}

class ComputeStuff2{...somethingElse(){

compVar.computeAlot();}...

}

class Compute{

...

computeAlot(){

compute1();

compute2();

compute3();

}

...

}

Page 31: 1 Object Oriented Programming Testing with Unit Testing & the JUnit tool Basic Refactoring techniques

32

The End...