Karma/Mocha单元测试中如何将失败时生成的Canvas图片纳入报告?
在Karma/Mocha中展示测试失败的Canvas错误图片
我之前做视觉回归测试时也碰到过这个问题——Karma跑在浏览器环境里确实没法直接操作文件系统,但我们可以通过把图片数据传到Node端或者直接嵌入HTML报告的方式解决,给你几个实用的方案:
方案一:用现成的视觉回归插件(最省心)
直接用集成好的插件就行,不用自己折腾base64和文件操作。比如karma-visual-regression,它内置了类似pixelmatch的对比逻辑,失败时会自动生成差异图并嵌入测试报告。
步骤:
- 安装插件:
npm install karma-visual-regression --save-dev
- 在
karma.conf.js里配置:
module.exports = function(config) { config.set({ frameworks: ['mocha'], reporters: ['visual-regression', 'spec'], visualRegression: { basePath: 'tests/reference-images', // 存放正确图片的目录 diffPath: 'tests/diff-images', // 差异图保存目录 generateDiff: true, // 开启差异图生成 threshold: 0.1 // 像素差异阈值 }, plugins: [ 'karma-mocha', 'karma-chrome-launcher', 'karma-visual-regression' ], browsers: ['ChromeHeadless'] }); };
- 测试代码里直接用插件的对比方法:
const { compare } = require('karma-visual-regression'); it('should match the reference image', function(done) { // 生成你的测试Canvas const testCanvas = document.createElement('canvas'); const ctx = testCanvas.getContext('2d'); // ... 绘制测试内容到canvas // 对比测试canvas和参考图片(会自动读取reference-images里的test-image.png) compare(testCanvas, 'test-image.png', done); });
测试失败后,插件会在diff-images目录生成差异图,并且在HTML报告里直接展示参考图、测试图和差异图,非常直观。
方案二:手动实现(自定义程度更高)
如果不想用现成插件,也可以自己处理图片数据,核心思路是把Canvas转成base64,再传递到报告里:
1. 测试代码里获取错误图的base64
在pixelmatch检测到差异时,把测试用的Canvas转成base64字符串,塞进错误信息里:
it('should match reference image', function(done) { const testCanvas = document.createElement('canvas'); const referenceCanvas = document.createElement('canvas'); // ... 加载参考图片到referenceCanvas,绘制测试内容到testCanvas const diffCanvas = document.createElement('canvas'); const diffCount = pixelmatch( testCanvas.getContext('2d').getImageData(0, 0, 500, 500).data, referenceCanvas.getContext('2d').getImageData(0, 0, 500, 500).data, diffCanvas.getContext('2d').getImageData(0, 0, 500, 500).data, 500, 500, { threshold: 0.1 } ); if (diffCount > 0) { // 把测试图转成base64 const errorImageBase64 = testCanvas.toDataURL('image/png'); // 把base64放进错误消息,方便后续reporter解析 throw new Error(`Image mismatch: ${diffCount} pixels differ. Error image: ${errorImageBase64}`); } done(); });
2. 用HTML报告插件嵌入图片
用karma-htmlfile-reporter生成HTML报告,然后自定义模板把base64图片显示出来:
- 安装插件:
npm install karma-htmlfile-reporter --save-dev
- 在
karma.conf.js配置:
module.exports = function(config) { config.set({ reporters: ['html'], htmlReporter: { outputFile: 'tests/test-report.html', templatePath: __dirname + '/test-report-template.html' // 自定义模板路径 } }); };
- 写一个简单的自定义模板
test-report-template.html,解析错误消息里的base64并显示图片:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Test Report</title> <style> .failed { color: red; } img { max-width: 500px; margin: 10px 0; } </style> </head> <body> <h1>Unit Test Report</h1> {{#each suites}} <div class="suite"> <h2>{{description}}</h2> {{#each tests}} <div class="test {{status}}"> <h3>{{description}} - {{status}}</h3> {{#if error}} <p>{{error.message}}</p> {{#if error.message.match(/data:image\/png;base64,/)}} <img src="{{error.message.match(/data:image\/png;base64,[^\s]+/)[0]}}" alt="Error Image"> {{/if}} {{/if}} </div> {{/each}} </div> {{/each}} </body> </html>
这样生成的HTML报告里,失败的测试会直接显示对应的错误图片,不用额外打开文件。
3. 自定义Reporter保存图片到本地(可选)
如果不想把base64嵌进报告(怕报告太大),可以写一个自定义Karma Reporter,把base64数据传到Node端保存成文件,再在报告里加链接:
在karma.conf.js里添加自定义Reporter:
const fs = require('fs'); const path = require('path'); function ImageSaveReporter(baseReporterDecorator, config) { baseReporterDecorator(this); // 创建错误图片保存目录 const errorImageDir = path.join(config.basePath, 'tests/error-images'); if (!fs.existsSync(errorImageDir)) { fs.mkdirSync(errorImageDir, { recursive: true }); } this.onSpecComplete = function(browser, result) { if (result.failed && result.error) { // 提取错误消息里的base64 const base64Match = result.error.message.match(/data:image\/png;base64,([^\s]+)/); if (base64Match) { const imageName = `${result.description}-${Date.now()}.png`; const imagePath = path.join(errorImageDir, imageName); // 保存图片到本地 fs.writeFileSync(imagePath, base64Match[1], { encoding: 'base64' }); // 更新错误消息,添加图片链接 result.error.message += `<br><a href="${imagePath}">查看错误图片</a>`; } } }; } ImageSaveReporter.$inject = ['baseReporterDecorator', 'config']; module.exports = function(config) { config.set({ reporters: ['spec', 'image-save'], plugins: [ // 其他插件 { 'reporter:image-save': ['type', ImageSaveReporter] } ] }); };
这样测试失败时,会把错误图片保存到tests/error-images目录,并且在控制台报告里显示链接。
内容的提问来源于stack exchange,提问作者sbat
相关产品推荐
相关产品推荐

