SlideShare uma empresa Scribd logo
1 de 98
Developer Testing 201
Goals

• Learn advanced unit testing techniques
• Build a toolbox for integration testing
• Begin to be able to assess appropriate
  testing needs and usages
Non-Goals


• Not an introduction to testing
• Not to necessarily learn how to write
  the best (code) tests, but getting closer
Resources
Code Samples
   https://github.com/elblinkin/DeveloperTesting201

PHPUnit Manual
   http://www.phpunit.de/manual/current/en/

PHPUnit GitHub
   https://github.com/sebastianbergmann/phpunit

Etsy PHPUnit Extensions
   https://github.com/etsy/phpunit-extensions/wiki

Mockery
   https://github.com/padraic/mockery
Topics
• Review Test Sizes
• Database Testing
• Custom Assertions
• Mock Objects
• Filesystem Testing
• Network Testing
Test Pyramid
Food Pyramid of the 90s
Test Types
Vocabulary Break!
Functional Tests


Does the overall
product satisfy the
the requirements?
Integration Tests


Do the pieces fit
together?
Unit Tests


Is the logic correct in
that function?
Functional
Understand the product.
The Tools
The Tools


• BeHat (Cucumber)
The Tools


• BeHat (Cucumber)
• PHPSpec
The Tools


• BeHat (Cucumber)
• PHPSpec
• Keyboard, Mouse, and You
When Do They Work?

• During prototyping
• Focused on the product requirements
• Refactoring
• Regression of key features
• Better for smaller teams
After
Greenfield
Inverted Test Pyramid
...Stop Helping?


• Focused on the implementation
• Rapidly changing functionality
• Large organizations
Test Pyramid
Food Pyramid of the 90s
Unit Tests
Simple and to the point.
Verify Correctness


• Line coverage
• Branch coverage
• Icky Bits-o-Logic
Gain Confidence

• Individual functions
• Variety of parameters
• Works for expected interactions with
  collaborators
Communication

• Show how to use the function
• Show expected interactions with other
  collaborators
• Increase discoverability of possible
  reuse
Tests should always be treated like every
other consumer of the subject under test.
Integration
For everything in-between.
You’re Paranoid

• Experimenting with third-party code or
  service
• You do not trust that your collaborators
  work as specified
Sorry! Piece of Testing
                 Functional


   Integration



                      Unit
Test Classification
External Dependencies

• Caches, ie. Memcache
• Databases, ie. MySQL, Postgres, etc.
• 3rd Party Services
• Filesystem
More Sources of Flake

• Sleep
• Date/Time
• Random Number Generators
• Multiple-Processes
@group

• @group cache
 •   for test that use memcache
• @group dbunit
 •   for test that use DBUnit and databases
• @group network
 •   for tests that talk to external services
• @group flaky
 •   for tests that fail without a code change
Unit Tests are DEFAULT



   There is NO @group for unit tests.
Test Sizes

• New in PHPUnit 3.6
• @small run in less than one second
• @medium run in less than 10 seconds
• @large run in less than 60 seconds
• Note: All times are configurable
Database Testing
DBUnit: Basic Steps
1. Set Up Fixture
 • getDataSet()
 • getConnection()
2. Exercise System Under Test
3. Verify Outcome
4. Tear Down
Supported Databases
• MySQL
• PostgreSQL
• Oracle
• SQLite
• IBM DB2 or Microsoft SQL Server
 • via Zend Framework or Doctrine 2
DataSet Options
•   XML             • Replacement
•   Flat XML        • Filter
•   MySQL XML       • Composite
•   YAML
•   CSV
•   Query (SQL)
•   Database (DB)
•   Array*
                     * from Etsy Extensions
Example Deep Dive

• 01 - Database
 • 01 - Simple (Read-Only DBUnit Test)

 • 02 - TestCase (Extract Custom)

 • 03 - Modify (Modifying Existing)

 • 04 - Create (Adding Data)

 • 05 - DRYing (Reducing Integration Points)
Custom Assertions
Custom Assert
Custom Assert: Lv. 1
Custom Assert: Lv. 1
           Multiple Asserts!!

