WP-CLI 命令行手册

title: "为 WP-CLI 编写 Behat 测试" post_status: publish comment_status: open taxonomy: category: - wp-cli-handbook post_tag: - Guides - Repos - Data


为 WP-CLI 编写 Behat 测试

WP-CLI 使用 Behat 进行功能测试。本指南将帮助您了解如何为 WP-CLI 命令和包编写并运行 Behat 测试。

简介

什么是 Behat 测试?

Behat 是一个面向 PHP 的行为驱动开发(BDD)框架。在 WP-CLI 中,Behat 测试被用作功能测试,用于执行完整命令并验证其是否按预期工作。与孤立测试单个函数的单元测试不同,功能测试确保命令能够端到端地正确运行。

Behat 测试的重要性

WP-CLI 向用户承诺的重要契约是版本间的稳定性。Behat 测试有助于确保:

大多数拉取请求都需要测试。 如果是新功能,需要测试。如果是修复错误,则需要测试以防止回归。

快速开始

每个包含命令的 WP-CLI 代码库都有一个 features/ 目录,其中包含一个或多个 YAML 格式的 *.feature 文件。

编写你的第一个测试

基本测试结构

以下是一个简单示例:

Feature: 管理 WordPress 选项

  Scenario: 读取单个选项
    Given 一个 WordPress 安装

    When 我运行 `wp option get home`
    Then STDOUT 应为:
      """
      https://example.com
      """

此测试遵循 Gherkin 语法,包含三个关键组成部分:

以更人性化的形式表述:

我有一个 WordPress 安装。当我运行 wp option get home 时,该命令的输出应为 'https://example.com'。

你的第一个测试

让我们为一个假设的显示问候语的命令编写测试:

  1. 创建文件 features/greeting.feature
Feature: 测试问候命令

  Scenario: 显示问候语
    Given 一个空目录

    When 我运行 `wp greeting hello`
    Then STDOUT 应包含:
      """
      Hello
      """
    And 返回码应为 0

这个测试: 1. 从一个空目录开始 2. 运行你的命令 3. 验证输出包含 "Hello" 4. 验证命令执行成功(退出码为 0)

常用步骤定义

WP-CLI 提供了许多预构建的步骤定义。以下是最常用的:

Given(前置条件)

何时(操作)

然后(断言)

完整可用步骤列表请参阅 Behat 步骤参考

运行测试

设置测试环境

运行测试前,你需要设置一个测试数据库。composer behat 脚本会自动检测数据库可用性,如果没有正在运行的数据库,则会回退到 SQLite,这使得无需任何设置即可轻松开始。

你有两个选择:

选项 1:SQLite(推荐,简单)

运行测试最简单的方法是使用 SQLite,它不需要数据库设置:

WP_CLI_TEST_DBTYPE=sqlite composer behat

或者直接运行 composer behat,如果没有配置数据库,它会自动使用 SQLite。

选项 2:MySQL/MariaDB

如果你更倾向于使用 MySQL 或 MariaDB,请运行设置脚本来创建测试数据库:

composer prepare-tests

这将创建一个 MySQL 用户 wp_cli_test,密码为 password1,该用户对 wp_cli_test 数据库拥有完全权限。

注意: MySQL 8.0 更改了默认的身份验证插件。如果你遇到连接问题,请参阅这篇博客文章以获取解决方案。

运行测试套件

运行所有测试:

composer behat

运行特定功能文件的测试:

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

这在编写测试时很有帮助,可以找到符合需求的正确步骤。

高级用法

编写有效的测试

每次只测试一件事

每个场景应测试单一功能:

# 良好 - 测试一个特定行为
场景:删除文章
  假设一个 WP 安装
  并且我运行 `wp post create --post_title='Test' --porcelain`
  并且将 STDOUT 保存为 {POST_ID}

  我运行 `wp post delete {POST_ID}`
  那么 STDOUT 应包含:
    """
    Success: Trashed post
    """

# 不佳 - 测试多个不相关的行为
场景:创建、更新和删除文章
  # 一个测试中内容过多...

使用描述性的场景名称

明确说明测试内容:

# 良好示例
场景:当文章不存在时优雅地失败

# 不良示例
场景:测试删除

同时测试成功与失败情况

不要只测试理想路径:

场景:成功创建文章
  假设一个 WP 安装
  我运行 `wp post create --post_title='Test'`
  那么返回码应为 0

场景:缺少必要参数时失败
  假设一个 WP 安装
  我尝试 `wp post create`
  那么返回码应为 1
  并且 STDERR 应包含:
    """
    错误
    """

使用变量

将命令输出存储在变量中供后续使用:

Scenario: 创建并获取文章
  Given 一个已安装的 WP

  When 我运行 `wp post create --post_title='Test Post' --porcelain`
  Then 将 STDOUT 保存为 {POST_ID}

  When 我运行 `wp post get {POST_ID} --field=title`
  Then STDOUT 应为:
    """
    Test Post
    """

测试表格和结构化输出

测试表格输出

Scenario: 以表格格式列出文章
  Given 一个已安装的 WP
  And 我运行 `wp post create --post_title='First'`
  And 我运行 `wp post create --post_title='Second'`

  When 我运行 `wp post list --fields=ID,post_title`
  Then STDOUT 应该是一个包含以下行的表格:
    | ID | post_title |
    | 1  | First      |
    | 2  | Second     |

Testing JSON Output

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: 将文章导出为 CSV
  Given 一个已安装的 WP

  When 我运行 `wp post list --format=csv`
  Then STDOUT 应为包含以下内容的 CSV:
    | ID | post_title | post_status |
    | 1  | Test       | publish     |

测试文件和目录

场景:创建一个插件文件
  假设有一个 WordPress 安装

  我运行 `wp scaffold plugin my-plugin`
  那么 my-plugin/my-plugin.php 文件应该存在
  并且 my-plugin/my-plugin.php 文件应包含:
    """
    Plugin Name: My Plugin
    """

背景部分

使用 Background: 为所有场景执行通用设置:

Feature: 文章管理

  Background:
    Given 一个已安装的 WP
    And 我运行 `wp post create --post_title='Test'`

  Scenario: 更新文章标题
    When 我运行 `wp post update 1 --post_title='Updated'`
    Then STDOUT 应包含:
      """
      Success
      """

  Scenario: 删除文章
    When 我运行 `wp post delete 1`
    Then STDOUT 应包含:
      """
      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: 使用不同标题创建文章
  Given 一个已安装的 WP

  When 我运行 `wp post create --post_title='<title>'`
  Then STDOUT 应包含:
    """
    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_DBTYPE=sqlite 使用 SQLite,从而完全避免数据库配置。

最佳实践

应该做的

注意事项

为新包搭建测试框架

创建新的 WP-CLI 包时,使用 wp scaffold package-tests 命令生成测试基础设施:

wp scaffold package my-package
cd my-package
wp scaffold package-tests .

这将创建: - .github/workflows/testing.yml - GitHub Actions 工作流文件 - features/ - 功能测试文件目录 - features/load-wp-cli.feature - 验证 WP-CLI 加载的基础测试 - 其他测试基础设施文件

更多详情请参阅 scaffold-package-command 文档

故障排除

测试无法连接数据库

如果出现数据库连接错误:

  1. 尝试改用 SQLite:WP_CLI_TEST_DBTYPE=sqlite composer behat
  2. 如果使用 MySQL,请确认其正在运行:mysql -u wp_cli_test -ppassword1 wp_cli_test
  3. 检查你的 MySQL 版本(MySQL 8.0 有身份验证变更)
  4. 确认数据库已创建:composer prepare-tests

本地测试通过但在 CI 中失败

常见原因: - PHP 版本不同(检查你的 CI 矩阵配置) - WordPress 版本不同(检查你的测试矩阵配置) - 时序问题(某些命令需要更长时间才能完成) - 数据库排序规则差异

命令未找到错误

如果在测试过程中命令未找到:

  1. 确认您的 composer.json 已正确声明该命令
  2. 检查 composer install 是否成功运行
  3. 确保您的命令类已正确自动加载

慢速测试

如果测试运行缓慢: - 尽量减少数据库操作 - 尽可能使用 Given an empty directory 而非 Given a WP install - 避免不必要的插件安装 - 使用 --porcelain 来减少输出解析

Additional Resources

WP-CLI 包中的示例

来自 WP-CLI 核心包的真实示例:

研究这些示例,了解在实践中如何测试不同类型的命令。