KEMBAR78
Testing with laravel | PPTX
Designing for Testability with Laravel
Derek Binkley
@DerekB_WI
About Me
★Lead Developer at National Conference of
Bar Examiners
★PHP and Java Developer
★MySQL DBA
★Father of Three
★Second ever talk
About NCBE
Examining Bars?
About NCBE
No, developing the bar exam for future lawyers.
Plus, supporting state admission authorities.
What will we cover?
What is built in to Laravel for Unit Testing
Strategies that make testing easier
Detailed examples
Unit Tests
• Lowest level of testing
• Typically done by developer
• Crucial to Test Driven Design
• Tests a Single Unit of Code and Verifies the
Results.
Why don’t developers test?
• Think code will get replaced soon.
• Think code is straightforward and won’t break.
• Tests are hard to write.
• Low perceived benefit.
• Don’t understand how to design code for
testability.
Laravel and PHPUnit
• PHPUnit Available by default
• Tests saved in Tests directory
• Tests should extend TestCase class
• Tests should be saved in file named *Test.php
• Tests method names should begin with test.
What Does Laravel Provide?
• Crawler – Gives us a mock browser/client to
run our controllers.
What Does Laravel Provide?
• Additional assertions
• ->assertResponseOk();
• ->assertResponseStatus($code);
• ->assertViewHas($key, $value = null);
• ->assertViewHasAll(array $bindings);
• ->assertViewMissing($key);
• ->assertRedirectedTo($uri, $with = []);
• ->assertRedirectedToRoute($name, $parameters = [], $with = []);
• ->assertRedirectedToAction($name, $parameters = [], $with = []);
• ->assertSessionHas($key, $value = null);
• ->assertSessionHasAll(array $bindings);
• ->assertSessionHasErrors($bindings = [], $format = null);
• ->assertHasOldInput();
Faking Data
• https://github.com/fzaninotto/Faker
• Allows us to not spend time making up test
data.
Example Form
Example Controller
Test Code – First Try
Problems?
• Database is not cleaned up. We could use
seeding in our setup and teardown methods.
• Email attempt adds a dependency upon a
network or cloud service.
• Testing all the logic of the controller at once
makes problems hard to diagnose.
Laravel Can Help
• Disabling Middleware allows testing only your controller code
• Wrapping test in a database transaction helps clean up
• Using migrations allows for resetting database to consistent
state.
How we can help ourselves
• DRY – Don’t Repeat Yourself – Be Lazy, write code once
• Single Responsibility Object – No “Jack of all Trades” Objects
• Dependency Injection – Give me what I need to do my job
• Keep cyclomatic complexity low – If there is a fork in the road
take it
• Law of Demeter – Don’t extend reach too far
• Design Patterns – Somebody has already solved our problems
Improving Our Example
• Remove dependency on session
Rerun Test and See Failure
• Remove if (is_numeric(session($user_id)))
Dependency Injection
• Pass in the objects you need
• Code to interfaces
• Avoid creating a “new” object.
• Setter Injection v. Constructor Injection
• Helps follow Law of Demeter
Arguments Against DI
• Our dependencies won’t change
• Too complex
Benefits of DI
• Can now mock objects while testing
• Test our code, not 3rd party libraries
• Loose coupling allows for easier upgrades
• Built in to Laravel
Let’s try it out
• Laravel will inject an instance of a class that is type hinted in a
constructor or method.
• Now we can use our factory anywhere within our controller.
Controller is Much Skinnier
Mock objects allow for easy controller testing
• We create a mock PersonFactory and specify
which methods will be called and what they
should return.
• Our person creation logic is now moved to a
single class (DRY), our controller can now be
tested without a database.
• Yet to test our person factory we must still
seed and clean up our database.
Repository Pattern
• Separate getting the data from the data
object.
• Code to an interface to allow for mocking.
Wrapper Around Class
• Takes class doing work as parameter
• Easy to Mock
• Won’t use underlying resources, e.g. API, to
run test.
Mocking a Facade
• The Mail class is a Laravel façade so we can
easily mock it like this.
• Laravel takes care of the rest for us.
Resources
• http://martinfowler.com/eaaCatalog/tableDataGateway.html
• https://www.youtube.com/watch?v=HhwElTL-mdI - Evan Dorn LA Ruby Meetup
• https://www.youtube.com/watch?v=X6c11niH-U8 - Chris Hartjes Ski PHP
• https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/
• https://github.com/fzaninotto/Faker
• http://laravelcoding.com/blog/laravel-5-beauty-testing
• https://laravel.com/docs/5.1/testing
• http://martinfowler.com/articles/mocksArentStubs.html
Thanks
• Derek Binkley - @DerekB_WI or dbinkley@ncbex.org
• Slides are at
http://www.slideshare.net/DerekBinkley/testing-
with-laravel
• Feedback on Joind.in at https://joind.in/talk/dc052

Testing with laravel

  • 1.
    Designing for Testabilitywith Laravel Derek Binkley @DerekB_WI
  • 2.
    About Me ★Lead Developerat National Conference of Bar Examiners ★PHP and Java Developer ★MySQL DBA ★Father of Three ★Second ever talk
  • 3.
  • 4.
    About NCBE No, developingthe bar exam for future lawyers. Plus, supporting state admission authorities.
  • 5.
    What will wecover? What is built in to Laravel for Unit Testing Strategies that make testing easier Detailed examples
  • 6.
    Unit Tests • Lowestlevel of testing • Typically done by developer • Crucial to Test Driven Design • Tests a Single Unit of Code and Verifies the Results.
  • 7.
    Why don’t developerstest? • Think code will get replaced soon. • Think code is straightforward and won’t break. • Tests are hard to write. • Low perceived benefit. • Don’t understand how to design code for testability.
  • 8.
    Laravel and PHPUnit •PHPUnit Available by default • Tests saved in Tests directory • Tests should extend TestCase class • Tests should be saved in file named *Test.php • Tests method names should begin with test.
  • 9.
    What Does LaravelProvide? • Crawler – Gives us a mock browser/client to run our controllers.
  • 10.
    What Does LaravelProvide? • Additional assertions • ->assertResponseOk(); • ->assertResponseStatus($code); • ->assertViewHas($key, $value = null); • ->assertViewHasAll(array $bindings); • ->assertViewMissing($key); • ->assertRedirectedTo($uri, $with = []); • ->assertRedirectedToRoute($name, $parameters = [], $with = []); • ->assertRedirectedToAction($name, $parameters = [], $with = []); • ->assertSessionHas($key, $value = null); • ->assertSessionHasAll(array $bindings); • ->assertSessionHasErrors($bindings = [], $format = null); • ->assertHasOldInput();
  • 11.
    Faking Data • https://github.com/fzaninotto/Faker •Allows us to not spend time making up test data.
  • 12.
  • 13.
  • 14.
    Test Code –First Try
  • 15.
    Problems? • Database isnot cleaned up. We could use seeding in our setup and teardown methods. • Email attempt adds a dependency upon a network or cloud service. • Testing all the logic of the controller at once makes problems hard to diagnose.
  • 16.
    Laravel Can Help •Disabling Middleware allows testing only your controller code • Wrapping test in a database transaction helps clean up • Using migrations allows for resetting database to consistent state.
  • 17.
    How we canhelp ourselves • DRY – Don’t Repeat Yourself – Be Lazy, write code once • Single Responsibility Object – No “Jack of all Trades” Objects • Dependency Injection – Give me what I need to do my job • Keep cyclomatic complexity low – If there is a fork in the road take it • Law of Demeter – Don’t extend reach too far • Design Patterns – Somebody has already solved our problems
  • 18.
    Improving Our Example •Remove dependency on session
  • 19.
    Rerun Test andSee Failure • Remove if (is_numeric(session($user_id)))
  • 20.
    Dependency Injection • Passin the objects you need • Code to interfaces • Avoid creating a “new” object. • Setter Injection v. Constructor Injection • Helps follow Law of Demeter
  • 21.
    Arguments Against DI •Our dependencies won’t change • Too complex
  • 22.
    Benefits of DI •Can now mock objects while testing • Test our code, not 3rd party libraries • Loose coupling allows for easier upgrades • Built in to Laravel
  • 23.
    Let’s try itout • Laravel will inject an instance of a class that is type hinted in a constructor or method. • Now we can use our factory anywhere within our controller.
  • 24.
  • 25.
    Mock objects allowfor easy controller testing • We create a mock PersonFactory and specify which methods will be called and what they should return.
  • 26.
    • Our personcreation logic is now moved to a single class (DRY), our controller can now be tested without a database. • Yet to test our person factory we must still seed and clean up our database.
  • 27.
    Repository Pattern • Separategetting the data from the data object. • Code to an interface to allow for mocking.
  • 28.
    Wrapper Around Class •Takes class doing work as parameter • Easy to Mock • Won’t use underlying resources, e.g. API, to run test.
  • 29.
    Mocking a Facade •The Mail class is a Laravel façade so we can easily mock it like this. • Laravel takes care of the rest for us.
  • 30.
    Resources • http://martinfowler.com/eaaCatalog/tableDataGateway.html • https://www.youtube.com/watch?v=HhwElTL-mdI- Evan Dorn LA Ruby Meetup • https://www.youtube.com/watch?v=X6c11niH-U8 - Chris Hartjes Ski PHP • https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/ • https://github.com/fzaninotto/Faker • http://laravelcoding.com/blog/laravel-5-beauty-testing • https://laravel.com/docs/5.1/testing • http://martinfowler.com/articles/mocksArentStubs.html
  • 31.
    Thanks • Derek Binkley- @DerekB_WI or dbinkley@ncbex.org • Slides are at http://www.slideshare.net/DerekBinkley/testing- with-laravel • Feedback on Joind.in at https://joind.in/talk/dc052

