WordPress | 単体テストを行う

WordPress でもPHPUnit で単体テストを行いたい。

wp-cli をインストールする

1
2
3
4
5
6
7
8
$ sudo curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5437k 100 5437k 0 0 7221k 0 --:--:-- --:--:-- --:--:-- 7221k
$ sudo chmod +x wp-cli.phar
$ sudo mv wp-cli.phar /usr/local/bin/wp
$ wp --version
WP-CLI 2.4.0

プラグインのテンプレートを作成する

1
2
3
$ sudo wp --allow-root scaffold plugin sample-plugin
Success: Created plugin files.
Success: Created test files.

wp-cli を管理者権限で実行するときは、–allow-root オプションを付与して実行する。

作成されるファイル

1
2
3
4
5
6
7
8
9
10
+- bin
| +- install-wp-tests.sh
+- Gruntfile.js
+- package.json
+- phpunit.xml.dist
+- readme.txt
+- sample-plugin.php
+- tests
+- bootstrap.php
+- test-sample.php

コマンド

テスト実行環境の設定を指定する。

1
$sudo bin/install-wp-tests.sh <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]

実際には以下のように指定する。

1
$sudo bin/install-wp-tests.sh wordpress_test wp_user wp_password localhost latest true

latest と true/false は省略できる。

テスト環境を作成する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ bin/install-wp-tests.sh wordpress_test wp_user wp_password
localhost
+ install_wp
+ '[' -d /tmp/wordpress/ ']'
+ return
+ install_test_suite
++ uname -s
+ [[ Linux == \D\a\r\w\i\n ]]
+ local ioption=-i
+ '[' '!' -d /tmp/wordpress-tests-lib ']'
+ mkdir -p /tmp/wordpress-tests-lib
+ svn co --quiet https://develop.svn.wordpress.org/tags/5.6/tests/phpunit/includes/ /tmp/wordpress-tests-lib/includes
+ svn co --quiet https://develop.svn.wordpress.org/tags/5.6/tests/phpunit/data/ /tmp/wordpress-tests-lib/data
+ '[' '!' -f wp-tests-config.php ']'
+ download https://develop.svn.wordpress.org/tags/5.6/wp-tests-config-sample.php /tmp/wordpress-tests-lib/wp-tests-config.php
++ which curl
+ '[' /usr/bin/curl ']'
+ curl -s https://develop.svn.wordpress.org/tags/5.6/wp-tests-config-sample.php
++ echo /tmp/wordpress/
++ sed 's:/\+$::'
+ WP_CORE_DIR=/tmp/wordpress
+ sed -i 's:dirname( __FILE__ ) . '\''/src/'\'':'\''/tmp/wordpress/'\'':' /tmp/wordpress-tests-lib/wp-tests-config.php
+ sed -i s/youremptytestdbnamehere/wordpress_test/ /tmp/wordpress-tests-lib/wp-tests-config.php
+ sed -i s/yourusernamehere/wp_user/ /tmp/wordpress-tests-lib/wp-tests-config.php
+ sed -i s/yourpasswordhere/wp_password/ /tmp/wordpress-tests-lib/wp-tests-config.php
+ sed -i 's|localhost|localhost|' /tmp/wordpress-tests-lib/wp-tests-config.php
+ install_db
+ '[' false = true ']'
+ PARTS=(${DB_HOST//\:/ })
+ local PARTS
+ local DB_HOSTNAME=localhost
+ local DB_SOCK_OR_PORT=
+ local EXTRA=
+ '[' -z localhost ']'
++ echo
++ grep -e '^[0-9]\{1,\}$'
+ '[' ']'
+ '[' -z ']'
+ '[' -z localhost ']'
+ EXTRA=' --host=localhost --protocol=tcp'
+ mysqladmin create wordpress_test --user=wp_user --password=wp_password --host=localhost --protocol=tcp

テスト用コード作成

sample-plugin.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
/**
* Plugin Name: Sample Plugin
* Plugin URI: PLUGIN SITE HERE
* Description: PLUGIN DESCRIPTION HERE
* Author: YOUR NAME HERE
* Author URI: YOUR SITE HERE
* Text Domain: sample-plugin
* Domain Path: /languages
* Version: 0.1.0
*
* @package Sample_Plugin
*/

// Your code starts here.
class SamplePlugin
{
public function method(string $message)
{
return "!{$message}!";
}
}

tests/test-sample.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
/**
* Class SampleTest
*
* @package Sample_Plugin
*/

/**
* Sample test case.
*/
class SampleTest extends WP_UnitTestCase {

/**
* A single example test.
*/
public function test_sample() {
// Replace this with some actual testing code.
$this->assertTrue( true );
}

public function test_method()
{
$object = new SamplePlugin();
$this->assertEquals('!Hello,world!', $object->method('Hello,world'));
}
}

テストを実行する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ sudo phpunit tests/test-sample.php --filter=method
Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 7.5.6 by Sebastian Bergmann and contributors.

Warning - The configuration file did not pass validation!
The following problems have been detected:

Line 11:
- Element 'testsuite': The attribute 'name' is required but missing.

Test results may not be as expected.


. 1 / 1 (100%)

Time: 11.04 seconds, Memory: 30.00 MB

OK (1 test, 1 assertion)

shortcode をテストする

sample-plugin.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
/**
* Plugin Name: Sample Plugin
* Plugin URI: PLUGIN SITE HERE
* Description: PLUGIN DESCRIPTION HERE
* Author: YOUR NAME HERE
* Author URI: YOUR SITE HERE
* Text Domain: sample-plugin
* Domain Path: /languages
* Version: 0.1.0
*
* @package Sample_Plugin
*/

add_shortcode('show_message', function(array $attr) {
$default = [
'message' => '',
];
extract(shortcode_atts($default, $attr));
return htmlspecialchars($message, ENT_QUOTES);
});

$ cat tests/test-sample.php †
<?php
/**
* Class SampleTest
*
* @package Sample_Plugin
*/

/**
* Sample test case.
*/
class SampleTest extends WP_UnitTestCase {

public function test_shortcode()
{
$output = do_shortcode('[show_message message="Hello,world"]');
$expected = 'Hello,world';
$this->assertEquals($expected, $output);
}
}

エラー

テスト環境が作成されていない

現象

PHPUnit を実行すると、下記のエラーが表示される。

1
2
$ phpunit
Could not find /tmp/wordpress-tests-lib/includes/functions.php, have you run bin/install-wp-tests.sh ?

対策

bin/install-wp-tests.sh を実行してテスト環境を作成する。

1
2
$ bin/install-wp-tests.sh
usage: bin/install-wp-tests.sh <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]

テスト環境の作成中にエラーが発生する(1) †

現象

1
svn: command not found

対応

Subvrsion をインストールする

1
$ sudo apt install subversion

テスト環境の作成中にエラーが発生する(2) †

現象

1
2
+ mysqladmin create wordpress_01 --user=wp_user --password=wppassword --host=localhost --protocol=tcp
mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'wordpress_01'; database exists'

対応

bin/install-wp-tests.sh コマンドで指定したテスト用データベースがすでに作成済みなので、別のデータベースを指定する。

テスト環境の作成中にエラーが発生する(2)

現象

1
2
+ mysqladmin create wordpress_test_01 --user=wp_user --password=wppassword --host=localhost --protocol=tcp
mysqladmin: CREATE DATABASE failed; error: 'Access denied for user 'wp_user'@'%' to database 'wordpress_test_01''

対応

bin/install-wp-tests.sh コマンドで指定したテスト用データベースに指定したユーザ名とパスワードでアクセスできないので、アクセス制限を確認する。