如何用insta crate测试PDF生成并实现可直观审阅的输出?
用insta测试二进制PDF文件的解决方案
针对insta默认不支持二进制文件的问题,有两种实用方案可以同时实现内容对比和PDF文件审阅:
方案一:分离生成与对比,保留PDF文件
直接将生成的PDF写入文件,再把文件内容转成十六进制字符串交给insta做快照对比,既验证内容一致性,又保留可直接打开的PDF文件:
use std::fs; use std::path::Path; #[test] fn test_generated_pdf() { let mut content = Vec::new(); // 生成PDF内容 to_pdf(&document, &mut content).expect("生成PDF失败"); // 指定保存路径(建议放在测试快照目录下) let pdf_path = Path::new("./tests/snapshots/generated_document.pdf"); // 确保父目录存在 fs::create_dir_all(pdf_path.parent().unwrap()).expect("创建目录失败"); // 写入PDF文件 fs::write(pdf_path, &content).expect("写入PDF文件失败"); // 将二进制内容转成十六进制字符串,交给insta做快照对比 assert_snapshot!("generated_document", hex::encode(&content)); }
方案二:自定义insta格式化器
通过实现insta的Formatter trait,让insta自动处理二进制PDF内容:既生成用于对比的文本快照,又保存PDF文件供审阅:
首先实现自定义格式化器:
use insta::internals::Formatter; use std::fmt; use std::fs; use std::path::Path; struct PdfFormatter; impl Formatter for PdfFormatter { fn format(&self, value: &dyn fmt::Debug) -> String { // 尝试将值转为二进制内容 if let Some(content) = value.downcast_ref::<Vec<u8>>() { // 保存PDF到快照目录 let pdf_path = Path::new("./tests/snapshots/generated_document.pdf"); let _ = fs::create_dir_all(pdf_path.parent().unwrap()); let _ = fs::write(pdf_path, content); // 返回十六进制字符串作为快照内容,用于insta对比 hex::encode(content) } else { // 非二进制内容按默认方式处理 format!("{:?}", value) } } }
然后在测试中使用该格式化器:
#[test] fn test_pdf_generation() { insta::with_settings!({ formatter: PdfFormatter, }, { let mut content = Vec::new(); to_pdf(&document, &mut content).expect("PDF生成失败"); assert_snapshot!("generated_document", &content); }); }
注意事项
- 需添加
hexcrate到Cargo.toml的测试依赖中,用于二进制与十六进制的转换 - 快照目录建议统一放在
tests/snapshots下,方便管理 - 若PDF文件较大,可使用SHA256哈希替代十六进制,减少快照文件体积
内容的提问来源于stack exchange,提问作者Emil L
相关产品推荐
相关产品推荐

