SlideShare une entreprise Scribd logo
1  sur  38
Test-driven
development
     Kerry Buckley
   2 November 2012
TDD refresher
Towards TDD
         0. manual testing




         Write
Design              Test     Release
         code
Towards TDD
            1. automated testing




         Write     Write
Design                        Test   Release
         code      tests
Towards TDD
          2. test-first development




         Write     Write
Design                        Test   Release
         tests     code
Towards TDD
           3. test-driven development

Design
   Write        Run            Write
   test         test           code
                                        Release
                        Run
         Refactor
                       tests
Towards TDD
3. test-driven development



 Red                Green




         Refactor
Beyond TDD?
      4. behaviour-driven development


                   Executable
Customer                                Release
                    examples




             Red                Green

                     TDD

                    Refactor
Types of test
Acceptance tests
      Test




     System
Integrated tests
  Test    Test
Unit tests
 Test          Test




Mock

        Mock     Mock
Anatomy of a test
           # Given some test accounts
➊ Setup    account_1 = Account.new(100)
           account_2 = Account.new(50)

           # When I transfer money
➋ Act      transfer(20, from: account_1,
                          to: account_2)

           # Then the balances should be updated
➌ Assert   account_1.balance.should eq(80)
           account_2.balance.should eq(70)
A good test…
A good test…
• Expresses the programmer’s intent
A good test…
• Expresses the programmer’s intent
• Gives confidence that the code works
A good test…
• Expresses the programmer’s intent
• Gives confidence that the code works
• Only tests one thing
A good test…
• Expresses the programmer’s intent
• Gives confidence that the code works
• Only tests one thing
• Gives clear failure message
A good test…
• Expresses the programmer’s intent
• Gives confidence that the code works
• Only tests one thing
• Gives clear failure message
• Is independent of other tests
A good test suite…
A good test suite…

• Gives confidence that the system works
A good test suite…

• Gives confidence that the system works
• Runs quickly
A good test suite…

• Gives confidence that the system works
• Runs quickly
• Is well-maintained
A good test suite…

• Gives confidence that the system works
• Runs quickly
• Is well-maintained
• Isolates each area under test
Benefits of TDD
Benefits of TDD
• Less manual testing required
Benefits of TDD
• Less manual testing required
• Faster feedback
Benefits of TDD
• Less manual testing required
• Faster feedback
• Make it safe to change code
Benefits of TDD
• Less manual testing required
• Faster feedback
• Make it safe to change code
• Reduced rework and debugging
Benefits of TDD
• Less manual testing required
• Faster feedback
• Make it safe to change code
• Reduced rework and debugging
• Improved design
How do I start?
How do I start?
• Greenfield project? JFDI! Otherwise…
How do I start?
• Greenfield project? JFDI! Otherwise…
• Automate highest value tests first
How do I start?
• Greenfield project? JFDI! Otherwise…
• Automate highest value tests first
  • Important features
How do I start?
• Greenfield project? JFDI! Otherwise…
• Automate highest value tests first
  • Important features
  • Where the most bugs occur
How do I start?
• Greenfield project? JFDI! Otherwise…
• Automate highest value tests first
  • Important features
  • Where the most bugs occur
• Use TDD for new features
How do I start?
• Greenfield project? JFDI! Otherwise…
• Automate highest value tests first
  • Important features
  • Where the most bugs occur
• Use TDD for new features
• Add tests for bugs when they’re found
Further reading

Contenu connexe

Tendances

Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Lars Thorup
 
Test Driven Development (TDD)
Test Driven Development (TDD)Test Driven Development (TDD)
Test Driven Development (TDD)David Ehringer
 
CI/CD Overview
CI/CD OverviewCI/CD Overview
CI/CD OverviewAn Nguyen
 
Building a CICD pipeline for deploying to containers
Building a CICD pipeline for deploying to containersBuilding a CICD pipeline for deploying to containers
Building a CICD pipeline for deploying to containersAmazon Web Services
 
Managing code quality with SonarQube
Managing code quality with SonarQubeManaging code quality with SonarQube
Managing code quality with SonarQubeRadu Vunvulea
 
Introduction to CICD
Introduction to CICDIntroduction to CICD
Introduction to CICDKnoldus Inc.
 
Code review guidelines
Code review guidelinesCode review guidelines
Code review guidelinesLalit Kale
 
GitLab for CI/CD process
GitLab for CI/CD processGitLab for CI/CD process
GitLab for CI/CD processHYS Enterprise
 
Behavior Driven Development (BDD)
Behavior Driven Development (BDD)Behavior Driven Development (BDD)
Behavior Driven Development (BDD)Ajay Danait
 
C++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkC++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkHumberto Marchezi
 
