Modifying legacy code the right way (hint: do not add "if" statements)
So you're a developer and you're asked to make a "simple" change to a Drupal site requiring a code change in a custom 200-line legacy function which uses global variables, calls the dreaded arg() function, and for good measure, communicates with a third-party API via REST.
If your team requires that even small changes need automated tests, you need a straightforward way to test monster legacy functions with minimal effort, minimal refactoring, and minimal risk.
In this talk, we'll discuss:
- why unit testing is preferable to functional testing for testing large functions: every if statement in a function doubles its possible scenarios, which can add up to hundreds of test cases, too long for functional testing which requires bootstrapping Drupal for every test;
- why you should add new testable functions rather than control statements to existing functions;
- how to convert a legacy function into a class method, extract externalities (anything which requires external systems or bootstrapping Drupal), into their own class methods;
- how to create a simple mock object where all externalities return mock data, allowing lightning-fast tests by calling your function repeatedly without bootstrapping Drupal;
- how to use PHPUnit's mocking capabilities to generate mock objects on the fly;
- how to sell testing to your team and organization by making best practices part of your definition of done.