Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
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

More Related Content

Developer testing 201: When to Mock and When to Integrate

Editor's Notes

  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