Test Driven Development



Similar documents
Effective unit testing with JUnit

JUnit. Introduction to Unit Testing in Java

Licensed for viewing only. Printing is prohibited. For hard copies, please purchase from

Java course - IAG0040. Unit testing & Agile Software Development

Introduction. Earlier programs structured as methods that call one another in a disciplined, hierarchical manner Recursive methods

Java. Java. e=mc 2. composition

Extreme Programming and Embedded Software Development

Testing Rails. by Josh Steiner. thoughtbot

Deep Agile Blending Scrum and Extreme Programming. Jeff Sutherland Ron Jeffries

Unit Testing and JUnit

Test Driven Development Part III: Continuous Integration Venkat Subramaniam

Test Driven Development

Agile.NET Development Test-driven Development using NUnit

Table of Contents. LESSON: The JUnit Test Tool...1. Subjects...2. Testing What JUnit Provides...4. JUnit Concepts...5

Test-Driven Development

Code Qualities and Coding Practices

Software Engineering. Top-Down Design. Bottom-Up Design. Software Process. Top-Down vs. Bottom-Up 13/02/2012

Testing Methodology Assignment 1 Unit testing using JUnit

Building a test harness is. an effort that often takes. on a life of its own. But it. doesn t have to get wildly out of control.

With a single download, the ADT Bundle includes everything you need to begin developing apps:

Fail early, fail often, succeed sooner!

OVERVIEW OF TESTING FIRST

TESTING WITH JUNIT. Lab 3 : Testing

CS170 Lab 11 Abstract Data Types & Objects

Debugging. Common Semantic Errors ESE112. Java Library. It is highly unlikely that you will write code that will work on the first go

You are to simulate the process by making a record of the balls chosen, in the sequence in which they are chosen. Typical output for a run would be:

Buyer Prospect Counseling

Unit testing with JUnit and CPPUnit. Krzysztof Pietroszek

Jenkins on Windows with StreamBase

sveltest: A testing language

Tutorial 7 Unit Test and Web service deployment

6.1. Example: A Tip Calculator 6-1

Break It Before You Buy It!

First Java Programs. V. Paúl Pauca. CSC 111D Fall, Department of Computer Science Wake Forest University. Introduction to Computer Science

CSE 326: Data Structures. Java Generics & JUnit. Section notes, 4/10/08 slides by Hal Perkins

Agile Testing and Extreme Programming

JUnit Howto. Blaine Simpson

J a v a Quiz (Unit 3, Test 0 Practice)

Announcement. SOFT1902 Software Development Tools. Today s Lecture. Version Control. Multiple iterations. What is Version Control