Editor's Notes

  • #4 Common misconception. I often get asked for good drink recipes.
  • #5 Standardized testing takes lots of data processing. We also collect and analyze lots of “customer” data.
  • #6 Getting your head around what to test can be challenging. I will show you some examples of code and see how to add good tests and maybe even encourage true TDD.
  • #7 Integration, System and Acceptance are other higher level tests.
  • #8 Poll the audience. I am not going into an argument on why to test.  That gets covered a lot and is important.  In my history I have found that I don’t test because I don’t know how to write the tests. Won’t argue about what and when to test. That is up to you. If testing is easier then you will be more likely to test.
  • #10 We go to the route /one and look for the text – Testing a Form assertResponseOk looks for 200 return code.
  • #11 Builds upon PHPUnit by adding specific assertions that hide some of the Laravel “magic”
  • #13 Fat Controller - All logic is contained with this controller. What if we
  • #14 This is a very long controller just to save a simple form
  • #15 Explain what each test is doing and then ask for problems
  • #16 Does anybody see what part doesn’t get tested?
  • #18 Law of Demeter states you can call your own methods, methods of objects passed, methods of objects you create locally.
  • #19 By moving the logged in check to our middleware we can test our login logic separately.
  • #20 Code redirects to login without our addition of a session variable. So, we remove the if statement we can still protect our routes with middleware. Show middleware example. Explain you can now write a test for CustomAuth class.
  • #22 Notice comment from open source project where a developer asserts to not code to an interface because of no plans to use other implementations. Of course we all know that three years from now a cool replacement to the JWT library will be all the rage and we will want to swap that out.
  • #25 Fat Model, Skinny Controller
  • #28 This can seem silly with all of the built in magic that Eloquent provides. However by not tightly coupling our code to Eloquent it becomes more flexible and mockable. Show examples including how interface gets bound in AppServerProvider