• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Automated Testing in WordPress, Really?!
 

Automated Testing in WordPress, Really?!

on

  • 4,460 views

Did you know that WordPress has an automated test suite? It contains well over 1500 integration tests and growing. However one of the primary culprits of WordPress is in the quality of its plugins. ...

Did you know that WordPress has an automated test suite? It contains well over 1500 integration tests and growing. However one of the primary culprits of WordPress is in the quality of its plugins. Most plugins don't have an automated test suite you can run to verify all features are working as expected, and fail gracefully.

In this talk, Ptah will introduce you to automated testing in WordPress using PHPUnit. We will cover concepts like unit testing, integration testing and end-to-end testing with examples in WordPress. You will leave the talk equipped with practical knowledge and ready to start adding an automated test suite to your plugins.

Statistics

Views

Total Views
4,460
Views on SlideShare
4,452
Embed Views
8

Actions

Likes
3
Downloads
25
Comments
0

1 Embed 8

https://twitter.com 8

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Automated Testing in WordPress, Really?! Automated Testing in WordPress, Really?! Presentation Transcript

    • Automated Testing in WordPress, Really?! Rate this talk: https://joind.in/10115 #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Ptah (Pirate) Dunbar ● Started with WordPress and PHP in ‘05 ● Contributing developer to WordPress, 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 to WordPress, 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 to WordPress, 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
    • Agenda In one hour ● Understand automated testing concepts, ideas and best practices. ● Learn PHPUnit basics and the WordPress testsuite. ● Resources and homework #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,510 2,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/ #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Fail.
    • Manual Testing Pull out the tools ● ● ● ● ● WP_DEBUG var_dump(); print_r(); error_log(); debug_backtrace(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Manual Testing Pull out the tools ● ● ● ● ● WP_DEBUG var_dump(); Temporary Ad-hoc & print_r(); error_log(); debug_backtrace(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Manual Testing Pull out the tools ● ● ● ● ● WP_DEBUG var_dump(); Error Prone SLOW & print_r(); error_log(); debug_backtrace(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Manual Testing Pull out the tools ● ● ● ● ● WP_DEBUG var_dump(); Doesn’t scale print_r(); error_log(); debug_backtrace(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing A scripted process that invokes your app to test features and compares the outcome with expected results. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing Persistent var_dumps(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing Better than checking the logs #dc4d - Automated Testing in WordPress with @ptahdunbar
    • The Bigger Picture Continuous Integration vagrant Phing Continuous Delivery BDD Automated Testing Scrum Agile TDD Continuous Inspection Releasing early, releasing often #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automate Testing Getting started #dc4d - Automated Testing in WordPress with @ptahdunbar
    • CHOOSE YOUR FRAMEWORK There are so many Frameworks #dc4d - Automated Testing in WordPress with @ptahdunbar
    • CHOOSE YOUR FRAMEWORK PHPUnit http://phpunit.de/manual/ Sebastian Bergmann #dc4d - Automated Testing in WordPress with @ptahdunbar
    • { "require-dev": { "phpunit/phpunit": "3.7.*", "phpunit/phpunit-selenium" : "*", } } http://getcomposer.org vim composer.json && composer update #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit $>./vendor/bin/phpunit #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Terminology #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Terminology ● Test Case A set of conditions that you set up in order to assert expected outcome. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Terminology ● Test Case A set of conditions that you set up in order to assert expected outcome. ● Test Class A collection of test cases, extends PHPUnit #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Terminology ● Test Case A set of conditions that you set up in order to assert expected outcome. ● Test Class A collection of test cases, extends PHPUnit ● Test Suite A collection of test classes #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit TEST CLASS <?php // test class class CalTest extends PHPUnit_Framework_TestCase { // test case public function testAddReturnsSumOfTwoPositiveIntegers() { // assert stuff. } } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit TEST CLASS <?php // test class class CalTest extends PHPUnit_Framework_TestCase { // test case public function testAddReturnsSumOfTwoPositiveIntegers() { // assert stuff. } } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit plugin/ loader.php includes/ admin.php api.php … phpunit.xml tests/ adminTest.php ApiTest.php … … #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit plugin/ loader.php includes/ admin.php functions.php … phpunit.xml tests/ integration/ … acceptance/ … … #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit phpunit.xml - configuration file for PHPUnit <?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> #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit phpunit.xml <?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> Configure your test suite location #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit phpunit.xml <?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> Configure your test suite location #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit phpunit.xml <?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> Bootstrap file is included before any tests run #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Assertions Explicitly check expected outcome agaisnt actual outcome. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Assertions Explicitly check expected outcome agaisnt actual outcome. $this->assertTrue(condition); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Arrange, Act, Assert #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit function testThatItsTestingTime() { 1. A 2. A 3. A } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit function testThatItsTestingTime() { 1. A 2. A 3. Assert (check for the expected behavior) } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit function testThatItsTestingTime() { 1. A 2. Act (call the method/trigger the action) 3. Assert (check for the expected behavior) } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit function testThatItsTestingTime() { 1. Arrange (the context/dependencies) 2. Act (call the method/trigger the action) 3. Assert (check for the expected behavior) } #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit Example #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange // Act // Assert } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange // Act // Assert } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange // Act // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange // Act $result = $calculator->add(1,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); // Act $result = $calculator->add(1,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); // Act $result = $calculator->add(1,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); Time: 148ms, Memory: 2.75Mb // 1 OK: (1 test, Actassertions) $result = $calculator->add(1,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); // Act $result = $calculator->add(1,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); // Act $result = $calculator->add(2,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); // Act $result = $calculator->add(2,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class CalTest extends PHPUnit_Framework_TestCase { public function testAddReturnsSumOfTwoPositiveIntegers() { // Arrange $calculator = new Calculator(); Failed asserting that 4 equals 3 // Act $result = $calculator->add(2,2); // Assert $this->assertEquals(3, $result); } } plugin/tests/unit/calTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange // Act // Assert } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange // Act // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; Time: 248ms, Memory: 1.95Mb // Act $user = $service->persist($validUserdata); OK: (1 test, 1 assertions) // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveNinjaUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveRacoonsUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveRacoonsUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; Failed asserting that false equals true // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveRacoonsUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit ASSERTIONS Appendix: http://phpunit.de/manual/3.7/en/appendixes.assertions.html Use the most specific assertion possible ● assertTrue(); ● assertFalse(); ● assertEquals(); ● assertNotEquals(); ● assertContains(); ● assertContainsOnly(); ● assertGreaterThan(); ● assertLessThan(); ● assertNotNull(); ● assertSame(); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit FAIL There was 1 failure: 1) Tests_Basic::test_readme readme.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 #dc4d - Automated Testing in WordPress with @ptahdunbar
    • FAIL There was 1 failure: 1) Tests_User_Author::test_get_the_author Failed 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' => 'user_2@example.org' + 'ID' => '2' + 'user_login' => 'test_author' + 'user_pass' => '$P$BUdMebxEjJ23.6LbH9ujvVUFBsUuZv/' + 'user_nicename' => 'test_author' + 'user_email' => 'user_1@example.org' '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 #dc4d - Automated Testing in WordPress with @ptahdunbar 'caps' => Array ( PHPUnit
    • FAIL There was 1 failure: 1) Tests_User_Author::test_get_the_author Failed 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' => 'user_2@example.org' + 'ID' => '2' + 'user_login' => 'test_author' + 'user_pass' => '$P$BUdMebxEjJ23.6LbH9ujvVUFBsUuZv/' + 'user_nicename' => 'test_author' + 'user_email' => 'user_1@example.org' '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 #dc4d - Automated Testing in WordPress with @ptahdunbar 'caps' => Array ( PHPUnit
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertTrue($user instanceof ‘LiveRacoonUserEntity’); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertInstanceOf(‘LiveNinjaUserEntity’, $user); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; // Act $user = $service->persist($validUserdata); // Assert $this->assertInstanceOf(‘LiveNinjaUserEntity’, $user); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar PHPUnit
    • ./vendor/bin/phpunit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithValidUserdataReturnsUserObject() { // Arrange $service = new LiveNinjaUserService; $validUserdata = [...]; Time: 148ms, Memory: 2.75Mb // Act $user = $service->persist($validUserdata); OK: (1 test, 1 assertions) // Assert $this->assertInstanceOf(‘LiveNinjaUserEntity’, $user); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar PHPUnit
    • PHPUnit <?php class UserServiceTest extends PHPUnit_Framework_TestCase { public function testPersistWithInvalidUserdataReturnsWPError() { // Arrange $service = new LiveNinjaUserService; $invalidUserdata = []; // Act $user = $service->persist($invalidUserdata); // Assert $this->assertInstanceOf(‘WP_Error’, $user); } //… } plugin/tests/unit/LiveNinja/User/ServiceTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite
    • WordPress Testsuite WordPress with Tests http://develop.svn.wordpress.org/trunk/ 1858 Tests, 8611 Assertions, 2.59 minutes #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
    • WordPress Testsuite Getting started #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
    • WordPress Testsuite <?php class PluginTest extends PHPUnit_Framework_TestCase { // test cases... } plugin/tests/integration/PluginTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class PluginTest extends WP_UnitTestCase { // test cases... } plugin/tests/integration/PluginTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite $>./vendor/bin/phpunit #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite Run Tests inside of an isolated WordPress Environment #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite bootstrap.php Configure $GLOBALS['wp_tests_options'] = [ 'active_plugins' => [ 'hello.php', ... ], 'current_theme' => 'kubrick', ... ]; WordPress Options #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite Configure bootstrap.php WordPress Includes function __muplugins_loaded() { // code and stuff. require_once 'env-debug.php'; } tests_add_filter('muplugins_loaded', '__muplugins_loaded'); #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite ● 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… #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function testRedirectForDateBasedPermalinks() { // Arrange // Act // Assert } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function testRedirectForDateBasedPermalinks() { // Arrange // Act // Assert $this->assertQueryTrue( 'is_404' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function 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' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function 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' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function 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' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function 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' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { // test cases function testRedirectForDateBasedPermalinks() { // Arrange $customWP = new WPCustomization; $this->factory->post->create(['post_date' => '2007-09-04 00:00:00']); Time: 148ms, Memory: 2.75Mb OK: (1// Act 1 assertions) test, $customWP->deprecate_unused_pages(); $this->go_to('/2007/'); // Assert $this->assertQueryTrue( 'is_404' ); } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class 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’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class 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’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class 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’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { /** * @dataProvider getRequiredPlugins */ function testAllRequiredPluginsAreActive($plugin) { // Assert $this->assertTrue( is_plugin_active($plugin), sprintf('%s is not activated.', $plugin) ); } Time: 148ms, Memory: 2.75Mb OK: (1 test, 1 assertions) function getRequiredPlugins() { return [ [‘hello.php’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class 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/’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • WordPress Testsuite <?php class 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/’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class 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/’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • ./vendor/bin/phpunit WordPress Testsuite <?php class WPCustomizationTest extends WP_UnitTestCase { /** * @dataProvider getWPOptions */ function testWPOptionSettingsAreConfigured($option_name, $option_value) { // Assert $this->assertSame($option_value, get_option($option_name)); } Time: 148ms, Memory: 2.75Mb OK: (1 test, 1 assertions) function getWPOptions() { return [ [‘home’, ‘http://example.org/wp/’], [‘siteurl’, ‘http://example.org/’], ]; } } plugin/tests/integration/WPCustomizationTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • http://www.seleniumhq.org/ #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class ConnectTest extends PHPUnit_Framework_TestCase { protected function setUp() { } public function testUserCanLogInViaTwitter() { } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class ConnectTest extends PHPUnit_Extensions_Selenium2TestCase { protected function setUp() { } public function testUserCanLogInViaTwitter() { } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class ConnectTest extends PHPUnit_Extensions_Selenium2TestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); } public function testUserCanLogInViaTwitter() { } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class ConnectTest extends PHPUnit_Extensions_Selenium2TestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); } public function testUserCanLogInViaTwitter() { $this->open("/"); } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class 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"); } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class 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"); } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class 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() ); } } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Testing <?php class ConnectTest extends PHPUnit_Extensions_Selenium2TestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("https://wpss.dev/"); } Time: 148ms, Memory: 2.75Mb 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() ); } OK: (1 test, 1 assertions) } plugin/tests/acceptance/ConnectTest.php #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Selenium IDE Plugin ● Visually navigate throughout your site and generate a PHPUnit test case. ● Download Extension ○ http://www.seleniumhq. org/projects/ide/ ● Download PHPUnit Formatter ○ https://addons.mozilla.org/enUS/firefox/addon/seleniumide-php-formatters/ #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Acceptance Selenium IDE Plugin ● Visually navigate throughout your site and generate a PHPUnit test case. ● Download Extension ○ http://www.seleniumhq. org/projects/ide/ ● Download PHPUnit Formatter ○ https://addons.mozilla.org/enUS/firefox/addon/seleniumide-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
    • Testing boundaries ● (User) Acceptance Testing ○ Verify that all features are done done. ○ Black-box testing, no knowledge of internals. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Testing boundaries ● (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. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Testing boundaries ● (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” #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Testing boundaries ● (User) Acceptance Testing Verify that all features are done done, black-box testing, no knowledge of Acceptance Testing internals ● Integration Testing Test WordPress settings/configuration, compatibility between plugins and Integration Testing themes ● Unit Testing Unit Testing Test class methods and functions in isolation, zero dependencies, does one “behavoir”. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Testing boundaries ● (User) Acceptance Testing Verify that all features are done done, black-box testing, no knowledge of Acceptance Testing internals ● Integration Testing Test WordPress settings/configuration, compatibility between plugins and Integration Testing themes ● Unit Testing Unit Testing Test class methods and functions in isolation, zero dependencies, does one “behavoir”. #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Testing boundaries ● (User) Acceptance Testing Verify that all features are done done, black-box testing, no knowledge of Acceptance Testing internals ● Integration Testing Test WordPress settings/configuration, compatibility between plugins and Integration Testing themes ● Unit Testing Unit Testing Test class methods and functions in isolation, zero dependencies, does one “behavoir”. #dc4d - Automated Testing in WordPress with @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 #ATWP // Automated Testing in WordPress // @ptahdunbar
    • What to not tests? 1. WordPress APIs #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 #ATWP // Automated Testing in WordPress // @ptahdunbar
    • Getting into the groove #ATWP // Automated Testing in WordPress // @ptahdunbar
    • Getting into the groove ● Build out templates #ATWP // Automated Testing in WordPress // @ptahdunbar
    • Getting into the groove ● Build out templates ○ Create HTML/CSS #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 :) #ATWP // Automated Testing in WordPress // @ptahdunbar
    • What’s Next?
    • 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.” ● 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 #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Resources ● 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 #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Homework! TODO ● Learn moar PHPUnit features ○ data providers, ○ mocks and stubs ○ wordpress testsuite ● Goal: Write at least 100 assertions! #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing increases your productivity #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing facilitates more shipping #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing scales with you #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Automated Testing is your professional duty as a developer #dc4d - Automated Testing in WordPress with @ptahdunbar
    • Thank you Automated Testing in WordPress Pirate Dunbar @ptahdunbar yarr@piratedunbar.com Rate this talk: https://joind.in/10115 #dc4d - Automated Testing in WordPress with @ptahdunbar