
NixpkgsredisTestHook实战指南在 checkPhase 自动拉起 Redis 测试服务器【免费下载链接】nixpkgsNix Packages collection NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgsredisTestHook是 Nixpkgs 提供的标准 setup hook用于在软件包的checkPhase期间自动启动一个 Redis实际为 Valkey 提供的redis-server二进制测试实例并在测试结束后自动停止。本指南基于 doc/hooks/redis-test-hook.section.md 与 pkgs/by-name/re/redisTestHook 的源码实现带你掌握其声明式用法、可调变量、自定义checkPhase的写法以及底层 hook 机制的工作原理使你的 Nix 包在构建阶段即可完成对 Redis 依赖的集成测试。redisTestHook 是什么在 checkPhase 自动拉起 RedisredisTestHook是 Nixpkgs 通过makeSetupHook生成的一个 setup hook定义见 package.nix。把它加入nativeCheckInputs后Nix 构建框架会自动将其中的preCheckHooks与postCheckHooks注入到checkPhase的执行流程中进入checkPhase之前即preCheck之后、测试命令执行之前自动执行redisStart启动一个 Redis 服务器checkPhase中的测试命令执行完毕后postCheck阶段自动执行redisStop关闭该服务器。整个生命周期由 hook 管理你不需要在checkPhase里手工写启动/清理逻辑也不必担心测试失败后残留 Redis 进程导致构建挂起详见下文底层实现一节关于输出重定向的设计。基础用法把 redisTestHook 加入 nativeCheckInputs最直接的用法是在stdenv.mkDerivation或其派生变体中声明依赖{ stdenv, redis, redisTestHook, }: stdenv.mkDerivation { # ... nativeCheckInputs [ redisTestHook ]; }需要说明的是这里的redis参数仅用于示例中的待测包依赖 Redis场景redisTestHook自身所需的redis-server/redis-cli二进制已通过substitutions内置见 package.nix 中的cli、server两个替换变量你无需手动传入redis当前仓库中redisTestHook实际替换的是Valkey提供的redis-server与redis-cli可执行文件lib.getExe valkey redis-cli/lib.getExe valkey redis-serverValkey 是 Redis 的社区分支向下兼容 Redis 协议与命令行接口因此测试客户端无论连接redis-cli还是各语言 Redis 客户端均可正常工作若测试产物需要在 build 目录之外连接该服务器请结合各平台网络限制如 Darwin 下需要设置__darwinAllowLocalNetworking见下文的测试示例。使用自定义 checkPhase必须保留 runHook 调用如果你在包中覆写了checkPhase那么 hook 机制依赖的runHook preCheck/runHook postCheck调用必须保留否则redisStart与redisStop不会被执行{ checkPhase runHook preCheck # ... your tests runHook postCheck ; }这是 Nixpkgs 所有 setup hook 的通用约定preCheckHooks会在runHook preCheck处依次执行postCheckHooks会在runHook postCheck处依次执行。省略其中任何一行都会导致 hook 提前或延后触发甚至完全失效例如只写runHook preCheck而不写runHook postCheck测试结束后 Redis 进程将不会被清理。可调变量端口与 Unix Socket 路径hook 启动的 Redis 同时监听一个 TCP 端口和一个 Unix Domain Socket二者都可以通过变量覆盖。文档 redis-test-hook.section.md 明确列出的变量如下导出变量子进程可见变量含义默认值REDIS_SOCKETUnix domain socket 路径$NIX_BUILD_TOP/run/redis.sockREDIS_SOCKET会被export因此checkPhase中的测试脚本以及被测试程序都能通过环境变量感知 socket 位置。仅 Bash 可见变量不导出变量含义默认值redisTestPortRedis 监听的 TCP 端口6379注意redisTestPort是 Bash 专用变量不导出它只在 hook 自身的redisStart函数中读取你的测试脚本若要使用端口号需要自行引用$redisTestPort。覆盖端口与 socket 路径的示例{ stdenv, redis, redisTestHook, }: stdenv.mkDerivation { # ... nativeCheckInputs [ redisTestHook ]; preCheck redisTestPort6390; ; }同理在preCheck中设置REDIS_SOCKET/tmp/customredis.sock即可自定义 socket 位置。端口冲突或系统限制如根目录 /tmp 的挂载选项下的路径调整都可以在这一步完成。底层实现读懂 redis-test-hook.sh 的完整工作流hook 的全部逻辑集中在 redis-test-hook.sh全文仅 45 行注册与实现一目了然preCheckHooks(redisStart) postCheckHooks(redisStop)redisStart()的执行流程端口默认值若redisTestPort未设置或为空则置为6379准备运行目录mkdir -p $NIX_BUILD_TOP/runRedis 的配置与 socket 都放在构建目录内保证一次构建一个隔离实例socket 默认值若REDIS_SOCKET为空则设为$NIX_BUILD_TOP/run/redis.sock并export REDIS_SOCKET生成 Redis 配置文件$NIX_BUILD_TOP/run/redis.conf该路径同时被export为REDIS_CONF关键配置项包括unixsocket ${REDIS_SOCKET} port ${redisTestPort} protected-mode no enable-debug-command yes enable-module-command yesprotected-mode no允许从本机非回环地址访问方便测试程序使用 TCP 连接如经127.0.0.1:端口enable-debug-command yes与enable-module-command yes开启 Redis 的 DEBUG 与 MODULE 命令为需要调试命令或动态加载模块的测试场景提供能力启动服务器以server $REDIS_CONF /dev/null 21 后台启动server是makeSetupHook在实例化时替换为valkey包内redis-server的绝对路径并记录 PID 到REDIS_PID等待就绪循环执行cli --scan -s $REDIS_SOCKET即redis-cli --scan -s socket直到命令成功返回才继续保证进入测试前服务器已可接受连接避免竞态。redisStop()则简单地执行kill $REDIS_PID结束后台服务器。关于输出重定向的 Darwin 设计源码注释专门说明了 /dev/null 21的用意在 DarwinmacOS上如果后台进程的标准输出未被重定向父进程会变成 launchd 而不是 bash。这意味着一旦测试失败导致postCheck的redisStop未执行Redis 进程会残留并一直运行使 Nix 构建永久挂起。通过将输出重定向到/dev/null确保进程的父进程始终是 bash从而让kill能够可靠生效。这一细节是测试失败不挂死构建的关键保障也是 hook 实现值得借鉴之处。官方自测一个完整的真实使用样例Nixpkgs 为redisTestHook提供了自测用例 test.nix它同时验证了 TCP 端口与 Unix socket 两种连接方式是学习该 hook 用法的绝佳参考stdenv.mkDerivation { name redis-test-hook-test; nativeCheckInputs [ valkey redisTestHook ]; dontUnpack true; doCheck true; preCheck redisTestPort6380 REDIS_SOCKET/tmp/customredis.sock ; checkPhase runHook preCheck echo running test if redis-cli --scan -p $redisTestPort; then echo connected to redis via localhost PORT_TEST_RAN1 fi if redis-cli --scan -s $REDIS_SOCKET; then echo connected to redis via domain socket SOCKET_TEST_RAN1 fi runHook postCheck ; installPhase [[ $PORT_TEST_RAN 1 $SOCKET_TEST_RAN 1 ]] echo test passed touch $out ; __darwinAllowLocalNetworking true; }该测试暴露了几个值得照抄的实践点两个连接通道都测通过redis-cli --scan -p $redisTestPort验证 TCP 端口连接通过redis-cli --scan -s $REDIS_SOCKET验证 Unix socket 连接并以环境变量记录结果、在installPhase中断言保证两路连接都真正可用自定义端口与 socket在preCheck里同时覆盖redisTestPort6380与REDIS_SOCKET/tmp/customredis.sock证明两个变量均可按需调整Darwin 网络权限设置__darwinAllowLocalNetworking true允许测试在 macOS 沙箱中发起本地网络连接TCP 通道在 Darwin 下需要该授权。此外package.nix 的passthru.tests还注册了python3-valkey python3Packages.valkey即使用 Python 的 Valkey 客户端库作为集成测试的一部分验证 hook 与语言级客户端配合工作的场景。应用场景与注意事项小结推荐场景凡是构建期测试需要真实 Redis 实例的 Nix 包——例如 Redis 模块/命令扩展、缓存中间件、消息队列客户端、需要SET/GET/PUBLISH等真实行为的单元与集成测试——都可以通过一行nativeCheckInputs [ redisTestHook ];获得开箱即用的测试数据库。注意事项覆写checkPhase时务必保留runHook preCheck/runHook postCheckredisTestPort默认6379若与构建环境中的其他服务冲突请在preCheck中改用一个高位端口socket 与配置文件均位于$NIX_BUILD_TOP/run下随构建目录隔离无需手动清理测试命令需在runHook postCheck之前完成所有 Redis 交互因为postCheck阶段会立即kill服务器进程。结合 redis-test-hook.sh 的实现与 test.nix 的验证你可以在自己的 Nix 包中安全、可复现地启用构建期 Redis 测试同时理解其在端口、socket、进程生命周期与平台差异上的完整行为。【免费下载链接】nixpkgsNix Packages collection NixOS项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考