简体   繁体   中英

Selenium Java image comparison

I am trying to compare two screen shots on a webpage. It is a practice page on saucelab. When you login as a standart_user and click the login button, it takes you to the products page. Then you see the pictures of products. (Backpacks, t-shirts etc.)

When you login as a problem_user, you see puppy pictures instead of products' picture. I want to screen shot the both pages and compare them. I took the shots by using WebdriverWait.

But the shots are taken before the pictures were loaded fully. What should I use to wait until the pictures on products page are fully loaded?

Below is my code.

public void waitElementVisibility(By visibleImage) {
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(40));
    wait.until(ExpectedConditions.visibilityOfElementLocated(visibleImage));
}

public void captureSuccesfulPageScreenShot() {
    waitElementVisibility(visibleImage);
    TakesScreenshot screenshot = (TakesScreenshot) driver;
    File file = screenshot.getScreenshotAs(OutputType.FILE);
    File path = new File("images/screenshot.png");
    try {
        FileUtils.copyFile(file, path);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public void captureProblemUserScreenShot() {
    waitElementVisibility(visibleImage);
    TakesScreenshot screenshot = (TakesScreenshot) driver;
    File file = screenshot.getScreenshotAs(OutputType.FILE);
    File path = new File("images/problemUserScrSh.png");
    try {
        FileUtils.copyFile(file, path);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

I've managed to create a wait method, but it fails on fifth image. Performing the render check take some time and I'm unable to simulate slow rendering.

Code:

package tests;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Saucedemo {

    
    public static void main(String[] args) {
        WebDriver driver = startChromeDriver();
        driver.get("https://www.saucedemo.com/");
        
        logIn(driver, "standard_user");
        List<WebElement> inventoryContainerImages = inventoryContainerImages(driver);
        waitForRenderingImages(driver, inventoryContainerImages, 4);
        saveScreenShotAs(driver, "standard_user");
        logOut(driver);
        
        logIn(driver, "problem_user");
        inventoryContainerImages = inventoryContainerImages(driver);
        waitForRenderingImages(driver, inventoryContainerImages, 4);
        saveScreenShotAs(driver, "problem_user");
        logOut(driver);
        
        driver.quit();
    }   

    public static WebDriver startChromeDriver() {
        String chromedriverPath = System.getProperty("user.dir") + "\\resources\\chromedriver.exe";
        System.setProperty("webdriver.chrome.driver", chromedriverPath);
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--ignore-certificate-errors");
        options.addArguments("--start-maximized");
        options.addArguments("--disable-notifications");
        WebDriver driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        return driver;
    }
    
    public static void logIn(WebDriver driver, String userName) {
        System.out.println("Login as user: " + userName);
        driver.findElement(By.id("user-name")).sendKeys(userName);
        driver.findElement(By.id("password")).sendKeys("secret_sauce");
        driver.findElement(By.id("login-button")).click();
    }
    
    public static void saveScreenShotAs(WebDriver driver, String fileName) {
        TakesScreenshot screenshot = (TakesScreenshot) driver;
        File file = screenshot.getScreenshotAs(OutputType.FILE);
        File path = new File(fileName + ".png");
        try {
            FileUtils.copyFile(file, path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void logOut(WebDriver driver) {
        System.out.println("Logout");
        driver.findElement(By.id("react-burger-menu-btn")).click();
        driver.findElement(By.id("logout_sidebar_link")).click();
    }
    
    public static BufferedImage getBufferedImageOfElement(WebDriver driver, WebElement element) {
        BufferedImage elementImage = null;
        BufferedImage fullImage = null;     
        TakesScreenshot screenshot = (TakesScreenshot) driver;
        File file = screenshot.getScreenshotAs(OutputType.FILE);
        try {
            fullImage = ImageIO.read(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Point point = element.getLocation();
        int width = element.getSize().getWidth();
        int height = element.getSize().getHeight();
        elementImage = fullImage.getSubimage(point.getX(), point.getY(), width, height);
        return elementImage;
    }
    
    public static BufferedImage getBufferedImageFromUrl(String imgSrc) {
        BufferedImage image = null;
        HttpURLConnection connection = null;
        try {
            connection = (HttpURLConnection) new URL(imgSrc).openConnection();
            connection.connect();
            image = ImageIO.read(connection.getInputStream());
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }
    
    public static Boolean imagesAreEqual(BufferedImage source, BufferedImage target) {
        Boolean samePixelColors = true;
        int sourceWidth = source.getWidth();
        int sourceHeight = source.getHeight();
        BufferedImage resizedTarget = resizeBufferedImage(source, sourceWidth, sourceHeight);
        for (int x = 0; x < sourceWidth; x++) {
            for (int y = 0; y < sourceHeight; y++) {
                int sourceRgb = source.getRGB(x, y);
                int resizedTargetRgb = resizedTarget.getRGB(x, y);
                if (sourceRgb != resizedTargetRgb) {
                    samePixelColors = false;
                    break;
                }
            }
        }
        if (samePixelColors) {
            return true;
        }
        else {
            return false;
        }
    }
    
    public static Boolean elementsImageEqualSrcImage(WebDriver driver, WebElement element) {
        BufferedImage imageOfElement = getBufferedImageOfElement(driver, element);
        String src = element.getAttribute("src");
        BufferedImage imageFromUrl = getBufferedImageFromUrl(src);
        return imagesAreEqual(imageFromUrl, imageOfElement);
    }
    
    public static void waitForRenderingImages(WebDriver driver, List<WebElement> images, int maxImages) {
        int maxIndex = maxImages - 1;
        if (maxIndex <= images.size()) {
            WebDriverWait wait10s = new WebDriverWait(driver, 10);
            for (int i = 0; i <= maxIndex; i++) {
                WebElement image = images.get(i);
                if (!elementsImageEqualSrcImage(driver, image)) {
                    System.out.println("Image " + (i + 1) + " of " + images.size() + " not equal with its URL source, waiting 100 ms.");
                    wait10s.until(new Function<WebDriver, Boolean> () {
                        public Boolean apply(WebDriver driver) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                
                            }
                            return elementsImageEqualSrcImage(driver, image);
                        }
                    });
                }
                else {
                    System.out.println("Image " + (i + 1) + " of " + images.size() + " equal with its URL source, no waiting.");
                }
            }
        }
        else {
            System.out.println("Error - argument maxImames is greater than images.size()");
        }
    }
    
    public static List<WebElement> inventoryContainerImages(WebDriver driver) {
        WebElement inventoryContainer = driver.findElement(By.id("inventory_container"));
        return inventoryContainer.findElements(By.tagName("img"));
    }
    
    public static BufferedImage resizeBufferedImage(BufferedImage sourceImage, int width, int height) { 
        Image image = sourceImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return resizedImage;
    } 
    
}

Output:

Starting ChromeDriver 104.0.5112.79 (3cf3e8c8a07d104b9e1260c910efb8f383285dc5-refs/branch-heads/5112@{#1307}) on port 22424
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Srp 29, 2022 2:12:39 ODP. org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Login as user: standard_user
Image 1 of 6 equal with its URL source, no waiting.
Image 2 of 6 equal with its URL source, no waiting.
Image 3 of 6 equal with its URL source, no waiting.
Image 4 of 6 equal with its URL source, no waiting.
Logout
Login as user: problem_user
Image 1 of 6 equal with its URL source, no waiting.
Image 2 of 6 equal with its URL source, no waiting.
Image 3 of 6 equal with its URL source, no waiting.
Image 4 of 6 equal with its URL source, no waiting.
Logout

I solved my problem by using Thread.sleep(). I also updated my methods so I don't have duplicated lines.

private void sleep(int milliSecond) {
    try {
        Thread.sleep(milliSecond);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM