咨询TAP::Harness::JUnit与prove实时刷新STDOUT输出的配置选项
我之前也碰到过这个一模一样的问题,折腾了好一会儿才搞明白——本质是TAP::Harness::JUnit为了生成完整的JUnit XML报告,默认会缓冲测试脚本的输出;而直接用perl运行时,终端环境下STDOUT默认是行缓冲模式,所以能实时看到输出。下面给你几个可行的解决方案,既能实时刷新STDOUT,又能正常生成XML报告:
1. 在测试脚本中强制关闭输出缓冲
最简单的办法就是在测试脚本的开头加一行代码,强制让STDOUT不缓冲:
BEGIN { $| = 1; }
这行代码会在脚本启动的瞬间就把STDOUT设置为无缓冲模式,不管是prove还是JUnit harness调用它,输出都会实时刷到终端。如果你的测试脚本是用Test::More这类框架写的,完全不用担心兼容性,不会影响测试结果的收集。
2. 通过prove传递参数全局关闭缓冲
要是不想修改测试脚本,可以通过prove的-e参数给perl传递命令,全局开启无缓冲:
prove -v --timer --harness=TAP::Harness::JUnit -MIO::Handle -e '$|=1;' <script name>
这里-MIO::Handle确保加载了必要的模块,-e '$|=1;'会在perl启动时执行关闭缓冲的代码,效果和修改脚本一样,但不用动你的测试文件。
3. 拆分TAP输出与JUnit转换(更灵活的方式)
如果上面两种方法还是有问题,可以换个思路:先用prove正常运行测试(保证实时输出),再把TAP输出转换成JUnit XML。你已经装了TAP::Harness::JUnit,那tap2junit工具应该也可用,试试这条命令:
prove -v --timer <script name> | tee test-output.tap | tap2junit --output junit-report.xml
这样做的好处是:
prove用默认的TAP harness运行,完全不会缓冲,实时输出测试细节tee把原始的TAP输出同时保存到文件,方便后续调试tap2junit把TAP内容转换成标准的JUnit XML文件
这种方式彻底避开了TAP::Harness::JUnit的缓冲问题,还保留了原始输出,实用性拉满。
额外小技巧:指定JUnit XML的输出文件
默认情况下,TAP::Harness::JUnit会把XML输出到STDOUT,可能会和prove的日志混在一起。你可以通过--formatter-args参数指定XML输出到文件,再结合缓冲关闭方法,体验更好:
prove -v --timer --harness=TAP::Harness::JUnit --formatter-args '{"output" : "junit-report.xml"}' <script name>
这样XML会乖乖写到指定文件里,prove的-v日志则实时输出到终端,完美达成你的需求。
内容的提问来源于stack exchange,提问作者Sudhir Mishra