Unit Testing like a Pro - The Circle of Purity
Unit Testing like a Pro - The Circle of PurityUnit Testing like a Pro - The Circle of Purity
Unit Testing like a Pro - The Circle of PurityVictor Rentea
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Victor Rentea
 
CI and CD with Jenkins
CI and CD with JenkinsCI and CD with Jenkins
CI and CD with JenkinsMartin Málek
 
TDD Flow: The Mantra in Action
TDD Flow: The Mantra in ActionTDD Flow: The Mantra in Action
TDD Flow: The Mantra in ActionDionatan default
 
A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) CodeOps Technologies LLP
 
CI/CD (DevOps) 101
CI/CD (DevOps) 101CI/CD (DevOps) 101
CI/CD (DevOps) 101Hazzim Anaya
 

Tendances (20)

Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
 
Test Driven Development (TDD)
Test Driven Development (TDD)Test Driven Development (TDD)
Test Driven Development (TDD)
 
CI/CD Overview
CI/CD OverviewCI/CD Overview
CI/CD Overview
 
Building a CICD pipeline for deploying to containers
Building a CICD pipeline for deploying to containersBuilding a CICD pipeline for deploying to containers
Building a CICD pipeline for deploying to containers
 
Managing code quality with SonarQube
Managing code quality with SonarQubeManaging code quality with SonarQube
Managing code quality with SonarQube
 
Introduction to CICD
Introduction to CICDIntroduction to CICD
Introduction to CICD
 
Sanity testing and smoke testing
Sanity testing and smoke testingSanity testing and smoke testing
Sanity testing and smoke testing
 
Code review guidelines
Code review guidelinesCode review guidelines
Code review guidelines
 
GitLab for CI/CD process
GitLab for CI/CD processGitLab for CI/CD process
GitLab for CI/CD process
 
Behavior Driven Development (BDD)
Behavior Driven Development (BDD)Behavior Driven Development (BDD)
Behavior Driven Development (BDD)
 
TDD - Agile
TDD - Agile TDD - Agile
TDD - Agile
 
Introduction to Agile Testing
Introduction to Agile TestingIntroduction to Agile Testing
Introduction to Agile Testing
 
C++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing FrameworkC++ Unit Test with Google Testing Framework
C++ Unit Test with Google Testing Framework
 
Unit Testing like a Pro - The Circle of Purity
Unit Testing like a Pro - The Circle of PurityUnit Testing like a Pro - The Circle of Purity
Unit Testing like a Pro - The Circle of Purity
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
 
CI and CD with Jenkins
CI and CD with JenkinsCI and CD with Jenkins
CI and CD with Jenkins
 
TDD Flow: The Mantra in Action
TDD Flow: The Mantra in ActionTDD Flow: The Mantra in Action
TDD Flow: The Mantra in Action
 
A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD)
 
CICD with Jenkins
CICD with JenkinsCICD with Jenkins
CICD with Jenkins
 
CI/CD (DevOps) 101
CI/CD (DevOps) 101CI/CD (DevOps) 101
CI/CD (DevOps) 101
 

En vedette

Javasccript MV* frameworks
Javasccript MV* frameworksJavasccript MV* frameworks
Javasccript MV* frameworksKerry Buckley
 
Testing http calls with Webmock and VCR
Testing http calls with Webmock and VCRTesting http calls with Webmock and VCR
Testing http calls with Webmock and VCRKerry Buckley
 
Adastral Park code retreat introduction
Adastral Park code retreat introductionAdastral Park code retreat introduction
Adastral Park code retreat introductionKerry Buckley
 
Single Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupSingle Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupEyal Golan
 

En vedette (7)

7li7w devcon5
7li7w devcon57li7w devcon5
7li7w devcon5
 
BDD with cucumber
BDD with cucumberBDD with cucumber
BDD with cucumber
 
Javasccript MV* frameworks
Javasccript MV* frameworksJavasccript MV* frameworks
Javasccript MV* frameworks
 
Testing http calls with Webmock and VCR
Testing http calls with Webmock and VCRTesting http calls with Webmock and VCR
Testing http calls with Webmock and VCR
 
Adastral Park code retreat introduction
Adastral Park code retreat introductionAdastral Park code retreat introduction
Adastral Park code retreat introduction
 
Jasmine
JasmineJasmine
Jasmine
 
Single Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupSingle Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance Meetup
 

Similaire à TDD refresher

Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference CardSeapine Software
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentbhochhi
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit TestingShaun Abram
 
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-BrockPragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-BrockJoseph Yoder
 
Pragmatic notdogmatictdd agile2012
Pragmatic notdogmatictdd   agile2012Pragmatic notdogmatictdd   agile2012
Pragmatic notdogmatictdd agile2012drewz lin
 
