Screenshooter.java 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package com.provectus.kafka.ui.screenshots;
  2. import io.qameta.allure.Allure;
  3. import io.qameta.allure.Attachment;
  4. import lombok.SneakyThrows;
  5. import org.junit.jupiter.api.Assertions;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import ru.yandex.qatools.ashot.AShot;
  9. import ru.yandex.qatools.ashot.Screenshot;
  10. import ru.yandex.qatools.ashot.comparison.ImageDiff;
  11. import ru.yandex.qatools.ashot.comparison.ImageDiffer;
  12. import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider;
  13. import javax.imageio.ImageIO;
  14. import java.awt.image.BufferedImage;
  15. import java.io.ByteArrayOutputStream;
  16. import java.io.File;
  17. import java.nio.file.FileSystems;
  18. import java.util.List;
  19. import static com.codeborne.selenide.WebDriverRunner.getWebDriver;
  20. import static org.junit.jupiter.api.Assertions.fail;
  21. public class Screenshooter {
  22. public static Logger log = LoggerFactory.getLogger(Screenshooter.class);
  23. private static int PIXELS_THRESHOLD =
  24. Integer.parseInt(System.getProperty("PIXELS_THRESHOLD", "200"));
  25. private static String SCREENSHOTS_FOLDER =
  26. System.getProperty("SCREENSHOTS_FOLDER", "screenshots/");
  27. private static String DIFF_SCREENSHOTS_FOLDER =
  28. System.getProperty("DIFF_SCREENSHOTS_FOLDER", "build/__diff__/");
  29. private static String ACTUAL_SCREENSHOTS_FOLDER =
  30. System.getProperty("ACTUAL_SCREENSHOTS_FOLDER", "build/__actual__/");
  31. private static boolean SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST =
  32. Boolean.parseBoolean(System.getProperty("SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST", "true"));
  33. private static boolean TURN_OFF_SCREENSHOTS =
  34. Boolean.parseBoolean(System.getProperty("TURN_OFF_SCREENSHOTS", "false"));
  35. private File newFile(String name) {
  36. var file = new File(name);
  37. if (!file.exists()) {
  38. file.mkdirs();
  39. }
  40. return file;
  41. }
  42. public Screenshooter() {
  43. List.of(SCREENSHOTS_FOLDER, DIFF_SCREENSHOTS_FOLDER, ACTUAL_SCREENSHOTS_FOLDER)
  44. .forEach(this::newFile);
  45. }
  46. public void compareScreenshots(String name) {
  47. compareScreenshots(name, false);
  48. }
  49. @SneakyThrows
  50. public void compareScreenshots(String name, boolean shouldUpdateScreenshotIfDiffer) {
  51. if (TURN_OFF_SCREENSHOTS) {
  52. return;
  53. }
  54. if (!doesScreenshotExist(name)) {
  55. if (SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST) {
  56. updateActualScreenshot(name);
  57. } else {
  58. throw new NoReferenceScreenshotFoundException(name);
  59. }
  60. } else {
  61. makeImageDiff(name, shouldUpdateScreenshotIfDiffer);
  62. }
  63. }
  64. @SneakyThrows
  65. private void updateActualScreenshot(String name) {
  66. Screenshot actual =
  67. new AShot().coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(getWebDriver());
  68. File file= newFile(SCREENSHOTS_FOLDER + name + ".png");
  69. ImageIO.write(actual.getImage(), "png", file);
  70. log.debug("created screenshot: %s \n at $s".formatted(name,file.getAbsolutePath()));
  71. }
  72. private static boolean doesScreenshotExist(String name) {
  73. return new File(SCREENSHOTS_FOLDER + name + ".png").exists();
  74. }
  75. @SneakyThrows
  76. private void makeImageDiff(String expectedName, boolean shouldUpdateScreenshotIfDiffer) {
  77. String fullPathNameExpected = SCREENSHOTS_FOLDER + expectedName + ".png";
  78. String fullPathNameActual = ACTUAL_SCREENSHOTS_FOLDER + expectedName + ".png";
  79. String fullPathNameDiff = DIFF_SCREENSHOTS_FOLDER + expectedName + ".png";
  80. // activating allure plugin for showing diffs in report
  81. Allure.label("testType", "screenshotDiff");
  82. Screenshot actual =
  83. new AShot().coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(getWebDriver());
  84. ImageIO.write(actual.getImage(), "png", newFile(fullPathNameActual));
  85. Screenshot expected = new Screenshot(ImageIO.read(newFile(fullPathNameExpected)));
  86. ImageDiff diff = new ImageDiffer().makeDiff(actual, expected);
  87. BufferedImage diffImage = diff.getMarkedImage();
  88. ImageIO.write(diffImage, "png", newFile(fullPathNameDiff));
  89. // adding to report
  90. diff(fullPathNameDiff);
  91. // adding to report
  92. actual(fullPathNameActual);
  93. // adding to report
  94. expected(fullPathNameExpected);
  95. if (shouldUpdateScreenshotIfDiffer) {
  96. if (diff.getDiffSize() > PIXELS_THRESHOLD) {
  97. updateActualScreenshot(expectedName);
  98. }
  99. } else {
  100. Assertions.assertTrue(
  101. PIXELS_THRESHOLD >= diff.getDiffSize(),
  102. ("Amount of differing pixels should be less or equals than %s, actual %s\n"+
  103. "diff file: %s")
  104. .formatted(PIXELS_THRESHOLD, diff.getDiffSize(), FileSystems.getDefault().getPath(fullPathNameDiff).normalize().toAbsolutePath().toString()));
  105. }
  106. }
  107. @SneakyThrows
  108. private byte[] imgToBytes(String filename) {
  109. BufferedImage bImage2 = ImageIO.read(new File(filename));
  110. var bos2 = new ByteArrayOutputStream();
  111. ImageIO.write(bImage2, "png", bos2);
  112. return bos2.toByteArray();
  113. }
  114. @SneakyThrows
  115. @Attachment
  116. private byte[] actual(String actualFileName) {
  117. return imgToBytes(actualFileName);
  118. }
  119. @SneakyThrows
  120. @Attachment
  121. private byte[] expected(String expectedFileName) {
  122. return imgToBytes(expectedFileName);
  123. }
  124. @SneakyThrows
  125. @Attachment
  126. private byte[] diff(String diffFileName) {
  127. return imgToBytes(diffFileName);
  128. }
  129. }