Oppia 测试模块映射体系全解析:core/tests/test-modules-mappings 如何驱动 GitHub CI 精准测试
教育后端前端【免费下载链接】oppiaA free, online learning platform to make quality education accessible for all.项目地址https://gitcode.com/gh_mirrors/op/oppia点击查看免费下载在 Oppia 的 CI 流程中每一次 Pull Request 并不会盲目跑完全部测试而是通过一套部分 CIPartial CI机制精确挑选出受代码变更影响的测试套件来运行。这套机制的核心数据源就是core/tests/test-modules-mappings/目录下的测试模块映射test-modules-mappings文件。本文将从该目录的职责与结构出发结合scripts/check_ci_test_suites_to_run.py、运行时收集器core/tests/test-dependencies/test-to-modules-matcher.ts以及验收测试运行器等源码完整还原这些.txt映射文件从生成、消费到校验的整条链路。读完本文你将理解 CI 何时提示你更新这些文件、为什么不能手改、以及本地运行测试时它们是如何被自动重建的。一、test-modules-mappings 目录职责与现状根据core/tests/test-modules-mappings/README.md的官方说明该目录存放每种测试类型的模块映射test-modules-mappings当前仓库中它只包含验收测试acceptance tests的映射。这些映射的用途是决定在 GitHub CI 中运行哪些测试——也就是说它们是文件变更 → 受影响测试套件这条关联链路的静态数据底座。core/tests/test-modules-mappings/ ├── README.md └── acceptance/ ├── blog-admin/ │ └── assign-roles-to-users-and-change-tag-properties.txt ├── blog-editor/ │ ├── create-and-delete-draft-blog-post.txt │ ├── create-and-publish-a-blog-post-with-required-details.txt │ └── try-to-publish-a-duplicate-blog-post-and-get-blocked.txt ├── curriculum-admin/ │ ├── create-edit-and-delete-classroom.txt │ └── create-publish-unpublish-and-delete-topic-and-skill.txt ├── exploration-editor/ │ ├── create-exploration-and-change-basic-settings.txt │ ├── load-complete-and-restart-exploration-preview.txt │ ├── manage-exploration-misconceptions.txt │ ├── modify-translations-through-modal.txt │ ├── publish-the-exploration-with-an-interaction.txt │ └── save-draft-publish-and-discard-the-changes.txt ├── logged-in-user/ ├── moderator/ ├── practice-question-admin/ ├── release-coordinator/ ├── super-admin/ ├── topic-manager/ ├── translation-admin/ └── voiceover-admin/每个子目录对应一类用户角色/功能域目录内每个.txt文件与一个验收测试套件一一对应。文件内容格式非常简单——每行一个 Angular 模块文件路径按字典序排列。以exploration-editor/create-exploration-and-change-basic-settings.txt为例其真实内容为core/templates/pages/creator-dashboard-page/creator-dashboard-page.module.ts core/templates/pages/exploration-editor-page/exploration-editor-page.module.ts这表示创建探索并修改基础设置这个验收测试在运行过程中会加载两个页面级 Angular 模块只要 PR 改动了这两个模块中的任何一个该测试套件就需要被重新运行。super-admin/use-misc-tab-features.txt则列出了 7 个模块覆盖 admin-page、blog-admin-page、blog-dashboard-page、creator-dashboard-page、exploration-editor-page、topic-editor-page、topics-and-skills-dashboard-page 等页面说明该套件会穿梭于多个管理后台页面。二、模块映射与测试套件配置的对应关系映射文件并非孤立存在它与 core/tests/ci-test-suite-configs/acceptance.json 中的测试套件定义严格对应。该配置文件中每个套件包含三个字段字段说明示例name套件唯一标识形如角色域/行为描述exploration-editor/load-complete-and-restart-exploration-previewmodule对应的验收测试 spec 文件路径core/tests/puppeteer-acceptance-tests/specs/exploration-editor/load-complete-and-restart-exploration-preview.spec.tsframework运行框架当前取值puppeteer或playwrightpuppeteer映射.txt文件的文件名去掉.txt扩展名必须与套件name完全一致二者才能建立关联。这一匹配逻辑由 scripts/check_ci_test_suites_to_run.py 中的get_test_suites_to_module_mapping_from_file实现test_suite get_test_suite_by_name_from_list( test_suites, file_path_without_extension ) if test_suite is not None: test_suites_to_modules_mapping[test_suite[name]] modules从源码可以推断如果某个.txt文件名在acceptance.json中找不到同名的套件该文件会被静默跳过、不参与映射计算当前仓库中确实存在少量此类命名不一致的历史文件。因此新增或重命名套件时务必同时保证两边的name同步。三、消费端源码剖析check_ci_test_suites_to_run.py 如何挑选测试scripts/check_ci_test_suites_to_run.py是映射文件的直接消费方。它通过常量指向映射目录第 125-127 行TEST_MODULES_MAPPING_DIRECTORY: Final os.path.join( core, tests, test-modules-mappings )3.1 递归读取映射get_test_suites_to_module_mapping_from_directory第 528-563 行使用os.walk递归遍历core/tests/test-modules-mappings/acceptance目录下的所有文件逐个调用get_test_suites_to_module_mapping_from_file最终产出一个{套件名: [模块路径...]}字典。3.2 判断受影响的测试套件get_test_suites_affected_by_root_file第 586-619 行负责核心判定对于某个被修改的 root file即 Angular 模块遍历所有测试套件的模块映射若该模块出现在某套件的映射列表中或该文件本身就是套件配置中的modulespec 文件则将该套件标记为受影响同时凡是没有出现在任何映射中的套件也会被无条件纳入兜底策略确保无映射数据的套件始终被运行。3.3 完整决策流程get_ci_test_suites_to_run与main第 648-749 行串起了整体流程通过git diff --name-status获取 PR 变更文件列表若变更中包含 Python 文件直接运行全部测试套件Python 影响面无法静态收敛借助 core/tests/root-files-config.json 判断变更触及RUN_ALL_TESTS_ROOT_FILES中的文件如src/main.ts→ 跑全部仅触及RUN_NO_TESTS_ROOT_FILES如core/tests/test-modules-mappings/README.md本身→ 一个测试都不用跑其余情况将变更文件映射到 root files 后与 acceptance 映射比对得出acceptancepuppeteer playwright 混合与acceptance_playwright仅 playwright 子集两个维度的待跑套件列表连同 lighthouse 分片一起以TEST_SUITES_TO_RUN变量输出给 GitHub Workflow。scripts/check_ci_test_suites_to_run_test.py的单元测试完整验证了这一链路它在临时目录中构造blog-admin/assign-roles.txt、blog-editor/publish.txt、exploration-player/view-exploration.txt等模拟映射并逐一断言改动splash-banner.component.html只触发 splash 相关套件改动 spec 文件本身触发对应套件改动package.json触发全部套件等行为。四、映射文件的生命周期运行时自动收集与生成README 明确指出这些文件不应手动混入你自己的 Angular modules如果 CI 要求更新要么在本地运行测试让它们自动生成要么把 CI 给出的模块列表复制粘贴到目标位置。为什么可以自动生成秘密藏在验收测试的运行时收集器里。4.1 测试运行前指定 golden 文件路径在 core/tests/puppeteer-acceptance-tests/utilities/common/puppeteer-utils.ts 的openBrowser()中测试框架会根据当前运行的套件名动态指定 golden 文件路径TestToModulesMatcher.setGoldenFilePath( core/tests/test-modules-mappings/acceptance/${specName}.txt );其中specName由 scripts/servers.py 的managed_acceptance_tests_server通过环境变量注入os.environ[SPEC_NAME] suite_name也就是说跑哪个套件就对应更新哪个.txt文件。4.2 运行时 URL → 模块匹配core/tests/test-dependencies/test-to-modules-matcher.ts 中的TestToModulesMatcher承担核心收集工作静态属性routeToModuleMapping通过route-to-module-mapping-generator.ts在测试进程启动时解析整个 Angular 路由树建立URL 路由 → 页面模块的映射registerPuppeteerBrowser(browser)监听浏览器targetcreated/targetchanged事件以及页面framenavigated事件把每次导航的真实 URL 交给registerUrlregisterUrl用 Angular Router 的DefaultUrlSerializer解析 URL 并匹配路由匹配成功即把对应模块记入collectedModules同时借助COMMON_MODULES_TO_EXCLUDE第 35-53 行过滤掉 splash、login、signup、admin、learner-dashboard 等几乎所有套件都会访问的公共模块——除非该 golden 文件命中白名单 glob如super-admin/*仍会收集 admin-page 模块。4.3 测试结束后的比对与写回compareCollectedModulesWithGoldenFile第 203-256 行在测试收尾时执行三类校验缺失模块运行时收集到、但 golden 文件中没有 → 报错多余模块golden 文件中有、但本次运行未收集到 → 报错排序校验golden 文件必须按字典序排列 → 否则报错。最关键的机制在第 225-229 行无论校验结果如何它都会先把本次收集到的模块排序后写回 golden 文件fs.mkdirSync(path.dirname(this.goldenFilePath), {recursive: true}); fs.writeFileSync( this.goldenFilePath, this.collectedModules.sort().join(\n) \n );这正是 README 所说本地运行测试会自动生成映射文件的源码级证据在本地开发环境测试结束后文件已被自动更新若 CI 环境出现差异错误信息会提示你把 GitHub Actions 上传的 artifact 内容复制粘贴到 golden 文件位置即可。这也解释了为何永远不需要手写模块列表——浏览器真实访问过的页面会精确记录在案。五、为什么不能随意手动修改CI 的双重校验README 的告诫并非多虑Oppia 对映射文件设有两道自动防线运行时比对如上一节所述每个验收测试结束时都会校验 golden 文件与运行时收集结果的一致性任何手改造成的偏差都会让对应测试在本地或 CI 中直接失败CI 决策依赖check_ci_test_suites_to_run.py会以这些文件为唯一依据计算待跑套件。若你擅自添加自己的模块哪怕只是格式错误、漏了换行、顺序不对要么导致该套件被错误地跳过测试覆盖漏洞要么让本应运行的测试被多跑/少跑进而影响 PR 的 CI 通过率与执行时长。正确的两种更新姿势README 已给出并可由源码验证本地运行测试自动生成执行python -m scripts.run_acceptance_tests --suite suite-name测试结束写入真实收集的模块列表粘贴 CI artifact当 CI 报出missing/extra modules差异时直接从 Actions 日志或上传的 artifact 中复制模块列表到对应的.txt文件。此外check_tests_are_captured_in_ci.py还会交叉校验acceptance.json中的套件集合与specs目录下的实际测试文件是否同步防止新写的测试没有被登记到 CI 配置中。六、本地运行验收测试完整命令与前提如果你需要让映射文件自动重建可以在仓库根目录运行scripts/run_acceptance_tests.py 的使用说明python -m scripts.run_acceptance_tests --suiteexploration-editor/create-exploration-and-change-basic-settings常用参数参数作用--suite必填指定要运行的套件名必须与acceptance.json中的name一致--skip_build跳过前端构建默认会先 build JS 文件--headless以无头模式运行浏览器--mobile以移动端视口iPhone 6 规格运行--prod_env以生产模式运行静态资源从 build 目录提供--update_snapshots更新 Playwright 截图基线对 puppeteer 套件无效脚本会依次启动 Redis、Firebase Auth Emulator、Cloud Datastore Emulator 与 dev appserver端口由common.GAE_PORT_FOR_ACCEPTANCE_TESTING指定再拉起 jestpuppeteer或 Playwright 测试进程并以SPEC_NAME环境变量把套件名传给测试端最终触发openBrowser()中的 golden 文件写回逻辑。七、配套机制一览把文件变更翻译成测试清单映射文件只是 Partial CI 拼图的一块理解它需要看清整个配套体系均位于 core/tests/test-dependencies/ 与 core/tests/文件作用core/tests/test-dependencies/root-files-mapping-generator.ts静态分析 TS 依赖生成root-files-mapping.json把每个源文件映射到所属 root modulecore/tests/test-dependencies/route-to-module-mapping-generator.ts解析 Angular 路由模块产出URL → 页面模块映射供运行时收集器使用core/tests/test-dependencies/test-to-modules-matcher.ts运行时 URL 匹配、模块收集、golden 文件比对与写回core/tests/ci-test-suite-configs/acceptance.json验收测试套件的权威登记表name/module/frameworkcore/tests/root-files-config.jsonRUN_NO_TESTS_ROOT_FILES与RUN_ALL_TESTS_ROOT_FILES白名单注意core/tests/test-modules-mappings/README.md本身被列为改动不触发任何测试的文件scripts/check_ci_test_suites_to_run.py汇总以上所有输入输出TEST_SUITES_TO_RUN给 GitHub Workflow整条链路可概括为PR 变更文件 →root-files-mapping→ root modules →test-modules-mappings 反向查表→ 受影响套件 → 输出 CI 执行清单。而test-modules-mappings正是这张反向查表里唯一需要测试自己维护的数据——它由运行时收集器自动维护由 CI 消费也由 CI 校验形成了一条自洽、免手写的闭环。八、结语给贡献者的操作速查新增验收测试套件在acceptance.json登记套件含framework字段在specs目录编写测试本地跑一遍该套件后提交自动生成的.txt映射文件CI 提示更新映射优先本地运行对应套件让文件自动重建若本地环境不便则将 CI 日志/artifact 中给出的模块列表按字典序写入对应.txt切勿手动臆造模块重命名套件同步修改acceptance.json中的name、spec 文件路径以及映射.txt的文件名三者必须对齐只想了解结构直接阅读 core/tests/test-modules-mappings/README.md 与 core/tests/test-dependencies/README.md再对照本文提到的源码入口逐一验证即可。赞分享教育后端前端【免费下载链接】oppiaA free, online learning platform to make quality education accessible for all.项目地址https://gitcode.com/gh_mirrors/op/oppia点击查看免费下载相关推荐用 repowise impacted-tests 精准锁定变更影响的测试从每测试覆盖率映射到 CI 测试门禁用 repowise impacted tests 精准锁定变更影响的测试从每测试覆盖率映射到 CI 测试门禁 本篇技术指南围绕 Claude Code 插件Oppia CI 测试套件配置指南解读 core/tests/ci-test-suite-configs 的注册机制与运行链路Oppia CI 测试套件配置指南解读 core/tests/ci test suite configs 的注册机制与运行链路 导读 core/tests教育后端前端Wazuh API 集成测试映射脚本实战用 JSON 映射驱动 PR 级精准测试Wazuh API 集成测试映射脚本实战用 JSON 映射驱动 PR 级精准测试 本篇技术指南以 Wazuh 开源仓库中的 API 集成测试映射脚本 map网络安全IDS日志分析应用安全漏洞扫描创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