Test Driven Development by Denis Lutz
Test Driven Development by Denis LutzTest Driven Development by Denis Lutz
Test Driven Development by Denis Lutzjazzman1980
 
Test Driven Development and Automation
Test Driven Development and AutomationTest Driven Development and Automation
Test Driven Development and AutomationMahesh Salaria
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012Pietro Di Bello
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25Jeremy Kendall
 
xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012Justin Gordon
 
What CS Class Didn't Teach About Testing
What CS Class Didn't Teach About TestingWhat CS Class Didn't Teach About Testing
What CS Class Didn't Teach About TestingCamille Bell
 
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven Development
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven DevelopmentABAP Code Retreat Frankfurt 2016: TDD - Test Driven Development
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven DevelopmentHendrik Neumann
 
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAP
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAPABAPCodeRetreat Frankfurt 2016 - TDD with ABAP
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAPABAPCodeRetreat
 

Similaire à TDD refresher (20)

Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference Card
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit Testing
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-BrockPragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
 
Pragmatic notdogmatictdd agile2012
Pragmatic notdogmatictdd   agile2012Pragmatic notdogmatictdd   agile2012
Pragmatic notdogmatictdd agile2012
 
TDD with Ruby
TDD with RubyTDD with Ruby
TDD with Ruby
 
Real Developers Don't Need Unit Tests
Real Developers Don't Need Unit TestsReal Developers Don't Need Unit Tests
Real Developers Don't Need Unit Tests
 
Test Driven Development by Denis Lutz
Test Driven Development by Denis LutzTest Driven Development by Denis Lutz
Test Driven Development by Denis Lutz
 
Test Driven Development and Automation
Test Driven Development and AutomationTest Driven Development and Automation
Test Driven Development and Automation
 
TDD talk
TDD talkTDD talk
TDD talk
 
TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012TDD reloaded - JUGTAA 24 Ottobre 2012
TDD reloaded - JUGTAA 24 Ottobre 2012
 
Tdd blog
Tdd blogTdd blog
Tdd blog
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25
 
xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012
 
What CS Class Didn't Teach About Testing
What CS Class Didn't Teach About TestingWhat CS Class Didn't Teach About Testing
What CS Class Didn't Teach About Testing
 
Tdd red-green-refactor
Tdd red-green-refactorTdd red-green-refactor
Tdd red-green-refactor
 
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven Development
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven DevelopmentABAP Code Retreat Frankfurt 2016: TDD - Test Driven Development
ABAP Code Retreat Frankfurt 2016: TDD - Test Driven Development
 
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAP
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAPABAPCodeRetreat Frankfurt 2016 - TDD with ABAP
ABAPCodeRetreat Frankfurt 2016 - TDD with ABAP
 
Introduction to TDD and Mocking
Introduction to TDD and MockingIntroduction to TDD and Mocking
Introduction to TDD and Mocking
 

Plus de Kerry Buckley

Ruby nooks & crannies
Ruby nooks & cranniesRuby nooks & crannies
Ruby nooks & cranniesKerry Buckley
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test communityKerry Buckley
 
What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)Kerry Buckley
 
MongoMapper lightning talk
MongoMapper lightning talkMongoMapper lightning talk
MongoMapper lightning talkKerry Buckley
 
The secret life of bees
The secret life of beesThe secret life of bees
The secret life of beesKerry Buckley
 
Background processing
Background processingBackground processing
Background processingKerry Buckley
 
Katas, Contests and Coding Dojos
Katas, Contests and Coding DojosKatas, Contests and Coding Dojos
Katas, Contests and Coding DojosKerry Buckley
 
Kanban and Iterationless Working
Kanban and Iterationless WorkingKanban and Iterationless Working
Kanban and Iterationless WorkingKerry Buckley
 
Software Development Trends
Software Development TrendsSoftware Development Trends
Software Development TrendsKerry Buckley
 
Kanban and Iterationless Working
Kanban and Iterationless WorkingKanban and Iterationless Working
Kanban and Iterationless WorkingKerry Buckley
 
Behaviour-Driven Development
Behaviour-Driven DevelopmentBehaviour-Driven Development
Behaviour-Driven DevelopmentKerry Buckley
 
REST: putting the web back in to web services
REST: putting the web back in to web servicesREST: putting the web back in to web services
REST: putting the web back in to web servicesKerry Buckley
 

Plus de Kerry Buckley (20)

Ruby nooks & crannies
Ruby nooks & cranniesRuby nooks & crannies
Ruby nooks & crannies
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)
 
Functional ruby
Functional rubyFunctional ruby
Functional ruby
 
MongoMapper lightning talk
MongoMapper lightning talkMongoMapper lightning talk
MongoMapper lightning talk
 
Ruby
RubyRuby
Ruby
 
Cloud
CloudCloud
Cloud
 
The secret life of bees
The secret life of beesThe secret life of bees
The secret life of bees
 
Background processing
Background processingBackground processing
Background processing
 
Katas, Contests and Coding Dojos
Katas, Contests and Coding DojosKatas, Contests and Coding Dojos
Katas, Contests and Coding Dojos
 
Rack
RackRack
Rack
 
Doing REST Right
Doing REST RightDoing REST Right
Doing REST Right
 
Kanban and Iterationless Working
Kanban and Iterationless WorkingKanban and Iterationless Working
Kanban and Iterationless Working
 
Software Development Trends
Software Development TrendsSoftware Development Trends
Software Development Trends
 
TDD
TDDTDD
TDD
 
Kanban and Iterationless Working
Kanban and Iterationless WorkingKanban and Iterationless Working
Kanban and Iterationless Working
 
TDD, BDD and mocks
TDD, BDD and mocksTDD, BDD and mocks
TDD, BDD and mocks
 
Behaviour-Driven Development
Behaviour-Driven DevelopmentBehaviour-Driven Development
Behaviour-Driven Development
 
REST: putting the web back in to web services
REST: putting the web back in to web servicesREST: putting the web back in to web services
REST: putting the web back in to web services
 
Git
GitGit
Git
 

TDD refresher

  • 1. Test-driven development Kerry Buckley 2 November 2012
  • 3. Towards TDD 0. manual testing Write Design Test Release code
  • 4. Towards TDD 1. automated testing Write Write Design Test Release code tests
  • 5. Towards TDD 2. test-first development Write Write Design Test Release tests code
  • 6. Towards TDD 3. test-driven development Design Write Run Write test test code Release Run Refactor tests
  • 7. Towards TDD 3. test-driven development Red Green Refactor
  • 8. Beyond TDD? 4. behaviour-driven development Executable Customer Release examples Red Green TDD Refactor
  • 10. Acceptance tests Test System
  • 11. Integrated tests Test Test
  • 12. Unit tests Test Test Mock Mock Mock
  • 13. Anatomy of a test # Given some test accounts ➊ Setup account_1 = Account.new(100) account_2 = Account.new(50) # When I transfer money ➋ Act transfer(20, from: account_1, to: account_2) # Then the balances should be updated ➌ Assert account_1.balance.should eq(80) account_2.balance.should eq(70)
  • 15. A good test… • Expresses the programmer’s intent
  • 16. A good test… • Expresses the programmer’s intent • Gives confidence that the code works
  • 17. A good test… • Expresses the programmer’s intent • Gives confidence that the code works • Only tests one thing
  • 18. A good test… • Expresses the programmer’s intent • Gives confidence that the code works • Only tests one thing • Gives clear failure message
  • 19. A good test… • Expresses the programmer’s intent • Gives confidence that the code works • Only tests one thing • Gives clear failure message • Is independent of other tests
  • 20. A good test suite…
  • 21. A good test suite… • Gives confidence that the system works
  • 22. A good test suite… • Gives confidence that the system works • Runs quickly
  • 23. A good test suite… • Gives confidence that the system works • Runs quickly • Is well-maintained
  • 24. A good test suite… • Gives confidence that the system works • Runs quickly • Is well-maintained • Isolates each area under test
  • 26. Benefits of TDD • Less manual testing required
  • 27. Benefits of TDD • Less manual testing required • Faster feedback
  • 28. Benefits of TDD • Less manual testing required • Faster feedback • Make it safe to change code
  • 29. Benefits of TDD • Less manual testing required • Faster feedback • Make it safe to change code • Reduced rework and debugging
  • 30. Benefits of TDD • Less manual testing required • Faster feedback • Make it safe to change code • Reduced rework and debugging • Improved design
  • 31. How do I start?
  • 32. How do I start? • Greenfield project? JFDI! Otherwise…
  • 33. How do I start? • Greenfield project? JFDI! Otherwise… • Automate highest value tests first
  • 34. How do I start? • Greenfield project? JFDI! Otherwise… • Automate highest value tests first • Important features
  • 35. How do I start? • Greenfield project? JFDI! Otherwise… • Automate highest value tests first • Important features • Where the most bugs occur
  • 36. How do I start? • Greenfield project? JFDI! Otherwise… • Automate highest value tests first • Important features • Where the most bugs occur • Use TDD for new features
  • 37. How do I start? • Greenfield project? JFDI! Otherwise… • Automate highest value tests first • Important features • Where the most bugs occur • Use TDD for new features • Add tests for bugs when they’re found

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n