Presents :

COQUARD Cyrille

06/10/2023

Testing the WordPress Waters:

A quick dive into plugin integration testing

COQUARD Cyrille

06/10/2023

COQUARD Cyrille

06/10/2023

Software engineer

At WP Media since 2 years

Always improve

COQUARD Cyrille

  • Always interested in testing
  • Start testing for WordPress 2 years ago

06/10/2023

Testing

  • Machine should serve the developer
  • Code doesn't have to be complex

Developer eXperience

What is testing?

COQUARD Cyrille

06/10/2023

  • Stands for automated tests
  • Code to assert application behavior
  • Multiple type of tests

Why this speak ?

COQUARD Cyrille

06/10/2023

Testing is limited.

J.B., WP Media CEO

In one quote....

2022

Testing should be an OKR.

J.B., WP Media CEO

2024

or maybe two

Effective testing is hard

COQUARD Cyrille

06/10/2023

  • Know what to test
  • Know how to test
  • Know when to test

Bad test

=

Useless

Effective testing is high reward

COQUARD Cyrille

06/10/2023

  • Delivering on time
  • Low number of bugs

Objective from that talk:

Guide you toward effective testing

Summary:

  • Why testing
  • Unit vs Integration
  • How to test
  • Usual testing scenarios

06/10/2023

COQUARD Cyrille

Unit

vs

Integration

COQUARD Cyrille

06/10/2023

Unit vs Integration:

The academic way

COQUARD Cyrille

06/10/2023

Unit

  • Class or method level
  • More isolated
  • Developper oriented
  • Easy to setup
  • First ones to learn

Integration

  • Feature level
  • More abstract
  • Business oriented
  • Complex to setup

Unit vs Integration:

The academic way

COQUARD Cyrille

06/10/2023

What is the issue?

Unit vs Integration:

The academic way

COQUARD Cyrille

06/10/2023

We ain't at school

  • CEO / Manager decides
  • Rentability / on schedule is key
  • Need to convince

Unit vs Integration:

The real world way

COQUARD Cyrille

06/10/2023

Unit

  • More fragile so low productivity
  • Developper language
  • Lot of tests
  • Need to create testcases

Integration

  • More abstract so high productivity
  • Business language
  • Reduced number of tests
  • Based on project definition

Unit vs Integration:

Start with integration

COQUARD Cyrille

06/10/2023

Integration

  • Higher productivity
  • Business language
  • Reduced number of tests
  • Ensure the feature is done

How to test

COQUARD Cyrille

06/10/2023

How to test:

Setup the environnement

COQUARD Cyrille

06/10/2023

  • Setup a development env: wordpress/env
  • Setup integration tests:  wp-media/phpunit
  • Ease filter mocking: wp-launchpad/phpunit-wp-hooks
  • Create the base for integration tests

How to test:

Create tests

COQUARD Cyrille

06/10/2023

Now what?

How to test:

What to test ?

COQUARD Cyrille

06/10/2023

Test Driven Development

  • Really trendy
  • Really dogmatic
  • Better done than perfect

How to test:

What to test ?

COQUARD Cyrille

06/10/2023

Most important in TDD

  • Write test before code
  • Make sure they fail before writing code
  • Make sure all tests pass when writing code

How to test:

What to test ?

COQUARD Cyrille

06/10/2023

Acceptance criteria

  • Simple sentence asserting a behavior
  • Done by the person scoping the project
  • Ensure you are not testing your code

How to test:

Structure a test

COQUARD Cyrille

06/10/2023

AAA

  • Arrange: put the plugin in a certain state
  • Act: run the logic to test
  • Assert: verify the plugin is in the expected state
<?php 

class Test_Logout extends TestCase {
    public function testLogoutShouldNotEdit()
    {
    	do_action(
        'grant_admin',
        wp_current_user()
        );
        
    	do_action('logout');
        
        $this->assertSame(
        	false,
        	apply_filters(
            'user_can_edit',
            false
            )
        );
    
    }
}

Usual testing scenarios

COQUARD Cyrille

06/10/2023

How to test:

Adapt to usual cases

COQUARD Cyrille

06/10/2023

Scenarios

  • Unleash CQRS power
  • Control filter value
  • Mock external API
  • Isolate callback

How to test:

Unleash CQRS power

COQUARD Cyrille

06/10/2023

Problem

Need to re-implement a way to interact with the element for each test

Solution

Use action and filter to cut your logic into small units

How to test:

Unleash CQRS power

COQUARD Cyrille

06/10/2023

Solution

Use action and filter to cut your logic into small units

<?php 

class Test_Logout extends TestCase {
    public function testLogoutShouldNotEdit()
    {
    	do_action(
        'grant_admin',
        wp_current_user()
        );
        
    	do_action('logout');
        
        $this->assertSame(
        	false,
        	apply_filters(
            'user_can_edit',
            false
            )
        );
    
    }
}

How to test:

Control filter value

COQUARD Cyrille

06/10/2023

Problem

Need control flow to direct the test into a certain state

Solution

Mock the filter with a callback function

How to test:

Control filter value

COQUARD Cyrille

06/10/2023

Solution

Mock the filter with a callback function

<?php 

class Test_Logout extends TestCase {
    public function testLogoutShouldNotEdit()
    {
      ...
    }
    
    /**
    * @hook my_filter 10
    */
    public function my_callback() {
    	return true;
    }
}

How to test:

Mock external API

COQUARD Cyrille

06/10/2023

Problem

The code call an external API and there is no control about it

Solution

Use wp_remote_request and mock the filter with a callback function

How to test:

Mock external API

COQUARD Cyrille

06/10/2023

Solution

Use wp_remote_request and mock the filter with a callback function

<?php 

class Test_Logout extends TestCase {
    public function testLogoutShouldNotEdit()
    {
      ...
    }
    
    /**
    * @hook my_filter 10
    */
    public function my_callback() {
    	return true;
    }
}

How to test:

Isolate callback

COQUARD Cyrille

06/10/2023

Problem

The callback to test is linked to an hook with lot of callbacks making lot of noise

Solution

Isolate the callback by removing all other callbacks

How to test:

Isolate callback

COQUARD Cyrille

06/10/2023

Solution

Isolate the callback by removing all other callbacks

<?php 

class Test_Logout extends TestCase {
    public function testLogoutShouldNotEdit()
    {
    	do_action(
        'grant_admin',
        wp_current_user()
        );
        
    	do_action('logout');
        
        $this->assertSame(
        	false,
        	apply_filters(
            'user_can_edit',
            false
            )
        );
    
    }
}

Launchpad

Framework with all good practices from WP Rocket

https://github.com/wp-launchpad/launchpad

COQUARD Cyrille

06/10/2023

Any question?

06/10/2023

COQUARD Cyrille

Copy of PHP bonne pratiques

By Cyrille Coquard

Copy of PHP bonne pratiques

  • 160