1
2
3
4
Custom Assert: Lv. 1
             No Message!!
Custom Assert: Lv. 1


           N ot
    N ot

    N ot


    N ot

    N ot
Custom Assert: Lv. 2
Custom Assert: Lv. 2



              Not An Assertion
Custom Assert: Lv. 2



    assertTrue(true);
Custom Assert: Lv. 2




                      Messaging
                     is Awkward


          * Look at PHPUnit assertEquals() output.
Custom Assert: Lv. 2

                      N ot
    !(

)



    ‘Expected %s to not be equal to %s.’
Custom Assert: Lv. 3
Custom Assert: Lv. 3


     Single Assert!
Custom Assert: Lv. 3

                Message!
Custom Assert: Lv. 3




     Easy Inverse!
Custom Assert: Lv. 3

                      Message!
     Single Assert!


     Easy Inverse!
Custom Assert: Lv. 3


             What’s this?!?
Constraints
Constraints

• Based on Hamcrest matchers

• Can be used in assertThat() for Custom
  Asserts

• Can also be used in with()for Mock Objects
Constraints
Custom Assert: Lv. 2



 (         This is It!
                       )
Constraints
Constraints with() Mocks
Constraints with() Mocks
with()
•   equalTo()              •   identicalTo()
•   anything()             •   isInstanceOf()
•   isTrue()               •   isType()
•   isFalse()              •   matchesRegularExpression
•   isNull()               •   matches()
•   contains()             •   stringStartWith()
•   containsOnly()         •   stringEndWith()
•   arrayHasKey()          •   stringContains()
•   isEmpty()              •   logicalAnd()
•   greaterThan()          •   logicalOr()
•   greaterThanOrEqual()   •   logicalNot()
•   lessThan()             •   logicalXor()
•   lessThanOrEqual()      •   more...
Custom Assert: Lv. 3




            Composed Constraint
Composed Constraint




        * See: Etsy PHPUnit-Extensions
Composed Constraint




        * See: Etsy PHPUnit-Extensions
Constraints v. Matcher(?)

 • PHPUnit Constraint
  • evaluate()

 • Hamcrest Matcher
  • matches()

 • Mockery Matcher
  • match()
Constraints
Mockery Matcher
Hamcrest Matcher
Mock Objects
Mock Object
Mock Object

          Have To Specify
      Occurrences Every Time




        Can Have Only ONE
      Expectation Per Method
Workarounds


• There are hacks to allow multiple expectations
  per method

• See: https://github.com/etsy/phpunit-
  extensions/wiki/Mock-object
Mockery
Mockery

You Can Use Hamcrest Matchers Instead!


               anyOf()



            This is Need for Verification
Bootstrap for Mockery


    bootstrap.php




              phpunit --boostrap=bootstrap.php
                  or set in your phpunit.xml
Mockery PHPUnit Listener
Mockery PHPUnit Listener


            No tearDown() Boilerplate




           Omit Mockery from Coverage
Incompatible with --strict



      N ot h i
  Nu m b       ng Co
         e r of E    u nt s t
                  xp e ct     he
                          atio n s
                                   !!
Mockery
Mockery TestCase


    PHPUnit_Extensions_Mockery_TestCase

                              $this->getMockery(‘s imple mock’);
                            anyOf()
Mockery TestCase
Mockery TestCase


Extra Namespace-ing, Gone!

                             Expectations Count!


               No bootstrap.php or TestListener
                         necessary!!
@mockery




   Creates a Mockery Instance
Mix and Match


         Create with Annotation



            Make a Partial Mock


     Use PHPUnit Mock Objects too!
Filesystem Testing
vfsStream

• Virtual FileSystem

• In-Memory

• Utilizes stream_wrapper_register
  • vfs://path/to/my/file.txt
Works With...
• file_exists
• copy
• mkdir
• unlink
• is_file
• is_dir
• ...
Pure Filenames Only


• realpath()
• symlink()
• SplFileInfo::getRealPath()
Not Supported in 5.3

• touch()
• chmod()
• chown()
• chgrp()
Other Limitations

