effizientere wordpress-plugin-entwicklung mit softwaretests

Post on 18-Dec-2014

655 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Introduction: How to use Unit Testing (TDD) and Behaviour Testing (BDD) for Wordpress, building a Continuous Integration workflow.

TRANSCRIPT

EffizientereWordPress-Plugin-Entwicklung mit

Softwaretests

Martin Schütte

About DECK36

• Small team of 7 engineers• Longstanding expertise in designing, implementing and operatingcomplex web systems

• Developing own data intelligence-focused tools and web services• Offering our expert knowledge in Automation & Operation,Architecture & Engineering, Analytics & Data Logistics

1. Dev & Test Environments

2. Testing VariantsStatic Code AnalysisUnit TestingIntegration TestingBehaviour Testing

3. Integration & Automation

Main Questions

How can I know (my) software is correct?

How does my boss know software is correct?

How do I know software implements a given design?

How can we discuss what “correct” is, anyway?

We always need:• implicit assumptions,• explicit specifications.

Levels of Testing

..

abstract

.

specific

.

Unit Tests

.

Integration Tests

.

AcceptanceTests

Use a DevEnvironment

Vagrant

Configuration tool for (VirtualBox) VMsetup and provisioning.

“Local cloud”• Self service• Instant provisioning

Useful for development• reproducible environment• independent PHP 5.x setups• try things and not jeopardiseyour dev environment

VagrantPress

$ git clone https://github.com/chad-thompson/vagrantpress.git$ cd vagrantpress$ vagrant up

will setup VM with:

• Ubuntu Precise (12.04), Apache 2.2, MySQL 5.5, PHP 5.3• Wordpress 3.8• phpMyAdmin• PHPUnit• phpcs, phploc, phpdepend, …

Testing Variants

Coding Style

$ phpcs --standard=WordPress freifunkmeta.php

FILE: [...]/plugins/freifunkmeta/freifunkmeta.php---------------------------------------------------------------------FOUND 360 ERROR(S) AND 406 WARNING(S) AFFECTING 338 LINE(S)---------------------------------------------------------------------

21 | ERROR | Incorrect indentation; expected 1 space, found 422 | WARNING | Line is indented with space not tab33 | ERROR | String "Unable to retrieve URL %s, error: %s" does

| | not require double quotes; use single quotes instead322 | ERROR | Closing parenthesis of a multi-line function

| | definition must be on a line by itself440 | ERROR | Expected next thing to be a escaping function,

| | not '"<option value='$city' $selected>$prettycity| | </option>"'

Code Metrics

$ php pdepend_summary.php freifunkmeta.php

Package/Class Method LoC %Comment CCN NPath------------- ------ --- -------- --- -----FF_Meta output_ff_contact 49 6.1 10 384FF_Meta shortcode_handler 41 2.4 9 48FF_Community __construct 12 0.0 7 15625FF_Meta register_stuff 18 0.0 5 16FF_Meta aux_get_all_locations 23 8.7 5 6FF_Community make_from_city 15 0.0 4 20[...]

Example Plugin: Freifunkmeta

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

Unit Testing

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

Simple PHPUnit Test Case

class LowLevelTests extends PHPUnit_Framework_TestCase {function setUp() {

$this->FFM = new FF_Meta();}

function test_output_ff_state() {$data = array("state" => array("nodes" => 429));$ret = $this->FFM->output_ff_state($data);$this->assertRegExp('/429/', $ret);

}}

Unit Testing (contd.)

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

Integration Testing

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

Unit Testing with Mock Object

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

Example: Test with Dependency Injection

class MockDataService {function get($url) {

return $some_fixed_data;}

}

class WpIntegrationTests extends WP_UnitTestCase {function setUp() {

parent::setUp();// get plugin instance and replace ext. data service:$this->plugin = $GLOBALS['wp-plugin-ffmeta'];$this->plugin->reset_external_data_service(

new MockDataService() );}

// ...

Example: Test with Dependency Injection

// ...function test_post_ff_services() {

$post_attribs = array('post_title' => 'Test','post_content' => '[ff_services]' );

$post = $this->factory->post->create_and_get($post_attribs );

// w/o filter:$this->assertEquals($post_content, $post->post_content);

// with filter:$output = apply_filters( 'the_content',

$post->post_content );$this->assertRegExp('/radio\.ffhh/', $output);

}}

PHPUnit Output

Behaviour Testing

