MongoDB Resmoke 模块配置(resmoke_modules)完全指南:为测试框架扩展 Fixtures、Hooks、Suites 与 JS 测试
【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo
导读
Resmoke 是 MongoDB 仓库自带的分布式测试运行框架(入口见 buildscripts/resmoke.py,核心逻辑位于 buildscripts/resmokelib)。本文围绕仓库文档 docs/testing/resmoke_modules.md 展开,系统讲解Resmoke 模块(Module)配置机制——如何通过 YAML 配置把目录之外的测试资源(fixtures、hooks、suites、jstests)注入 Resmoke 运行体系。读完本文,你将掌握模块配置文件的完整字段语义、启用/禁用模块的命令行方式、底层加载与过滤原理,并理解真实仓库中enterprise、streams、atlas三个内置模块的实际配置样例,能够为自己的功能模块编写同样规范的 Resmoke 模块配置。
一、Resmoke 模块配置是什么
在 MongoDB 仓库中,Resmoke 的默认测试配置(suites、fixtures、hooks)集中在 buildscripts/resmokeconfig 目录。然而,诸如enterprise、streams、atlas这类功能模块的测试资源并不位于该目录下,而是散落在各自模块的目录中。
Resmoke 模块配置机制的用途正是解决这一问题:通过一份 YAML 文件(默认位于 buildscripts/resmokeconfig/resmoke_modules.yml),为每个模块声明其专属的测试资源目录,让 Resmoke 在测试过程中感知并加载这些目录。按原文档的描述,模块可以指定 fixtures、hooks、suites 和 JavaScript 测试四类目录,Resmoke 会在测试流程中将其纳入使用。
这一机制的价值在于:
- 模块的测试资源与模块代码放在一起,职责内聚、便于维护;
- Resmoke 通过配置自动发现这些资源,无需硬编码路径;
- 当某个模块被禁用时,属于它的 jstests 会被自动从测试筛选中排除,避免跨模块误跑。
二、添加一个新模块:配置格式与字段语义
2.1 基本结构与示例
要添加新模块,只需在模块配置文件中定义模块名,并在其下指定fixture_dirs、hook_dirs、suite_dirs、jstest_dirs四个字段(均为目录路径列表)。原文档给出的最小完整示例:
my_new_module: fixture_dirs: - path/to/my_new_module/fixtures hook_dirs: - path/to/my_new_module/hooks suite_dirs: - path/to/my_new_module/suites jstest_dirs: - path/to/my_new_module/jstests2.2 字段详解
| 字段 | 作用 | 是否必填 |
|---|---|---|
fixture_dirs | 存放与该模块关联的 Fixture(测试环境的搭建器,如单机、副本集、分片集群)的目录 | 可省略或留空列表 |
hook_dirs | 存放与该模块关联的 Hook(测试执行前后的钩子,如校验、清理、监控)的目录 | 可省略或留空列表 |
suite_dirs | 存放模块自带套件(Suite,即测试运行配置)的目录 | 可省略或留空列表 |
jstest_dirs | 存放模块专属 JavaScript 测试的目录;当模块被禁用时,这些测试会从其他套件的配置中被过滤掉 | 可省略或留空列表 |
2.3 真实仓库中的模块配置
仓库内置的模块配置文件 buildscripts/resmokeconfig/resmoke_modules.yml 给出了三个真实模块的配置,可作为编写新模块配置的直接参照:
enterprise: jstest_dirs: - src/mongo/db/modules/enterprise/jstests streams: suite_dirs: - buildscripts/modules/streams/suites atlas: fixture_dirs: - buildscripts/modules/atlas/fixtures hook_dirs: - buildscripts/modules/atlas/hooks suite_dirs: - buildscripts/modules/atlas/suites matrix_suite_dirs: - buildscripts/modules/atlas/matrix_suites jstest_dirs: - src/mongo/db/modules/atlas/jstests从中可以看出一个工程事实:并非每个模块都必须声明全部四个字段。enterprise模块只声明了jstest_dirs,streams模块只声明了suite_dirs,而atlas模块则完整声明了 fixture、hook、suite、matrix suite、jstest 五类目录。这也印证了原文档 Notes 中“字段可以省略或为空列表”的约定。此外,atlas模块还展示了另一个仓库实际支持的字段matrix_suite_dirs(矩阵套件目录),它专门服务于测试矩阵配置(matrix suites),源码解析见 buildscripts/resmokelib/configure_resmoke.py 与 buildscripts/resmokelib/suitesconfig.py。
三、模块加载与过滤的底层实现
3.1 配置文件的读取与校验
Resmoke 启动时,通过--resmokeModulesPath参数(默认值为buildscripts/resmokeconfig/resmoke_modules.yml)定位模块配置文件,默认路径定义在 buildscripts/resmokelib/config.py。随后 buildscripts/resmokelib/configure_resmoke.py 中的_get_module_configs()使用yaml.safe_load加载该文件,得到模块名到配置字典的映射。
_set_up_modules()(见 buildscripts/resmokelib/configure_resmoke.py)是模块处理的枢纽,其流程可概括为:
- 校验启用的模块存在:遍历
_config.MODULES中的每个模块名,若不在配置文件内则抛出RuntimeError; - 重置全局状态:将
MODULE_SUITE_DIRS、MODULE_MATRIX_SUITE_DIRS、MODULE_DISABLED_JSTEST_DIRS置空,避免多次 Resmoke 调用在共享 Python 环境中重复加载; - 逐个模块处理:对配置中的每个模块(无论启用与否)执行加载或过滤逻辑。
3.2 模块“存在性”判定:fixture_dirs 与 hook_dirs 是硬依赖
源码注释与实现(buildscripts/resmokelib/configure_resmoke.py)揭示了一个重要细节:
A module is considered "present" when the dirs that are actually imported (fixture_dirs and hook_dirs) all exist. suite_dirs and jstest_dirs are optional path hints...
也就是说,只有fixture_dirs与hook_dirs中列出的目录被真正导入(import),因此这两类目录是判断模块是否“存在/可加载”的硬性条件;而suite_dirs和jstest_dirs只是可选路径提示——如果它们不存在(例如在 Bazel 沙箱中只声明了 data 依赖的场景),模块的 Python 代码依然能正确加载。
具体逻辑为:仅当模块处于启用状态且所有fixture_dirs、hook_dirs指向的目录都存在时,才执行以下加载动作:
- 将
fixture_dirs与hook_dirs中的每个目录通过 buildscripts/resmokelib/utils/autoloader.py 的load_all_modules动态导入(fixture 和 hook 只需被导入一次,Resmoke 即可识别并注册它们); - 将存在的
suite_dirs追加到MODULE_SUITE_DIRS; - 将存在的
matrix_suite_dirs追加到MODULE_MATRIX_SUITE_DIRS(并去重)。
3.3 禁用模块的 jstest 过滤
当模块未启用(或处于禁用状态)时,源码会收集其jstest_dirs到全局的MODULE_DISABLED_JSTEST_DIRS(buildscripts/resmokelib/configure_resmoke.py)。
真正的过滤动作发生在测试选择器 buildscripts/resmokelib/selector.py 的filter_module_tests()方法中:
def filter_module_tests(self): """Exclude tests that start directories of disabled module jstest dirs.""" if not config.MODULE_DISABLED_JSTEST_DIRS: return new_filtered = [] for test in self._filtered: in_disabled_module = False for disabled_jstest_dir in config.MODULE_DISABLED_JSTEST_DIRS: if os.path.normpath(test).startswith(os.path.normpath(disabled_jstest_dir)): in_disabled_module = True break if not in_disabled_module: new_filtered.append(test) self._filtered = new_filtered这段实现与原文档 Notes 中的描述完全对应:启用模块时,任何套件都可以使用任意目录下的 jstests,配置的jstest_dirs不起作用;只有模块被禁用时,才会过滤掉那些可能被其他模块的套件配置进来的测试。过滤采用路径前缀匹配(规范化后以disabled_jstest_dir开头),因此jstest_dirs中配置的目录层级需要与实际测试路径保持一致。
3.4 模块套件目录的合并与根路径解析
模块的 suite 目录最终会与内置套件目录合并。在 buildscripts/resmokelib/suitesconfig.py 的get_named_suites()中,套件搜索目录由三部分组成:
- 内置套件目录:
CONFIG_DIR/suites,根路径为RESMOKE_ROOT; - 模块套件目录(
MODULE_SUITE_DIRS):由于这些模块本身内置于 MongoDB 仓库,因此根路径同样解析为RESMOKE_ROOT; - 外部模块套件目录(
EXTERNAL_MODULE_SUITE_DIRS):根路径解析为EXTERNAL_MODULE_ROOT。
每个套件文件(.yml/.yaml)以其文件名(不含扩展名)作为套件短名注册,并记录其所属根路径(_suite_roots),供后续解析套件内测试路径时使用。外部模块的加载逻辑见 buildscripts/resmokelib/configure_resmoke.py,其 YAML 支持suite_directories、matrix_suite_directories、fixture_directories、hook_directories等键,且这些目录相对EXTERNAL_MODULE_ROOT(当前工作目录)解析。
四、命令行启用与禁用模块
4.1--modules参数
Resmoke 提供--modules参数控制启用的模块,定义于 buildscripts/resmokelib/run/init.py:
--modules MODULES Comma separated list of modules enabled, by default all modules that exist on dist will be enabled.参数的取值语义在 buildscripts/resmokelib/configure_resmoke.py 中解析:
| 取值 | 行为 |
|---|---|
default(默认值) | 尝试启用所有模块,即取模块配置文件中全部模块名 |
none | 不启用任何模块 |
逗号分隔的模块名列表,如enterprise,atlas | 仅启用列出的模块 |
| 空字符串 | 抛出RuntimeError,提示必须显式指定none |
4.2--resmokeModulesPath参数
--resmokeModulesPath(见 buildscripts/resmokelib/run/init.py)用于覆盖模块配置文件的路径,帮助“testing different configurations”(测试不同的配置组合)。该路径会相对于RESMOKE_ROOT解析后写入MODULES_CONFIG_PATH(buildscripts/resmokelib/configure_resmoke.py)。
4.3 实际使用示例
# 默认行为:启用发行版上存在的所有模块 python buildscripts/resmoke.py run --suites=core # 显式关闭所有模块(例如只想跑纯社区版测试) python buildscripts/resmoke.py run --suites=core --modules=none # 只启用 enterprise 与 atlas 两个模块 python buildscripts/resmoke.py run --suites=core --modules=enterprise,atlas # 使用自定义模块配置文件 python buildscripts/resmoke.py run --suites=core --resmokeModulesPath=my/config/modules.yml注意:上述命令假设已按仓库构建文档完成 mongod/mongos 等二进制构建,并用
--mongod/--mongos或环境配置指向对应可执行文件;--modules与--resmokeModulesPath均为可选的运行期参数。
五、编写新模块配置的最佳实践
结合原文档约定与仓库真实实现,编写模块配置时建议遵循以下要点:
- 目录路径相对仓库根目录书写。真实配置中
src/mongo/db/modules/enterprise/jstests、buildscripts/modules/atlas/suites等路径均以仓库根目录为基准,便于与RESMOKE_ROOT的拼接逻辑一致。 - fixture 与 hook 目录必须真实存在。二者是模块“存在性”判定的硬条件(见 buildscripts/resmokelib/configure_resmoke.py);若目录缺失,模块即便在启用列表中也不会加载其 Python 代码。
- suite 与 jstest 目录可以“迟到”存在。它们是可选路径提示,Bazel 沙箱等环境下即使目录未就绪,模块加载也不会失败。
- 按需声明字段,不用的字段直接省略(参考
enterprise、streams模块的极简写法),保持配置可读性。 - 记住禁用语义:
jstest_dirs只在模块被禁用时发挥过滤作用(前缀匹配过滤,见 buildscripts/resmokelib/selector.py),启用状态下任何套件仍可引用任意目录的 jstests。 - 矩阵套件单独声明:如果模块需要参与测试矩阵,使用
matrix_suite_dirs字段单独列出矩阵套件目录(参考atlas模块)。
六、总结
Resmoke 模块配置机制为 MongoDB 各功能模块提供了标准化的测试资源注册入口。通过 buildscripts/resmokeconfig/resmoke_modules.yml 这类 YAML 文件,模块可以声明自己的 fixtures、hooks、suites 与 JavaScript 测试目录;Resmoke 在启动阶段根据--modules与--resmokeModulesPath参数决定启用集合,并通过autoloader动态注册 fixture/hook 代码、合并套件目录、过滤禁用模块的 jstests。理解了配置字段语义与底层的 configure_resmoke.py、selector.py、suitesconfig.py 实现后,你便可以为任意新模块编写规范、可复用的 Resmoke 测试配置。
【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考