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.

(This talk was initially given at Drupal North 2016, slides can be found here.)

Resources:

Session track: 
Session skill level: 
Session speaker(s): 
Session time slot: 
Session room: