View
676
Download
1
Category
Tags:
Preview:
DESCRIPTION
MELJUN CORTES Java lecture Intro to TDD
Citation preview
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.
Recommended