Test Driven Development Tutorial
-
Upload
guillem-font -
Category
Documents
-
view
123 -
download
4
Transcript of Test Driven Development Tutorial
![Page 1: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/1.jpg)
Test Driven Development
Kirrily Robert
![Page 2: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/2.jpg)
The problem
Good
Cheap Fast
![Page 3: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/3.jpg)
No silver bullet
![Page 4: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/4.jpg)
However, with testing...
• A bit faster
• A bit cheaper
• A bit better
![Page 5: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/5.jpg)
Faster
![Page 6: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/6.jpg)
Time taken to fix bugs
0
250
500
750
1,000
Design Implementation QA Post-release
![Page 7: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/7.jpg)
Cheaper
![Page 8: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/8.jpg)
Technical debt
• “We’ll leave it for now”
• Delayed payment plan
• Compound interest
![Page 9: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/9.jpg)
The most powerful force in the universe is compound interest.
Albert Einstein
![Page 10: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/10.jpg)
Time taken to fix bugs
0
250
500
750
1,000
Design Implementation QA Post-release
![Page 11: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/11.jpg)
Easy payment plan
• Don’t go into debt
• Make regular payments
• Pay down the principal
![Page 12: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/12.jpg)
Cheap programmers
• Best programmers 10x as effective
• Testing can close the gap (somewhat)
![Page 13: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/13.jpg)
Better
![Page 14: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/14.jpg)
Software quality
• “Instinctive”
• Hard to measure
![Page 15: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/15.jpg)
Software Kwalitee
• Indicative
• Measurable
• Testable
![Page 16: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/16.jpg)
• Testing
• Test Driven Development
The solution
![Page 17: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/17.jpg)
Testing
Test
Design
Implement
![Page 18: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/18.jpg)
TDD
Design
Test
Implement
![Page 19: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/19.jpg)
TDD
Design
Implement
Test
Test
![Page 20: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/20.jpg)
TDD
Design
Implement
TestTest
![Page 21: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/21.jpg)
TDD
Design
Implement
TestTest
![Page 22: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/22.jpg)
How to do it
• Design: figure out what you want to do
• Test: write a test to express the design
• It should FAIL
• Implement: write the code
• Test again
• It should PASS
![Page 23: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/23.jpg)
Design
The subroutine add() takes two arguments and adds them together. The result is returned.
![Page 24: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/24.jpg)
Test
use Test::More tests => 1;
is(add(2,2), 4, “Two and two is four”);
![Page 25: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/25.jpg)
FAIL
$ prove -v add.tadd....Undefined subroutine &main::add called at add.t line 3.# Looks like your test died before it could output anything.1..1dubious Test returned status 255 (wstat 65280, 0xff00)DIED. FAILED test 1 Failed 1/1 tests, 0.00% okayFailed Test Stat Wstat Total Fail List of Failed-------------------------------------------------------------------------------add.t 255 65280 1 2 1Failed 1/1 test scripts. 1/1 subtests failed.Files=1, Tests=1, 0 wallclock secs ( 0.02 cusr + 0.01 csys = 0.03 CPU)Failed 1/1 test programs. 1/1 subtests failed.
![Page 26: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/26.jpg)
Implement
sub add {my ($first, $second) = @_;return $first + $second;
}
![Page 27: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/27.jpg)
Test
$ prove -v add.tadd....1..1ok 1 - Two and two is fourokAll tests successful.Files=1, Tests=1, 0 wallclock secs ( 0.02 cusr + 0.01 csys = 0.03 CPU)
![Page 28: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/28.jpg)
Wait...
• What if there are fewer than two arguments?
• What if there are more than two arguments?
• What if the arguments aren’t numeric?
![Page 29: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/29.jpg)
Iterate
Design
Implement
TestTest
![Page 30: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/30.jpg)
Design
• The subroutine add() takes two arguments and adds them together. The result is returned.
• If fewer than two arguments are provided, add() will return undef.
• If more than two arguments are provided, add() will return the sum of the first two.
• If any argument is non-numeric, add() will return undef.
![Page 31: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/31.jpg)
Testuse Test::More tests => 4;
is(add(2,2), 4, “Simple case: two and two is four”);
is(add(3), undef, “Return undef for < 2 args”);
is(add(2,2,2), 4, “Only add first 2 args”);
is(add(“foo”, “bar”), undef, “Return undef for non-numeric args”);
![Page 32: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/32.jpg)
FAIL
<insert test failure here>
![Page 33: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/33.jpg)
Implement
sub add {my ($first, $second) = @_;# insert error-checking herereturn $first + $second;
}
![Page 34: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/34.jpg)
Test
prove -v add.tadd....1..4ok 1 - Two and two is fourok 2 - Return undef for < 2 argsok 3 - Only add first 2 argsok 4 - Return undef for non-numeric argsokAll tests successful.
![Page 35: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/35.jpg)
Effective tests must be automated
![Page 36: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/36.jpg)
print “Now calculating shipping...”;
![Page 37: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/37.jpg)
print “Oops, something’s gone wrong...”;
![Page 38: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/38.jpg)
warn “Oops, something’s gone wrong...”;
![Page 39: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/39.jpg)
die “This should never happen!”;
![Page 40: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/40.jpg)
Now calculating shipping...Let’s see if this works.Oops, something’s gone wrong...ERROR: weirdness afoot!?!?(Contact Mike on ext. 2345)Bailing out, very confused!$
![Page 41: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/41.jpg)
Write once, run often
• Write tests once
• Keep them somewhere sensible
• Run frequently (one click)
• No human input
• Machine-parsable output
![Page 42: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/42.jpg)
Questions so far?
![Page 43: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/43.jpg)
Testing scenarios
• Public APIs
• Bug fixing/QA
• Legacy code
![Page 44: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/44.jpg)
Public APIs
![Page 45: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/45.jpg)
The steps
Design
Implement
TestTest
![Page 46: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/46.jpg)
API testing tips
• Maintain backward compatibility
• Consider cross-platform issues
• Turn edge cases into tests
![Page 47: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/47.jpg)
Bug fixing
![Page 48: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/48.jpg)
Bug report“I’m writing a system to automatically send gift
baskets to elderly maiden aunts in Timbuktu, using Gift::Basket to build the basket and Geo::Names to
figure out where the heck Timbuktu is, but I have this problem that whenever I try to calculate the shipping costs, something breaks and it says that something’s not numeric, and I don’t know what’s going on but I
think maybe the arithmetic code is broken, or maybe something else. Perhaps Timbuktu doesn’t really exist.
Can you help me? I need this fixed by 5pm at the latest. Unless Timbuktu really doesn’t exist, in which case do you think Kathmandu would work instead?”
![Page 49: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/49.jpg)
“... it says that something’s not numeric ... maybe the
arithmetic code is broken ...”
![Page 50: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/50.jpg)
Steps
• Get some sample code (that breaks)
• Turn it into a test
• Test should fail
• Fix bug
• Test should now pass
![Page 51: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/51.jpg)
Steps
Bug report
Bug fix
TestTest
![Page 52: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/52.jpg)
Sample codemy $basket = Gift::Basket->new();$basket->add(“flowers”, “chocolate”, “teddy bear”);
my $price = $basket->price();
# shipping is 15% of pricemy $shipping = multiply($price, 0.15);
# code dies horribly on the following linemy $total_price = add($price, $shipping);
![Page 53: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/53.jpg)
Test
my $price = 10.00; # typical gift basket price
my $shipping = multiply($price, 0.15);
is($shipping, 1.5, “Shipping price calculated successfully”);
is(add($shipping, $price), 11.5, “Add shipping to price”);
![Page 54: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/54.jpg)
FAILprove -v giftbasket.tgiftbasket....1..2ok 1 - Shipping price calculated successfully1.5 isn't numeric at giftbasket.t line 16.
# Failed test 'Add shipping to price'# at giftbasket.t line 8.# got: undef# expected: '11.5'# Looks like you failed 1 test of 2.not ok 2 - Add shipping to price
![Page 55: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/55.jpg)
Fix
• Examine code
• Look for likely problem
• Fix
![Page 56: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/56.jpg)
Examine code
sub add { my ($first, $second) = @_; return undef unless $first and $second; foreach ($first, $second) { unless (is_numeric($_)) { warn "$_ isn't numeric"; return undef; } } return $first + $second;}
![Page 57: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/57.jpg)
Examine code
sub is_numeric { my ($number) = @_; return int($number) == $number ? 1 : 0;}
![Page 58: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/58.jpg)
Fix
use Scalar::Util;
sub is_numeric { my ($number) = @_; return Scalar::Util::looks_like_number($number);}
![Page 59: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/59.jpg)
Test
$ prove -v giftbasket.tgiftbasket....1..2ok 1 - Shipping price calculated successfullyok 2 - Add shipping to priceokAll tests successful.Files=1, Tests=2, 0 wallclock secs ( 0.03 cusr + 0.01 csys = 0.04 CPU)
![Page 60: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/60.jpg)
Bug fix tips
• Try to get users to submit tests
• Record bug tracking numbers
![Page 61: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/61.jpg)
Legacy Code
![Page 62: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/62.jpg)
Legacy code =
Technical debt
![Page 63: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/63.jpg)
“Does anyone know what this does?”
![Page 64: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/64.jpg)
“I don’t suppose we have any
documentation for that?”
![Page 65: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/65.jpg)
“If we change X it will probably break Y.”
![Page 66: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/66.jpg)
“Last time we touched that, we spent a week
fixing it.”
![Page 67: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/67.jpg)
Improve legacy code
•Document
•Understand
•Clean up
•Refactor
•Remove cruft
•Standardise
•Strengthen
•Secure
![Page 68: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/68.jpg)
The Steps
WTF?
Ah!
TestTest
![Page 69: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/69.jpg)
The Steps
• Look at legacy code. Be confused.
• Write a test to see if you understand
• Test FAILS
• Adapt test (iteratively)
• Test PASSES
• Move on to next piece.
![Page 70: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/70.jpg)
Legacy code tips
• CAUTION!
• Go very slowly
• Be prepared to back out changes
• Track test coverage
![Page 71: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/71.jpg)
Test coverage
• How much of the code is tested?
• What areas still need testing?
• Where are the greatest risks?
![Page 72: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/72.jpg)
Coverage tools
Perl Devel::Cover
Python Coverage.py
Java Quilt
PHP PHPUnit
![Page 73: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/73.jpg)
Devel::Cover
![Page 74: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/74.jpg)
![Page 75: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/75.jpg)
•Perl
•PHP
•Python
•Ruby
•Java
•Javascript
•C/C++
Testing libraries
![Page 76: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/76.jpg)
Perl
![Page 77: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/77.jpg)
Test::More
• Standard library
• Comes with Perl
• Also on CPAN
![Page 78: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/78.jpg)
lib/Arithmetic.pmpackage Arithmetic;
use strict;use warnings;
sub add {# ...
}
sub subtract {# ...
}
1;
![Page 79: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/79.jpg)
t/arithmetic.t
use Test::More tests => 5;
use_ok(“Arithmetic.pm”);can_ok(“Arithmetic.pm”, “add”);
ok(is_numeric(1.23), “1.23 is numeric”);
is(add(2,2), 4, “2 + 2 = 4”);
![Page 80: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/80.jpg)
Other Test::More functions
like(“An elephant”, qr/^\w+$/, “String contains only word chars”);
my $user_agent = LWP::UserAgent->new();isa_ok($user_agent, “LWP::UserAgent”);can_ok($user_agent, “get”);
![Page 81: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/81.jpg)
See also
• http://qa.perl.org/
• Test::More::Tutorial
• http://search.cpan.org/
• search for “Test”
![Page 82: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/82.jpg)
Python
![Page 83: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/83.jpg)
PyUnit
• “The standard unit testing framework for Python”
• http://pyunit.sourceforge.net/
• Included with Python dist
• Port of JUnit
![Page 84: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/84.jpg)
arithmetic.py
def add(x, y): """add two numbers""" return x + y
![Page 85: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/85.jpg)
arithmetic_test.pyimport arithmeticimport unittest
class AdditionTests(unittest.TestCase): knownValues = ( (1, 1, 2), (2, 2, 4), (0, 0, 0), (-3, -4, -7))
def testAddition(self): for x, y, sum in self.knownValues: result = arithmetic.add(x, y) self.assertEqual(result, sum)
unittest.main()
![Page 86: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/86.jpg)
Run arithmetic_test.py
$ python arithtest.py.-----------------------------------------------Ran 1 test in 0.000s
OK
![Page 87: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/87.jpg)
PHP
![Page 88: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/88.jpg)
PHP
• PHPUnit
• http://phpunit.de/
• SimpleTest
• http://simpletest.org/
![Page 89: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/89.jpg)
PHPUnit<?phprequire_once 'PHPUnit/Framework.php'; class ArrayTest extends PHPUnit_Framework_TestCase { public function testNewArrayIsEmpty() { $foo = array(); $this->assertEquals(0, sizeof($foo)); } public function testArrayContainsAnElement() { $foo = array(); $foo[] = 'Element'; $this->assertEquals(1, sizeof($foo)); }}?>
![Page 90: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/90.jpg)
PHPUnit
![Page 91: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/91.jpg)
SimpleTest<?php require_once('simpletest/unit_tester.php'); require_once('simpletest/reporter.php'); require_once('../classes/log.php');
class TestOfLogging extends UnitTestCase { function TestOfLogging() { $this->UnitTestCase(); } function testCreatingNewFile() { @unlink('/tmp/test.log'); $log = new Log('/tmp/test.log'); $log->message('Should write this to a file'); $this->assertTrue(file_exists('/tmp/test.log')); } }
$test = &new TestOfLogging(); $test->run(new HtmlReporter());?>
![Page 92: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/92.jpg)
SimpleTest
![Page 93: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/93.jpg)
Ruby
![Page 94: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/94.jpg)
Ruby
• Test::Unit
• Yet another JUnit clone
• Part of standard distribution
• http://ruby-doc.org/
![Page 95: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/95.jpg)
Test::Unitrequire 'test/unit'
class TestArithmetic < Test::Unit::TestCase
def test_pass assert(true, 'Assertion was true') end
def test_fail assert(false, 'Assertion was false.') end
def test_arithmetic assert(2 + 2 == 4, '2 plus 2 is 4') end
end
![Page 96: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/96.jpg)
Run testsruby arithtest.rbLoaded suite arithtestStarted.F.Finished in 0.009103 seconds.
1) Failure:test_fail(TestArithmetic) [arithtest.rb:10]:Assertion was false.<false> is not true.
3 tests, 3 assertions, 1 failures, 0 errors
![Page 97: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/97.jpg)
Java
![Page 98: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/98.jpg)
Java
• JUnit
• Standard library
• Parent of many *Unit test suites
• http://junit.org
![Page 99: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/99.jpg)
Javascript
![Page 100: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/100.jpg)
Javascript
• Several libraries available
• No clear standard
• I like Test.More from JSAN
![Page 101: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/101.jpg)
Test.More
• Port of Perl’s Test::More
• Common output format (TAP)
• http://openjsan.org/
![Page 103: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/103.jpg)
C/C++
![Page 104: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/104.jpg)
C/C++
• libtap
• outputs TAP
• similar to Perl’s Test::More
![Page 105: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/105.jpg)
test.c
#include <stdio.h>#include "tap.h"
int main(void) { plan_tests(2);
ok(1 + 1 == 2, "addition"); ok(3 - 2 == 1, "subtraction");
return exit_status();}
![Page 106: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/106.jpg)
Output
1..2ok 1 - additionok 2 - subtraction
![Page 107: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/107.jpg)
CPPUnit
• C++ only
• http://cppunit.sourceforge.net/
![Page 108: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/108.jpg)
CPPUnit
class ComplexNumberTest : public CppUnit::TestCase {public: ComplexNumberTest( std::string name ) : CppUnit::TestCase( name ) {} void runTest() { CPPUNIT_ASSERT( Complex (10, 1) == Complex (10, 1) ); CPPUNIT_ASSERT( !(Complex (1, 1) == Complex (2, 2)) ); }};
![Page 109: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/109.jpg)
Three families
• XUnit
• TAP
• Miscellaneous
![Page 110: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/110.jpg)
XUnit
• Distinctive markings: “assert”
• Output:
• ...F.....F...FF...
• JUnit, PyUnit, CPPUnit, JSUnit, etc
![Page 111: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/111.jpg)
TAP
• Distinctive markings: “ok” or “is”
• Output:
• ok 1 - some comment
• Test::More, Test.More, libtap, etc
![Page 112: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/112.jpg)
Miscellaneous
• eg. xmllint
• wrappers/ports/equivalents often exist
![Page 113: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/113.jpg)
TAP
• Test Anything Protocol
• Standardised test reporting format
• Many languages
• http://testanything.org/
![Page 114: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/114.jpg)
TAP output
1..4ok 1 - Input file openednot ok 2 - First line of the input valid# Failed test ‘First line of input valid’# at test.pl line 42# ‘begin data...’# doesn't match '(?-xism:BEGIN)’ok 3 - Read the rest of the filenot ok 4 - Summarized correctly # TODO Not written yet
![Page 115: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/115.jpg)
TAP Producers
• Anything that outputs TAP
• eg. Test::More, Test.More, libtap
![Page 116: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/116.jpg)
TAP Consumers
• Anything that reads/parses TAP
• eg. Perl’s Test::Harness
![Page 117: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/117.jpg)
More test libraries
• http://opensourcetesting.org/
• Ada, C/C++, HTML, Java, Javascript, .NET, Perl, PHP, Python, Ruby, SQL, Tcl, XML, others
![Page 118: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/118.jpg)
Questions?
![Page 119: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/119.jpg)
TDD Cookbook
![Page 120: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/120.jpg)
Private code
• Can you test private code?
• private/protected/hidden/internal
• Should you test private code?
![Page 121: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/121.jpg)
The argument against
• Private code should never be accessed externally
• You want to change private code at will, without breaking tests
![Page 122: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/122.jpg)
The argument for
• Assists in refactoring
• Testing is better than not testing
• If tests break, change/fix them with impunity
![Page 123: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/123.jpg)
“Black box” testing
• Examine inputs and outputs
• Don’t “see” anything inside
![Page 124: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/124.jpg)
“Glass box” testing
• Look inside the code
• Examine inner workings
![Page 125: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/125.jpg)
Examplesub display_details {
my ($inventory_id) = @_;my $output;
# 1,000 lines of legacy code ...
$price = ‘$’ . $price;if (int($price) == $price) {
$price = $price . “.00”;}
$output .= “Price: $price\n”;
# 1,000 more lines of legacy code
return $output;}
![Page 126: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/126.jpg)
Bug report
“There’s something wrong with the price display. I occasionally see prices like $123.400, when only two
digits should appear after the decimal point.”
![Page 127: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/127.jpg)
Black box
• Comprehend 2000+ lines of legacy code
• Write tests for entire subroutine
• Check price embedded in larger output
• Curl up under desk, whimper
![Page 128: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/128.jpg)
White box
• Extract private method
• Test private method
![Page 129: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/129.jpg)
Extract method
sub _format_price {my ($price) = @_;$price = ‘$’ . $price;if (int($price) == $price) {
$price = $price . “.00”;}return $price;
}
![Page 130: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/130.jpg)
Test
is(_format_price(12), ‘$12.00’, ‘12 becomes $12.00’);
is(_format_price(11.99, ‘$11.99’, ‘11.99 becomes $11.99’);
is(_format_price(12.3, ‘$12.30’, ’12.3 becomes $12.30’);
![Page 131: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/131.jpg)
Conclusion
• I like glass box testing
• Some people don’t
• They are obviously misguided
• Q.E.D.
![Page 132: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/132.jpg)
External applications
• scripts
• executables
• foreign APIs
![Page 133: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/133.jpg)
External applications
• Do you trust them?
• “Black box” testing
![Page 134: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/134.jpg)
Things to test
• Return values
• Output
• Side effects
![Page 135: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/135.jpg)
Return values
• Works on Unix
• success == 0
• Otherwise, ???
![Page 136: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/136.jpg)
Output
• Printed output
• Warnings/log messages
• Use pipes/redirection
![Page 137: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/137.jpg)
Side effects
• Eg. changed files
• Risky
![Page 138: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/138.jpg)
Example
is(system($some_command), 0, “Command ran OK”);
ok(! -e $somefile, “File doesn’t exist.”);is(system($create_file_command), 0, “Command ran OK”);ok(-e $somefile, “File exists now.”)
![Page 139: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/139.jpg)
Testing complex systems
• Complex libraries
• Side effects
• Pre-requisites
![Page 140: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/140.jpg)
Example
sub notify { my ($user_id) = @_; if (my $user = fetch_from_db($user_id)) { send_notification_email($user->email()); return 1; } return 0;};
![Page 141: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/141.jpg)
Example
• Requires database access
• Actually sends email
![Page 142: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/142.jpg)
Mocking
• Fake database connection
• Fake email sending
• Only test notify() logic
![Page 143: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/143.jpg)
Mock libraries
Perl Test::MockObject
Python python-mock
Java jMock
PHP PHPUnit (builtin)
![Page 144: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/144.jpg)
Test::MockObject
use OurDB::User;use Test::MockObject::Extends;
my $user = OurDB::User->fetch($user_id);$user = Test::MockObject::Extends->new($user);
$user->mock('email', sub { ‘[email protected]' });
![Page 145: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/145.jpg)
python-mock
>>> from mock import Mock>>> myMock = Mock( {"foo" : "you called foo"} ) >>> myMock.foo() 'you called foo' >>> f = myMock.foo >>> f <mock.MockCaller instance at 15d46d0> >>> f() 'you called foo' >>> f( "wibble" ) 'you called foo' >>>
![Page 146: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/146.jpg)
Databases
• “Real” data
• Unchanging data
• Set up/tear down
![Page 147: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/147.jpg)
Fixtures
• Known data
• Setup/teardown
• Repeatable tests
![Page 148: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/148.jpg)
Ruby on Rails
• Built-in fixtures
• YAML or CSV format
• Automatically loaded
• Tests occur inside transaction
![Page 149: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/149.jpg)
YAML format
david: id: 1 name: David Heinemeier Hansson birthday: 1979-10-15 profession: Systems development
steve: id: 2 name: Steve Ross Kellock birthday: 1974-09-27 profession: guy with keyboard
![Page 150: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/150.jpg)
CSV format
id, username, password, stretchable, comments1, sclaus, ihatekids, false, I like to say ""Ho! Ho! Ho!"" 2, ebunny, ihateeggs, true, Hoppity hop y'all3, tfairy, ilovecavities, true, "Pull your teeth, I will"
![Page 151: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/151.jpg)
Loading fixtures
require '/../test_helper'require 'user'
class UserTest < Test::Unit::TestCase
fixtures :users
def test_count_my_fixtures assert_equal 5, User.count end
end
![Page 152: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/152.jpg)
Websites
• Complex systems
• Backend/frontend
• Browser dependent
![Page 153: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/153.jpg)
Backend strategy
• Refactor mercilessly
• Separate
• Database access
• Business logic
• Everything you can
• MVC good!
![Page 154: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/154.jpg)
Front-end strategy
• Web pages and links
• Forms
• Javascript
• Browser compatibility
![Page 155: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/155.jpg)
Web links
• Use a web browser / user agent
• WWW::Mechanize
• Check HTTP GET on each page
• Status 200
• Follow links on pages
![Page 156: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/156.jpg)
Forms
• Use web browser / user agent
• HTTP GET / HTTP POST
• Check validation
• Check results of form
![Page 157: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/157.jpg)
Javascript
• Refactor into libraries
• Test using Test.More or similar
![Page 158: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/158.jpg)
Browser testing
• Mimic actual browser use
• Selenium
• http://openqa.org/selenium/
![Page 159: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/159.jpg)
Selenium
• Firefox / IE / Safari / others
• Linux/Mac/Windows
• Record browser actions
• Save as scripts
• Language integration
• Java, .Net, Perl, Python, Ruby
![Page 160: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/160.jpg)
Selenium IDE
![Page 161: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/161.jpg)
Team testing
• Many developers
• Distributed/asynchronous development
• Different platforms
• One test strategy
![Page 162: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/162.jpg)
Who’s responsible?
![Page 163: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/163.jpg)
Team responsibility
• Everyone is responsible
• See a problem, fix it
• No code ownership
![Page 164: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/164.jpg)
Individual blame
• Correlate failures with checkins
• “svn blame”
• “Golden fork-up award”
![Page 165: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/165.jpg)
Team testing tips
• Use standard tools
• Document processes
• Nightly smoke test
• Integrate with version control
![Page 166: Test Driven Development Tutorial](https://reader031.fdocuments.in/reader031/viewer/2022012918/5475c8a1b4af9f3d118b4581/html5/thumbnails/166.jpg)
Questions?