该技能用于 Drupal 项目的测试驱动开发(TDD),配合 test-writer 与 test-runner 智能体使用,本技能负责“怎么做”,智能体负责“由谁做”。
用途与判断标准:写测试前先判断是否值得提交。只有同时满足两点才值得:未来某次正常改动可能悄悄导致回归;且该回归影响用户行为、数据完整性、金钱、安全或 API/客户端契约。否则该测试只是维护负担。高价值场景包括业务与算法逻辑、数据转换、计费与权益、安全与权限门(在路由层固定)、缓存失效与新鲜度、外部客户端依赖的 API/JSON 响应形状(契约测试)、以及反复出现的回归。低价值场景包括一次性 UI 元素的存在性、精确文案(除非文案本身即契约)、像素位置、核心或 contrib 已覆盖的内容、以及复述实现细节的测试。外观与文案修正的验证方式是截图(如 Playwright),不是提交 DOM 存在性断言。
Bug 修复的 TDD:先写能复现 bug 的测试,运行并确认它按报告症状失败;再修改生产代码;最后重跑确认通过。RED 步骤不可跳过,红转绿是测试确实覆盖该 bug 的唯一证明。同时建议写负向用例,展示失败模式与成功模式。
测试基类选择与成本:按 UnitTestCase、KernelTestBase、DTT ExistingSite、Functional/BrowserTestBase 顺序优先选最便宜的。BrowserTestBase 每类需完整重装站点,通常 20-60 秒以上;ExistingSiteBase 只在站点安装/播种时付一次成本。在 ExistingSite 内,服务逻辑直接调用 \Drupal::service(...),模板渲染用 renderer->renderInIsolation($build),实体渲染用 EntityCrawlerTrait::getRenderedEntityCrawler(),仅在验证控制器、鉴权、重定向时使用 drupalLogin + drupalGet,每个功能保留一个冒烟测试。数据提供器带 N 行时不要在其中放 HTTP,拆分为快速服务/渲染矩阵加单个 HTTP 冒烟测试。提速手段包括用 XDEBUG_MODE=off、避免 sleep()、减少登录与 HTTP 调用。
DTT ExistingSite 模式与限制:一次播种、共享 fixture;将 maximumMetaRefreshCount 设为小值(如 3)以防 meta-refresh 循环挂起;setUp() 跳过时需在 tearDown() 加 !\Drupal::hasContainer() 守卫;匿名 CSRF 令牌跨请求可能不通过校验,需先 drupalLogin;新鲜度测试应通过真实 HTTP 写入路径变更数据。ExistingSiteBase 无事务回滚、共享数据库、进程长驻,副作用会持久化:fixture 应尽量以未发布状态创建或立即 markEntityForCleanup;drupalLogin() 有持久副作用;不要写共享 config 单例,应使用作用域限定于测试容器的 ConfigFactoryOverrideInterface;进程级静态会钉住已死内核导致内存线性增长,需在基类 #[After] 钩子释放 drupal_static_reset()、重置 MIME guesser、清理 shutdown 函数列表并回收内存,但不要调用 \Drupal::unsetContainer()。
资料未提供安装命令、版本要求与示例仓库结构,暂未提供相关内容。