Programmieren II. Unit Testing & Test-Driven Development. Alexander Fraser.

Similar documents
CS159. Nathan Sprague. September 30, 2015

Object Oriented Software Design - I

Test-Driven Development JUnit

EECS 4313 Software Engineering Testing

Tools for Unit Test - JUnit

Test-Driven Development JUnit

C07: Testing and JUnit

Test automation / JUnit. Building automatically repeatable test suites

Test automation Test automation / JUnit

White-box testing. Software Reliability and Testing - Barbara Russo SERG - Laboratory of Empirical Software Engineering.

Test suites Obviously you have to test your code to get it working in the first place You can do ad hoc testing (testing whatever occurs to you at

Lecture 20: SW Testing Presented by: Mohammad El-Ramly, PhD

Principles of Software Construction: Objects, Design, and Concurrency (Part 2: Designing (Sub )Systems)

JUnit tes)ng. Elisa Turrini

Tools for Unit Test JUnit

Overview. State-of-the-Art. Relative cost of error correction. CS 619 Introduction to OO Design and Development. Testing.

Testing on Steriods EECS /30

Introduction to Programming Using Java (98-388)

Testing. My favourite testing quote: Program testing can be used to show the presence of bugs, but never to show their absence!

Junit Overview. By Ana I. Duncan

CS201 - Assignment 3, Part 1 Due: Friday February 28, at the beginning of class

Object Oriented Programming. Week 1 Part 3 Writing Java with Eclipse and JUnit

Testing. Topics. Types of Testing. Types of Testing

Topics. Software Testing Test Driven Development Black Box Testing Unit Testing White Box Testing Coverage Testing Software Debugging

Agile Software Development. Lecture 7: Software Testing

Test-Driven Development (a.k.a. Design to Test) CSE260, Computer Science B: Honors Stony Brook University

Analysis of the Test Driven Development by Example

xtreme Programming (summary of Kent Beck s XP book) Stefan Resmerita, WS2015

Programmieren II. Polymorphism. Alexander Fraser. June 4, (Based on material from T. Bögel)

Tutorial 3: Unit tests and JUnit

Introduc)on to tes)ng with JUnit. Workshop 3

What's that? Why? Is one "better" than the other? Terminology. Comparison. Loop testing. Some experts (e.g. Pezze & Young) call it structural testing

Software Design Models, Tools & Processes. Lecture 6: Transition Phase Cecilia Mascolo

Software Engineering Testing and Debugging Testing

8. Quality Assurance

CS211 Computers and Programming Matthew Harris and Alexa Sharp July 9, Boggle

CHAPTER 7 OBJECTS AND CLASSES

Announcements. Testing. Announcements. Announcements

Software Engineering I (02161)

White box testing. White-box testing. Types of WBT 24/03/15. Advanced Programming

Tuesday, November 15. Testing

JUnit in EDA Introduction. 2 JUnit 4.3

Advanced Software Engineering

CS-152: Software Testing

Binghamton University. CS-140 Fall Problem Solving. Creating a class from scratch

Test automation / JUnit. Building automatically repeatable test suites

Assertions, pre/postconditions

Testing. Technion Institute of Technology Author: Assaf Israel. Author: Assaf Israel - Technion

All code must follow best practices. Part (but not all) of this is adhering to the following guidelines:

Testing. CMSC 433 Programming Language Technologies and Paradigms Spring A Real Testing Example. Example (Black Box)?

Topics covered. Introduction to JUnit JUnit: Hands-on session Introduction to Mockito Mockito: Hands-on session. JUnit & Mockito 2

Manuel Oriol, CHCRC-C, Software Testing ABB

public static boolean isoutside(int min, int max, int value)

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 15 Testing

Software Engineering

Java Review via Test Driven Development

Unit Testing. SWEN-610 Foundations of Software Engineering. Department of Software Engineering Rochester Institute of Technology

Unit Tes2ng Ac2vity. SWEN-261 Introduc2on to So3ware Engineering. Department of So3ware Engineering Rochester Ins2tute of Technology

Week 3 Classes and Objects

CHAPTER 7 OBJECTS AND CLASSES

Software Engineering. Top-Down Design. Bottom-Up Design. Software Process. Top-Down vs. Bottom-Up 15/06/2011

Unit Testing. CS 240 Advanced Programming Concepts

CSC207 Week 3. Larry Zhang

Framework for Enhancing the Performance of Unit Testing in Java Based Projects

Software Testing Lecture 1. Justin Pearson

CS18000: Programming I

UNIT TESTING. Krysta Yousoufian CSE 331 Section April 19, With material from Marty Stepp, David Notkin, and The Pragmatic Programmer

