Selenium TakesScreenshot生成损坏图片,Cucumber报告异常求助
解决Cucumber报告中截图偶尔损坏的建议
针对你遇到的截图损坏导致报告无内容的问题,可尝试以下几种方案:
1. 增加截图重试机制
偶尔截图失败可能是浏览器渲染未完成或WebDriver临时响应异常,通过重试可以降低概率:
private void takeScreenshotIfScenarioFailed() { if (Context.scenario.isFailed()) { byte[] screenshot = null; int retryCount = 3; // 重试3次 while (retryCount > 0 && screenshot == null) { try { screenshot = ((TakesScreenshot) Context.driver).getScreenshotAs(OutputType.BYTES); // 简单验证字节数组有效性 if (screenshot.length < 100) { // 有效PNG至少有几百字节 screenshot = null; retryCount--; Thread.sleep(500); // 间隔500ms重试 } } catch (Exception e) { retryCount--; try { Thread.sleep(500); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } if (screenshot != null) { Context.scenario.attach(screenshot, "image/png", "screenshot"); } } }
2. 验证截图字节的有效性
在attach之前先验证字节数组是否为有效PNG,避免损坏的图片嵌入报告:
private boolean isPngValid(byte[] data) { if (data == null || data.length < 8) { return false; } // PNG文件头固定为8字节:89 50 4E 47 0D 0A 1A 0A byte[] pngHeader = {(byte)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; for (int i = 0; i < pngHeader.length; i++) { if (data[i] != pngHeader[i]) { return false; } } return true; } // 在截图方法中调用 private void takeScreenshotIfScenarioFailed() { if (Context.scenario.isFailed()) { try { byte[] screenshot = ((TakesScreenshot) Context.driver).getScreenshotAs(OutputType.BYTES); if (isPngValid(screenshot)) { Context.scenario.attach(screenshot, "image/png", "screenshot"); } } catch (Exception e) { // 记录日志,避免影响测试流程 e.printStackTrace(); } } }
3. 延迟截图
场景失败后,页面可能仍处于加载或状态变化中,延迟几秒再截图:
private void takeScreenshotIfScenarioFailed() { if (Context.scenario.isFailed()) { try { Thread.sleep(1000); // 延迟1秒,可根据实际调整 byte[] screenshot = ((TakesScreenshot) Context.driver).getScreenshotAs(OutputType.BYTES); Context.scenario.attach(screenshot, "image/png", "screenshot"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (Exception e) { e.printStackTrace(); } } }
4. 改用临时文件中转截图
避免直接通过OutputType.BYTES获取可能的异常,先保存为临时文件再读取字节:
private void takeScreenshotIfScenarioFailed() { if (Context.scenario.isFailed()) { try { File tempFile = ((TakesScreenshot) Context.driver).getScreenshotAs(OutputType.FILE); byte[] screenshot = Files.readAllBytes(tempFile.toPath()); if (isPngValid(screenshot)) { Context.scenario.attach(screenshot, "image/png", "screenshot"); } // 删除临时文件 tempFile.delete(); } catch (Exception e) { e.printStackTrace(); } } }
5. 确保WebDriver未提前关闭
检查测试代码中是否存在场景失败后提前关闭driver的逻辑,确保截图时driver仍处于活跃状态。比如在After钩子中,先执行截图再关闭driver:
@After public void tearDown() { takeScreenshotIfScenarioFailed(); // 之后再关闭driver if (Context.driver != null) { Context.driver.quit(); } }
内容的提问来源于stack exchange,提问作者Said
相关产品推荐
相关产品推荐