编译原理基础:从语言定义到文法分类与语法分析

编译原理基础:从语言定义到文法分类与语法分析

1. 项目概述语言的定义是整个编译原理的起点,也是最容易被初学者一带而过的部分。很多人学编译原理一上来就啃词法分析、语法分析,结果看到自动机、文法推导就懵了,根子就在于没有真正理解“语言”到底是个什么东西。哈工大这套课程把语言的定…

2026/10/15 16:28:41 阅读更多 →
Qt低功耗蓝牙开发实战:从GATT通信到MTU协商与Notify订阅

Qt低功耗蓝牙开发实战:从GATT通信到MTU协商与Notify订阅

简介:本资源是一套基于Qt框架的低功耗蓝牙(BLE)特征值读写测试例程,面向嵌入式开发、物联网应用及跨平台桌面端BLE通信初学者与进阶开发者,解决BLE设备调试中服务发现、GATT特征交互、异步读写响应等核心实践难点。压缩…

2026/10/15 16:28:41 阅读更多 →
AP-0316语音处理模组实战:回声消除与波束成形调试指南

AP-0316语音处理模组实战:回声消除与波束成形调试指南

1. 这块模组到底解决了什么问题语音交互这件事,看起来简单,做起来处处是坑。你对着设备喊一句话,设备听到的可能是:你自己的声音、隔壁房间的电视声、空调出风口的呼呼声、桌面共振的低频嗡嗡声,以及电路本身产生的底噪…