• ext/zip
 • does not support user-land stream wrappers

• is_executable()
 • always returns false
Not Implemented


• stream_set_blocking()
• stream_set_timeout()
• stream_set_write_buffer()
Examples


• 05 - Filesystem
 • vfsStream/examples
 • Taggle
Network Tests
Web Services


• SOAP/WSDL
 • $this->getMockFromWsdl();

• Thin Wrap Your Web Service Client
Closing Thoughts
• Minimize Integration Points
• Minimize Integration Tests
• Wrap External (Hostile) Dependencies
• Try to Avoid Test Fixture Files
• Test Your Custom Test Tools
• Consider Alert Systems, not CI
Resources
Code Samples
   https://github.com/elblinkin/DeveloperTesting201

PHPUnit Manual
   http://www.phpunit.de/manual/current/en/

PHPUnit GitHub
   https://github.com/sebastianbergmann/phpunit

Etsy PHPUnit Extensions
   https://github.com/etsy/phpunit-extensions/wiki

Mockery
   https://github.com/padraic/mockery

Mais conteúdo relacionado

Mais procurados

Test in action week 3
Test in action   week 3Test in action   week 3
Test in action week 3
Yi-Huan Chan
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and Fallacies
Roman Elizarov
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
Roman Elizarov
 
Executable specifications for xtext
Executable specifications for xtextExecutable specifications for xtext
Executable specifications for xtext
meysholdt
 

Mais procurados (20)

Test in action week 3
Test in action   week 3Test in action   week 3
Test in action week 3
 
Mozilla Web QA - Evolution of our Python WebDriver framework
Mozilla Web QA - Evolution of our Python WebDriver frameworkMozilla Web QA - Evolution of our Python WebDriver framework
Mozilla Web QA - Evolution of our Python WebDriver framework
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
 
Learn To Test Like A Grumpy Programmer - 3 hour workshop
Learn To Test Like A Grumpy Programmer - 3 hour workshopLearn To Test Like A Grumpy Programmer - 3 hour workshop
Learn To Test Like A Grumpy Programmer - 3 hour workshop
 
Object Oriented Exploitation: New techniques in Windows mitigation bypass
Object Oriented Exploitation: New techniques in Windows mitigation bypassObject Oriented Exploitation: New techniques in Windows mitigation bypass
Object Oriented Exploitation: New techniques in Windows mitigation bypass
 
Testing in Django
Testing in DjangoTesting in Django
Testing in Django
 
DIY Java Profiling
DIY Java ProfilingDIY Java Profiling
DIY Java Profiling
 
Automated Testing in Django
Automated Testing in DjangoAutomated Testing in Django
Automated Testing in Django
 
Java Serialization Facts and Fallacies
Java Serialization Facts and FallaciesJava Serialization Facts and Fallacies
Java Serialization Facts and Fallacies
 
Non blocking programming and waiting
Non blocking programming and waitingNon blocking programming and waiting
Non blocking programming and waiting
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
 
Test-Driven Development of Xtext DSLs
Test-Driven Development  of Xtext DSLsTest-Driven Development  of Xtext DSLs
Test-Driven Development of Xtext DSLs
 
Php extensions
Php extensionsPhp extensions
Php extensions
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Executable specifications for xtext
Executable specifications for xtextExecutable specifications for xtext
Executable specifications for xtext
 
Py.test
Py.testPy.test
Py.test
 
YAPC::NA 2007 - An Introduction To Perl Critic
YAPC::NA 2007 - An Introduction To Perl CriticYAPC::NA 2007 - An Introduction To Perl Critic
YAPC::NA 2007 - An Introduction To Perl Critic
 
Extending Perl Critic
Extending Perl CriticExtending Perl Critic
Extending Perl Critic
 

Destaque (8)

Auto Backwash Filter Simplex Type
Auto Backwash Filter Simplex TypeAuto Backwash Filter Simplex Type
Auto Backwash Filter Simplex Type
 
Apache Persistence Layers
Apache Persistence LayersApache Persistence Layers
Apache Persistence Layers
 