..WP Blog.

FF_Meta

.

WP Core

.

Other Plugins

.

FF_Community

.

FF_Dir

.

OutputFormatter

.

HTTP GetService

WordPress Shortcode Plugin Test..

Feature: Use ShortcodesIn order to use my PluginAs a website authorI need to write posts with shortcodes

Background:Given I am logged in as "admin" with "vagrant"

Scenario: Without the pluginGiven the plugin "freifunkmeta" is "inactive"When I write a post with title "test" and content "[ff_contact]"Then I should see "ff_contact"

Scenario: With the pluginGiven the plugin "freifunkmeta" is "active"When I write a post with title "test" and content "[ff_contact]"Then I should see "Twitter" in the ".ff_contact" elementAnd I should not see "ff_contact"

Behat Output

Implementation / Translation

A look behind the curtain:• framework is clever but not magical• some translation needed• statements have to become executable code

Mechanism:• plain sentence → method name• quoted words → arguments• matching with annotated regular expressions• methods yield success, exception, or pending exception

Example: Behat Context (PHP)

/*** from MinkContext* Checks, that page contains specified text.** @Then /^(?:|I )should see "(?P<text>(?:[^"]|\\")*)"$/*/

public function assertPageContainsText($text){

$this->assertSession()->pageTextContains($this->fixStepArgument($text));

}

The Big Picture

..Features.

Step Definitions

.

WebDriver

.

Browser

The Big Picture

..Features.

Behat (PHP)

.

cucumber.js

.

Cucumber(Ruby)

.

PhantomJS

.

Goutte

.

Selenium

.

Firefox

.

Chrome

Unit & Behaviour Testing

Unit Tests• unit testing• programmers• programming language• bottom-up• assertXYZ• tests derived from user stories

⇒ development tool

Behaviour Tests• acceptance test scenarios• non-developers• language of business domain• top-down / outside-in• X should do Y• execute user stories

⇒ design & communication tool

Automate!

Scripting

Basis for all automation.Lots of useful builtins and packages:

• wp core download/install/config/…• wp export/import• wp plugin get/install/update/…• wp scaffold _s/plugin/plugin-tests• wp server

wp scaffold

Generate skeleton code for a new plugin & unit tests:

$ cd wordpress/wp-content/plugins$ wp scaffold plugin-tests awesome$ find awesomeawesome/awesome/awesome.phpawesome/binawesome/bin/install-wp-tests.shawesome/testsawesome/tests/bootstrap.phpawesome/tests/test-sample.phpawesome/.travis.ymlawesome/phpunit.xml

wp scaffold (contd.)

Create WP instance and run unit tests:$ cd awesome$ bash ./bin/install-wp-tests.sh wp_tests root vagrant latest...$ phpunitPHPUnit 4.0.17 by Sebastian Bergmann.[...]

Configuration read from [...]/plugins/awesome/phpunit.xml

.

Time: 5.52 seconds, Memory: 23.50Mb

OK (1 test, 1 assertion)

Version Control

• use version control!• many possible workflows,e. g. branches for dev and release

• use pre-commit hooks,e. g. with php -l syntax check

Travis-CI

Continuous Integration service for GitHub1. gets notified on push

2. builds project

3. runs phpunit

4. summarizes results,alert on failure

Example .travis.yml

language: php

php:- 5.4- 5.5- hhvm

env:- WP_VERSION=3.8.3- WP_VERSION=latest

before_script:- bash bin/install-wp-tests.sh wordpress_test \

root '' localhost $WP_VERSION

script: phpunit

Automated Testing

Target: no manual effort.

Continuous Integration:• frequent code check-ins• verified by automatedbuilds and tests

• quickly find bugsand regressions

Continuous Deployment:• (semi-)automated deployment• plan for rollback

Costs and Benefits of Testing

• Testing (like Documentation) has a cost• usually: productivity improvement > cost• but find the right balance

Conclusion

I get paid for code that works, not for tests, so my philosophy is to testas little as possible to reach a given level of confidence.

– Kent Beck

Links

• http://phpqatools.org/: PHP Quality Assurance Toolchain• http://wpgear.org/: compendium of useful WP developer tools• http://wptest.io/: test data for WP plugins and themes

• Ptah Dunbar: Automated Testing in WordPress, Really?!• tuts+ articles by Tom McFarlin• Conversation “Is TDD Dead?”

Thank You

top related