Developing a better functional tests dedicated WordPress module for Codeception - 00

Rethinking the functional tests dedicated module of wp-browser.

Current solution is not ideal

The wp-browser library has offered, for some time now, the WordPress module in trying to offer a solution to lack of real functional tests solution in the WordPress context.
The current module falls short of its expectations not offering one of the main benefits of functional tests: to have the tested code, WordPress in this instance, defined in the same scope as the tests for it.
In code terms it means I should be able to do this in a functional test method:

function test_api_requests_are_logged(FunctionalTester $I) {
    $I->sendGET('/wp-json/wp/v2/posts');

    // this is a WordPress function!
    $logged = get_option('api_calls');
    $I->assertEquals(1, count($logged));
    $I->assertEquals('/wp-json/wp/v2/posts', $logged[0]);
}

Where the first line of code, $I->sendGET('/wp-json/wp/v2/posts');, looks like a line from an acceptance test and the following lines like PHPUnit assertions.
The power of the test method above is clear in the use of the get_option() function; such use of WordPress provided and defined functions, and objects, is possible in “WordPress unit” and integration tests using the WPLoader module, but not in the current implementation of the WordPress module.
This creates a gap between low-level unit and integration tests and acceptance tests; that gap is the one where I would be able, in a test, to hit an endpoint of my WordPress application (the main index.php file, an API endpoint, the wp-admin/admin-ajax.php file, et cetera) as a client UI or application would and tap into the implementation internals to verify state changes with knowledge of the architecture and code flow.

A difficult client

There are two main reasons to the now available WordPress module not being able to support code like the one above:

  1. functional tests rely on the code to be able to handle more than one request per run; WordPress reliance on side effects like constants and globals does not allow that especially when changing the request context (e.g. administration area to non administration area)
  2. WordPress reliance on constants, exit and die functions, and a general “owning” of the global space, makes it very invasive toward its variable scope; this opens the door to many issues when mixing with the test code

The pain points outlined above were too much to tackle in my first iteration of the module but I’m willing to try another run.
I will put some effort on a “WordPress functional module” version 2 in the near future; the goal is to be able to write code like the one above and other, trickier, code.

Why does WordPress needs a functional test module, again?

The purpose of functional testing is to exercise the code the same way a client would do and check on the internal state changes; the code snippet above is a short but good example of it.
Using the WPDb module I could have made the same assertion about the presence and content of the option but not all cases are that easy; the footprint of a request handling on the database might be pervasive and complex enough to make writing and maintaining the test code an exercise in duplication and redundancy.
Complex classes and methods could offer a façade for very complex queries and interpolations and being able to use them in code serves a three-fold purpose:

  1. keeping the code DRY
  2. implicit testing of the code
  3. greater abstraction in tests allowing high-level functions to still tap into low-level and implementation specific internals

Next

I will work on the new module in a branch publishing a post when I get some relevant update.