Slide 1

Slide 1 text

Hack With Me: Unit and Behavioral Tests PDXWP APRIL 27, 2013

Slide 2

Slide 2 text

Who am I? @MAXCUTLER HTTP://WWW.MAXCUTLER.COM

Slide 3

Slide 3 text

Why write tests? Verify functionality Validate technical design Protect against regressions Refactor with confidence Documentation

Slide 4

Slide 4 text

Unit testing

Slide 5

Slide 5 text

What is a unit?

Slide 6

Slide 6 text

But, what about the rest? Integration testing Acceptance testing Behavioral testing

Slide 7

Slide 7 text

Code coverage How much of the non-test code is exercised by test cases 100% coverage? Depends on project priorities Pragmatic, not dogmatic WordPress core has plenty of room for improvement ◦ Patches!

Slide 8

Slide 8 text

Code coverage

Slide 9

Slide 9 text

Frameworks PHP: PHPUnit, SimpleTest, Behat JavaScript: QUnit, Jasmine, Mocha And many more, for almost every programming language For UI automation: Selenium, Watir For headless browser testing: Phantom.js

Slide 10

Slide 10 text

PHPUnit HTTP://PHPUNIT.DE

Slide 11

Slide 11 text

Anatomy of a test Class extending PHPUnit_Framework_TestCase At least one test method Optional setUp and tearDown ◦ Shared among all test methods in the class setUp testMethod •Assertion 1 •Assertion 2 •… tearDown

Slide 12

Slide 12 text

Anatomy of a test

Slide 13

Slide 13 text

Assertions assertArrayHasKey() assertClassHasAttribute() assertClassHasStaticAttribute() assertContains() assertContainsOnly() assertContainsOnlyInstancesOf() assertCount() assertEmpty() assertEqualXMLStructure() assertEquals() assertFalse() assertFileEquals() assertFileExists() assertGreaterThan() assertGreaterThanOrEqual() assertInstanceOf() assertInternalType() assertJsonFileEqualsJsonFile() assertJsonStringEqualsJsonFile() assertJsonStringEqualsJsonString() assertLessThan() assertLessThanOrEqual() assertNull() assertObjectHasAttribute() assertRegExp() assertStringMatchesFormat() assertStringMatchesFormatFile() assertSame() assertSelectCount() assertSelectEquals() assertSelectRegExp() assertStringEndsWith() assertStringEqualsFile() assertStringStartsWith() assertTag() assertThat() assertTrue() assertXmlFileEqualsXmlFile() assertXmlStringEqualsXmlFile() assertXmlStringEqualsXmlString() expectOutputString() setExpectedException()

Slide 14

Slide 14 text

Data providers

Slide 15

Slide 15 text

Stubs & Mocks When testing a unit, replace any dependencies with fakes that are fully under control of the test Stubs ◦ Replaces all methods with stubs ◦ You configure return values of any methods Mocks ◦ Verify the behavior of interactions between unit and other objects ◦ Beware of coupling test to implementation

Slide 16

Slide 16 text

Running tests Usage: phpunit [switches] UnitTest [UnitTest.php] phpunit [switches] --filter Filter which tests to run. --group ... Only runs tests from the specified group(s). --exclude-group ... Exclude tests from the specified group(s). --list-groups List available test groups. --repeat Runs the test(s) repeatedly. --colors Use colors in output. --stderr Write to STDERR instead of STDOUT. --stop-on-error Stop execution upon first error. --stop-on-failure Stop execution upon first error or failure. --stop-on-skipped Stop execution upon first skipped test. --stop-on-incomplete Stop execution upon first incomplete test. --strict Run tests in strict mode. -v|--verbose Output more verbose information. --debug Display debbuging information during test execution. --process-isolation Run each test in a separate PHP process. --bootstrap A "bootstrap" PHP file that is run before the tests. -c|--configuration Read configuration from XML file. --no-configuration Ignore default configuration file (phpunit.xml). --include-path Prepend PHP's include_path with given path(s). -d key[=value] Sets a php.ini value. -h|--help Prints this usage information. --version Prints the version and exits. --debug Output debugging information.

Slide 17

Slide 17 text

Running tests Command-line IDE Integrations ◦ PHPStorm ◦ Eclipse ◦ Netbeans ◦ Sublime Text 2 ◦ … Continuous Integration Servers ◦ Jenkins ◦ Travis ◦ …

Slide 18

Slide 18 text

WordPress testing

Slide 19

Slide 19 text

WordPress Core Unit Tests http://make.wordpress.org/core/handbook/automated-testing/ On WP Core trac ◦ “Unit Tests” component ◦ “needs-unit-tests” keyword Jenkins CI ◦ http://jenkins.kpayne.co:8080 ◦ Automatically runs unit tests after commits ◦ Provides pass/fail history, code coverage, automatic code documentation, and more

Slide 20

Slide 20 text

Organization Base classes ◦ WP_UnitTestCase ◦ WP_Ajax_UnitTestCase ◦ WP_XMLRPC_UnitTestCase WP_UnitTest_Factory ◦ Use to create data for tests ◦ WP_UnitTest_Factory_For_* ◦ Post, Attachment, User, Term, Blog, Comment ◦ create, create_and_get, create_many Annotations: ◦ @group ◦ @ticket Mocks: ◦ MockAction ◦ MockPHPMailer ◦ WP_Image_Editor_Mock

Slide 21

Slide 21 text

WP_UnitTestCase setUp ◦ Open database connection ◦ Create WP_UnitTest_Factory ◦ Clean up global scope ◦ Clear $_GET, $_POST, flush object cache ◦ Beware global scope – avoid constants (see multisite, ajax) ◦ Start a DB transaction tearDown ◦ Rollback the DB transaction Correlates @ticket annotation to Trac tickets and skips tests for known issues ◦ Works for Core, Unit Tests, and Plugin tickets

Slide 22

Slide 22 text

How can you help? Fix failing test cases Improve code coverage Write patches for core tickets that are causing skipped/failed tests ◦ needs-unit-tests tickets ◦ Tests for any core bugs Does your plugin use a core API or action? Write a test for it so that core devs do not unintentionally break your use-case. Write tests for your plugins!