Test First!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!
requirement -> code!

test!
requirement -> test!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- co...
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- co...
requirement -> test! <- code!
!
requirement -> test! <- code!
! Refactor!
requirement -> test! <- code!
!
requirement -> t...
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- co...
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- code!
!
requirement -> test! <- co...
Test First!
!
Faster feedback!
Code coverage!
Effective tests!
Better Code!
Refactoring!
Productivity!
Documentation!
Conf...
Test first?!
Everybody!!
Email validation!
/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/!
Valid email addresses!
email@domain.com!
firstname.lastname@domain.com!
email@subdomain.domain.com!
firstname+lastname@dom...
Merge load more data!
- (void)mergeData:(NSDictionary *)response!
intoStream:(NUSStream *)stream;!
Merge load more data!
testMergeData_ShouldUpdateLoadMoreUrl_WhenItExis
tsInTheResponse();!
!
testMergeData_ShouldClearExis...
Merge load more data!
testMergeData_ShouldUpdateLoadMoreUrl_WhenItExis
tsInTheResponse();!
!
testMergeData_ShouldClearExis...
Faster feedback!
Faster feedback!
The code you just wrote isn’t doing
what you think.!
The line you just removed will break
PYMK load more ...
Code coverage!
Code coverage!
function save(input) {!
if (isValid(input)) {!
if (lixEnabled()) {!
" " logger.info(‘new save’);!
newSave(i...
Code coverage!

// SaveHelper.js!
function save(input);!
!
!
// SaveHelperSpec.js!
testSave();!
Code coverage!
// SaveHelper.js!
function save(input);!
!

!

!

!

!

// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenIn...
Code coverage!
// SaveHelper.js!
function save(input);!
!

!

!

!

// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenInput...
Code coverage!
// SaveHelper.js!
function save(input);!
!

!

!

// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenInputIsI...
Code coverage!
// SaveHelper.js!
function save(input);!
!

!

// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenInputIsInva...
Code coverage!
// SaveHelper.js!
function save(input);!
!
// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenInputIsInvalid(...
Code coverage!
// SaveHelper.js!
function save(input);!
!
// SaveHelperSpec.js!
testSave_ShouldNotSave_WhenInputIsInvalid(...
Effective tests!

Fail when the functionality breaks!
!
KISS!
!
Test functionality, not the
implementation.!
!
Don’t repea...
Effective tests!
Fail when the functionality breaks!
// code!
paymentService = util.getPS();!
paymentService.submit();!
!
...
Effective tests!
Fail when the functionality breaks!
// code!
paymentService = util.getPS();!
paymentService.submit();!
!
...
Effective tests!
Keep It Simple Stupid!
// unit test assertion!
assert(“m_sim2_guided_edit_photo_add_actionsh
eet_camera_t...
Effective tests!
Test functionality, not the implementation.!
void addNewRow(row) {!
. . .!
row.setDisplay(“block”);!
row....
Effective tests!
Test functionality, not the implementation.!
void addNewRow(row) {!
. . .!
row.setDisplay(“block”);!
row....
Effective tests!
Don’t repeat your code in the test!
String getDateForDisplay() {!
Date date = service.loadDate();!
Simple...
Better code!
Testable!
!
Modular!
!
Loosely coupled!
!
Singletons !
!
Law of Demeter"!
!
Complexity!
Refactoring!
Restructuring code without
changing its functionality!
!
!
Refactoring now & later!
!
!
Migration projects!
Productivity!
Faster Feedback!
!
No wasting time with debugger!
!
Avoid dependencies!
!
Save time now and later!
!
It does...
Productivity!
Documentation!

Working examples of code!
Documentation!

Working examples of code!
Tests won’t get outdated!
Confidence!
When you develop new features!
When you handover your work!
Try it! And you’ll feel it!!
Test First!
!
Faster feedback!
Code coverage!
Effective tests!
Better Code!
Refactoring!
Productivity!
Documentation!
Conf...
Thank you!!
Test First
Upcoming SlideShare
Loading in …5
×

Test First

432 views

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
432
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Test First

  1. 1. Test First!
  2. 2. requirement -> code!
  3. 3. requirement -> code! requirement -> code!
  4. 4. requirement -> code! requirement -> code! requirement -> code!
  5. 5. requirement -> code! requirement -> code! requirement -> code! requirement -> code!
  6. 6. requirement -> code! requirement -> code! requirement -> code! requirement -> code! requirement -> code!
  7. 7. requirement -> code! requirement -> code! requirement -> code! requirement -> code! requirement -> code! test!
  8. 8. requirement -> test! !
  9. 9. requirement -> test! <- code! !
  10. 10. requirement -> test! <- code! ! requirement -> test! !
  11. 11. requirement -> test! <- code! ! requirement -> test! <- code! !
  12. 12. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! !
  13. 13. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! !
  14. 14. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! !
  15. 15. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! !
  16. 16. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! !
  17. 17. requirement -> test! <- code! ! requirement -> test! <- code! ! Refactor! requirement -> test! <- code! ! requirement -> test! <- code! !
  18. 18. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! !
  19. 19. requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! ! requirement -> test! <- code! !
  20. 20. Test First! ! Faster feedback! Code coverage! Effective tests! Better Code! Refactoring! Productivity! Documentation! Confidence!
  21. 21. Test first?!
  22. 22. Everybody!!
  23. 23. Email validation! /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/!
  24. 24. Valid email addresses! email@domain.com! firstname.lastname@domain.com! email@subdomain.domain.com! firstname+lastname@domain.com! email@123.123.123.123! email@[123.123.123.123]! "email"@domain.com! 1234567890@domain.com! email@domain-one.com! _______@domain.com! email@domain.name! email@domain.co.jp! firstname-lastname@domain.com! Invalid email addresses! #@%^%#$@#$@#.com! @domain.com! Joe Smith <email@domain.com>! email.domain.com! email@domain@domain.com! .email@domain.com! email.@domain.com! email..email@domain.com! email@domain! email@-domain.com! email@domain.web! email@111.222.333.44444! email@domain..com!
  25. 25. Merge load more data! - (void)mergeData:(NSDictionary *)response! intoStream:(NUSStream *)stream;!
  26. 26. Merge load more data! testMergeData_ShouldUpdateLoadMoreUrl_WhenItExis tsInTheResponse();! ! testMergeData_ShouldClearExistingLoadMoreUrl_Whe nItDoesNotExistInTheResponse();! ! testMergeData_ShouldMergePYMKInOrder_WhenTheResp onseHasPYMKData();! ! testMergeData_ShouldNotCrash_WhenResponseDataHav eEmptyValues();! ! ! //edge case! testMergeData_ShouldNotCrash_WhenResponseDataIsI nvalid();!
  27. 27. Merge load more data! testMergeData_ShouldUpdateLoadMoreUrl_WhenItExis tsInTheResponse();! ! testMergeData_ShouldClearExistingLoadMoreUrl_Whe nItDoesNotExistInTheResponse();! ! testMergeData_ShouldMergePYMKInOrder_WhenTheResp onseHasPYMKData();! ! testMergeData_ShouldNotCrash_WhenResponseDataHav eEmptyValues();! ! ! //edge case! testMergeData_ShouldNotCrash_WhenResponseDataIsI nvalid();!
  28. 28. Faster feedback!
  29. 29. Faster feedback! The code you just wrote isn’t doing what you think.! The line you just removed will break PYMK load more functionality.! Are you crazy? If you remove that conditional check, it would break apps with > 7.0 iOS versions.!
  30. 30. Code coverage!
  31. 31. Code coverage! function save(input) {! if (isValid(input)) {! if (lixEnabled()) {! " " logger.info(‘new save’);! newSave(input);! } else {! logger.info(‘old save’);! if (input.type === ‘x’) {! oldXSave(input);! } else {! oldYSave(input);! }! }! }! }!
  32. 32. Code coverage! // SaveHelper.js! function save(input);! ! ! // SaveHelperSpec.js! testSave();!
  33. 33. Code coverage! // SaveHelper.js! function save(input);! ! ! ! ! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();!
  34. 34. Code coverage! // SaveHelper.js! function save(input);! ! ! ! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();! testSave_ShouldUseNewAPI_WhenLixEnabled();!
  35. 35. Code coverage! // SaveHelper.js! function save(input);! ! ! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();! testSave_ShouldUseNewAPI_WhenLixEnabled();! testSave_ShouldUseOldAPI_WhenLixDisabled();!
  36. 36. Code coverage! // SaveHelper.js! function save(input);! ! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();! testSave_ShouldUseNewAPI_WhenLixEnabled();! testSave_ShouldUseOldAPI_WhenLixDisabled();! testSave_ShouldUseOldXAPI_WhenInputTypeIsX();!
  37. 37. Code coverage! // SaveHelper.js! function save(input);! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();! testSave_ShouldUseNewAPI_WhenLixEnabled();! testSave_ShouldUseOldAPI_WhenLixDisabled();! testSave_ShouldUseOldXAPI_WhenInputTypeIsX();! testSave_ShouldUseOldYAPI_WhenInputTypeIsY();!
  38. 38. Code coverage! // SaveHelper.js! function save(input);! ! // SaveHelperSpec.js! testSave_ShouldNotSave_WhenInputIsInvalid();! testSave_ShouldUseNewAPI_WhenLixEnabled();! testSave_ShouldUseOldAPI_WhenLixDisabled();! testSave_ShouldUseOldXAPI_WhenInputTypeIsX();! testSave_ShouldUseOldYAPI_WhenInputTypeIsY();!
  39. 39. Effective tests! Fail when the functionality breaks! ! KISS! ! Test functionality, not the implementation.! ! Don’t repeat your code in test.!
  40. 40. Effective tests! Fail when the functionality breaks! // code! paymentService = util.getPS();! paymentService.submit();! ! ! ! ! // unit test assertion! util.stub(‘getPS’).returns(mockService);! mockService.expect(‘submit’);!
  41. 41. Effective tests! Fail when the functionality breaks! // code! paymentService = util.getPS();! paymentService.submit();! ! ! // unit test assertion! util.stub(‘getPS’).returns(mockService);! mockService.expect(‘submit’);! ! forgot to verify!!
  42. 42. Effective tests! Keep It Simple Stupid! // unit test assertion! assert(“m_sim2_guided_edit_photo_add_actionsh eet_camera_tap_use_photo”, result);! ! " " " " " " "(vs)! ! assert(metricsRevisionPrefix + pageKey + widget + actionVerb + name, result);!
  43. 43. Effective tests! Test functionality, not the implementation.! void addNewRow(row) {! . . .! row.setDisplay(“block”);! row.setPaddingTop(0);! row.setMargin(0);! }! ! ! ! ! unit test type 1! verify(rowMock).setDisplay(“block”);! verify(rowMock).setPaddingTop(0);! Verify(rowMock).setMargin(0);!
  44. 44. Effective tests! Test functionality, not the implementation.! void addNewRow(row) {! . . .! row.setDisplay(“block”);! row.setPaddingTop(0);! row.setMargin(0);! }! ! unit test type 1! verify(rowMock).setDisplay(“block”);! verify(rowMock).setPaddingTop(0);! Verify(rowMock).setMargin(0);! ! unit test type 2! assertTrue(lastRow.bottom === newRow.top);!
  45. 45. Effective tests! Don’t repeat your code in the test! String getDateForDisplay() {! Date date = service.loadDate();! SimpleDateFormat dateFormat ! = newSimpleDateFormat("yyyy-MM-dd z");! return dateFormat.format(date);! }! ! // unit test! assertEquals(“2014-02-02 PST”, result);! ! assertEquals(new SimpleDateFormat(“yyyy-MM-dd z”).format(expectedDate), result);!
  46. 46. Better code! Testable! ! Modular! ! Loosely coupled! ! Singletons ! ! Law of Demeter"! ! Complexity!
  47. 47. Refactoring! Restructuring code without changing its functionality! ! ! Refactoring now & later! ! ! Migration projects!
  48. 48. Productivity! Faster Feedback! ! No wasting time with debugger! ! Avoid dependencies! ! Save time now and later! ! It doesn’t slow you down!
  49. 49. Productivity!
  50. 50. Documentation! Working examples of code!
  51. 51. Documentation! Working examples of code! Tests won’t get outdated!
  52. 52. Confidence! When you develop new features! When you handover your work! Try it! And you’ll feel it!!
  53. 53. Test First! ! Faster feedback! Code coverage! Effective tests! Better Code! Refactoring! Productivity! Documentation! Confidence!
  54. 54. Thank you!!

×