资讯动态

ScyllaDB test.py 回归测试框架实战:环境配置、运行机制与调试指南

发布时间:2026/9/14 10:16:15 来源:尧图企业网站定制
ScyllaDB test.py 回归测试框架实战环境配置、运行机制与调试指南【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb本文围绕 ScyllaDB 仓库自带的回归测试工具test.py展开它是运行 C 单元测试、CQL 测试和 Python 集成测试的统一入口。读完本篇你可以独立完成测试环境搭建、按目录/用例/表达式精确筛选测试、理解 pytest 封装与 pytest-xdist 并行的底层机制并掌握 CQL 审批测试、Boost 单测和拓扑类测试的日志定位与调试方法。框架定位test.py 是 pytest 的薄封装ScyllaDB 仓库根目录下的 test.py 是随源码一起发布的回归测试框架regression testing harness负责运行 C 单元测试、CQL 测试和 Python 测试。从源码结构看它的核心逻辑非常清晰启动时通过ninja查询当前仓库配置的构建模式build modes构建一组 pytest 命令行参数调用pytest.main()完成测试发现、收集与执行。也就是说测试发现discovery、收集collection和执行完全交由 pytest 及其收集器完成收集器定义在 test/pylib 目录下。每个测试目录test/下的子目录包含一个test_config.yaml文件声明套件suite类型和选项例如 test/boost/test_config.yaml、test/cqlpy/test_config.yaml、test/cql/test_config.yaml。pytest 收集器依据这些配置定位测试文件套件类型文件匹配规则CBoost/Seastar*_test.ccCQL*_test.cqlPython*_test.py或test_*.py仓库根目录下./testlog目录用于存放构建产物测试输出、框架输出Scylla 数据文件则存放在/tmp。安装与运行环境Python 版本与依赖运行test.py需要Python 3.11 或更高版本。这一点在 test.py 末尾被硬性校验if sys.version_info (3, 11): print(Python 3.11 or newer is required to run this program) sys.exit(-1)仓库提供的 install-dependencies.sh 会安装所需的全部 Python 模块。如果你的发行版不被该脚本支持请按脚本中列出的模块手动用pip安装。另外也可以用toolchain/dbuild来运行test.py$ ./tools/toolchain/dbuild ./test.py使用 toolchain 容器时无需再执行./install-dependencies.sh。--gather-metrics与 cgroup 要求test.py默认启用--gather-metrics参数用于从 cgroup 采集测试期间的 CPU/RAM 用量。这要求执行test.py的当前终端进程位于一个当前用户具有读写权限的 cgroup 中。部分桌面环境会自动把进程放入用户拥有的 scope 或 slice有些环境不会。可以按以下步骤检查查看当前 cgroup$ cat /proc/self/cgroup输出形如0::/user.slice/user-1000.slice/user1000.service/app.slice/取::之后的路径前置/sys/fs/cgroup后检查权限$ ls -la /sys/fs/cgroup/user.slice/user-1000.slice/user1000.service/app.slice/所有条目的属主都应是当前用户说明条件满足。若不满足有四种替代方案通过 toolchain 运行test.py运行时追加--no-gather-metrics并可做成持久别名$ echo alias testpy./test.py --no-gather-metrics ~/.profile $ source ~/.profile之后用testpy别名即可关闭指标采集。用systemd-run启动$ systemd-run --user --scope ./test.py同样可以做成别名。手动创建 cgroup 并把当前终端进程放入其中$ mkdir /sys/fs/cgroup/user.slice/user-1000.slice/user1000.service/test_py.slice $ echo $! | sudo tee /sys/fs/cgroup/user.slice/user-1000.slice/user1000.service/test_py.slice/cgroup.procs该方案需要sudo权限因为修改进程 cgroup 需要对旧、新两个 cgroup 都有读写权限。注意每次打开新终端都要重新执行。Docker 镜像部分测试会利用嵌套的Docker 镜像提供 mock/测试服务用来承载 Scylla 的对外依赖特性。这些镜像一般在测试首次使用时被拉取例如docker.io/fsouza/fake-gcs-server:1.52.3。常用用法调用test.py前必须先完成构建。./test.py不带参数时会运行所有已配置构建模式下的全部测试$ ./test.py常用选择方式可自由组合多个路径与选项# 只运行某个构建模式 $ ./test.py --modedev # 只运行某个目录下的测试 $ ./test.py test/cqlpy/ # 只运行某个具体测试文件 $ ./test.py test/cqlpy/test_null.py # 运行某个文件内的具体用例Boost 套件支持 file.cc::casename 形式 $ ./test.py test/boost/aggregate_fcts_test.cc::test_aggregate_avg支持-k表达式按测试名过滤$ ./test.py -k test_null or test_empty # 名称包含 test_null 或 test_empty $ ./test.py -k not test_slow # 排除名称包含 test_slow 的用例使用--skip跳过匹配模式的测试$ ./test.py --skip test_slow从源码看-k与--skip在 test.py 中被声明为互斥参数同时给出会直接报错--skip的实现方式是把每个模式转换为not pattern后用and拼接再作为-k表达式传给 pytest。若未提供任何路径默认执行test/全目录见 test.py 的files_to_run回退逻辑。构建模式集合定义在 test/init.py 中debug、release对应 RelWithDebInfo、dev、sanitize、coverage。运行机制HOST_ID 与并行隔离HOST_ID是一个由主机名和当前时间派生的短哈希也可通过环境变量SCYLLA_TEST_HOST_ID显式指定生成逻辑见 test/init.pyHOST_ID os.environ.get(SCYLLA_TEST_HOST_ID) if HOST_ID is None: HOST_ID hashlib.sha3_224((socket.gethostname() str(time.time())).encode(utf-8)).hexdigest()[:5]它被附加到日志文件名、报告路径和指标数据库上从而保证 Jenkins 把多个 CI 构建节点的结果汇聚到同一目录时互不覆盖。并发度ThreadsCalculator测试通过pytest-xdist并行执行test.py 中还指定了--distworksteal工作窃取调度。worker 进程数由可用 CPU 核数、系统内存和构建模式共同决定核心算法是 test.py 中的ThreadsCalculator类系统内存预留取「总内存 / 16」并限制在 5 GB ~ 8 GB 之间其余内存视为可分配给测试的量单测试内存预算总内存 / 8debug 模式上限 5 GB非 debug 模式上限 4 GB若处于 debug 模式再乘以 1.5CPU 维度每个测试任务在 debug 模式按 1.5 核估算、非 debug 模式按 1.0 核估算最终 worker 数 min(内存维度上限, CPU 维度上限)可再乘--threads-multiplier系数调整。你也可以直接用--jobs/-j指定并发数或用--cpus限定测试运行在哪些 CPU 上taskset 格式。其他值得注意的运行行为./testlog目录不存在则创建存在则清空上一次运行的产物即使有测试失败test.py也会跑完全部测试才退出退出码为 5 表示没有收集到任何测试test.py 会提示检查测试名、模式和标记运行结束时还会打印 CPU 利用率统计test.py退出码刻意保持在 0-124、126-127 范围内以兼容git bisect的期望test.py。CQL 测试审批测试Approval TestingCQL 测试的核心思想是测试作者只负责编写针对 Scylla 执行的 CQL 语句其余几乎全部由test.py代劳——语句的输出被记录到专用文件中之后用于校验测试的正确性。这种先人工确认初始基线、后续自动比对的方法被称为审批测试approval testing。执行链路实现于 test/pylib/cql_repl.py自定义的 pytest 文件收集器识别以_test.cql结尾的文件源码中CQL_TEST_SUFFIX _test.cql由CqlTest.runtest()方法完成实际执行——读取 CQL 输入文件通过 CQL 数据库连接对已启动的 Scylla 实例逐条求值并用 tabulate 以表格形式把输出写入testlog下的临时输出文件。默认 keyspace 会被自动创建。最后测试将临时文件中的输出与预录的输出文件test/suitename/testname_test.result比对。测试在以下情况被判为失败执行某条 CQL 语句时产生错误例如服务器在执行过程中崩溃服务器输出与testname.result中记录的不一致testname.result不存在通常是该测试首次运行的情形。输出不匹配时会生成test/suitename/testname_test.reject文件并打印两份文件 diff 的前几行。确认无误后用 reject 文件覆盖.result文件即可更新基线mv test/suitename/testname.re*注意.result文件实际上是测试的一部分。开发者必须仔细审查 diff理解每一处变更的原因后才能覆盖.result文件。调试 CQL 测试调试 CQL 测试的常用办法是对一台独立启动的 Scylla可以放在调试器里启动用cqlsh手动执行同样的 CQL 语句进行复现。单元测试Boost / Seastar同一份单元测试可以在不同的 seastar 配置下运行即使用不同的命令行参数。自定义参数写在test_config.yaml的custom_args键下。例如 test/boost/test_config.yaml 中为多个测试指定了 reactor 核数与内存custom_args: mutation_reader_test: - -c3 -m2G scrub_test: - -c1 -m2G --logger-log-level compactiondebug --logger-log-level compaction_managerdebug ... sstable_test: - -c1 -m2GBoost 套件中的测试被划分为 test-cases即由BOOST_AUTO_TEST_CASE、SEASTAR_TEST_CASE等宏包裹的顶层函数因此支持上文path/to/file_name.cc::casename的用例级选择。该文件还展示了run_first长耗时测试优先启动、no_parallel_cases用例间有依赖、不能逐用例并行等 suite 级配置。调试单元测试测试失败时其日志位于testlog/{mode}/{suitename}.{testname}.{casename}_stdout.{run_id}.log例如testlog/dev/boost.aggregate_fcts_test.test_aggregate_avg_stdout.1.log。默认所有单元测试都会以 stripped 方式构建。如需保留调试符号可用./configure加--tests-debuginfo list-of-tests参数指定需要非 stripped 构建的测试列表。另外test.py还会为单元测试追加一些命令行参数。Python 测试test.py支持 pytest 的标准测试写法在其test_config.yaml中声明Python类型的套件目录下会为一组测试创建独立的服务器实例并把连接 URI 传给测试。借助便捷 fixtures测试作者无需自己创建或清理连接、keyspace。test.py会跟踪正在使用的服务器并在所有使用它的测试结束后关闭服务器。部分套件提供名为run的便捷辅助脚本更多说明见 test/cqlpy/README.md 与 test/alternator/README.md。pytest 套件中所有测试都是 test-cases——以test_开头的顶层函数——因此同样支持path/to/test_file.py::casename形式的用例选择。服务器共享与隔离机制为什么共享服务器一个目录下可能存在大量 pytest如 cqlpytest.py会用多个pytest-xdistworker 并行执行它们每个 worker 拥有各自的服务器。在单个 worker 内部则按测试文件为单位创建集群供该文件内所有测试用例共享以节省 setup/teardown 开销。这种提速方式在测试失败时也会让调试变复杂——所以应避免在测试中留下全局残留物即使测试失败了。典型做法是使用内置的keyspace()fixture 创建随机命名的 keyspace。每个测试开始和结束时test.py都会对所用服务器做健康检查服务器应处于正常运行状态服务器中不应包含任何非 system keyspace。调试失败的 pytest要完整定位一个失败的 pytest需要找到运行它所用的服务器以及服务器日志中的相关片段。测试经pytest-xdistworkergw0、gw1……并行运行每个 worker 把日志写到testlog/pytest_log/pytest_gw{N}_{HOST_ID}.log其中包含集群生命周期消息和测试通过/失败状态。例如假设cqlpy/test_null.py失败worker 日志中会出现INFO installing Scylla server in .../testlog/dev/scylla-gw0-1... INFO starting server at host 127.1.191.1 in scylla-gw0-1... INFO started server at host 127.1.191.1 in scylla-gw0-1, pid 675 INFO Leasing Scylla cluster ... for test gw0.cqlpy.test_null.1 INFO Test gw0.cqlpy.test_null.1 failed从这些消息即可定位服务器工作目录testlog/dev/scylla-gw0-1/和服务器日志testlog/dev/scylla-gw0-1.log。服务器日志中带有测试开始/结束的特殊标记------ Starting test gw0.cqlpy.test_null.1 ------ ... ------ Ending test gw0.cqlpy.test_null.1 ------每个测试的失败输出pytest traceback被捕获在testlog/pytest_tests_logs/下例如testlog/pytest_tests_logs/cqlpy-test_null.py-test_insert_null_key.dev.1-call-c8a46.log扩展日志可以使用标准logging模块 API。调试结束后无需手动清理test.py下次执行时会自动清掉上次残留。服务器隔离实现细节运行多个服务器时要避免 host/port 或临时目录冲突并保证即使test.py被用户中断或因异常退出也不会留下仍在运行的服务器。为此test.py内部维护了一个专门的服务器注册表registry为每个服务器分配127.*.*.*子网内的唯一地址。只要不是被SIGKILL杀死test.py都会在退出时关闭它创建的所有服务器。测试用的服务器使用一组预定义的启动选项以加快开机速度其中一些是仅供开发使用的选项如flush_schema_tables_after_modification: false。如果需要扩展所用服务器的选项可以在test_config.yaml中添加extra_scylla_cmdline_options或extra_scylla_config_options。实际配置可见# test/cqlpy/test_config.yaml extra_scylla_cmdline_options: - --rf-rack-valid-keyspaces1 - --enable-tabletstrue# test/cluster/test_config.yaml extra_scylla_config_options: authenticator: AllowAllAuthenticator authorizer: AllowAllAuthorizer拓扑类 pytestmanager fixture部分 pytest 套件运行在 Scylla 集群上并支持拓扑操作标准managerfixture 为这些测试提供能力通过它访问各个节点、启动/停止/重启实例、向集群添加或移除节点。从源码结构看managerfixture 通过一个「集群管理器」驱动集群——它是一个运行在独立事件循环上的进程内 Python 对象调用会被桥接到该事件循环上。这保证测试框架完全知晓所有拓扑操作并在测试结束时清理资源包括新增的服务器。test.py能自动检测集群是否因被操作过而不能与后续测试共享。目前的判定相当直接任何发生过节点增删、启动或停止的集群哪怕最终恢复到与测试开始时相同的状态也被视为脏dirty。这样的集群不会被下一个测试用例复用而是被销毁并重建新集群。测试指标Metrics--gather-metrics参数用于采集测试期间的 CPU/RAM 用量来自 cgroup以及系统整体 CPU/RAM 使用率。指标以 SQLite 数据库形式存储在testlog/sqlite_{HOST_ID}.db位于testlog目录中包含以下表表名内容tests执行的测试列表含测试名、目录、架构和构建模式test_metrics每个测试的指标内存峰值、CPU 用量、耗时system_resource_metrics整个运行期间的系统 CPU/内存使用率百分比cgroup_memory_metrics测试运行期间的 cgroup 内存用量自动化、CI 与 Jenkins任何测试失败时test.py都会返回非零退出状态。汇总的 JUNIT XML 报告写入testlog/report/pytest_cpp_{HOST_ID}.xml路径构造见 test.pyJenkins 用它生成格式化构建报告。如果这还不够CI 中也可以进行与本地类似的调试之旅进入 Jenkins 构建页面的 Build artifacts那里保存了测试失败时 Jenkins 保留的全部测试日志目录。测试稳定性实践测试本身很难测试 ScyllaDB 更难但目标是让测试套件尽可能稳固。第一步就是贡献一个稳定即非 flaky的测试在开发测试时请(1) 在 debug 模式下运行并 (2) 连续运行 100 次使用--repeat 100确认全部通过。Allure 报告为了让测试结果分析更方便ScyllaDB 引入了 Allure 报告工具。toolchain 镜像中已包含allure-pytestPython 模块并新增了采集 Allure 数据的参数test.py会把--alluredir指向testlog/report/allure_{HOST_ID}。但 Allure 二进制本身不包含在 toolchain 镜像中要充分利用该报告工具需在本机安装 Allure。安装时按 Allure 官方文档的 Linux 安装方式操作即可。注意rpm 包依赖default-jre-headless但在 Fedora 38/39 上没有任何包提供该依赖需要手动安装 Allure。基本用法打开存放测试结果目录例如testlog/report/执行allure serve展示报告$ allure serve -h localhost .系统默认浏览器会打开交互式 Allure 报告。更多参数可参考allure -h。命令行参数速查完整的命令行帮助可用$ ./test.py --help结合 test.py 的参数定义常用选项包括参数说明name位置参数测试名或测试文件路径列表可为空默认全部--mode只运行指定构建模式的测试可多次指定--jobs/-j并发 worker 数默认由ThreadsCalculator计算--threads-multiplier并发数倍率小于 1.0 减少线程大于 1.0 增加--repeat重复执行次数稳定性验证可用--repeat 100--timeout单个测试的超时时间默认 3600 秒--session-timeouttest.py/pytest 会话超时默认 24000 秒-kpytest 表达式按名称过滤与--skip互斥--skip跳过匹配模式的测试--markers按 pytest mark 表达式过滤如not slow目前仅 Python 测试支持--list只打印测试列表而不执行--save-log-on-success/-s成功时也保留日志并跳过运行前清理--no-parallel-cases不逐用例并行--cpus仅使用指定 CPU 运行测试taskset 格式--gather-metrics/--no-gather-metrics是否采集 cgroup/系统指标--coverage/--coverage-mode处理覆盖率数据并生成 lcov 报告--manual-execution在脚本本应运行测试可执行文件时暂停交由手动运行--pytest-arg向 pytest 透传额外参数如--pytest-arg-v -x--extra-scylla-cmdline-options为所有测试追加 Scylla 命令行选项如--logger-log-level rafttrace--tmpdir测试数据与日志目录默认testlog此外--skip-internet-dependent-tests可跳过依赖互联网资源的测试--exe-path/--exe-url支持直接测试外部可执行文件与--mode互斥。小结test.py以极薄的封装层把 ScyllaDB 的三类测试统一收敛到 pytest 生态test_config.yaml声明套件行为自定义收集器处理.cql等特殊格式pytest-xdist 与ThreadsCalculator负责按机器资源动态分配并发HOST_ID与服务器注册表保证多机、多 worker 场景下的结果隔离与资源回收。掌握本文的用法与日志定位路径后无论是本地复现一个失败的 CQL 审批用例还是在 CI 中追溯某个拓扑测试的服务器日志都有了明确的入手路径。【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价