meljun cortes java lecture intro to tdd

37
Introduction to Unit Introduction to Unit Testing & Test-Driven Testing & Test-Driven Development Development Java Fundamentals and Object- Java Fundamentals and Object- Oriented Programming Oriented Programming The Complete Java Boot Camp The Complete Java Boot Camp MELJUN CORTES MELJUN CORTES MELJUN CORTES MELJUN CORTES

Upload: meljun-cortes

Post on 13-May-2015

680 views

Category:

Technology


1 download

DESCRIPTION

MELJUN CORTES Java lecture Intro to TDD

TRANSCRIPT

Page 1: MELJUN CORTES Java Lecture Intro to TDD

Introduction to Unit Introduction to Unit Testing & Test-Driven Testing & Test-Driven DevelopmentDevelopment

Java Fundamentals and Object-Oriented Java Fundamentals and Object-Oriented ProgrammingProgramming

The Complete Java Boot CampThe Complete Java Boot Camp

MELJUN CORTESMELJUN CORTES

MELJUN CORTESMELJUN CORTES

Page 2: MELJUN CORTES Java Lecture Intro to TDD

What is unit testing?What is unit testing?

Testing is often divided into categories such as:Testing is often divided into categories such as: Unit testingUnit testing

Testing a ‘unit’ of code, usually a class or method Integration testingIntegration testing

Testing a module of code (e.g. a package) Application testingApplication testing

Testing the code as the user would see it (black box)

Types of Automated TestsTypes of Automated Tests unit testsunit tests acceptance testsacceptance tests

Page 3: MELJUN CORTES Java Lecture Intro to TDD

RationaleRationale

Fixing a bug is usually pretty quick… Fixing a bug is usually pretty quick… finding it is a nightmare.finding it is a nightmare.

Page 4: MELJUN CORTES Java Lecture Intro to TDD

RationaleRationale

It is easier to find a needle in a haystack if It is easier to find a needle in a haystack if you have a smaller haystack.you have a smaller haystack.

Page 5: MELJUN CORTES Java Lecture Intro to TDD

RationaleRationale

A suite of tests is a powerful bug-detector A suite of tests is a powerful bug-detector that decapitates the time it takes to find that decapitates the time it takes to find bugs.bugs.

Page 6: MELJUN CORTES Java Lecture Intro to TDD

What is Junit?What is Junit?

JUnit is a unit testing framework written by JUnit is a unit testing framework written by Erich Gamma and Kent Beck Erich Gamma and Kent Beck

primary unit testing tool for javaprimary unit testing tool for java Can integrated into IDE, run stand-alone, or part Can integrated into IDE, run stand-alone, or part

of scripted environments (e.g. ANT)of scripted environments (e.g. ANT) It is found at It is found at www.junit.org It consists of classes that the developer can It consists of classes that the developer can

extend to write a test – notably extend to write a test – notably junit.framework.TestCasejunit.framework.TestCase - - and related and related structure to run and report the testsstructure to run and report the tests

Page 7: MELJUN CORTES Java Lecture Intro to TDD

Writing a testWriting a test

• Directions can be found in the Junit cookbook - Directions can be found in the Junit cookbook - http://junit.sourceforge.net/doc/cookbook/cookbook.htm

• Sound bite summarySound bite summary• Subclass Subclass TestCase, call them <XXX>Test, call them <XXX>Test• Write methods which run your tests, calling them Write methods which run your tests, calling them

test<Foo>test<Foo>• Call a test runner with your testCall a test runner with your test• When you want to check a value, call an assert method When you want to check a value, call an assert method

(e.g. assertTrue()) and pass a condition that is true if the (e.g. assertTrue()) and pass a condition that is true if the test succeedstest succeeds

Page 8: MELJUN CORTES Java Lecture Intro to TDD

Writing a test - exampleWriting a test - example

public void testAddingDifferentCurrencies() {      public void testAddingDifferentCurrencies() {      // [12 CHF] + [14 CHF] + [28 USD] == {[26 CHF][28 USD]} // [12 CHF] + [14 CHF] + [28 USD] == {[26 CHF][28 USD]} Money f26CHF = new Money(26,”CHF”);Money f26CHF = new Money(26,”CHF”);Money f28USD = new Money(28,”USD”);Money f28USD = new Money(28,”USD”);Money f12CHF = new Money(12,”CHF”);Money f12CHF = new Money(12,”CHF”);Money f14CHF = new Money(14,”CHF”);     Money f14CHF = new Money(14,”CHF”);     Money bag[]= { f26CHF, f28USD };      Money bag[]= { f26CHF, f28USD };      MoneyBag expected= new MoneyBag(bag);   MoneyBag expected= new MoneyBag(bag);   MoneyBag result = f12CHF.add(f28USD.add(f14CHF));  MoneyBag result = f12CHF.add(f28USD.add(f14CHF));  assertEquals(expected,result);assertEquals(expected,result);

} }

Page 9: MELJUN CORTES Java Lecture Intro to TDD

Test Fixture methodsTest Fixture methods

setUp – does initialization common to all testssetUp – does initialization common to all tests It is run each time a test is run (can’t store It is run each time a test is run (can’t store

state in variables that are set in setUp)state in variables that are set in setUp) tearDown – releases resources, e.g. database tearDown – releases resources, e.g. database

connections. connections. TestCase can also have other helper methods, just TestCase can also have other helper methods, just

don’t name them test<anythingdon’t name them test<anything>>

Page 10: MELJUN CORTES Java Lecture Intro to TDD

Assert methodsAssert methods

There are a variety of assert methods available, e.g.There are a variety of assert methods available, e.g. assertTrue, assertFalse, assertNull, assertSame, assertTrue, assertFalse, assertNull, assertSame,

assertEquals, etc.assertEquals, etc. In general, the syntax is In general, the syntax is

assert<Foo>(<type> expected, <type> testVal)assert<Foo>(<type> expected, <type> testVal) assert<Foo>(String message, <type> expected, assert<Foo>(String message, <type> expected,

<type> testVal)<type> testVal)

Page 11: MELJUN CORTES Java Lecture Intro to TDD

Running testsRunning tests

Call from IDE /Ant – no need for main classCall from IDE /Ant – no need for main class Stand-alone: need to call a runner run method, e.g Stand-alone: need to call a runner run method, e.g

junit.textui.TestRunner.run(suite());junit.textui.TestRunner.run(suite()); Example main class for running testsExample main class for running tests// imports// importspublic class ATestSuite {public class ATestSuite { public static TestSuite suite () {public static TestSuite suite () {

TestSuite suite = newTestSuite(“MyPackageTests”); TestSuite suite = newTestSuite(“MyPackageTests”); suite.addTestSuite(“MyClassTests.class”); suite.addTestSuite(“MyClassTests.class”); return suite; return suite;

}} public static void main(String args[]) { public static void main(String args[]) { junit.textui.TestRunner.run(suite());junit.textui.TestRunner.run(suite()); }}}}

Page 12: MELJUN CORTES Java Lecture Intro to TDD

Project structureProject structure

One way to organize tests is to put them in a parallel One way to organize tests is to put them in a parallel directory tree (recommended):directory tree (recommended): E.g. src/com.company.MyPackage. …. Has a E.g. src/com.company.MyPackage. …. Has a

parallel tree of test/ com.company.MyPackage. parallel tree of test/ com.company.MyPackage. ……

Alternative way is to put them in their own package:Alternative way is to put them in their own package: E.g. com.company.MyPackage Has tests in E.g. com.company.MyPackage Has tests in

com.company.Mypackage.testscom.company.Mypackage.tests

Page 13: MELJUN CORTES Java Lecture Intro to TDD

Junit DemoJunit Demo

Lets try it out!Lets try it out! Test Money ClassTest Money Class

Page 14: MELJUN CORTES Java Lecture Intro to TDD

Money ExampleMoney Example

– package com.onb.moneyexample;package com.onb.moneyexample;

