test driven development tdd. testing ”testing can never demonstrate the absence of errors in...
TRANSCRIPT
TestingTesting
””Testing can never demonstrate the Testing can never demonstrate the absence of errors in software, only absence of errors in software, only their presence”their presence”
Edsger W. DijkstraEdsger W. Dijkstra
(but it is very good at the latter).(but it is very good at the latter).
TestingTesting
““If it's worth building, it's worth If it's worth building, it's worth testing.testing.
If it's not worth testing, why are you If it's not worth testing, why are you wasting your time working on it?”wasting your time working on it?”
(http://www.agiledata.org/essays/(http://www.agiledata.org/essays/tdd.html)tdd.html)
TDDTDD
Test-first or test-driven development Test-first or test-driven development has origins in eXtreme Programming has origins in eXtreme Programming (XP)(XP)
It is one part of XP that can be It is one part of XP that can be extracted and used on its ownextracted and used on its own
eXtreme ProgrammingeXtreme Programming
Is a methodology for software Is a methodology for software developmentdevelopment
Focuses on the customerFocuses on the customer
Has rules for:Has rules for:– PlanningPlanning– DesigningDesigning– CodingCoding– TestingTesting
TDD is also embraced by:TDD is also embraced by:
Rational Unified Process (RUP) Rational Unified Process (RUP)
Agile Unified Process (AUP) Agile Unified Process (AUP)
Open Unified Process (Open UP) Open Unified Process (Open UP)
ScrumScrum
(agile methods)(agile methods)
TDDTDD
Is NOT a testing methodologyIs NOT a testing methodology
It IS a development methodologyIt IS a development methodology
Does not replace QA or thorough Does not replace QA or thorough testingtesting
TDD TestsTDD Tests
Are only part of the development Are only part of the development processprocess
Not intended to aggressively find bugsNot intended to aggressively find bugs
They’re weakThey’re weak
A programmer taking a TDD approach A programmer taking a TDD approach refuses to write a new function until refuses to write a new function until there is first a test that fails because there is first a test that fails because that function isn’t present that function isn’t present
What are the purposes of a test?What are the purposes of a test?
Does the code work?Does the code work?– What do we mean by work?What do we mean by work?
Make sure that changes don’t break Make sure that changes don’t break anything that is already workinganything that is already working
Documents featuresDocuments features
Measure of completenessMeasure of completeness
Advantages of writing tests firstAdvantages of writing tests firstQuick results: Quick results: Developers can see the effect of Developers can see the effect of design decisions within minutes. design decisions within minutes. Flexibility: Flexibility: Changes are easy because of the short Changes are easy because of the short distance between commits. distance between commits. Automatic catalog of regression tests: Automatic catalog of regression tests: If If something developed six months ago suddenly something developed six months ago suddenly breaks under today's code, it is known breaks under today's code, it is known immediately. immediately. Good, clean code that works: Good, clean code that works: As the mantra of As the mantra of JUnit testing proclaims, "If the light is green, the JUnit testing proclaims, "If the light is green, the code is clean." code is clean."
(www.developer.com)(www.developer.com)
Disadvantages of writing tests firstDisadvantages of writing tests first
Doesn’t work well for GUIs or multi-Doesn’t work well for GUIs or multi-threaded applicationsthreaded applications
Impractical for use with legacy codeImpractical for use with legacy code
Effect or Side-effect?Effect or Side-effect?
Documentation/specificationDocumentation/specification– This group of tests you have written This group of tests you have written
becomes part of your documentation.becomes part of your documentation.– They are a list of behaviors that you They are a list of behaviors that you
have shown work.have shown work.– List of tests might not be exhaustive but List of tests might not be exhaustive but
does document what HAS been tested.does document what HAS been tested.
DocumentationDocumentation
Design specification?Design specification?– Tests are not sufficient but definitely an Tests are not sufficient but definitely an
important partimportant part
Requirements documentation?Requirements documentation?– Not part of requirementsNot part of requirements– Acceptance testing helps with Acceptance testing helps with
requirements documentationrequirements documentation
Good Unit TestsGood Unit TestsRun fast (they have short setups, run Run fast (they have short setups, run times, and break downs). times, and break downs). Run in isolation (you should be able to Run in isolation (you should be able to reorder them). reorder them). Use data that makes them easy to read Use data that makes them easy to read and to understand. and to understand. Use real data (e.g. copies of production Use real data (e.g. copies of production data) when they need to. data) when they need to. Represent one step towards your overall Represent one step towards your overall goal. goal.
(Kent Beck – creator eXtreme Programming)(Kent Beck – creator eXtreme Programming)
Test FirstTest First
Give an exampleGive an example
Write test caseWrite test case
Write code – just enough to pass the Write code – just enough to pass the testtest
Run testRun test
(fail) Repeat (goto “write code”)(fail) Repeat (goto “write code”)
(pass) Refactor code or write new test(pass) Refactor code or write new test
(how do we decide which to do?)(how do we decide which to do?)
Writing a testWriting a testWhat should the code do?What should the code do?How can you tell if it does it?How can you tell if it does it?What does reasonable input look What does reasonable input look like?like?What does UNreasonable input look What does UNreasonable input look like?like?
What about side effects? How do we What about side effects? How do we test for them?test for them?
Side-effects?Side-effects?
Good code should not have side Good code should not have side effectseffects
Your methods (functions) should do Your methods (functions) should do one thing onlyone thing only
TDD won’t test of side-effectsTDD won’t test of side-effects
What should your code do?What should your code do?
What are the input parameters?What are the input parameters?
What is the expected result?What is the expected result?
How do you know if it works?How do you know if it works?
Write a test to see if it works “as Write a test to see if it works “as expected”expected”
Run the test.Run the test.
Rewrite the code.Rewrite the code.
““as expected”as expected”
What do you expect it to do?What do you expect it to do?
What about bad inputs?What about bad inputs?– Out of range valuesOut of range values– Uninitialized values? (pointers)Uninitialized values? (pointers)
Assertions vs error-handling codeAssertions vs error-handling code
Error handling codeError handling code
Conditions you expect to occurConditions you expect to occur
Consider how much this particular Consider how much this particular piece of code is protected from bad piece of code is protected from bad input in useinput in use– Is it a private method?Is it a private method?– Should it be?Should it be?
AssertionsAssertionsassert()assert()
These are used during development These are used during development in your CODE, not your tests.in your CODE, not your tests.
Use for conditions you expect NEVER Use for conditions you expect NEVER to occur.to occur.
ConsiderConsider(an extremely simple example)(an extremely simple example)
A function to divide one number by anotherA function to divide one number by another
r = div(num,den);r = div(num,den);
Test1:Test1:r = div(4,3);r = div(4,3);
Run Test1:Run Test1:r = 1r = 1
What did we learn?What did we learn?
Div: Test1Div: Test1What did we learn?What did we learn?
Div returns an INTDiv returns an INT
Is that what we want?Is that what we want?
Div: Test1 (again)Div: Test1 (again)We’ve changed to code to return float.We’ve changed to code to return float.(This is the only change we make! (This is the only change we make!
Why?)Why?)
r = div(4, 3);r = div(4, 3);r = 1.333333;r = 1.333333;
Pass: refactor or new test?Pass: refactor or new test?(how do we decide?)(how do we decide?)
Div: Test2Div: Test2(6 new tests)(6 new tests)
What should we test?What should we test?– NegativeNegative
DividendDividend
DivisorDivisor
BothBoth
– 0 0 DividendDividend
DivisorDivisor
BothBoth
Div: Test2Div: Test2How about divide by 0?How about divide by 0?
r = div(4, 3);r = div(4, 3);r = div(5.0, 0.0);r = div(5.0, 0.0);
(notice that I still run test 1)(notice that I still run test 1)
Should divide by zero be handled by an Should divide by zero be handled by an assertion or by error handling code?assertion or by error handling code?
What have we accomplished?What have we accomplished?
We have refined the definition of “div”We have refined the definition of “div”
We have tests that we know our code We have tests that we know our code passespasses
We’ve documented some of the We’ve documented some of the behavior of “div”behavior of “div”
When something fails in the future, we When something fails in the future, we have a list of tests. We can look to see have a list of tests. We can look to see if there are new tests that need to be if there are new tests that need to be written.written.
Example: Calculate EW RatioExample: Calculate EW RatioWe can approximate the ratio of the We can approximate the ratio of the distance between elevations EW as distance between elevations EW as compared to NS as cos(latitude)compared to NS as cos(latitude)Requirement:Requirement:– Integer where 1 unit = 1/1000 arc Integer where 1 unit = 1/1000 arc
second per unitsecond per unit– Example:Example:
N40 12 42.018 = (40*3600 + 12*60 + N40 12 42.018 = (40*3600 + 12*60 + 42.018)*100042.018)*1000=144762018=144762018
EWScalingEWScaling
Things to test for:Things to test for:– Magnitude of inputMagnitude of input– Range:Range:
-90 – 90 degrees-90 – 90 degrees
Latitudes above 90 and below -90Latitudes above 90 and below -90– What behavior should it have?What behavior should it have?– The tests should reflect your DEFINITION of the The tests should reflect your DEFINITION of the
behavior and should help you refine the definitionbehavior and should help you refine the definition
TestsTests
Ratio = EWScaling(0);Ratio = EWScaling(0); // 1.0// 1.0
Ratio = EWScaling(90*3600*1000); // Ratio = EWScaling(90*3600*1000); // 0.00.0
Ratio = EWScaling(60*3600*1000); // Ratio = EWScaling(60*3600*1000); // 0.50.5
To employ TDDTo employ TDDYou design organically, with the running code You design organically, with the running code providing feedback between decisions. providing feedback between decisions. You write your own tests because you can't wait 20 You write your own tests because you can't wait 20 times per day for someone else to write them for times per day for someone else to write them for you. you. Your development environment must provide rapid Your development environment must provide rapid response to small changes (e.g you need a fast response to small changes (e.g you need a fast compiler and regression test suite). compiler and regression test suite). Your designs must consist of highly cohesive, loosely Your designs must consist of highly cohesive, loosely coupled components (e.g. your design is highly coupled components (e.g. your design is highly normalized) to make testing easier (this also makes normalized) to make testing easier (this also makes evolution and maintenance of your system easier evolution and maintenance of your system easier too). too).
(Beck)(Beck)