Are Your Tests Really Helping You?
Are Your Tests Really Helping You?Are Your Tests Really Helping You?
Are Your Tests Really Helping You?
 
Achieving beneficial backwash
Achieving  beneficial backwashAchieving  beneficial backwash
Achieving beneficial backwash
 
Achieving beneficial blackwash
Achieving beneficial blackwashAchieving beneficial blackwash
Achieving beneficial blackwash
 
Weaving aspects in PHP with the help of Go! AOP library
Weaving aspects in PHP with the help of Go! AOP libraryWeaving aspects in PHP with the help of Go! AOP library
Weaving aspects in PHP with the help of Go! AOP library
 
Achievement tests
Achievement testsAchievement tests
Achievement tests
 
Presentation Validity & Reliability
Presentation Validity & ReliabilityPresentation Validity & Reliability
Presentation Validity & Reliability
 

Semelhante a Developer testing 201: When to Mock and When to Integrate

20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial
garrett honeycutt
 
Grails Spock Testing
Grails Spock TestingGrails Spock Testing
Grails Spock Testing
TO THE NEW | Technology
 

Semelhante a Developer testing 201: When to Mock and When to Integrate (20)

TDD with phpspec2
TDD with phpspec2TDD with phpspec2
TDD with phpspec2
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Testing sync engine
Testing sync engineTesting sync engine
Testing sync engine
 
TDD and mock objects
TDD and mock objectsTDD and mock objects
TDD and mock objects
 
20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial
 
Behat bdd training (php) course slides pdf
Behat bdd training (php) course slides pdfBehat bdd training (php) course slides pdf
Behat bdd training (php) course slides pdf
 
Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015
 
How and what to unit test
How and what to unit testHow and what to unit test
How and what to unit test
 
Getting started-php unit
Getting started-php unitGetting started-php unit
Getting started-php unit
 
Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
 
Building XWiki
Building XWikiBuilding XWiki
Building XWiki
 
Grails Spock Testing
Grails Spock TestingGrails Spock Testing
Grails Spock Testing
 
33rd degree
33rd degree33rd degree
33rd degree
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
How to Test PowerShell Code Using Pester
How to Test PowerShell Code Using PesterHow to Test PowerShell Code Using Pester
How to Test PowerShell Code Using Pester
 
Design p atterns
Design p atternsDesign p atterns
Design p atterns
 
Unit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - KenyaUnit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - Kenya
 
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWJest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRW
 

Mais de LB Denker

Testing and DevOps Culture: Lessons Learned
Testing and DevOps Culture: Lessons LearnedTesting and DevOps Culture: Lessons Learned
Testing and DevOps Culture: Lessons Learned
LB Denker
 
Php com con-2011
Php com con-2011Php com con-2011
Php com con-2011
LB Denker
 

Mais de LB Denker (6)

Testing and DevOps Culture: Lessons Learned
Testing and DevOps Culture: Lessons LearnedTesting and DevOps Culture: Lessons Learned
Testing and DevOps Culture: Lessons Learned
 
Php|tek '12 It's More Than Just Style
Php|tek '12  It's More Than Just StylePhp|tek '12  It's More Than Just Style
Php|tek '12 It's More Than Just Style
 
phpDay 2012: Scaling Communication via Continuous Integration
phpDay 2012: Scaling Communication via Continuous IntegrationphpDay 2012: Scaling Communication via Continuous Integration
phpDay 2012: Scaling Communication via Continuous Integration
 
QC Merge 2012: Growing community
QC Merge 2012: Growing communityQC Merge 2012: Growing community
QC Merge 2012: Growing community
 
PHP UK Conference 2012: Scaling Communication via Continuous Integration
PHP UK Conference 2012: Scaling Communication via Continuous IntegrationPHP UK Conference 2012: Scaling Communication via Continuous Integration
PHP UK Conference 2012: Scaling Communication via Continuous Integration
 
Php com con-2011
Php com con-2011Php com con-2011
Php com con-2011
 

Último

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Último (20)

MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 

Developer testing 201: When to Mock and When to Integrate

Notas do Editor

  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
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n