Continuous Integration with Jenkins. Coaching of Programming Teams (EDA270) J. Hembrink and P-G. Stenberg [dt08jh8

14:440:127 Introduction to Computers for Engineers. Notes for Lecture 06

CPSC 330 Software Engineering

Programming Exercises

CS 141: Introduction to (Java) Programming: Exam 1 Jenny Orr Willamette University Fall 2013

Agile processes. Extreme Programming, an agile software development process. Extreme Programming. Risk: The Basic Problem

Unit Testing JUnit and Clover

Towards Software Configuration Management for Test-Driven Development

The Social Accelerator Setup Guide

A Practical Guide to Test Case Types in Java

Upping the game. Improving your software development process

AppendixA1A1. Java Language Coding Guidelines. A1.1 Introduction

How To Test In Bluej

Reverse proxy for Tomcat Project Plan

XP & Scrum. extreme Programming. XP Roles, cont!d. XP Roles. Functional Tests. project stays on course. about the stories

Vim, Emacs, and JUnit Testing. Audience: Students in CS 331 Written by: Kathleen Lockhart, CS Tutor

CEFNS Web Hosting a Guide for CS212

Hands on exercise for

So you want to create an a Friend action

Software Development Tools

The Rules 1. One level of indentation per method 2. Don t use the ELSE keyword 3. Wrap all primitives and Strings

WA2099 Introduction to Java using RAD 8.0 EVALUATION ONLY. Student Labs. Web Age Solutions Inc.

Club Accounts Question 6.

An Example Checklist for ScrumMasters

Arrays. Introduction. Chapter 7

Extreme Programming, an agile software development process

Test Driven Development with Continuous Integration: A Literature Review

XP and TDD. Extreme Programming and Test Driven Development. Bertrand Meyer, Manuel Oriol Andreas Leitner. Chair of Software Engineering ETH Zurich

Extreme Programming, an agile software development process

Agile Techniques for Object Databases

Using Testing and JUnit Across The Curriculum

Software Development Process

Chapter 3. Input and output. 3.1 The System class

Unit Testing & JUnit

1 Hour, Closed Notes, Browser open to Java API docs is OK

Hypercosm. Studio.

Kotlin for Android Developers

Overview. What is software testing? What is unit testing? Why/when to test? What makes a good test? What to test?

Introduction. Motivational Principles. An Introduction to extreme Programming. Jonathan I. Maletic, Ph.D.

16.1 DataFlavor DataFlavor Methods. Variables

Jiří Tomeš. Nástroje pro vývoj a monitorování SW (NSWI026)

Automated Testing Options for PL/SQL Steven Feuerstein PL/SQL Evangelist, Quest Software

Agile version control with multiple teams

Continuous Integration: Improving Software Quality and Reducing Risk. Preetam Palwe Aftek Limited

How to Outsource Without Being a Ninnyhammer

Interviewing for Software Jobs. Matt Papakipos Brown Math/CS 93 Slides presented at Brown University on October 7, 2014

Parsing Technology and its role in Legacy Modernization. A Metaware White Paper

Unit Testing. and. JUnit

Test Driven Development for Embedded Software

AP Computer Science A - Syllabus Overview of AP Computer Science A Computer Facilities

AP Computer Science Java Mr. Clausen Program 9A, 9B

Mortgage marketing guide 2015 summers hottest lead generation tips

Colleen s Interview With Ivan Kolev

Topics covered. Agile methods Plan-driven and agile development Extreme programming Agile project management Scaling agile methods

Java CPD (I) Frans Coenen Department of Computer Science

Unit testing with EUnit. Richard Carlsson

Eclipse Help

Merlin A Continuous Integration Tool for VisualWorks

Agile In a Nutshell. Note - all images removed to fit 2MB limit Actual presentation has much more content. Jonathan Rasmusson

An Experience Report on Implementing a Custom Agile Methodology on a C++/Python Project

Igniting young minds through computer programming

Transcription:

Test Driven Development Introduction Test Driven development (TDD) is a fairly recent (post 2000) design approach that originated from the Extreme Programming / Agile Methodologies design communities. Its primary goal is to produce better code by introducing the testing process earlier into the overall design process. In TDD, tests become the design. The official book on TDD is Test-Driven Development by Example, by Kent Beck (see references). It outlines the philosophy behind TDD as well as providing an excellent example of TDD in actual use. Test-Driven Development follows the general script test (fail); code the simplest thing to pass the test; test (pass); refactor The goal of TDD is clean code that works, according to Ron Jeffries. Some of the advantages of TDD include: - It is predictable. You know when you are finished without worrying about hidden bugs. - It gives you time to reflect on the code you are writing. First you write tests, then you write code to pass the tests, then you reflect on the code and refactor it to make it better. - It improves the lives of the people using the software - It allows people to count on you, and you on them. - It feels good to write it From Test-Driven Development by Example, by Kent Beck In TDD, there are two simple rules: 1. Write new code only if an automated test fails 2. Eliminate Duplication TDD follows on many of the principles of Extreme Programming (and Agile Programming). A good synopsis of Extreme Programming can be found here http://ootips.org/xp.html Another goal of TDD is for the programmer to become test infected. That is, the programmer becomes convinced of the benefits of writing tests first and so starts thinking of programming in terms of what test would illustrate this requirement instead of how should I code this requirement. Hopefully, after working through the example I ve provided, and doing TME4, you too will see value in TDD. Fibonacci Example Using TDD, let us build a class to provide the Fibonacci series for any given input, n. The Fibonacci series is {1, 1, 2, 3, 5, 8, 13, 21, 34, 55,. The value of n starts at n=0 and increments, such than the Fibonacci number for n=3 (for example) is 3. Fibonacci (4) = 5, Fibonacci (8) = 34 and so on. To start our development using TDD, we first need a framework in which to develop. What I do (using the information on programming tips from Unit 8 and 9), is to start with a working project, and strip it down. In this case, I create a directory structure much like that from the Unit 8 example: fibonacci fibonacci/source fibonacci/source/fibonacci

fibonacci/source/fibonaccitest Into fibonacci/source I place a copy of build.xml, borrowed from another working project (in this case, Unit8). I examine and modify the build.xml file so that it will work with the new project. In this case, all I need to do is search and replace all occurrences of unit8 with fibonacci. At this time I also modify the file packages, making the same substitution so that javadoc will work for this project. Next, I require the one basic Unit test file, AllTests.java. This is the starting point for all tests, so I copy it from Unit8 as well, and modify it such that any references to Unit8 are changed to fibonacci. I also remove all of the suite.addtest( ); lines from the Test method, since I have no test suites yet. This seems both too easy, and rather silly but the point here is to not re-invent the wheel. Taking working code and modifying it to suit a new purpose is perfectly good programming practice. The benefit of this approach comes when you run ant build with this new project, and everything works. Of course, the only file to comile was AllTests.java, but it compiles and runs without error so you have a working clean slate from which to begin TDD. First, we require a test suite for our Fibonacci tests, so I add the line suite.addtest(fibonaccitest.suite()); to the Test method of AllTests.java. If I build this, the Unit tests will fail as I have no class FibonacciTest yet defined. We can create FibonacciTest.java from scratch, or copy it from unit8/unit8tests. I d copy and modify MyGeometryTest.java by renaming it FibonacciTest.java and then removing all the code inside the methods that does not pertain to an empty test suite. Here s what you get: / Title: FibonacciTest Description: JUnit Test Object Copyright: Copyright (c) 2003-2004, Richard S. Huntrods Author: Richard S. Huntrods Version: 1.0 Date: December 9, 2003 @author Richard S. Huntrods @version 1.0 / / Fibonacci public interface / package fibonaccitest; import fibonacci.; import junit.framework.; import java.util.vector; public class FibonacciTest extends TestCase {

public FibonacciTest(String name) { super(name); public static Test suite() { return new TestSuite(FibonacciTest.class); public static void main(string[] args) { System.out.println("Executing FibonacciTest suite"); junit.textui.testrunner.run(suite()); protected void setup() throws Exception { System.out.println(" FibonacciTest Begin"); protected void teardown() throws Exception { System.out.println(" FibonacciTest End"); public void testconstructors() { public void testmutators() { Pretty bare, isn t it? However, if we run ant build, the Unit tests come up green (0 errors, 0 failures) once again. Progress! OOPS! I spoke too soon. We have a compile error. It seems the statement import fibonacci.; in our FibonacciTest class won t compile because the fibonacci/source/fibonacci directory is empty. There are two solutions. Either we can comment out this line, or we can build an empty Fibonacci class in our fibonacci/source/fibonacci directory. Since we will require the Fibonacci class in moments anyway, let s build it now. This time, I ll build it from scratch as it will be so simple: / Title: Fibonacci Description: TME2 Geometry class Copyright: Copyright (c) 2003-2004, Richard S. Huntrods Author: Richard S. Huntrods Version: 1.0 Date: December 9, 2003 @author Richard S. Huntrods @version 1.0 / package fibonacci; public class Fibonacci { Now if we run ant build, the test results are green. Now we do have progress!

Take a moment to examine the javadocs that were automatically build during the build. It s nice to have this automated. Also notice the test output says 2 tests run, even though we didn t actually do anything. Where did these two tests come from? If you re-examine FibonacciTest, notice the two empty methods testconstructors() and testmutators(), which I didn t remove from the Unit8 copy (because we may still want to test the Fibonacci constructors and any mutators). These empty methods, whose names start with test are automatically turned into tests by the JUnit framework. You can remove them if you don t like seeing these empty methods. Now for some real work. Let s create a method testfibonacci inside the FibonacciTest class. Rather than start with an empty method, lets put our first test there. We know that Fibonacci(0) = 1 by definition, so let s test that. Here s the new method: public void testfibonacci() { assertequals("testfibonacci Fibonacci.calculate(0) = 1",1, Fibonacci.calculate(0)); A couple of points. You are the designer here, so you can call this method anything you like. Some suggestions are fibonacci, getfibonacci, calculate, number. You decide. Convention dictates that methods which calculate some value and return it to a calling method are usually declared static (so that you don t require and instance variable), and so I ve implied that here by the way I have called calculate. If you try and build this, the build fails due to compiler errors the calculate method is missing. Now is a good time to establish your TDD environment. That is, in your IDE or editor, you want a window open to build.log, FibonacciTest.java and Fibonacci.java. With these three windows, you can examine and modify everything necessary to complete this TDD example. We start by adding a calculate method. It must return an integer, so have it return 0. Build, and the tests are red. Fix that by having calculate return 1. Now the tests are green. The process for TDD is always the same: Test, Fix, Refactor. First you write the test (that should fail). Next, you write the minimum code to make the test pass. Finally, you refactor that code to make it elegant and simple. By running the tests after every step, you always know the code is correct. This gives you the confidence to continue. Let s do that. Next, we want to test Fib(1) = 1. We add the test to our method: assertequals("testfibonacci Fibonacci.calculate(1) = 1",1, Fibonacci.calculate(1)); The tests are green! Why is this? Well, returning 1 from our calculate() method happens to be the correct answer for both tests. Next test: Fib(2) = 2. Add the test, and it fails. What s the simplest fix? Add an if-else condition to the calculate method: if(number < 2) { else { return 2;

Again, tests are green. But, is it time to refactor? Examining the code in Fibonacci, probably not. It s still pretty simple, and there s no more elegant solution to the current tests. Another point to consider. This process seems pretty boring for such a simple result. Why not jump ahead and program more tests at once? The answer is twofold. First, jumping ahead is often a very good way to get into trouble. If you add several tests and one fails, you don t always know if one or more tests failed. You may spend time fixing the first failure, only to discover that the fix makes it worse for subsequent tests. Better to fix one thing at a time and then proceed. Second, as you gain experience programming and in TDD, you will find there are times you CAN leap ahead. Other times, you will find you must test/fix/refactor one line at a time. In general, let your confidence (and the green tests) be a guide. If things are going well, and you feel comfortable taking bigger steps, then do it. However, if you get an unexpected red light, don t be afraid to comment out (or remove) all the new stuff since the last green light and take smaller steps. Next test: Fib(3) = 3. To start, we fix the red light with another if-else. However, it looks like (from where we stand in these tests) that Fib(0) returns 1, but the others return the input number. Let s refactor our code from this: if(number < 3) { if(number < 2) { else { return 2; else { return 3; (which is getting pretty ugly), to this: if(number <= 1) { else { return number; This is much more elegant, and still gives us the green light on all tests. (NOTE: if(number <= 0) also works which you choose is entirely up to you). Again, you are saying but this is WRONG, and in the grand scheme of things (and Fibonacci numbers), you are correct. However, this is and EXAMPLE, and the purpose of this example is to illustrate the TDD process using something you understand (so you can follow the process clearly). In fact, for the tests we ve built so far, this code is 100% correct! But, we re about to break that. Next test: Fib(4) = 5. Now the tests are red, and the fix is to again put an if statement in the code. However, as we refactor, we realize that there is no simple solution as before. Instead, we must examine the input and output. It seems as if the number we output is really the sum of the two previous output numbers. Let s write this out as a table to see:

Fib(0) = 1 (seems to be a defined output to begin the series) Fib(1) = 1 (also seems to be defined) Fib(2) = 1 + 1 = 2 Fib(3) = 2 + 1 = 3 Fib(4) = 3 + 2 = 5 Fib(n) = Fib(n-1) + Fib(n-2)??? (Of course we know this is the true algorithm for Fibonacci numbers) Lets try this with numbers up to Fib(8) and see. Fib(5) = Fib(4) + Fib(3) = 5 + 3 = 8? correct Fib(6) = Fib(5) + Fib(4) = 8 + 5 = 13 Fib(7) = Fib(6) + Fib(5) = 13 + 8 = 21 Fib(8) = Fib(7) + Fib(6) = 21 + 13 = 34 Indeed, this seems to be the correct algorithm. We can write tests for these numbers, but then we need to convert the algorithm into code to fix the tests. Rather than fix the tests with a series of if statements (or a switch), let s make that leap to code the algorithm By the way, notice that you added four new tests (Fib 5-8), but only get one error. The test framework stops on the first error in any test method. That s why it s important to make small steps until you get comfortable. You only get to see the first error or failure. As it turns out, Java frees us from a terrible burden of programming, as it allows recursive method calls. As a result, we can write this code: if(number <= 1) { else { return calculate(number-1) + calculate(number-2); As it happens, this is the correct code for the algorithm, and (thanks to recursion) happens to be pretty elegant and simple as well! Add a few more tests, confirm the green light and we re DONE. The completed example can be found in the TDD Fibonacci Example link. References Beck, Kent, Test-Driven Development, 2003, Addison Wesley.