我有一个使用 Jest 运行的测试套件。我想在任何失败的测试后触发一个钩子,最好是测试上下文仍然可用。
具体来说,我通过 jest-puppeteer 使用 Puppeteer。目标是在测试失败后、在 tearDown 函数中关闭页面之前截取页面的屏幕截图。
实现这一目标的最佳方法是什么?
我的测试套件的一个例子:
describe('My tests', () => {
beforeAll(async () => {
await page.goto('http://example.com');
});
// TODO I need something like this
onFailure(async (something) => {
page.takeScrenshot();
});
test('My example test', async () => {
return await page.waitFor('.example-selector');
});
});
我发现设置测试运行程序时有 onTestFailure 选项,是否可以利用它?
是的,您可以在设置 Jest 时使用 onTestFailure 选项,以在任何失败的测试后触发挂钩。此选项接受一个回调函数,该函数将以测试结果对象作为参数进行调用,其中包含有关失败测试的信息,例如其标题和错误消息。
以下是如何使用 onTestFailure 选项在测试失败后截取页面屏幕截图的示例:
const jestPuppeteer = require('jest-puppeteer');
jest.setTimeout(30000);
process.on('unhandledRejection', (reason, p) => {
console.error('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
const config = {
launch: {
headless: true,
slowMo: 100,
args: ['--no-sandbox']
},
server: {
command: 'node server.js',
port: 4444,
launchTimeout: 10000,
debug: true
},
onTestFailure: async (testResult) => {
await page.screenshot({path: `./screenshots/${testResult.testFilePath}-${testResult.fullName}.png`});
},
};
module.exports = jestPuppeteer.configure(config); 这将在测试结果对象的任何失败测试后调用 onTestFailure 函数,您可以使用 testFilePath 和 fullName 创建文件名来保存屏幕截图。
请注意,要使上面的示例正常工作,您需要在 onTestFailure 函数的范围内提供可用的页面对象,如果您使用 Jest-puppeteer,则可以使用该变量。
您还可以考虑使用 afterEach 在每次测试后关闭浏览器,并添加一个条件来检查测试是否失败,并在这种情况下截图。
describe('My tests', () => {
let page;
beforeAll(async () => {
page = await browser.newPage();
await page.goto('http://example.com');
});
afterEach(async () => {
if (test.hasFailed()) {
await page.screenshot({path: `./screenshots/${testResult.testFilePath}-${testResult.fullName}.png`});
}
await page.close();
});
test('My example test', async () => {
return await page.waitFor('.example-selector');
});
});
这应该有帮助。
您可以使用 Jest 的内置生命周期挂钩以及 Puppeteer 的 page.screenshot() 方法来捕获测试失败的屏幕截图。具体来说,您可以利用 afterEach 并通过检查测试对象来检查测试失败。以下是如何设置挂钩来触发失败测试的屏幕截图:
使用 afterEach 挂钩:每次测试后,都会调用此 Jest 生命周期挂钩。
验证测试是否失败:要查明测试是否失败,请使用expect.getState()方法。
页面截图:测试失败时,使用页面截图.screenshot()。
describe('My tests', () => {
beforeAll(async () => {
await page.goto('http://example.com');
});
// This runs after every test
afterEach(async () => {
// Check if the current test failed
const { currentTestName, testPath } = expect.getState();
if (expect.getState().currentTest.errors.length > 0) {
console.log(`Test failed: ${currentTestName}`);
// Create a screenshot with a unique name based on the test name
const screenshotPath = `./screenshots/${currentTestName.replace(/\s+/g, '_')}.png`;
await page.screenshot({ path: screenshotPath });
console.log(`Screenshot captured: ${screenshotPath}`);
}
});
test('My example test', async () => {
await expect(page).toMatchElement('.example-selector');
});
test('Another failing test', async () => {
await expect(page).toMatchElement('.non-existent-selector');
});
});