CSE 331 Final Exam 3/16/15 Sample Solution

Chapter 4 Defining Classes I

Ingegneria del Software Corso di Laurea in Informatica per il Management

Functional Testing (Testování funkčnosti)

What is software testing? Software testing is designing, executing and evaluating test cases in order to detect faults.

4. A Testing Framework

Testing. UW CSE 160 Winter 2016

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

6.005 Elements of Software Construction Fall 2008

Anatomy of a Class Encapsulation Anatomy of a Method

Video 2.1. Arvind Bhusnurmath. Property of Penn Engineering, Arvind Bhusnurmath. SD1x-2 1

Credit where Credit is Due. Lecture 29: Test-Driven Development. Test-Driven Development. Goals for this lecture

Software Development Tools. COMP220/COMP285 Sebastian Coope Eclipse and JUnit: Creating and running a JUnit test case

Test Driven Development TDD

Agenda. JUnit JaCoCo Project. CSE 4321, Jeff Lei, UTA

Array Based Lists. Collections

Levels of Testing Testing Methods Test Driven Development JUnit. Testing. ENGI 5895: Software Design. Andrew Vardy

Unit Testing with JUnit and CppUnit

ArrayList. Introduction. java.util.arraylist

COURSE 2 DESIGN PATTERNS

About this exam review

Frameworks and Testing

Conduite de Projet Cours 9 Test-Driven Development

linaye/gl.html

Software-Architecture Unit Testing (JUnit)

CS 520 Theory and Practice of Software Engineering Fall 2018

3. Convert 2E from hexadecimal to decimal. 4. Convert from binary to hexadecimal

Chapter 11, Testing. Using UML, Patterns, and Java. Object-Oriented Software Engineering

AP COMPUTER SCIENCE JAVA CONCEPTS IV: RESERVED WORDS

Second assignment came out Monday evening. Find defects in Hnefetafl rules written by your classmates. Topic: Code Inspection and Testing

CSSE 220 Day 3. Check out UnitTesting and WordGames from SVN

Unit Testing and JUnit

Subclass Gist Example: Chess Super Keyword Shadowing Overriding Why? L10 - Polymorphism and Abstract Classes The Four Principles of Object Oriented

Transcription:

Programmieren II Unit Testing & Test-Driven Development Alexander Fraser fraser@cl.uni-heidelberg.de (Based on material from Lars Vogel and T. Bögel) July 2, 2014 1 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 2 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 3 / 62

OOP Principles OOP Principles Minimize Accessibility of Classes and Members (Encapsulation) Favor Composition over Inheritance Program to an Interface, not an Implementation The Open-Closed Principle (open for extension, closed for modification) The Single Choice Principle (Strategy Pattern) The Liskov Substitution Principle 4 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 5 / 62

Motivation for testing In 1998, NASA lost the USD 655 Million Mars Climate Orbiter The peer review preliminary findings indicate that one team used English units (e.g., inches, feet and pounds) while the other used metric units for a key spacecraft operation. Finding: had the interface between the two teams been extensively tested, this could have been avoided http://thephp.cc/viewpoints/blog/2014/03/disintegration-testing 6 / 62

Motivation for unit testing Why should you write unit tests? Make sure your code does what you want it to do Speed up development and optimization/refactoring Create better interfaces and functionality Get other people to use your contribution Make sure nobody else breaks your feature (Also, make sure you don t break your feature) http://ed.agadak.net/2008/03/why-you-should-write-unit-tests 7 / 62

Good testing is not trivial Appropriate number of test cases? Implementing tests is tedious (stubs, mock objects etc.) Categories of test cases Logical test cases: value ranges for input/output Concrete test cases: specific values for input/output 8 / 62

Typical test methods Black box approach Testing an object as an interface No control about the internal structure of the test object Interface knowledge Examples: equivalence classes, boundary cases, state of objects White box approach Testing different flows within a test object Exploits knowledge about the internal structure (code) Examples: coverage of statements, branches, conditions, paths 9 / 62

Test methods Positive test Correct input (expects correct results) Negative test Invalid input (expects appropriate exception handling) Intuitive/empirical test Based on knowledge about error situations Should be tested alongside systematic test methods 10 / 62

Test execution Test framework (often: requirement to run tests) 11 / 62

Component tests Component tests Component: self-contained unit of code, e.g. class, method, module White box and black box testing Common errors Code does not terminate Erroneous or missing result Unexpected or wrong error message Inconsistent state of memory Unnecessary requirement of resources Unexpected behavior (e.g. crash) 12 / 62

