On Github ericmann / two-test-suites
I once worked with a developer who ...
No one wants to be that guy at the conference admitting they've not yet built out a test suite.The Core Framework aims to test the entire WordPress stack
The Core testing framework isn't a unit test suite, it's an integration test suite. It loads the entire WordPress API and communicates actively with a real MySQL database.class Importer { /** * @var Array Mapping of MT usernames to WordPress user IDs */ private $mtnames = array(); /** * Check that the author exists within WordPress and, if not, create it. * * @param String $author * * @return int|\WP_Error */ public function checkauthor( $author ) { $pass = wp_generate_password(); if ( ! isset( $this->mtnames[ $author ] ) ) { $user_id = wp_create_user( $author, $pass ); $this->mtnames[ $author ] = $user_id; } else { $user_id = $this->mtnames[ $author ]; } return $user_id; } }Our test code comes from a MovableType importer. Our object needs to test incoming author names against existing WordPress objects. First things first, it tests to see if we already know of an author - if so, we return the existing ID and move along. If not, we create a new WordPress user, store their ID for later, and return the new entry.
/** * Make sure new authors are created in WordPress */ public function test_checkauthor() { $command = new Importer(); // First author $mary_id = $command->checkauthor( 'maryshelley' ); $mary = \get_user_by( 'id', $mary_id ); $this->assertEquals( 'maryshelley', $mary->user_login ); // Second author $jane_id = $command->checkauthor( 'janeausten' ); $this->assertNotEquals( $mary_id, $jane_id ); // Repeat first $mary_redux = $command->checkauthor( 'maryshelley' ); $this->assertEquals( $mary_id, $mary_redux ); }We test our checkauthor() function by requesting authors that should be in the database. If a user doesn't exist, a new entry is created. We want to verify new entries are created each time and are unique. We'll test against a real WordPress database.
Two sides of the same coin ...
Integration testing and unit testing are different, but share many of the same goals: preventing regressions, ensuring proper behavior, and documenting potential side-effects.WP_Mock tests only your code, not its environment
WPMock isn't an integration testing suite, its goal is to separate your code into the smallest _units possible and test them individually.class Importer { /** * @var Array Mapping of MT usernames to WordPress user IDs */ private $mtnames = array(); /** * Check that the author exists within WordPress and, if not, create it. * * @param String $author * * @return int|\WP_Error */ public function checkauthor( $author ) { $pass = wp_generate_password(); if ( ! isset( $this->mtnames[ $author ] ) ) { $user_id = wp_create_user( $author, $pass ); $this->mtnames[ $author ] = $user_id; } else { $user_id = $this->mtnames[ $author ]; } return $user_id; } }For comparison's sake, we're going to use the same code as before. This way, we compare apples to apples when viewing the two different test paradigms.
/** * Make sure new authors are created in WordPress */ public function test_checkauthor() { \WP_Mock::wpFunction( 'wp_generate_password', array( 'times' => 3, 'return' => 'password', ) ); \WP_Mock::wpFunction( 'wp_create_user', array( 'times' => 2, 'return_in_order' => array( 1, 2 ), ) ); $command = new Importer(); // First author $mary_id = $command->checkauthor( 'maryshelley' ); $this->assertEquals( 1, $mary_id ); // Second author $jane_id = $command->checkauthor( 'janeausten' ); $this->assertNotEquals( $mary_id, $jane_id ); // Repeat first $mary_redux = $command->checkauthor( 'maryshelley' ); $this->assertEquals( $mary_id, $mary_redux ); }We test the same function as before, but this time we use WPMock to _mock WordPress' API. There is no wp_generate_password() or wp_create_user() function, so we have to program the implementations.