meljun cortes java lecture intro to tdd

Post on 13-May-2015

680 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

MELJUN CORTES Java lecture Intro to TDD

TRANSCRIPT

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

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

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.

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.

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.

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

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

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);

} }

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>>

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)

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()); }}}}

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

Junit DemoJunit Demo

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

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;– }

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;– }

Money Example (3)Money Example (3)

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

}– }}

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());

}

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));

}

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());

}

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);

}

– }}

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

DefinitionDefinition

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

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.

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.

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…

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.

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

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

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

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!

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

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.

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.

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.

Legacy TestingLegacy Testing

Adding Tests to an Existing ProjectAdding Tests to an Existing Project

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

Legacy TestingLegacy Testing

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

top related