Introduction

Design by contract

Object Oriented Programming Design by contract & Unit testing

Ver´ onica Gaspes School of Information Science, Computer and Electrical Engineering

ceres

April 30, 2009

Unit testing

Introduction

Design by contract

Unit testing

Application frameworks Putting application frameworks to work You have to understand the requirements that the designer of the framework set forth for the apps programmer! Applet framework You have to extend Applet or JApplet. You have to define methods init, start, stop and paint. You can provide command line arguments (parameters) via the HTML document that contains the applet.

Introduction

Design by contract

Unit testing

Application frameworks The graphic editor of graphs framework You have to extend the class Graph (defining the methods getNodePrototypes and getEdgePrototypes) For each type of node and edge you have to extend the classes Node and Edge to supply methods for drawing and containment testing. import javax.swing.*; public class SimpleGraphEditor{ public static void main(String[] args){ JFrame frame = new GraphFrame(new SimpleGraph()); frame.setVisible(true); } }

Introduction

Design by contract

Unit testing

Application frameworks Designing your own application frameworks Is a far bigger challenge! 1

You have to understand the problem domain

2

You have to put to use design patterns that enable application programmers to add app-specific code

3

You should shield app-programmers from internal mechanisms

4

You have to provide hooks that modify the generic framework behavior.

Your framework will be used by other programmers So you need to put a lot of effort in quality assurance. Today we will discuss techniques and tools for doing this!

Introduction

Design by contract

Unit testing

Software contracts

In object oriented programming A way of describing the obligations and benefits of a class. Spell out responsabilities of the implementor and the caller to increase reliability and efficiency.

1

The class invariant describes how the representation is intended to be (more than the type of the fields!)

2

A method precondition describes what the method can expect when called (more than the type of the arguments!)

3

A method postcondition describes what the method guarantees on termination (more than the type of the result of the method!)

Introduction

Design by contract

Unit testing

Using contracts Documentation The contract becomes a very good documentation of the class. It is a very systematic way of documenting a class! Clients of your class know what they can expect and how they can use it. Monitoring Before releasing your programs you might want to monitor its behaviour. In Java we can write assertions. Contracts can be used to design the assertions! Testing Contracts can be used to define test cases based on specifications. Tools such as JUnit can be used to program tests as you program your classes.

Introduction

Design by contract

Class invariants - polynomials Some polynomials x2 + 4 3x 6 + 2x 3 + x coefficients are real numbers exponents are non-negative integers. The complete versions ... 1x 2 + 0x 1 + 4x 0 3x 6 + 0x 5 + 0x 4 + 2x 3 + 0x 2 + 1x 1 + 0x 0 Implementing polynomials Represent a polynomial using an array of coefficients!

Unit testing

Introduction

Design by contract

Class invariants - polynomials public class Poly{ private double [] poly; public public public public public

Poly(?) int deg() Poly add(Poly p) Poly diff() String toString()

} The representation of our examples x2 + 4

poly = [4,0,1]

3x 6 + 2x 3 + x

poly = [0,1,0,2,0,0,3]

Unit testing

Introduction

Design by contract

Unit testing

Class invariants - polynomials

The O polynomial The polynomial for which p + O = p. O

is

0x 0

poly = [0] Towards the invariant Not all arrays of doubles are representations of polynomials! We want to express which ones are so that when we write the constructors and the public methods we are carefull not to produce meaningless arrays!

Introduction

Design by contract

Unit testing

Class invariants - polynomials The length of poly is at least 1. When poly.length > 1, the element in position poly.length-1 is always not 0.

Practical consequence We can calculate the degree of a polynomial very easily: public int deg(){ return poly.length-1; }

Practical consequence We can write a function that is useful for testing the class: private boolean polyOk(){ return poly != null && poly.length!=0 && (poly[poly.length-1]!=0 || poly.length == 1); }

Introduction

Design by contract

Unit testing

Class invariants - binary search trees What about invariants in mutable types? Mutators must preserve the invariant! Binary Search Trees Binary trees with the search property: All nodes in the left child are smaller than the root All nodes in the right child are larger than the root The left child and the rigth child have the search property

Introduction

Design by contract

Unit testing

Class invariants - binary search trees The representation public class BinarySearchTree { private BinaryNode root; ... } class BinaryNode{ BinaryNode( E theElement ){ element = theElement; left = right = null; } E element; BinaryNode left; BinaryNode right; }

BUT! Not all BinaryNodes have the search property!

Introduction

Design by contract

Unit testing

Class invariants - binary search trees We document the invariant public class BinarySearchTree /** @invariant root has the search property: root == null or all nodes in root.left are smaller than root.element and all nodes in root.right are larger than root.element and root.left has the search property and root.right has the search property */ private BinaryNode root;

Introduction

Design by contract

Unit testing

Invariant documentation

Running Javadoc javadoc -private -tag invariant:f:"inv" BST.java

Why this is good The documentation follows the code, we do not have to maintain 2 documents: the source code and the documentation (that is more difficult to keep consistent!).

Introduction

Design by contract

Unit testing

Invariants and the contract

What is the contract? 1 The constructors establish the invariant (make it hold!) 2

