Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TDD - Test Driven Drupal

71c9ebde850996d2533c5df4df2c93c6?s=47 Oliver Davies
December 11, 2020

TDD - Test Driven Drupal

71c9ebde850996d2533c5df4df2c93c6?s=128

Oliver Davies

December 11, 2020
Tweet

Transcript

  1. TDD: Test Driven Drupal Oliver Davies, Inviqa

  2. Software Engineer, open-source maintainer and contributor @opdavies

  3. @opdavies

  4. @opdavies

  5. @opdavies

  6. Why write tests? • Peace of mind • Prevent regressions

    • Catch bugs earlier • Write less code • Documentation • Drupal core requirement • More important with regular D8/D9 releases and supporting multiple versions @opdavies
  7. Testing in Drupal • Drupal 7 - SimpleTest (testing) module

    provided as part of core • Drupal 8 - PHPUnit added as a core dependency, later became the default via the PHPUnit initiative • Drupal 9 - SimpleTest removed from core, moved back to contrib @opdavies
  8. Writing Tests (Drupal 8/9) • PHP class with .php extension

    • tests/src directory within each module • Within the Drupal\Tests\module_name namespace • Class name must match the filename • Namespace must match the directory structure • One test class per feature @opdavies
  9. Arrange, Act, Assert @opdavies

  10. Given, When, Then @opdavies

  11. What to test? • Creating nodes with data from an

    API • Calculating attendance figures for an event • Determining if an event is purchasable • Promotions and coupons for new users • Cloning events • Queuing private message requests • Re-opening closed support tickets when comments are added @opdavies
  12. @opdavies

  13. What does a test look like? 1 // web/modules/custom/example/tests/src/Functional. 2

    3 namespace Drupal\Tests\example\Functional; 4 5 use Drupal\Tests\BrowserTestBase; 6 7 class ExampleTest extends BrowserTestBase { 8 9 public function testSomething() { 10 $this->assertTrue(FALSE); 11 } 12 13 } @opdavies
  14. Writing test methods 1 public function testSomething() 2 3 public

    function test_something() 4 5 /** @test */ 6 public function it_does_something() @opdavies
  15. Types of Tests • Functional/FunctionalJavascript (web, browser, feature) • Kernel

    (integration) • Unit @opdavies
  16. Functional Tests • Tests end-to-end functionality • UI testing •

    Interacts with database • Full Drupal installation • Slower to run • With/without JavaScript @opdavies
  17. Kernel tests • Integration tests • Can install modules, interact

    with services, container, database • Minimal Drupal bootstrap • Faster than functional tests • More setup required @opdavies
  18. Unit Tests • Tests PHP logic • No database interaction

    • Fast to run • Need to mock dependencies • Can become tightly coupled • Can be hard to refactor @opdavies
  19. Running Tests @opdavies

  20. Core script $ php core/scripts/run-tests.sh $ php core/scripts/run-tests.sh --module example

    $ php core/scripts/run-tests.sh --class ExampleTest @opdavies
  21. PHPUnit $ vendor/bin/phpunit \ -c core \ modules/contrib/examples/phpunit_example @opdavies

  22. Creating a phpunit.xml file • Configures PHPUnit • Needed to

    run some types of tests • Ignored by Git by default • Copy core/phpunit.xml.dist to core/phpunit.xml • Add and change as needed • SIMPLETEST_BASE_URL, SIMPLETEST_DB, BROWSERTEST_OUTPUT_DIRECTORY • stopOnFailure="true" @opdavies
  23. Example @opdavies

  24. @opdavies

  25. Specification • Job adverts created in Broadbean UI, create nodes

    in Drupal. • Application URL links users to separate application system. • Constructed from domain, includes role ID as a GET parameter and optionally UTM parameters. • Jobs need to be linked to offices. • Job length specified in number of days. • Path is specified as a field in the API. @opdavies
  26. @opdavies

  27. Implementation • Added route to accept data from API as

    XML • Added system user with API role to authenticate • active_for converted from number of days to UNIX timestamp • branch_name and locations converted from plain text to entity reference (job node to office node) • url_alias property mapped to path @opdavies
  28. Incoming data $data = [ 'command' => 'add', 'username' =>

    'bobsmith', 'password' => 'p455w0rd', 'active_for' => '365', 'details' => 'This is the detailed description.', 'job_title' => 'Healthcare Assistant (HCA)', 'locations' => 'Bath, Devizes', 'role_id' => 'A/52/86', 'summary' => 'This is the short description.', 'url_alias' => 'healthcare-assistant-aldershot-june17', // ... ]; @opdavies
  29. Implementation • If no error, create the job node, return

    OK response to Broadbean • If an Exception is thrown, return an error code and message @opdavies
  30. Types of tests • Functional: job nodes are created with

    the correct URL and the correct response code is returned • FunctionalJavaScript: application URL is updated with JavaScript based on UTM parameters (hosting) • Kernel: job nodes can be added and deleted, expired job nodes are deleted, application URL is generated correctly • Unit: ensure number of days are converted to timestamps correctly @opdavies
  31. Results • 0 bugs! • Easier to identify where issues

    occurred and responsibilities • Reduced debugging time • Added more tests for any bugs to prevent regressions @opdavies
  32. Test Driven Development • Write a failing test • Write

    code until the test passes • Refactor • Repeat @opdavies
  33. Red, Green, Refactor @opdavies

  34. Porting Modules to Drupal 8 • Make a new branch

    • Add/update the tests • Write code to make the tests pass • Refactor • Repeat @opdavies
  35. How I Write Tests - "Outside In" • Start with

    functional tests • Drop down to integration or unit tests where needed • Programming by wishful thinking • Write comments first, then fill in the code • Sometimes write assertions first @opdavies
  36. Demo: Building a blog module @opdavies

  37. Acceptance criteria • As a site visitor • I want

    to see a list of published articles at /blog • Ordered by post date, most recent first @opdavies
  38. Tasks • Ensure the blog page exists • Ensure only

    published articles are shown • Ensure the articles are shown in the correct order @opdavies
  39. @opdavies

  40. @opdavies

  41. Thanks! References: • https://opdavi.es/testing-workshop • https://testdrivendrupal.com Me: • https://www.oliverdavies.uk @opdavies