Elementor PHPUnit 测试完全指南:本地运行、版本矩阵与 CI 流水线深度解析
【免费下载链接】elementorThe most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor
本文基于 Elementor 仓库的 PHPUnit 开发文档,系统讲解该 WordPress 页面构建器插件的 PHP 单元测试体系:如何准备本地测试环境、如何用一条命令跑通全量测试、如何按类/方法/正则过滤执行,以及 CI 如何按 WordPress 与 PHP 双维度版本矩阵运行测试。读完本文,你既能独立在本地复现仓库的完整测试流程,也能从源码层面理解测试引导(bootstrap)、Docker MySQL 容器编排与覆盖率门槛的实现机制。
一、测试体系总览:PHPUnit 9 + WordPress 测试框架
PHPUnit 是 Elementor 中所有 PHP 单元测试的唯一测试框架,测试代码统一存放于tests/phpunit/目录,并按模块/功能组织。从 phpunit.xml 可以看到测试套件的核心约定:
<phpunit bootstrap="tests/bootstrap.php" backupGlobals="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" failOnIncomplete="true" > <php> <env name="PLUGIN_FILE" value="elementor.php"/> <env name="WP_TESTS_DIR" value="./tmp/wordpress-tests-lib"/> </php> <testsuites> <testsuite name="elementor"> <directory prefix="test-" suffix=".php">./tests/phpunit/</directory> </testsuite> </testsuites>几个值得注意的配置点:
- 测试文件命名约定:
<directory prefix="test-" suffix=".php">表示只有以test-开头、.php结尾的文件才会被收集进elementor测试套件,例如tests/phpunit/elementor/test-fonts.php、tests/phpunit/elementor/test-widgets.php等。 - 严格模式:
failOnIncomplete="true"加上三类convert*ToExceptions意味着不完整的测试、错误、告警都会被当作失败处理,测试必须写完整、跑干净。 - 引导文件:
bootstrap="tests/bootstrap.php"指向 tests/bootstrap.php,它负责加载 Composer 自动加载器、定义常量、激活插件并拉起 WordPress 测试框架(下文第三节展开)。 - 环境变量:
PLUGIN_FILE固定为根目录的elementor.php入口文件;WP_TESTS_DIR默认指向./tmp/wordpress-tests-lib,可被外部环境变量覆盖——这正是bin/phpunit-local.sh把 WP 测试库装到/tmp/后注入该变量的原因。 - 覆盖率白名单:配置中的
<filter><whitelist>对整个仓库根目录取白名单,但排除了assets、bin、build、docs、node_modules、tests、includes/libraries、vendor、vendor_prefixed等目录,保证覆盖率统计只针对真正的插件业务代码。
composer.json的require-dev中还声明了测试相关的依赖链,与上述配置相互印证:
"require-dev": { "phpunit/phpunit": "^9", "yoast/phpunit-polyfills": "^1.0", "spatie/phpunit-snapshot-assertions": "^4.2", "thor-juhasz/phpunit-coverage-check": "^0.3.0", ... }即 PHPUnit 9 版本线(通过 Yoast polyfills 兼容低版本 PHP 的测试 API)、快照断言库(用于 CSS/序列化结果的回归比对)与覆盖率检查工具。
二、环境准备:Docker、Composer 与 SVN
官方文档 docs/devlopment/phpunit.md 列出了三个前置依赖,各自承担明确分工:
| 依赖 | 用途 |
|---|---|
| Docker | 以容器方式运行 MySQL 服务器,本地无需安装 MySQL 服务端或客户端工具 |
| Composer | 安装 PHP 依赖(含 PHPUnit 本体),详见仓库相邻的 composer 指南 |
| SVN | 用于从 WordPress 官方 SVN 拉取 WP 测试套件(develop.svn.wordpress.org) |
SVN 的检查与安装方式(文档原文步骤):
# 检查是否已安装;若输出路径(如 /usr/bin/svn)则跳过安装 which svn # macOS brew install svn # Linux sudo apt-get install subversion这些检查并非文档"口头要求",脚本里有硬性门禁。bin/phpunit-local.sh 在启动时会执行:
check_docker() { if ! command -v docker &>/dev/null; then echo "Error: Docker is not installed or not in PATH." exit 1 fi } check_svn() { if ! command -v svn &>/dev/null; then echo "Error: svn is not installed or not in PATH." echo "Mac: brew install subversion" echo "Linux: sudo apt-get install subversion" exit 1 fi }任一缺失都会直接exit 1终止。
三、本地运行测试
3.1 全量套件:一条命令
composer run phpunit:localphpunit:local对应 composer.json 中的bash ./bin/phpunit-local.sh。该命令"包办一切":启动(或复用)MySQL Docker 容器、把 WordPress 核心与 WP 测试套件下载到/tmp/、重建测试数据库,最后运行全部测试。
从 bin/phpunit-local.sh 的实现可以看清整个编排细节:
- 固定的容器与库约定:容器名
elementor-wp-tests-mysql、库名wordpress_test、账号root/root、端口3306、测试库目录/tmp/wordpress-tests-lib。 - 智能复用容器:
find_container_on_port会扫描当前 3306 端口已被哪个容器占用,若是则直接复用;否则检查既有容器的状态(exited/created则docker start,missing则新建)。新建时按 CPU 架构选镜像——x86_64用mysql:8.0,arm64用mysql:8.4。 - 等待就绪:以最多 60 秒的循环
mysqladmin ping等待 MySQL 就绪;超时会提示排查方向,例如"端口上跑着另一个容器、凭据可能不匹配,请docker stop后重试"或docker logs查看初始化日志。 - 重建测试库:
recreate_test_database通过docker exec执行DROP DATABASE IF EXISTS wordpress_test; CREATE DATABASE wordpress_test;,确保每次都在干净库上运行。 - 安装 WP 核心与测试套件:调用 bin/install-wp-tests.sh 完成 WordPress 核心下载与
svn co .../tests/phpunit/includes/套件检出(这就是 SVN 依赖的由来),并通过WP_TESTS_DIR环境变量把套件路径传出去。 - 执行测试:
FILTER="${1:-}" if [ -n "${FILTER}" ]; then WP_TESTS_DIR="${WP_TESTS_DIR}" ./vendor/bin/phpunit --filter "${FILTER}" else WP_TESTS_DIR="${WP_TESTS_DIR}" composer run test # test 即 vendor/bin/phpunit fi3.2 运行单个测试类或方法
# 运行某个类中的全部测试 composer run phpunit:local -- Test_Module # 运行单个方法 composer run phpunit:local -- Test_Module::test_get_favorites # 跨类部分匹配(正则) composer run phpunit:local -- test_get_favorites过滤参数会原样透传给phpunit --filter,匹配对象是完整限定测试名(类名::方法名),因此给出类名片段或方法名片段即可命中。
3.3 指定 WordPress 版本
WP_VERSION=6.8 composer run phpunit:localWP_VERSION取值与 CI 对齐,支持latest、6.9、6.8。脚本侧的解析逻辑在 bin/install-wp-tests-local.sh 中:若版本号形如X.Y(.Z)则取 SVN 的tags/$WP_VERSION;否则请求 WordPress API 的version-check接口解析出最新版本号,再取对应 tag。
3.4 补充:无数据库的快速单测通道
仓库还提供了一个文档之外的轻量通道 tests/phpunit/run-unit.sh:针对不依赖 WordPress/MySQL的纯逻辑测试(脚本注释点名 css-converter、prop-types 一类),用 tests/phpunit/unit-bootstrap.php 替代完整 bootstrap——后者只定义ABSPATH、注入esc_html/__()/wp_json_encode等最小 WordPress 函数桩,并按includes/autoloader.php相同的"类名→文件路径"规则注册Elementor\前缀的自动加载器。用法示例:
tests/phpunit/run-unit.sh tests/phpunit/elementor/modules/atomic-widgets/css-converter/converters/test-string-property-converter.php # 支持 --filter 等额外参数透传,也支持一次传多个测试文件该脚本会为传入的.php文件动态生成临时 phpunit 配置(绕过 PHPUnit 对test-*.php文件名与类名映射的假设),适合开发过程中高频迭代单个测试文件。需要 WordPress/MySQL 的测试仍必须走完整套件。
四、tests/bootstrap.php:测试环境的"装配线"
完整套件的每个测试进程都会经过 tests/bootstrap.php,它做了几件关键事情:
- 常量与插件激活:定义
ELEMENTOR_TESTS、ELEMENTOR_DEBUG、PLUGIN_FILE(来自 phpunit.xml 环境变量)等常量,并通过$GLOBALS['wp_tests_options']把插件加入active_plugins、主题设为twentytwentyone。 - 手动加载插件:挂在
muplugins_loaded钩子中require根目录的elementor.php,随后Autoloader::run()启动插件自研自动加载器。 - 关闭 WordPress 自更新:
remove_action('admin_init', '_maybe_update_themes'/'_maybe_update_core'/'_maybe_update_plugins'),避免测试期间触发核心/插件/主题更新请求。 - 默认激活全部可变更实验(Experiments):监听
elementor/experiments/feature-registered动作,对每个mutable的实验调用set_feature_default_state(..., STATE_ACTIVE)——这使得实验性功能在测试环境中默认开启、可被直接测试。 - 收尾清理:
tests_add_filter('shutdown', 'drop_tables', 999999)在进程退出时删掉测试新建的 SQL 表,保证数据库不残留状态。 - 语言文件复制:
copy_language_files()把tests/phpunit/resources/languages/plugins/elementor-he_IL.mo拷入测试库的data/languages/plugins/目录,供需要校验 Hebrew 翻译字符串的测试使用。
五、CI 如何运行测试
CI 定义在 .github/workflows/phpunit.yml,与文档描述一一对应,并可通过 workflow 文件进一步验证:
触发条件(文档 + 源码双重印证):
- PR / merge group:仅当 diff 涉及 PHP 相关文件时触发。
file-diffjob 使用 get-diff-action 检查的模式为**/*.php、**/*.twig、composer.+(json|lock)、.github/**/*.yml、install-wp-tests.sh; - 定时任务:
cron: '30 08 * * 0,1,2,3,4,5',即工作日(周一到周五)08:30 UTC; - 手动
workflow_dispatch也会执行 Nightly 矩阵。
版本矩阵(文档中的表格,与 workflow 中wordpress_versions/php_versions参数完全一致):
| Job | WordPress 版本 | PHP 版本 |
|---|---|---|
| PR / Merge | latest、6.9、6.8 | 7.4–8.3 |
| Nightly | latest、6.9、6.8、nightly | 7.4–8.4 |
覆盖率门槛:文档说明覆盖率报告仅在 PHP 8.3 + latest WordPress 上生成;对应的本地验证命令在 composer.json 中同样可见:
"coverage": "composer run coverage:test && composer run coverage:check", "coverage:test": "phpdbg -qrr vendor/phpunit/phpunit/phpunit --coverage-clover coverage-report/clover.xml", "coverage:check": "phpunit-coverage-check -t 64 coverage-report/clover.xml"即覆盖率需达到64%阈值(-t 64),且依赖phpdbg提供的原生覆盖率支持。
结果汇总与告警:test-resultjob 用if: always()汇总两个矩阵 job 的结果,Nightly 失败时会通过post-to-slack工作流推送 Slack 通知,并以exit 1标记整次运行失败。
六、小结:一次典型本地开发循环
把上述机制串起来,一个标准的本地测试工作流是:
- 确认三件套就绪:
docker在 PATH 中、composer可执行、which svn有输出; composer install安装依赖(post-install-cmd会自动执行 php-scoper 与dump-autoload);- 日常快速验证单文件:
tests/phpunit/run-unit.sh <测试文件>(纯逻辑测试)或composer run phpunit:local -- <类名|方法名|正则>(需要 WordPress 环境时); - 提交前跑全量:
composer run phpunit:local,脚本会自动复用/重建 Docker MySQL 与 WP 测试库; - 若怀疑特定 WordPress 版本兼容性问题:
WP_VERSION=6.8 composer run phpunit:local,与 CI 的 PR 矩阵(6.8/6.9/latest)保持一致。
关键文件索引:测试配置 phpunit.xml、引导逻辑 tests/bootstrap.php、本地编排 bin/phpunit-local.sh 与 bin/install-wp-tests-local.sh、无 DB 快速通道 tests/phpunit/unit-bootstrap.php、tests/phpunit/run-unit.sh、CI 定义 .github/workflows/phpunit.yml。
【免费下载链接】elementorThe most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考