Download - Automated Testing in WordPress, Really?!
Automated Testing in
WordPress,Really?!
Rate this talk: https://joind.in/10115
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
Ptah (Pirate) Dunbar
● Started with WordPress and PHP in ‘05
● Contributing developer toWordPress, BuddyPress, bbPress
● Full stack Web Developer
● Architect at LiveNinja.com
● WPMIA co-organizer and SoFloPHP member
☠ Became Pirate Dunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
Ptah (Pirate) Dunbar
● Started with WordPress and PHP in ‘05
● Contributing developer toWordPress, BuddyPress, bbPress
● Full stack Web Developer
● Architect at LiveNinja.com
● WPMIA co-organizer and SoFloPHP member
☠ Became Pirate Dunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Started with WordPress and PHP in ‘05
● Contributing developer toWordPress, BuddyPress, bbPress
● Full stack Web Developer
● Architect at LiveNinja.com
● WPMIA co-organizer and SoFloPHP member
☠ Became Pirate Dunbar
Ptah (Pirate) Dunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Understand automated testing concepts,ideas and best practices.
● Learn PHPUnit basics and the WordPress testsuite.
● Resources and homework
Agenda
In one hour
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress powers
1 in 5 websites
source: http://w3techs.com/blog/entry/wordpress_powers_1_in_5_websites
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress community
28,5102,177
source: http://w3techs.com/blog/entry/wordpress_powers_1_in_5_websites
#dc4d - Automated Testing in WordPress with @ptahdunbar
“The result is that a lot of the plugins are written in poor code and turn out to be poorly compatible with other plugins”
— Yoast
http://yoast.com/plugin-future/
Fail.
#dc4d - Automated Testing in WordPress with @ptahdunbar
● WP_DEBUG
● var_dump();
● print_r();
● error_log();
● debug_backtrace();
Manual Testing
Pull out the tools
#dc4d - Automated Testing in WordPress with @ptahdunbar
● WP_DEBUG
● var_dump();
● print_r();
● error_log();
● debug_backtrace();
Manual Testing
Pull out the tools
Ad-hoc & Temporary
#dc4d - Automated Testing in WordPress with @ptahdunbar
● WP_DEBUG
● var_dump();
● print_r();
● error_log();
● debug_backtrace();
Manual Testing
SLOW & Error Prone
Pull out the tools
#dc4d - Automated Testing in WordPress with @ptahdunbar
● WP_DEBUG
● var_dump();
● print_r();
● error_log();
● debug_backtrace();
Pull out the tools
Manual Testing
Doesn’t scale
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
A scripted process that invokes your app to test
features and compares the outcome with expected
results.
Automated Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
Persistent var_dumps();
Automated Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
Better than checking the logs
Automated Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
The Bigger Picture
Automated Testing
Continuous Integration
Continuous Delivery
TDD
BDD
Agile
Scrum
Continuous InspectionReleasing early, releasing often
Phingvagrant
#dc4d - Automated Testing in WordPress with @ptahdunbar
Getting started
Automate Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
There are so many
Frameworks
CHOOSE YOUR FRAMEWORK
#dc4d - Automated Testing in WordPress with @ptahdunbar
CHOOSE YOUR FRAMEWORK
PHPUnithttp://phpunit.de/manual/
Sebastian Bergmann
#dc4d - Automated Testing in WordPress with @ptahdunbar
vim composer.json && composer update
{ "require-dev": {
"phpunit/phpunit": "3.7.*",
"phpunit/phpunit-selenium" : "*",
}
}
http://getcomposer.org
#dc4d - Automated Testing in WordPress with @ptahdunbar
$>./vendor/bin/phpunit
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
Terminology
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Test CaseA set of conditions that you set up in order to assert expected outcome.
PHPUnit
Terminology
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
Terminology
● Test CaseA set of conditions that you set up in order to assert expected outcome.
● Test ClassA collection of test cases, extends PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
Terminology
● Test CaseA set of conditions that you set up in order to assert expected outcome.
● Test ClassA collection of test cases, extends PHPUnit
● Test SuiteA collection of test classes
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?php// test classclass CalTest extends PHPUnit_Framework_TestCase{
// test case public function testAddReturnsSumOfTwoPositiveIntegers() { // assert stuff. }}
PHPUnit
TEST CLASS
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?php// test classclass CalTest extends PHPUnit_Framework_TestCase{
// test case public function testAddReturnsSumOfTwoPositiveIntegers() { // assert stuff. }}
PHPUnit
TEST CLASS
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/loader.phpincludes/
admin.phpapi.php…
phpunit.xmltests/
adminTest.phpApiTest.php…
…
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/loader.phpincludes/
admin.phpfunctions.php…
phpunit.xmltests/
integration/…
acceptance/…
…
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="tests"> <directory suffix="Test.php">tests/</directory> </testsuite> </testsuites></phpunit>
PHPUnit
phpunit.xml - configuration file for PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="tests"> <directory suffix="Test.php">tests/</directory> </testsuite> </testsuites></phpunit>
PHPUnit
phpunit.xml
Configure your test suite location
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="integration"> <directory suffix="Test.php">tests/integration</directory> </testsuite> <testsuite name="acceptance"> <directory suffix="Test.php">tests/acceptance</directory> </testsuite> </testsuites></phpunit>
PHPUnit
phpunit.xml
Configure your test suite location
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="vendor/autoload.php"> <testsuites> <testsuite name="tests"> <directory suffix="Test.php">tests/</directory> </testsuite> </testsuites></phpunit>
PHPUnit
phpunit.xml
Bootstrap file is included before any tests run
#dc4d - Automated Testing in WordPress with @ptahdunbar
Assertions
PHPUnit
Explicitly check expected outcomeagaisnt actual outcome.
#dc4d - Automated Testing in WordPress with @ptahdunbar
Assertions
PHPUnit
Explicitly check expected outcomeagaisnt actual outcome.
$this->assertTrue(condition);
#dc4d - Automated Testing in WordPress with @ptahdunbar
Arrange, Act, Assert
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
function testThatItsTestingTime(){
}
1. A
2. A
3. A
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
function testThatItsTestingTime(){
}
1. A
2. A
3. Assert (check for the expected behavior)
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
function testThatItsTestingTime(){
}
1. A
2. Act (call the method/trigger the action)
3. Assert (check for the expected behavior)
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
function testThatItsTestingTime(){
}
1. Arrange (the context/dependencies)
2. Act (call the method/trigger the action)
3. Assert (check for the expected behavior)
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
Example
PHPUnit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
// Act
// Assert
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
// Act
// Assert
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
// Act
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
// Act $result = $calculator->add(1,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(1,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(1,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(1,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(1,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(2,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(2,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass CalTest extends PHPUnit_Framework_TestCase{ public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange
$calculator = new Calculator();
// Act $result = $calculator->add(2,2);
// Assert $this->assertEquals(3, $result);
}}
PHPUnit
plugin/tests/unit/calTest.php
./vendor/bin/phpunit
Failed asserting that 4 equals 3
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange
// Act
// Assert
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange
// Act
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
./vendor/bin/phpunit
Time: 248ms, Memory: 1.95Mb
OK: (1 test, 1 assertions)
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveNinja\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveRacoons\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveRacoons\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveRacoons\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
Failed asserting that false equals true
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
ASSERTIONSAppendix: http://phpunit.de/manual/3.7/en/appendixes.assertions.html
PHPUnit
Use the most specific assertion possible
● assertTrue();
● assertEquals();
● assertContains();
● assertGreaterThan();
● assertNotNull();
● assertFalse();
● assertNotEquals();
● assertContainsOnly();
● assertLessThan();
● assertSame();
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
There was 1 failure:
1) Tests_Basic::test_readmereadme.html's version needs to be updated to 3.9.Failed asserting that '3.8' matches expected '3.9'.
/private/tmp/wordpress-tests/tests/phpunit/tests/basic.php:29
FAIL
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
There was 1 failure:
1) Tests_User_Author::test_get_the_authorFailed asserting that two objects are equal.--- Expected+++ Actual@@ @@ WP_User Object ( 'data' => stdClass Object (- 'ID' => '3'- 'user_login' => 'User 1'- 'user_pass' => '$P$BpIqOzMNRGZNy9qxKL/3cCDCMe85o2.'- 'user_nicename' => 'user-1'- 'user_email' => '[email protected]'+ 'ID' => '2'+ 'user_login' => 'test_author'+ 'user_pass' => '$P$BUdMebxEjJ23.6LbH9ujvVUFBsUuZv/'+ 'user_nicename' => 'test_author'+ 'user_email' => '[email protected]' 'user_url' => '' 'user_registered' => '2013-12-20 15:31:01' 'user_activation_key' => '' 'user_status' => '0'- 'display_name' => 'User 1'+ 'display_name' => 'test_author' )- 'ID' => 3+ 'ID' => 2 'caps' => Array (- 'subscriber' => true+ 'author' => true ) 'cap_key' => 'wptests_capabilities' 'roles' => Array (- 0 => 'subscriber'+ 0 => 'author' ) 'allcaps' => Array ( 'read' => true 'level_0' => true- 'subscriber' => true+ 'upload_files' => true+ 'edit_posts' => true+ 'edit_published_posts' => true+ 'publish_posts' => true+ 'level_2' => true+ 'level_1' => true+ 'delete_posts' => true+ 'delete_published_posts' => true+ 'author' => true ) 'filter' => null )
/private/tmp/wordpress-tests/tests/phpunit/tests/user/author.php:50
FAIL
#dc4d - Automated Testing in WordPress with @ptahdunbar
PHPUnit
There was 1 failure:
1) Tests_User_Author::test_get_the_authorFailed asserting that two objects are equal.--- Expected+++ Actual@@ @@ WP_User Object ( 'data' => stdClass Object (- 'ID' => '3'- 'user_login' => 'User 1'- 'user_pass' => '$P$BpIqOzMNRGZNy9qxKL/3cCDCMe85o2.'- 'user_nicename' => 'user-1'- 'user_email' => '[email protected]'+ 'ID' => '2'+ 'user_login' => 'test_author'+ 'user_pass' => '$P$BUdMebxEjJ23.6LbH9ujvVUFBsUuZv/'+ 'user_nicename' => 'test_author'+ 'user_email' => '[email protected]' 'user_url' => '' 'user_registered' => '2013-12-20 15:31:01' 'user_activation_key' => '' 'user_status' => '0'- 'display_name' => 'User 1'+ 'display_name' => 'test_author' )- 'ID' => 3+ 'ID' => 2 'caps' => Array (- 'subscriber' => true+ 'author' => true ) 'cap_key' => 'wptests_capabilities' 'roles' => Array (- 0 => 'subscriber'+ 0 => 'author' ) 'allcaps' => Array ( 'read' => true 'level_0' => true- 'subscriber' => true+ 'upload_files' => true+ 'edit_posts' => true+ 'edit_published_posts' => true+ 'publish_posts' => true+ 'level_2' => true+ 'level_1' => true+ 'delete_posts' => true+ 'delete_published_posts' => true+ 'author' => true ) 'filter' => null )
/private/tmp/wordpress-tests/tests/phpunit/tests/user/author.php:50
FAIL
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertTrue($user instanceof ‘\LiveRacoon\User\Entity’);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertInstanceOf(‘\LiveNinja\User\Entity’, $user);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertInstanceOf(‘\LiveNinja\User\Entity’, $user);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithValidUserdataReturnsUserObject() {
// Arrange$service = new \LiveNinja\User\Service;$validUserdata = [...];
// Act$user = $service->persist($validUserdata);
// Assert$this->assertInstanceOf(‘\LiveNinja\User\Entity’, $user);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
./vendor/bin/phpunit
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
#dc4d - Automated Testing in WordPress with @ptahdunbar
<?phpclass UserServiceTest extends PHPUnit_Framework_TestCase{ public function testPersistWithInvalidUserdataReturnsWPError() {
// Arrange$service = new \LiveNinja\User\Service;$invalidUserdata = [];
// Act$user = $service->persist($invalidUserdata);
// Assert$this->assertInstanceOf(‘WP_Error’, $user);
}
//…}
PHPUnit
plugin/tests/unit/LiveNinja/User/ServiceTest.php
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress with Testshttp://develop.svn.wordpress.org/trunk/
1858 Tests, 8611 Assertions, 2.59 minutes
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
Getting started
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress Testsuite
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="tests/bootstrap-wp.php"> <testsuites> <testsuite name="tests"> <directory suffix="Test.php">tests/</directory> </testsuite> </testsuites></phpunit>
#dc4d - Automated Testing in WordPress with @ptahdunbar
WordPress Testsuite
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="tests/bootstrap-wp.php"> <testsuites> <testsuite name="tests"> <directory suffix="Test.php">tests/</directory> </testsuite>
<testsuite name="integration"> <directory suffix="Test.php">integration/</directory> </testsuite> </testsuites></phpunit>
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/PluginTest.php
<?phpclass PluginTest extends PHPUnit_Framework_TestCase{ // test cases...}
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/PluginTest.php
<?phpclass PluginTest extends WP_UnitTestCase{ // test cases...}
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
$>./vendor/bin/phpunit
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
Run Testsinside of an isolated
WordPress Environment
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
ConfigureWordPressOptions
$GLOBALS['wp_tests_options'] = ['active_plugins' => [
'hello.php',...
],'current_theme' => 'kubrick',...
];
bootstrap.php
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
ConfigureWordPress
Includesfunction __muplugins_loaded(){
// code and stuff.require_once 'env-debug.php';
}tests_add_filter('muplugins_loaded', '__muplugins_loaded');
bootstrap.php
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Navigate to site URL (Updates globals)$this->get_url($url);
● Test WP_Query for Conditionals (is_page, is_single, is_404)$this->assertQueryTrue($arg1, $arg2, ...);
● Test for Errors$this->assertWPError($thing);
● Genereate WordPress data fixtures$this->factory->post->create_and_get();
$this->factory->comment->create_post_comments($pid, 100);
$this->factory->user->create_many(5);
$this->factory->blog->create();
and more…
WordPress Testsuite
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange
// Act
// Assert
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange
// Act
// Assert$this->assertQueryTrue( 'is_404' );
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange$customWP = new WPCustomization;$this->factory->post->create(['post_date' => '2007-09-04 00:00:00']);
// Act$customWP->deprecate_unused_pages();$this->go_to('/2007/');
// Assert$this->assertQueryTrue( 'is_404' );
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange$customWP = new WPCustomization;$this->factory->post->create(['post_date' => '2007-09-04 00:00:00']);
// Act$customWP->deprecate_unused_pages();$this->go_to('/2007/');
// Assert$this->assertQueryTrue( 'is_404' );
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange$customWP = new WPCustomization;$this->factory->post->create(['post_date' => '2007-09-04 00:00:00']);
// Act$customWP->deprecate_unused_pages();$this->go_to('/2007/');
// Assert$this->assertQueryTrue( 'is_404' );
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange$customWP = new WPCustomization;$this->factory->post->create(['post_date' => '2007-09-04 00:00:00']);
// Act$customWP->deprecate_unused_pages();$this->go_to('/2007/');
// Assert$this->assertQueryTrue( 'is_404' );
}}
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
// test casesfunction testRedirectForDateBasedPermalinks(){
// Arrange$customWP = new WPCustomization;$this->factory->post->create(['post_date' => '2007-09-04 00:00:00']);
// Act$customWP->deprecate_unused_pages();$this->go_to('/2007/');
// Assert$this->assertQueryTrue( 'is_404' );
}}
./vendor/bin/phpunit
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getRequiredPlugins */function testAllRequiredPluginsAreActive($plugin){
// Assert$this->assertTrue( is_plugin_active($plugin),
sprintf('%s is not activated.', $plugin) );}
function getRequiredPlugins(){
return [[‘hello.php’],
];}
}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getRequiredPlugins */function testAllRequiredPluginsAreActive($plugin){
// Assert$this->assertTrue( is_plugin_active($plugin),
sprintf('%s is not activated.', $plugin) );}
function getRequiredPlugins(){
return [[‘hello.php’],
];}
}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getRequiredPlugins */function testAllRequiredPluginsAreActive($plugin){
// Assert$this->assertTrue( is_plugin_active($plugin),
sprintf('%s is not activated.', $plugin) );}
function getRequiredPlugins(){
return [[‘hello.php’],
];}
}
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getRequiredPlugins */function testAllRequiredPluginsAreActive($plugin){
// Assert$this->assertTrue( is_plugin_active($plugin),
sprintf('%s is not activated.', $plugin) );}
function getRequiredPlugins(){
return [[‘hello.php’],
];}
}
./vendor/bin/phpunit
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getWPOptions */function testWPOptionSettingsAreConfigured($option_name, $option_value){
// Assert$this->assertSame($option_value, get_option($option_name));
}
function getWPOptions(){
return [[‘home’, ‘http://example.org/wp/’],[‘siteurl’, ‘http://example.org/’],
];}
}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getWPOptions */function testWPOptionSettingsAreConfigured($option_name, $option_value){
// Assert$this->assertSame($option_value, get_option($option_name));
}
function getWPOptions(){
return [[‘home’, ‘http://example.org/wp/’],[‘siteurl’, ‘http://example.org/’],
];}
}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getWPOptions */function testWPOptionSettingsAreConfigured($option_name, $option_value){
// Assert$this->assertSame($option_value, get_option($option_name));
}
function getWPOptions(){
return [[‘home’, ‘http://example.org/wp/’],[‘siteurl’, ‘http://example.org/’],
];}
}
./vendor/bin/phpunit
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/integration/WPCustomizationTest.php
WordPress Testsuite
<?phpclass WPCustomizationTest extends WP_UnitTestCase{
/** * @dataProvider getWPOptions */function testWPOptionSettingsAreConfigured($option_name, $option_value){
// Assert$this->assertSame($option_value, get_option($option_name));
}
function getWPOptions(){
return [[‘home’, ‘http://example.org/wp/’],[‘siteurl’, ‘http://example.org/’],
];}
}
./vendor/bin/phpunit
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
http://www.seleniumhq.org/
#dc4d - Automated Testing in WordPress with @ptahdunbar
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Framework_TestCase{ protected function setUp() { }
public function testUserCanLogInViaTwitter() { }}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { }
public function testUserCanLogInViaTwitter() { }}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { }}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { $this->open("/");
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { $this->open("/"); $this->click("link=Log in"); $this->waitForPageToLoad("30000");
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { $this->open("/"); $this->click("link=Log in"); $this->waitForPageToLoad("30000"); $this->click("css=img[alt=\"Twitter\"]"); $this->waitForPageToLoad("30000");
}}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { $this->open("/"); $this->click("link=Log in"); $this->waitForPageToLoad("30000"); $this->click("css=img[alt=\"Twitter\"]"); $this->waitForPageToLoad("30000"); $this->assertContains( ‘dashboard’, $this->title() ); }}
#dc4d - Automated Testing in WordPress with @ptahdunbar
plugin/tests/acceptance/ConnectTest.php
Acceptance Testing
<?phpclass ConnectTest extends PHPUnit_Extensions_Selenium2TestCase{ protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); }
public function testUserCanLogInViaTwitter() { $this->open("/"); $this->click("link=Log in"); $this->waitForPageToLoad("30000"); $this->click("css=img[alt=\"Twitter\"]"); $this->waitForPageToLoad("30000"); $this->assertContains( ‘dashboard’, $this->title() ); }}
Time: 148ms, Memory: 2.75Mb
OK: (1 test, 1 assertions)
#dc4d - Automated Testing in WordPress with @ptahdunbar
Acceptance
Selenium IDE Plugin
● Visually navigate throughout your site and generate a PHPUnittest case.
● Download Extension○ http://www.seleniumhq.
org/projects/ide/
● Download PHPUnit Formatter○ https://addons.mozilla.org/en-
US/firefox/addon/selenium-ide-php-formatters/
#dc4d - Automated Testing in WordPress with @ptahdunbar
Acceptance
Selenium IDE Plugin
● Visually navigate throughout your site and generate a PHPUnittest case.
● Download Extension○ http://www.seleniumhq.
org/projects/ide/
● Download PHPUnit Formatter○ https://addons.mozilla.org/en-
US/firefox/addon/selenium-ide-php-formatters/
#dc4d - Automated Testing in WordPress with @ptahdunbar
How can we be confident that our tests
cover everything?
#dc4d - Automated Testing in WordPress with @ptahdunbar
Testing boundaries
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
○ Verify that all features are done done.
○ Black-box testing, no knowledge of internals.
Testing boundaries
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
○ Verify that all features are done done.
○ Black-box testing, no knowledge of internals.
● Integration Testing
○ Test WordPress settings/configuration;
○ Compatibility between plugins and themes.
Testing boundaries
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
○ Verify that all features are done done.
○ Black-box testing, no knowledge of internals.
● Integration Testing
○ Test WordPress settings/configuration,
○ Compatibility between plugins and themes
● Unit Testing
○ Test class methods and functions in isolation, zero dependencies
○ Does one “behavoir”
Testing boundaries
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
Verify that all features are done done,
black-box testing, no knowledge of
internals
● Integration Testing
Test WordPress settings/configuration,
compatibility between plugins and
themes
● Unit Testing
Test class methods and functions in
isolation, zero dependencies,
does one “behavoir”.
Testing boundaries
AcceptanceTesting
Integration Testing
Unit Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
Verify that all features are done done,
black-box testing, no knowledge of
internals
● Integration Testing
Test WordPress settings/configuration,
compatibility between plugins and
themes
● Unit Testing
Test class methods and functions in
isolation, zero dependencies,
does one “behavoir”.
Testing boundaries
AcceptanceTesting
Integration Testing
Unit Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
● (User) Acceptance Testing
Verify that all features are done done,
black-box testing, no knowledge of
internals
● Integration Testing
Test WordPress settings/configuration,
compatibility between plugins and
themes
● Unit Testing
Test class methods and functions in
isolation, zero dependencies,
does one “behavoir”.
Testing boundaries
Integration Testing
Unit Testing
AcceptanceTesting
#ATWP // Automated Testing in WordPress // @ptahdunbar
What to tests?
● Test plugin works in various WordPress setups
○ Does it work under multisite?
○ What about a custom content directory?
● Test all code paths in functions and methods
● Test compatiblity between most popular plugins
● Test that default pages exists
#ATWP // Automated Testing in WordPress // @ptahdunbar
What to tests?
● Test for theme support
● Test that post formats contain property elements
● Test any required assets that need to be loaded in
templates
● Test for required elements on a page
● Verify search results template displays search term
● Verify SEO meta tags
1. WordPress APIs
#ATWP // Automated Testing in WordPress // @ptahdunbar
What to not tests?
#ATWP // Automated Testing in WordPress // @ptahdunbar
What to not tests?
1. WordPress APIs
2. PHP language features
#ATWP // Automated Testing in WordPress // @ptahdunbar
What to not tests?
1. WordPress APIs
2. PHP language features
3. Third party vendor code
Getting into the groove
#ATWP // Automated Testing in WordPress // @ptahdunbar
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
● Build out templates
● Build out templates○ Create HTML/CSS
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
● Build out templates○ Create HTML/CSS○ Identify dynamic elements and their data
structure
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
● Build out templates○ Create HTML/CSS○ Identify dynamic elements and their data
structure○ Label them and fill them with dummy data
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
○ Verbally state your trying to do
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
○ Verbally state your trying to do
○ Verbally explain what the code does
#ATWP // Automated Testing in WordPress // @ptahdunbar
Getting into the groove
○ Verbally state your trying to do
○ Verbally explain what the code does
○ Do this alone or with a fellow dev :)
What’s Next?
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Download WP Skeleton Family
○ https://github.com/ptahdunbar/wp-skeleton-site
○ https://github.com/ptahdunbar/wp-skeleton-plugin
○ https://github.com/ptahdunbar/wp-skeleton-theme
Get started
“A Walking Skeleton is a tiny implementation of the thinnest possible slice of real functionality that we can automatically
build, deploy and test end-to-end.”
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Art of Unit Testing (.NET)
○ https://leanpub.com/u/royosherove
○ Udemy Five day course
● #GOOS Book (Java)
● XUnit Test Patterns (Java)
● Grumpy Books (PHP)
○ https://leanpub.com/u/chartjes
● Misko Hevery
Resources
#dc4d - Automated Testing in WordPress with @ptahdunbar
● Learn moar PHPUnit features
○ data providers,
○ mocks and stubs
○ wordpress testsuite
● Goal: Write at least 100 assertions!
Homework!
TODO
#dc4d - Automated Testing in WordPress with @ptahdunbar
Automated Testing
#dc4d - Automated Testing in WordPress with @ptahdunbar
Automated Testingincreases your productivity
#dc4d - Automated Testing in WordPress with @ptahdunbar
Automated Testingfacilitates more shipping
#dc4d - Automated Testing in WordPress with @ptahdunbar
Automated Testingscales with you
#dc4d - Automated Testing in WordPress with @ptahdunbar
Automated Testingis your professional duty
as a developer
#dc4d - Automated Testing in WordPress with @ptahdunbar
Thank youAutomated Testing in WordPress
Pirate Dunbar@[email protected]
Rate this talk:https://joind.in/10115