– public class Money {public class Money {– private int amount;– private String currency;– public Money(int amount, String currency) {

this.amount = amount; this.currency = currency;

– }– public int getAmount() {

return amount;– }– public String getCurrency() {

return currency;– }

Page 15: MELJUN CORTES Java Lecture Intro to TDD

Money Example (2)Money Example (2)

– public boolean equals(Object other){ if (!(other instanceof Money)){ return false; } Money m = (Money) other; return (amount == m.amount) && (currency.equals(m.currency));

– }– public int hashCode(){

return amount * 7 * currency.hashCode();– }– public String toString(){

return amount + " " + currency;– }

Page 16: MELJUN CORTES Java Lecture Intro to TDD

Money Example (3)Money Example (3)

public Money times(int multiplier) {– return new Money(amount * multiplier,– currency);

}– }}

Page 17: MELJUN CORTES Java Lecture Intro to TDD

MoneyTest ExampleMoneyTest Example

– package com.onb.moneyexample;package com.onb.moneyexample;– import junit.framework.TestCase;import junit.framework.TestCase;– public class MoneyTest extends TestCase {public class MoneyTest extends TestCase {

public static void main(String[] args) {– junit.textui.TestRunner.run(MoneyTest.class);

} public void testCreateMoney(){

– Money fivepesos = new Money(5,"PhP");

– assertNotNull(fivepesos);

– assertEquals(5,fivepesos.getAmount());

– assertEquals("PhP", fivepesos.getCurrency());

}

Page 18: MELJUN CORTES Java Lecture Intro to TDD

MoneyTest Example (2)MoneyTest Example (2)

public void testEquals(){– Money apeso = new Money(1,"PhP");

– Money anotherpeso = new Money(1,"PhP");

– assertTrue(apeso.equals(anotherpeso));

– Money twopesos = new Money(2,"PhP");

– assertFalse(twopesos.equals(apeso));

– assertFalse(twopesos.equals("1 PhP"));

– Money adollar = new Money(1,"USD");

– assertFalse(adollar.equals(apeso));

}

Page 19: MELJUN CORTES Java Lecture Intro to TDD

MoneyTest Example (3)MoneyTest Example (3)

public void testHashCode(){– Money tenpesos = new Money(10,"PhP");

– assertEquals(7*10* "PhP".hashCode(), tenpesos.hashCode());

– Money tendollars = new Money(10,"USD");

– assertFalse(tendollars.hashCode() == tenpesos.hashCode());

– Money ninepesos = new Money(9,"PhP");

– assertFalse(ninepesos.hashCode() == tenpesos.hashCode());

}

Page 20: MELJUN CORTES Java Lecture Intro to TDD

MoneyTest Example(4)MoneyTest Example(4)

public void testToString(){– Money fivepesos = new Money(5,"PhP");

– assertEquals("5 PhP", fivepesos.toString());

} public void testAddMoney(){

– Money fivepesos = new Money(5,"PhP");

– assertEquals(new Money(10,"PhP"), fivepesos.times(2));

– assertEquals(new Money(15,"PhP"), fivepesos.times(3));

– assertEquals(new Money(5,"PhP"), fivepesos);

}

– }}

Page 21: MELJUN CORTES Java Lecture Intro to TDD

Test-Driven Test-Driven DevelopmentDevelopment

Java Fundamentals and Object-Oriented Java Fundamentals and Object-Oriented ProgrammingProgramming

The Complete Java Boot CampThe Complete Java Boot Camp

Page 22: MELJUN CORTES Java Lecture Intro to TDD

DefinitionDefinition

Software-development philosophy where Software-development philosophy where the writing of automated tests is central.the writing of automated tests is central.

Page 23: MELJUN CORTES Java Lecture Intro to TDD

Test-FirstTest-First

Tests are written Tests are written beforebefore the code. the code. Tests specify the behavior of the component.Tests specify the behavior of the component. Tests guide designTests guide design

Programmers are forced to write decoupled classes.

Programmers see the class from the point of view of the user of the class.

Page 24: MELJUN CORTES Java Lecture Intro to TDD

Programmer TestsProgrammer Tests

Unit Tests are written by the programmers Unit Tests are written by the programmers who wrote the components being tested.who wrote the components being tested. ……not delegated to junior programmers or to not delegated to junior programmers or to

“QA” programmers.“QA” programmers.

Page 25: MELJUN CORTES Java Lecture Intro to TDD

Test as You CodeTest as You Code

Writing unit tests should not be done at Writing unit tests should not be done at the the same timesame time you write your component. you write your component.

Rhythm of coding:Rhythm of coding: Code a little… Test a little… Code a little… Code a little… Test a little… Code a little…

Test a little… Code a little… Test a little…Test a little… Code a little… Test a little…

Page 26: MELJUN CORTES Java Lecture Intro to TDD

Management ImplicationsManagement Implications

If code has no automated test case written If code has no automated test case written to prove that it works, it must be assumed to prove that it works, it must be assumed not to work.not to work. Team leaders may validly reject code submitted Team leaders may validly reject code submitted

without unit tests.without unit tests. Unit tests are usually easier to read and QA, Unit tests are usually easier to read and QA,

making code-management easier.making code-management easier.

Page 27: MELJUN CORTES Java Lecture Intro to TDD

Software without automated test cases Software without automated test cases cannot be economically refactored.cannot be economically refactored.

Automated unit-level testing of Java Automated unit-level testing of Java classes is an essential ingredient to classes is an essential ingredient to continuous integration.continuous integration.

Other ImplicationsOther Implications

Page 28: MELJUN CORTES Java Lecture Intro to TDD

Java Fundamentals and Object-Oriented Java Fundamentals and Object-Oriented ProgrammingProgramming

The Complete Java Boot CampThe Complete Java Boot Camp

Unit-Testing Best Unit-Testing Best PracticesPractices

Page 29: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Tests shouldn’t be dependent on other Tests shouldn’t be dependent on other teststests

Don’t test things that can’t breakDon’t test things that can’t break Ex: simple getters and settersEx: simple getters and setters

Page 30: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Don’t rely on the ordering of test casesDon’t rely on the ordering of test cases Avoid side effectsAvoid side effects Read test data from a relative path or the Read test data from a relative path or the CLASSPATHCLASSPATH

Avoid code duplication in test casesAvoid code duplication in test cases TDD: test should fail first, to assure that the TDD: test should fail first, to assure that the

test is ok!test is ok!

Page 31: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Separate production and test codeSeparate production and test code But typically in the same packagesBut typically in the same packages

Measure test coverageMeasure test coverage Use automated tools to measure test-coverageUse automated tools to measure test-coverage

Page 32: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Debugging w/ TestsDebugging w/ Tests

Martin Fowler: "Whenever you are Martin Fowler: "Whenever you are tempted to type something into a print tempted to type something into a print statement or a debugger expression, statement or a debugger expression, write it as a test instead.”write it as a test instead.”

1.1. Use tests to reproduce the bug.Use tests to reproduce the bug.

2.2. Fix the bug until your tests pass.Fix the bug until your tests pass.

Page 33: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Once your tests are running, make sure Once your tests are running, make sure they stay running. they stay running. If you start to allow your tests to fail, pretty soon If you start to allow your tests to fail, pretty soon

your suite will be useless.your suite will be useless.

Page 34: MELJUN CORTES Java Lecture Intro to TDD

Best PracticesBest Practices

Optimize your test suiteOptimize your test suite Try to have a fast test suite so that all tests Try to have a fast test suite so that all tests

can be run for every change.can be run for every change. Fast machines will help.Fast machines will help. If this can’t be done, group your tests into If this can’t be done, group your tests into

smaller suites that can be run appropriately smaller suites that can be run appropriately when relevant portions are changed.when relevant portions are changed.

But make sure all tests are run at least once a day.

Maybe you can have a dedicated machine that runs all your tests on new builds.

Page 35: MELJUN CORTES Java Lecture Intro to TDD

Legacy TestingLegacy Testing

Adding Tests to an Existing ProjectAdding Tests to an Existing Project

Page 36: MELJUN CORTES Java Lecture Intro to TDD

Legacy TestingLegacy Testing

Some tests are better than no testsSome tests are better than no tests Think in terms of cost-benefit analysis. Think in terms of cost-benefit analysis.

Prioritize:Prioritize:

1.1. common casecommon case

2.2. alternate casesalternate cases

3.3. error conditionserror conditions

4.4. boundary conditionsboundary conditions

5.5. extreme conditionsextreme conditions

Page 37: MELJUN CORTES Java Lecture Intro to TDD

Legacy TestingLegacy Testing

Add tests before fixing bugs.Add tests before fixing bugs. Add tests before refactoring.Add tests before refactoring.