Public methods preserve the invariant (assuming that the invariant holds, public methods re-establish it!)

Constructor public BinarySearchTree(){ root = null; }

Insertion public void insert(E x){ root = insert(x, root); }

Introduction

Design by contract

Unit testing

Invariants and the contract

Insertion continued protected BinaryNode insert(E x, BinaryNode t){ if(t == null) t = new BinaryNode( x ); else if( x.compareTo( t.element ) < 0 ) t.left = insert( x, t.left ); else if( x.compareTo( t.element ) > 0 ) t.right = insert( x, t.right ); return t; }

Introduction

Design by contract

Unit testing

Monitoring the invariant Monotoring and assertions Before release it can be worth to monitor that the implementation complies with the contract! In java we can use assertions: assert condition : explanation; that test the condition and print the explanation if the condition does not hold! To do so: java -enableassertions BST Efficiency Assertions are disabled by default. They are not tested when disabled, no need to modify the program when releasing it!

Introduction

Design by contract

Monitoring the invariant

For insertion in binary search trees public void insert( E x ){ assert invariant() : "problem calling insert with " + root + " and " + x; root = insert( x, root ); assert invariant() : "problem after inserting with " + root + " and " + x; }

Unit testing

Introduction

Design by contract

Unit testing

Monitoring the invariant

You have to define a method boolean invariant() that can be used to test the invariant! It should have no side effects. You will notice that it takes a lot of time to execute! Produces very good error messages, very easy to locate problems!

Introduction

Design by contract

Unit testing

Preconditions - findMin in binary search trees findMin There is a method returning the least element in the search tree with signature public E findMin() How should it behave when the tree is empty? Why should it do something at all? It might be the case that there is not something reasonable to do! Program as if that case could not happen! Preconditions Tell the client programs that the method works only for non empty trees. These programs will then have to be carefull!

Introduction

Design by contract

Preconditions - findMin

Documentation /** * Find the smallest item in the tree. * @return smallest item or null if empty. * @precondition root != null */ public E findMin( ) Then run javadoc -private -tag invariant:f:"inv" -tag precondition:m:"pre" BST.java

Unit testing

Introduction

Design by contract

Unit testing

Preconditions and the contract The caller has to ensure that the precondition holds when calling findMin. Consequence The caller has to have the possibility of testing the condition! In our case there should be a public method for testing emptyness: public boolean isEmpty()

The implementor has to write code that works only when the precondition holds! No need to test for the precondition. (efficiency!) (contrast with defensive programming!)

Introduction

Design by contract

Unit testing

Monitoring preconditions

Assertions can be used to monitor preconditions. It is very easy to localize possibl errors. Remark! Assertions (like testing) help disclose the presence of errors, not their absence!

Introduction

Design by contract

Unit testing

Postconditions - insert in binary search trees insert The method public void insert(E x) is a mutator: it changes the state of a binary search tree by adding one more element to the binary node used to carry the elements of the search tree. We already know that it must preserve the invariant! We can also state other things we know it will achieve: The resulting binary search tree is not empty!

Introduction

Design by contract

Postconditions and the contract

The implementor of the method promises to establish the postcondition insert /** * Insert into the tree. * @param x the item to insert. * @invariant invariant() * @postcondition root != null */ public void insert( E x )

Unit testing

Introduction

Design by contract

Unit testing

Postconditions - insert Enough? Can we say something more about what insert(x) can ensure? Hopefully the inserted element will be present in the tree! If we look for it we should find it! To understand how to formulate this we have to understand the signature of find! Insert and find public class BinarySearchTree { public void insert( E x ) public E find( E x )

Introduction

Design by contract

Postconditions insert

insert /** * Insert into the tree. * @param x the item to insert. * @invariant invariant() * @postcondition root != null and find(x).compareTo(x) == 0 */ public void insert( E x )

Unit testing

Introduction

Design by contract

Unit testing

Contracts The caller of insert can assume that after an insert the search tree is not empty. The precondition of findMin is established! The caller doesn’t need to test it! When you program classes that will be used (and reused) by other programmers or other programs, contracts are a good way of describing what your classes are! The contract provides an invariant for the class representation and pre and post conditions for the public methods. It can be used for documentation, separation of concerns and monitoring And also for testing!

Introduction

Design by contract

Unit testing

Unit testing and JUnit Unit testing Testing individual classes, as opposed to testing a complete application. Using contracts Instead of testing input data against output data we can test what the class promisses: the contract. JUnit A tool that allows us to program unit tests so that we can run them as often as we want! Methodology Using the contract we can program the tests before programmig the implementation. Whenever we change the implementations we can run the tests again!

Introduction

Design by contract

Unit testing

Using JUnit

public class C1{ private int x; public C1(){x=0;} public void inc(){ x++; } public void reset(){ x=0; } }

import junit.framework.*; public class C1Test extends TestCase{ public void testmethod1(){ assertTrue(???); } }

Introduction

Design by contract

Unit testing

Using JUnit

public class C1{ import junit.framework.*; private int x; public class C1Test public C1() extends TestCase{ public void inc() public void reset() public void testisOK(){ public boolean isOK(int n){ C1 c = new C1(); for(int i = 1; i