pazone / ashot

WebDriver Screenshot utility. Take screenshots, crop, prettify, compare
Other
636 stars 157 forks source link

addIgnoredElement and setIgnoredAreas on screenshots still creating diff #189

Open varshasaha opened 4 years ago

varshasaha commented 4 years ago

I have added both of these in my code, still this produces a diff. Attaching code for reference,

package com.flipkart.qop.imagecompare;

import com.flipkart.qop.drivers.AppiumDriverCapabilities;
import com.flipkart.qop.logger.LoggingManager;
import com.flipkart.qop.models.DeviceConfig;
import com.flipkart.qop.utils.FileUtility;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import io.qameta.allure.Allure;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.springframework.stereotype.Component;
import ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;
import ru.yandex.qatools.ashot.comparison.ImageDiff;
import ru.yandex.qatools.ashot.comparison.ImageDiffer;
import ru.yandex.qatools.ashot.coordinates.Coords;
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;

@Component
public class ImageComparator extends DeviceConfig {
    WebDriver driver;
    DeviceConfig deviceConfig;
    public static boolean COMPARE = false;
    public static String MODE = "visual";
    String baselineImageDirFullPath;

    AppiumDriverCapabilities appiumDriverCapabilities = new AppiumDriverCapabilities();

    public ImageComparator() {
    }

    public ImageComparator(WebDriver driver) {
        this.driver = driver;
        baselineImageDirFullPath = "baselineImages/" + getExecutionDevice() + "/" +  getExecutionPlatform() + "/";
    }

    public static void setCOMPARE(boolean COMPARE) {
        ImageComparator.COMPARE = COMPARE;
    }

    private BufferedImage getBaselineImage(String imageName) throws IOException {
        try {
            File expectedImageFile = FileUtils.getFile(FileUtility.getFile(baselineImageDirFullPath + imageName + ".png").getAbsolutePath());
            BufferedImage expectedImage = ImageIO.read(expectedImageFile);
            ImageIO.write(expectedImage, "png", expectedImageFile);
            LoggingManager.logMessage("Retrieving the baseline image " + imageName + " from " + baselineImageDirFullPath);
            return expectedImage;
        }catch (IIOException e) {
            LoggingManager.logMessage("Baseline image" + imageName +  "not found" + e);
        }
        return null;
    }
//        attachScreenshotAllure("Expected image is", expectedImageFile.getName());

    public BufferedImage captureActualImage(String imageName) throws IOException {
        File imageFile;
        if (ImageComparator.COMPARE) {
            imageFile = new File(imageName + "_actual.png");
        } else {
            imageFile = new File(imageName + ".png");
        }
        Screenshot ss = new AShot().coordsProvider(new WebDriverCoordsProvider()).addIgnoredElement(By.xpath("//*[@data-testid='CART_ADD_multiWidgetPage_1']")).takeScreenshot(driver);
        BufferedImage image = ss.getImage();
        if (driver instanceof IOSDriver || driver instanceof AndroidDriver) {
            DeviceViewportModel viewportModel = appiumDriverCapabilities.readDeviceViewportConfig().getDeviceViewport(executionDevice);
            image = image.getSubimage(viewportModel.getX(), viewportModel.getY(), viewportModel.getWidth(), viewportModel.getHeight());
        }
        ImageIO.write(image, "png", imageFile);
        attachScreenshotAllure("Captured image is", imageFile.getName());
        FileUtility.copyFileToDirectory(imageFile, new File(baselineImageDirFullPath));
        LoggingManager.logMessage("Capturing the image " + imageName + " into local baselineImages directory " + baselineImageDirFullPath);
        FileUtility.forceDelete(imageFile);
        return image;
    }

    public Screenshot capturess(String imageName) throws IOException {
        File imageFile;
        if (ImageComparator.COMPARE) {
            imageFile = new File(imageName + "_actual.png");
        } else {
            imageFile = new File(imageName + ".png");
        }
        Screenshot ss = new AShot()
                            .coordsProvider(new WebDriverCoordsProvider())
                            .addIgnoredElement(By.xpath("//*[@data-testid='CART_ADD_multiWidgetPage_1']"))
                            .takeScreenshot(driver);
        return ss;
    }

    public void createDiffImageAs(ImageDiff diffImg, String imageName) throws IOException {
        BufferedImage diffImage = diffImg.getMarkedImage();
        File diffImageFile = new File(imageName + "_diffImage.png");
        ImageIO.write(diffImage, "png", diffImageFile);
        attachScreenshotAllure("Different image is", diffImageFile.getName());
        FileUtility.copyFileToDirectory(diffImageFile, new File(baselineImageDirFullPath));
        LoggingManager.logMessage("Saving the difference image into " + baselineImageDirFullPath);
        FileUtility.forceDelete(diffImageFile);
    }

    public boolean compare(String imageName) throws IOException {
        boolean imageMatchFlag = true;
        if (MODE.equalsIgnoreCase("visual")) {
            BufferedImage actualImage, expectedImage;
            Screenshot exp;
            ImageDiff diffImage;
            if (!ImageComparator.COMPARE) {
                captureActualImage(imageName);
            } else {
                expectedImage = getBaselineImage(imageName);
                exp = new Screenshot(expectedImage);
                actualImage = captureActualImage(imageName);
                Set<Coords> ignoredAreas = capturess(imageName).getIgnoredAreas();
                Set<Coords> coordstocompare = capturess(imageName).getCoordsToCompare();
                Screenshot act = new Screenshot(actualImage);
                exp.setIgnoredAreas(ignoredAreas);
                act.setIgnoredAreas(ignoredAreas);
                exp.setCoordsToCompare(coordstocompare);
                act.setCoordsToCompare(coordstocompare);
                if (exp != null && act != null) {
                        diffImage = new ImageDiffer().makeDiff(exp, act);
                        LoggingManager.logMessage("Comparing the expected baseline image with actual image");
                        int diff = diffImage.getDiffSize();
                        if (diff > 0) {
                            createDiffImageAs(diffImage, imageName);
                            imageMatchFlag = false;
                        } else {
                            imageMatchFlag = true;
                        }
                    }
                }
            }
        return imageMatchFlag;
    }

    public void attachScreenshotAllure(String message,String fileName) throws IOException {
        Path content = Paths.get(fileName);
        try (InputStream is = Files.newInputStream(content)) {
            Allure.addAttachment(message, is);
        }
    }
}
jbadeau commented 4 years ago

I have noticed that only css selector based ignore works. When using other selector types, the ignore bounds are there there but not at the correct coordinates. I have my written my own image compare tool and it suffers from issue so I think the root is in the webdriver get coords.

jbadeau commented 4 years ago

Have you solved this? I will look into it of not

varshasaha commented 4 years ago

Hey! No I could not solve this yet, the coords are definitely wrong, but could not figure out why.

jbadeau commented 4 years ago

I ended up using the jquery provider. Jquery can be injected if your site doesn’t use it