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