Black box component test Testing a self-contained unit, e.g. an operation Typical test methods Empirical or random tests Equivalence classes (especially borderline cases) State assessments Is unable to detect redundant parts of the code 13 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 14 / 62

Example: Test cases Determine a suitable number of test cases. int search ( int [] a, int k) pre: a. length > 0 post : ( result >= 0 and a[ result ] == k) or ( result == -1 and ( not exists i: i >=0 and i < a. length and a[ i] == k) ) 15 / 62

Equivalence classes I Equivalence class Subset of possible input values Assumption Reaction of the code is identical for all values in the equivalence class Test cases Cover all equivalence classes: at least one representative for each class Borderline cases Test borderline cases Typical equivalence classes Valid/invalid ranges of values Critical values Separation into buckets of similar output values 16 / 62

Equivalence classes II Multiple input parameter Combine all valid equivalence classes of different input parameters Combine each invalid equivalence class with other, valid equivalence classes Simplification Frequent combinations Testing critical values only Restrict test coverage to pairwise combinations Minimal: each valid equivalence class occurs in one test case 17 / 62

Example: equivalence classes I Function int search ( int [] a, int k) pre : a. length > 0 post : ( result >= 0 and a[ result ] == k) or ( result == -1 and ( not exists i: i >=0 and i < a. length and a[ i] == k) ) 18 / 62

Example: equivalence classes II Valid equivalence classes Param1: a.length > 0 Param2: k in a, k not in a Refinement for param1: a.length = 1 a.length > 1 Refinement for param2: k is first in the middle last element of a not in a Invalid equivalence class Param1: a.length=0 19 / 62

Test cases a element k result [] (a.length=0) x invalid [x] (a.length=1) x (in a) 1 [y] (a.length=1) x (not in a) -1 [..., x,... ] (a.length>1) x (in the middle of a) n [... ] (a.length>1) x (not in a) -1 [x,... ] (a.length>1) x (first element of a) 1 [...,x] (a.length>1) x (last element of a) n 20 / 62

State assessment Considers not only input/output, but also history of states of a component Example: Stack States: initial, empty, filled, full, deleted Successful test: cover all states and branches at least once 21 / 62

White box test Coverage of statements Coverage of branches Coverage of paths Requirement: control flow diagram Main advantage Each part of the code is tested Disadvantages Difficulty of finding appropriate input values to cover all paths Difficulty of finding appropriate output values usually: Grey Box testing 22 / 62

Testing Classes I Defining a structure of tests Constructors Getters Boolean Methods Setters Iterators Complex computations Other methods (Destructors) 23 / 62

Testing Classes II Testing interactions between methods Dependencies between methods Non-modal: no dependency Uni-modal: fixed order (e.g. traffic light) Quasi-modal: content dependent order (e.g. Stack) Modal: functional dependency (e.g. bank account) 24 / 62

Fundamentals of Testing I Principle 1 Complete test coverage is impossible. Principle 2 Program testing can be used to show the presence of bugs, but never to show their absence! Edsger Dijkstra Principle 3 Write tests early! Don t defer them to the end of the development cycle! Principle 4 Bugs are not evenly distributed across the code. If a component contains multiple bugs, it is likely to contain even more. 25 / 62

Fundamentals of Testing II Principle 5 Repeating tests doesn t give you new insights. You need to assess, update and modify your test cases. Principle 6 Testing depends on the context and the application. Security relevant code needs to be tested more thoroughly. (Thanks, Captain Obvious!) Principle 7 A program without bugs does not necessary fulfill the specification of a client. Principle 8 Challenge: minimal number of test cases (= invested time) vs. highest quality. 26 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 27 / 62

Test-Driven Development Test-Driven Development Test-first approach Thinking about tests before implementing functionality Writing tests before programming Advantages All code is tested Forces you to think about functionality your code needs to provide Simple solutions (KISS): writing the smallest amount of code to make the test pass Alternative programming workflow. 28 / 62

Fear Test-driven development is a way of managing fear during programming. (Beck, 2002) Start simply. Write automated tests. Refactor to add design decisions one at a time. 29 / 62

The secrets of the ancients 1960s It was just assumed that any pro would do a damn good job of this activity, not to be embarrassed by unit bugs found in integration test or system test or god help us, in production. (Jerry Weinberg) 1 1 source: http://secretsofconsulting.blogspot.de/2008/12/ how-we-used-to-do-unit-testing.html 30 / 62

The secrets of the ancients 1970s It said the way to program is to look at the input tape and manually type in the output tape you expect. Then you program until the actual and expected tapes match. I thought, what a stupid idea. I want tests that pass, not tests that fail. Why would I write a test when I was sure it would fail. Well, I m in the habit of trying stupid things out just to see what happens, so I tried it and it worked great. 31 / 62

