如何在独立测试库中访问OCaml库的私有定义?
解决方案
能否不公开私有函数访问?
可以实现,推荐用条件编译+Dune环境配置的方式:
- 在原库的
src.ml中,添加条件编译的私有模块导出,仅在测试环境下可见:
(* lib/src.ml *) let public_function = ... (* 私有函数 *) let private_function x = x + 1 (* 仅测试环境下导出内部模块 *) #ifdef TEST module Internal = struct let private_function = private_function end #endif
- 修改原库的
dune配置,给测试环境添加编译宏:
(library (name my_lib) (libraries base my_other_lib pp) (env (test (flags (:standard -DTEST)))))
- 在测试库的
dune中,依赖原库并启用测试环境:
(library (name Test_my_lib) (preprocess (pps ppx_inline_test ppx_expect)) (libraries base my_other_lib pp ppx_inline_test my_lib) (inline_tests) (env (test (flags (:standard -DTEST)))))
发布原库时,-DTEST不会被启用,Internal模块不会对外公开;测试编译时会启用宏,测试库就能通过My_lib.Internal.private_function访问私有函数。
若上述方法不适用,替代方案(不嵌入测试到原库)
如果不想用条件编译,可拆分出内部依赖库彻底分离代码:
- 调整目录结构,新增内部库存放私有实现:
lib_internal/ dune internal.ml internal.mli lib/ dune src.ml src.mli test/ dune test.ml
lib_internal/dune配置为基础库,公开所有需要测试的函数:
(library (name my_lib_internal) (libraries base))
- 原库
lib/dune依赖内部库,在src.ml中封装对外接口:
(library (name my_lib) (libraries base my_other_lib pp my_lib_internal))
src.ml中仅导出公开函数,私有逻辑调用My_lib_internal的实现。
- 测试库
test/dune直接依赖内部库:
(library (name Test_my_lib) (preprocess (pps ppx_inline_test ppx_expect)) (libraries base my_other_lib pp ppx_inline_test my_lib_internal) (inline_tests))
这种方式彻底分离公开接口、私有实现和测试代码,符合你想要的“不嵌入测试到原库”的最佳实践。
关于你尝试的独立.mli报错问题
你之前在测试模块添加独立.mli找不到源文件,大概率是路径问题:测试目录下的.mli无法直接引用lib目录的.ml文件。如果强行用这种方式,需在测试库的dune中添加(include_subdirs ../lib),但这会把原库代码纳入测试库,破坏“独立库”的设定,不推荐。
内容的提问来源于stack exchange,提问作者2048points
相关产品推荐
相关产品推荐