2026/10/15 16:27:40 阅读更多 →

最新新闻

ASP.NET 实现 QQ 在线客服:可配置、权重轮询与移动端适配方案

ASP.NET 实现 QQ 在线客服:可配置、权重轮询与移动端适配方案

简介:这份资源面向具备一定C#与Web开发基础的ASP.NET学习者,围绕“QQ在线客服”这一典型场景,提供一套可参考的实现代码与配套素材,帮助理解如何将第三方开放平台能力嵌入自有网站。压缩包共14个文件,约117KB&#xff…

2026/10/15 17:14:23 阅读更多 →
最长公共子串长度求解:从动态规划到滚动数组优化与工程应用

最长公共子串长度求解:从动态规划到滚动数组优化与工程应用

“求两个字符串的最长公共子串长度”,这个题目我估计很多人在面试和实际工程里都撞到过。名字和最长公共子序列(LCS)只差两个字,但解法思路和代码细节完全是两码事,很多新手上来就套LCS的模板,结果死在“连…

2026/10/15 17:14:23 阅读更多 →
ESP32三源融合高度计:GPS+气压计+IMU实现可信升降率测量

ESP32三源融合高度计:GPS+气压计+IMU实现可信升降率测量

简介:这是一款基于ESP32的高精度GPS高度计(Vario)开源固件与开发套件,面向嵌入式开发者、飞控爱好者及物联网硬件工程师,解决滑翔伞、无人机等场景中实时气压/IMU/GPS多源融合测高、航迹记录与无线配置的工程需求。资源…