Rhythm of TDD 1 Quickly add a test. 2 Run all tests and see the new one fail. 3 Make a little change. 4 Run all tests and see them all succeed. 5 Refactor to remove duplication. 32 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 33 / 62

JUnit test framework Based on the tutorial by Lars Vogel: http://www.vogella.com/articles/junit/article.html JUnit TestClass Separate class for testing (test class) that contains multiple test methods Test methods indicated by annotations Requirement: all methods can be executed in an arbitrary order (no dependencies) Writing a test method Annotate a method with @org.junit.test annotation Use a JUnit method to check the expected result versus the actual result 34 / 62

JUnit annotations (version 4.x) I @Test Specifies that a method is a test method @Before Method is executed before each test, e.g. to prepare the test environment (reading data, initializing classes etc.) @After Method is executed after each test. Used to clean up the test environment, e.g. delete temporary data, free memory @BeforeClass Method is executed once before the start of all tests. Use cases: connection to a database etc. Note: methods need be be declared as static @AfterClass Method is executed once after all tests have been finished. Note: methods need to be declared as static @Ignore Ignore a method @Test (expected = Exception.class) Fails, if the method does not throw the named exception @Test(timeout=100) Fails, if the method takes longer than 100 milliseconds 35 / 62

Assert statements I Assert statements Special methods of the Assert class to test for certain conditions Required: expected result and actual result [message]: error message (optional) Write meaningful error messages! fail(string): Let the method fail (e.g. to check that a certain part of the code is not reached) asserttrue([message], boolean condition) Checks that the boolean condition is true assertsequals([string message], expected, actual) Tests whether two values are the same 36 / 62

Assert statements II assertsequals([string message], expected, actual, tolerance) Test for matching floating point values. Tolerance: number of decimals that need to be identical assertnull([message], object) Checks that an object is null assertnotnull([message], object) Checks that an object is not null assertsame([string], expected, actual) Checks that both variables refer to the same object assertnotsame([string], expected, actual) Tests whether both variables refer to different objects 37 / 62

Test Suite Test suites Multiple test classes can be combined into a test suite Running a test suite runs all corresponding test classes Example: two test classes import org. junit. runner. RunWith ; import org. junit. runners. Suite ; import org. junit. runners. Suite. SuiteClasses ; @RunWith ( Suite. class ) @ SuiteClasses ({ TestClassA. class, TestClassB. class }) public class AllTests { } 38 / 62

Practical workflow Outside of eclipse Add JUnit jar file (library) to the class path Method runclasses() in org.junit.runner.junitcore: run test classes Returns object of type org.junit.runner.result Result provides information about failures, successful tests etc. Unit testing with eclipse Eclipse supports most of the workflows necessary for JUnit You should use Eclipse 39 / 62

Class to test: Money.java I public class Money { private final int amount ; private final String currency ; public Money ( int amount, String currency ) { this. amount = amount ; this. currency = currency ; } public int getamount () { return amount ; } public String getcurrency () { return currency ; } public boolean equals ( Object anobject ) { if ( anobject instanceof Money ) { 40 / 62

Class to test: Money.java II } } Money money = ( Money ) anobject ; return money. getcurrency (). equals ( getcurrency ()) && getamount () == money. getamount (); } return false ; 41 / 62

Testing Money.java I Things to test Constructor equals() method 42 / 62

Testing Money.java II Testing the constructor import static org. junit. Assert.*; import org. junit. Test ; public class MoneyTest { @Test public void constructorshouldsetamountandcurrency () { Money m = new Money (10, " USD "); } } assertequals (10, m. getamount ()); assertequals (" USD ", m. getcurrency ()); 43 / 62

Testing for exceptions I Modification of the constructor If amount < 0 or an invalid currency is used: throw IllegalArgumentException 44 / 62

Testing for exceptions II Modified constructor public Money ( int amount, String currency ) { if ( amount < 0) { throw new IllegalArgumentException ( " illegal amount : [" + amount + "]"); } } if ( currency == null currency. isempty ()) { throw new IllegalArgumentException ( " illegal currency : [" + currency + "]"); } this. amount = amount ; this. currency = currency ; 45 / 62

Testing for exceptions III Testing for the occurrence of an exception @Test ( expected = IllegalArgumentException. class ) public void constructorshouldthrowiaeforinvalidamount () { Money m = new Money ( -10," USD "); } 46 / 62

Testing for exceptions IV Running the tests from the command line import org. junit. runner. JUnitCore ; import org. junit. runner. Result ; import org. junit. runner. notification. Failure ; public class MoneyTestRunner { public static void main ( String [] args ) { Result result = JUnitCore. runclasses ( MoneyTest. class ); for ( Failure failure : result. getfailures ()) { System. out. println ( failure. tostring ()); } } } 47 / 62

Creating and running tests from eclipse Simply do File > New > JUnit test It will ask you for which class file you want to write a test Type in the test, and run it to see if it passes 48 / 62

Client and Address Client and Address Client: a client stores a collection of Address objects Address: one address of a client We start with the test 49 / 62

Testing Client I public class ClientTest { private Address addressa = new Address (" street A"); private Address addressb = new Address (" street B"); @Test public void aftercreationshouldhavenoaddress () { Client client = new Client (); assertequals (0, client. getaddresses (). size ()); } @Test public void shouldallowtoaddaddress () { Client client = new Client (); client. addaddress ( addressa ); assertequals (1, client. getaddresses (). size ()); asserttrue ( client. getaddresses (). contains ( addressa )); } @Test 50 / 62

Testing Client II } public void shouldallowtoaddmanyaddresses () { Client client = new Client (); client. addaddress ( addressa ); client. addaddress ( addressb ); assertequals (2, client. getaddresses (). size ()); asserttrue ( client. getaddresses (). contains ( addressa )); asserttrue ( client. getaddresses (). contains ( addressb )); } problematic: code duplication (Client is instantiated in each method). 51 / 62

Creating Address Address.java Address only needs to store an address as a String Constructor expects the string public class Address { private String address ; public Address ( String add ) { this. address = add ; } } public String getaddress () { return this. address ; } 52 / 62

Creating Client I Implementing Clients Collection of Address objects Size of collection is 0 after instantiation Provides methods for adding an address and getting all addresses 53 / 62

Creating Client II Client.java public class Client { } private List < Address > addresses ; public Client () { this. addresses = new ArrayList < Address >(); } public List < Address > getaddresses () { return addresses ; } public void addaddress ( Address newaddress ) { this. addresses. add ( newaddress ); } 54 / 62

Running initialization before testing To avoid to repeat the same code for each test: @Before annotation public class ClientTest { private Address addressa = new Address (" street A"); private Address addressb = new Address (" street B"); private Client client ; @Before public void setup () { client = new Client (); } } // the rest of the code identical to the previous listing... 55 / 62

assert vs. asserttrue Java defines an assert statement which is only actually checked if you give the jvm the -ea argument The (good) intention is to allow programmers to develop using -ea and then to leave it away when code is in production Unfortunately, in practice people don t use this! Instead use methods like asserttrue from JUnit in your code (everywhere, not only in tests) import static org. junit. Assert.* public void mymethod ( int i) { // code here modifies i, should never result in i being less than 1 } asserttrue (" mymethod : i not greater than 0", i >0); 56 / 62

Outline 1 Recap 2 Testing - Introduction General Testing Component Tests 3 Testing in more detail Equivalence classes Fundamentals of Testing 4 Test-Driven Development 5 Unit Testing in Java JUnit Introduction Tests in Practice 6 Mocking 57 / 62

What is mocking? Motivation Java classes usually depend on other classes Mock object: dummy implementation for interface or class User-defined output of certain method calls Benefit: testing without dependencies This is a commonly used form of integration testing (think of Mars Climate Observer) Example: data provider (database replacement) Creating mock objects Manually (via code) Mock framework: create mock objects at runtime and define their behavior 58 / 62

Mock frameworks jmock http://jmock.org/ EasyMock http://easymock.org/ Mockito http://code.google.com/p/mockito/ 59 / 62

Example: EasyMock I Object instantiation // ICalcMethod is the object which is mocked ICalcMethod calcmethod = EasyMock. createmock ( ICalcMethod. class ) ; 60 / 62

Example: EasyMock II Specifying output expect(): simulate a method with certain arguments andreturn(): return value of the method for specified parameters times(): how often the Mock object will be called // setup the mock object expect ( calcmethod. calc ( Position. BOSS )). andreturn (70000.0). times (2) ; expect ( calcmethod. calc ( Position. PROGRAMMER )). andreturn (50000.0) ; // Setup is finished need to activate the mock replay ( calcmethod ); 61 / 62

Literature Vogel, Lars. JUnit - Tutorial http://www.vogella.com/articles/junit/article.html Ullenboom, Ch. Javainsel-Blog: Java Tests mit Junit http://www.tutego.de/blog/javainsel/2010/04/ junit-4-tutorial-java-tests-mit-junit Beck, Kent. Test Driven Development: By Example. Addison-Wesley Professional, 2002. 62 / 62