WP-CLI 使用 Behat 进行功能测试。本指南介绍如何为 WP-CLI 命令和包编写、运行 Behat 测试。WP-CLI 是 WordPress 的命令行接口,可通过程序执行管理和开发任务;项目地址为 wp-cli.org 和 WordPress CLI 团队页面。
简介
什么是 Behat 测试?
Behat 是 PHP 的行为驱动开发(BDD)框架。PHP 是广泛使用的开源通用脚本语言,尤其适合 Web 开发,可嵌入 HTML;名称是 PHP: Hypertext Preprocessor 的递归缩写,参阅 PHP 手册。在 WP-CLI 中,Behat 测试作为功能测试执行整个命令,验证其行为是否符合预期。单元测试隔离检查单个函数;功能测试验证命令从头到尾是否正确运行。
为什么 Behat 测试很重要
保持版本之间的稳定性,是 WP-CLI 对用户的重要承诺。Behat 测试帮助确保:
- 命令与文档描述一致。
- 修改不会破坏现有功能。
- 边界情况得到正确处理。
- 完整的命令执行流程得到验证。
大多数拉取请求都需要测试。新增功能需要测试;修复缺陷也需要测试,以防回归。
开始使用
每个包含命令的 WP-CLI 仓库都有 features/ 目录,其中有一个或多个 *.feature 文件。原文称其为 YAML 格式;这些文件实际采用下文展示的 Gherkin 语法。
编写第一个测试
基本测试结构
下面是一个简单示例:
Feature: Manage WordPress options
Scenario: Read an individual option
Given a WP install
When I run `wp option get home`
Then STDOUT should be:
"""
https://example.com
"""
这个测试采用 Gherkin 语法,包含三个关键步骤组成部分:
Feature::记录文件的范围,应描述待测的整体功能。Scenario::描述具体测试用例。每个 feature 文件可以包含多个场景。- Given:准备测试初始环境,即前置条件。
- When:触发事件,即待测动作。
- Then:断言事件完成后的预期结果,即验证。
用更自然的语言描述就是:
已有一个 WordPress 安装实例。当运行
wp option get home时,命令输出应为“https://example.com”。
第一个测试
为一个输出问候语的假想命令编写测试:
- 创建
features/greeting.feature文件:
Feature: Test greeting command
Scenario: Display a greeting
Given an empty directory
When I run `wp greeting hello`
Then STDOUT should contain:
"""
Hello
"""
And the return code should be 0
此测试:
1. 从空目录开始。
2. 运行命令。
3. 验证输出包含“Hello”。
4. 验证命令成功,退出码为 0。
常用步骤定义
WP-CLI 提供许多内置步骤定义,以下是最常用的一些:
Given:准备环境
Given an empty directory:创建干净的工作目录。Given a WP install:安装一个全新的 WordPress 实例。Given a WP multisite install:安装多站点模式的 WordPress。Multisite 可在一次 WordPress 安装中创建站点网络,自 3.0 起提供,延续了已停止的 WPMU(WordPress Multiuser)项目,其功能已并入核心。参阅高级管理手册:创建站点网络。Given a database:创建空数据库。
When:执行动作
When I run 'wp command':执行命令,并预期成功。When I try 'wp command':执行命令,允许成功或失败。When I launch in the background 'wp command':在后台运行命令。
Then:断言
Then STDOUT should be::输出精确匹配。Then STDOUT should contain::输出包含指定文本。Then STDOUT should not contain::输出不包含指定文本。Then the return code should be 0:命令执行成功。Then the return code should be 1:命令执行失败。Then STDOUT should be empty:没有输出。
全部可用步骤见 Behat 步骤参考。
运行测试
配置测试环境
运行测试前,需要准备测试数据库。composer behat 脚本会自动检测数据库是否可用;没有正在运行的数据库时回退到 SQLite,便于零配置开始。
有两种选择:
方案一:SQLite(简便起见推荐)
最简单的方法是使用 SQLite,无需配置数据库:
WP_CLI_TEST_DBTYPE=sqlite composer behat
也可直接运行 composer behat,未配置数据库时由它自动选择 SQLite。
方案二:MySQL/MariaDB。MySQL 是关系型数据库管理系统,数据库用于结构化保存内容、配置和其他选项;参阅 MySQL 官网。
若希望使用 MySQL 或 MariaDB,运行准备脚本创建测试数据库:
composer prepare-tests
这会创建 MySQL 用户 wp_cli_test,密码为 password1,并授予其对 wp_cli_test 数据库的全部权限。
注意:MySQL 8.0 更改了默认认证插件。遇到连接问题时,参阅这篇博文。原页的术语提示也解释了 WordPress 插件:它们是以 PHP 编写、与 WordPress 集成、用于扩展网站功能的软件,可以来自免费插件目录,也可以是第三方付费插件;这里的数据库认证插件与 WordPress 插件不是同一概念。
运行测试套件
运行全部测试:
composer behat
运行某个 feature 文件的测试:
composer behat -- features/option.feature
按行号运行特定场景:
composer behat -- features/option.feature:10
显示详细输出:
composer behat -- features/option.feature --format pretty
仅重新运行失败的测试:
composer behat-rerun
查找可用步骤
查看所有可用步骤定义:
composer behat -- --definitions l
编写测试时,这有助于找到适用的步骤。
进阶用法
编写有效的测试
每次测试一件事
每个场景应只测试一个功能点:
# Good - tests one specific behavior
Scenario: Delete a post
Given a WP install
And I run `wp post create --post_title='Test' --porcelain`
And save STDOUT as {POST_ID}
When I run `wp post delete {POST_ID}`
Then STDOUT should contain:
"""
Success: Trashed post
"""
# Bad - tests multiple unrelated behaviors
Scenario: Create, update, and delete a post
# Too much in one test...
使用描述性的场景名称
清楚说明测试对象:
# Good
Scenario: Fail gracefully when post doesn't exist
# Bad
Scenario: Test delete
同时测试成功和失败
不要只测试顺利成功的路径:
Scenario: Successfully create a post
Given a WP install
When I run `wp post create --post_title='Test'`
Then the return code should be 0
Scenario: Fail when required argument is missing
Given a WP install
When I try `wp post create`
Then the return code should be 1
And STDERR should contain:
"""
Error
"""
使用变量
把命令输出保存到变量中,供后续使用:
Scenario: Create and then fetch a post
Given a WP install
When I run `wp post create --post_title='Test Post' --porcelain`
Then save STDOUT as {POST_ID}
When I run `wp post get {POST_ID} --field=title`
Then STDOUT should be:
"""
Test Post
"""
测试表格和结构化输出
测试表格输出
Scenario: List posts in table format
Given a WP install
And I run `wp post create --post_title='First'`
And I run `wp post create --post_title='Second'`
When I run `wp post list --fields=ID,post_title`
Then STDOUT should be a table containing rows:
| ID | post_title |
| 1 | First |
| 2 | Second |
测试 JSON 输出
Scenario: List posts in JSON format
Given a WP install
And I run `wp post create --post_title='Test' --porcelain`
When I run `wp post list --format=json`
Then STDOUT should be JSON containing:
"""
[{"post_title":"Test"}]
"""
测试 CSV 输出
Scenario: Export posts as CSV
Given a WP install
When I run `wp post list --format=csv`
Then STDOUT should be CSV containing:
| ID | post_title | post_status |
| 1 | Test | publish |
测试文件和目录
Scenario: Create a plugin file
Given a WP install
When I run `wp scaffold plugin my-plugin`
Then the my-plugin/my-plugin.php file should exist
And the my-plugin/my-plugin.php file should contain:
"""
Plugin Name: My Plugin
"""
Background 段
使用 Background: 为所有场景执行共同的准备步骤:
Feature: Post management
Background:
Given a WP install
And I run `wp post create --post_title='Test'`
Scenario: Update post title
When I run `wp post update 1 --post_title='Updated'`
Then STDOUT should contain:
"""
Success
"""
Scenario: Delete post
When I run `wp post delete 1`
Then STDOUT should contain:
"""
Success
"""
测试错误消息
使用 When I try 替代 When I run,允许命令失败:
Scenario: Error when plugin doesn't exist
Given a WP install
When I try `wp plugin activate non-existent-plugin`
Then the return code should be 1
And STDERR should contain:
"""
Error: The 'non-existent-plugin' plugin could not be found.
"""
使用 Scenario Outline
用一个场景测试多组输入:
Scenario Outline: Create posts with different titles
Given a WP install
When I run `wp post create --post_title='<title>'`
Then STDOUT should contain:
"""
Success
"""
Examples:
| title |
| Simple Title |
| Title's Quotes |
| UTF-8: 日本語 |
编写自定义步骤
高级用例可能需要自定义步骤定义。这些定义使用 PHP 编写,放在包的测试引导文件中。
自定义步骤定义示例:
/**
* @Given a custom configuration file
*/
public function aCustomConfigurationFile() {
$config = <<<EOT
custom_setting: value
another_setting: 123
EOT;
$this->proc( "echo '{$config}' > wp-cli.yml" )->run_check();
}
自定义步骤应:
– 使用有描述性的文档块注解。
– 遵循 Gherkin 的 Given/When/Then 约定。
– 可在多个测试中复用。
– 使用已有的 WP-CLI 测试框架方法。
对大多数包来说,wp-cli/wp-cli-tests 的内置步骤已经够用。只有必要时才创建自定义步骤。
使用不同 PHP 和 WordPress 版本测试
WP-CLI 在 CI 中针对多个 PHP 和 WordPress 版本运行测试。你的测试应在这些版本上均可工作。
需要注意:
– 不同 WordPress 版本的行为可能不同。
– 使用与版本相适应的预期结果。
– 避免测试 WordPress 核心自身的缺陷,应测试你的命令。核心是运行 WordPress 所需的软件集合,由核心开发团队构建。
数据库凭据
MySQL/MariaDB 测试默认使用:
– 数据库:wp_cli_test
– 用户名:wp_cli_test
– 密码:password1
– 主机:localhost
可用 wp-cli/wp-cli-tests 提供的环境变量覆盖:
WP_CLI_TEST_DBNAMEWP_CLI_TEST_DBUSERWP_CLI_TEST_DBPASSWP_CLI_TEST_DBHOST
也可设置 WP_CLI_TEST_DBTYPE=sqlite,使用 SQLite,完全避开数据库配置。
最佳实践
建议这样做
- 测试命令行为,而非实现。验证命令做什么,而非具体怎么做。
- 让测试相互独立。每个测试都应能单独成功运行。
- 使用有意义的测试数据。例如贴近实际的文章标题、用户名等。
- 测试边界情况。例如空字符串、特殊字符和大数值。
- 保持场景专注。每个场景只包含一个逻辑测试。
- 用 Given 准备环境。不要混合准备工作和测试动作。
- 测试错误情况。验证命令是否按预期失败。
避免这样做
- 不要测试 WordPress 核心功能。测试的是你的命令。
- 不要让测试互相依赖。每个场景都应独立。
- 不要硬编码 ID。使用变量或 porcelain 输出。
- 不要跳过错误测试。命令失败的情况同样重要。
- 不要测试实现细节。专注于用户可见行为。
- 不要忘记测试帮助文本。加入
wp help your-command的场景。
为新包生成测试框架
创建新 WP-CLI 包时,用 wp scaffold package-tests 生成测试基础设施:
wp scaffold package my-package
cd my-package
wp scaffold package-tests .
这会创建:
.github/workflows/testing.yml:GitHub Actions 工作流。原页术语提示将 GitHub 解释为在线托管 Git 仓库、供开发者分享、复制和修改代码的网站,并介绍了拉取请求:分支修改可在合并前接受审核讨论。原提示关于私有仓库须付费的说法带有历史性,不能据此判断当前套餐。features/:存放 feature 文件的目录。features/load-wp-cli.feature:验证 WP-CLI 能加载的基础测试。- 其他测试基础设施文件。
详情见 scaffold-package-command 文档。
故障排查
测试无法连接数据库
遇到数据库连接错误时:
- 尝试改用 SQLite:
WP_CLI_TEST_DBTYPE=sqlite composer behat。 - 如果使用 MySQL,确认其正在运行:
mysql -u wp_cli_test -ppassword1 wp_cli_test。 - 检查 MySQL 版本;MySQL 8.0 更改了认证方式。
- 确认数据库已创建:
composer prepare-tests。
本地通过,CI 失败
常见原因:
- PHP 版本不同,检查 CI 矩阵。
- WordPress 版本不同,检查测试矩阵。
- 时序问题,有些命令需要更长时间。
- 数据库排序规则不同。
找不到命令
测试期间找不到命令时:
- 确认
composer.json正确声明了命令。 - 确认
composer install成功运行。 - 确认命令类已正确自动加载。
测试缓慢
测试太慢时:
- 尽量减少数据库操作。
- 可以时用
Given an empty directory替代Given a WP install。 - 避免不必要的插件安装。
- 用
--porcelain减少输出解析。
更多资源
- Behat 步骤参考:全部可用步骤。
- WP-CLI 测试框架:底层测试框架。
- Behat 文档:官方文档。
- 为 WP-CLI 包编写功能测试:详细教程。
- 拉取请求指南:贡献指南。
WP-CLI 包中的实例
来自 WP-CLI 核心包的真实示例:
- Core Command 测试:安装与更新测试。
- Search-Replace Command 测试:数据库操作测试。
- Scaffold Command 测试:文件生成测试。
研究这些示例,了解各种命令在实践中如何测试。
现在可以为自己的 WP-CLI 命令编写全面的 Behat 测试了。好的测试会让 WP-CLI 对所有用户更加可靠。
来源与版权
来源:WordPress.org WP-CLI Handbook,WP-CLI 贡献者。《Writing Behat Tests for WP-CLI》中文译稿,依据用户已取得的转载授权,保留完整原示例。 阅读原文。











暂无评论内容