2026/10/15 17:14:23 阅读更多 →
DreamDojo评估完全指南:eval.sh参数逐一拆解,复现In-lab与EgoDex评测集

DreamDojo评估完全指南:eval.sh参数逐一拆解,复现In-lab与EgoDex评测集

【免费下载链接】DreamDojo Official Codebase for "DreamDojo: A Generalist Robot World Model from Large-Scale Human Videos" (ICML 2026) 项目地址: https://gitcode.com/gh_mirrors/dr/DreamDojo 点击查看 免费下载 DreamDojo 是从 44k 小时人类第…

2026/10/15 17:14:23 阅读更多 →
使用 shuttle-axum 在 Shuttle 上部署 Axum 应用:零配置 Web 服务实战指南

使用 shuttle-axum 在 Shuttle 上部署 Axum 应用:零配置 Web 服务实战指南

云原生后端DevOps 【免费下载链接】shuttle Build & ship backends without writing any infrastructure files. 项目地址: https://gitcode.com/gh_mirrors/sh/shuttle 点击查看 免费下载 Axum 是 Rust 生态中广受欢迎的异步 Web 框架,而 shuttle-…

2026/10/15 17:14:23 阅读更多 →
选矿方向的文献综述怎么写:把“品位与回收率“这对指标讲透

选矿方向的文献综述怎么写:把“品位与回收率“这对指标讲透

选矿研究里有个绕不开的矛盾:品位与回收率互相牵制。 想提高精矿品位,往往要牺牲回收率;想把回收率拉上去,品位又容易掉。所以一篇文献只报其中一个指标,实际上等于没把结果说清。看懂这点,综述的骨架就有了…

2026/10/15 17:13:23 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →