]> source.dussan.org Git - vaadin-framework.git/commitdiff
Support taking test screenshots of individual elements
authorArtur Signell <artur@vaadin.com>
Fri, 26 Jun 2015 08:17:58 +0000 (11:17 +0300)
committerVaadin Code Review <review@vaadin.com>
Fri, 26 Jun 2015 11:48:37 +0000 (11:48 +0000)
Change-Id: Iac06c3df156c68f3ec995e00d3cf7703c2673a81

uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java

diff --git a/uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java b/uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java
new file mode 100644 (file)
index 0000000..a70eeee
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.tb3;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.imageio.IIOException;
+import javax.imageio.ImageIO;
+
+import org.openqa.selenium.Dimension;
+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 com.vaadin.testbench.Parameters;
+import com.vaadin.testbench.screenshot.ImageComparison;
+import com.vaadin.testbench.screenshot.ImageFileUtil;
+
+/**
+ * Internal hack to support capturing screenshots for elements.
+ * 
+ * Most parts are from TestBenchCommandExecutor and the feature should be
+ * integrated into TB4.
+ * 
+ * @author Vaadin Ltd
+ */
+public class CustomTestBenchCommandExecutor {
+
+    private ImageComparison imageComparison = new ImageComparison();
+    private final WebDriver actualDriver;
+
+    public CustomTestBenchCommandExecutor(WebDriver driver) {
+        actualDriver = driver;
+    }
+
+    /**
+     * Compares the screenshot of the given element with the reference.
+     * 
+     * Copied from TestBenchCommandExecutor
+     */
+    public boolean compareScreen(WebElement element, File reference,
+            boolean isIE8) throws IOException {
+        BufferedImage image = null;
+        try {
+            image = ImageIO.read(reference);
+        } catch (IIOException e) {
+            // Don't worry, an error screen shot will be generated that later
+            // can be used as the reference
+        }
+        return compareScreen(element, image, reference.getName(), isIE8);
+    }
+
+    /**
+     * Compares the screenshot of the given element with the reference.
+     * 
+     * Copied from TestBenchCommandExecutor and added cropToElement
+     */
+    public boolean compareScreen(WebElement element, BufferedImage reference,
+            String referenceName, boolean isIE8) throws IOException {
+        for (int times = 0; times < Parameters.getMaxScreenshotRetries(); times++) {
+            BufferedImage screenshotImage = cropToElement(element,
+                    ImageIO.read(new ByteArrayInputStream(
+                            ((TakesScreenshot) actualDriver)
+                                    .getScreenshotAs(OutputType.BYTES))), isIE8);
+            if (reference == null) {
+                // Store the screenshot in the errors directory and fail the
+                // test
+                ImageFileUtil.createScreenshotDirectoriesIfNeeded();
+                ImageIO.write(screenshotImage, "png",
+                        ImageFileUtil.getErrorScreenshotFile(referenceName));
+                getLogger().severe(
+                        "No reference found for "
+                                + referenceName
+                                + " in "
+                                + ImageFileUtil
+                                        .getScreenshotReferenceDirectory());
+                return false;
+            }
+            if (imageComparison.imageEqualToReference(screenshotImage,
+                    reference, referenceName,
+                    Parameters.getScreenshotComparisonTolerance())) {
+                return true;
+            }
+            pause(Parameters.getScreenshotRetryDelay());
+        }
+        return false;
+    }
+
+    /**
+     * Crops the image to show only the element. If the element is partly off
+     * screen, crops to show the part of the element which is in the screenshot
+     * 
+     * @param element
+     *            the element to retain in the screenshot
+     * @param fullScreen
+     *            the full screen image
+     * @param isIE8
+     *            true if the browser is IE8
+     * @return
+     * @throws IOException
+     */
+    private BufferedImage cropToElement(WebElement element,
+            BufferedImage fullScreen, boolean isIE8) throws IOException {
+        Point loc = element.getLocation();
+        Dimension size = element.getSize();
+        int x = loc.x, y = loc.y;
+        int w = size.width;
+        int h = size.height;
+
+        if (isIE8) {
+            // IE8 border...
+            x += 2;
+            y += 2;
+        }
+        if (x >= 0 && x < fullScreen.getWidth()) {
+            // X loc on screen
+            // Get the part of the element which is on screen
+            w = Math.min(fullScreen.getWidth() - x, w);
+        } else {
+            throw new IOException("Element x is outside the screenshot (x: "
+                    + x + ", y: " + y + ")");
+        }
+
+        if (y >= 0 && y < fullScreen.getHeight()) {
+            // Y loc on screen
+            // Get the part of the element which is on screen
+            h = Math.min(fullScreen.getHeight() - y, h);
+        } else {
+            throw new IOException("Element y is outside the screenshot (x: "
+                    + x + ", y: " + y + ")");
+        }
+
+        return fullScreen.getSubimage(x, y, w, h);
+    }
+
+    private void pause(int delay) {
+        try {
+            Thread.sleep(delay);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private static Logger getLogger() {
+        return Logger.getLogger(CustomTestBenchCommandExecutor.class.getName());
+    }
+}
index e059dea78db2a062121606852a06bd6bad405cf1..6b8fb1741b7afd926f1248df782a0bb3cd4d9233 100644 (file)
@@ -30,6 +30,8 @@ import org.junit.Rule;
 import org.junit.rules.TestRule;
 import org.junit.rules.TestWatcher;
 import org.junit.runner.Description;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
 import org.openqa.selenium.remote.DesiredCapabilities;
 
 import com.vaadin.testbench.Parameters;
@@ -119,6 +121,11 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
      * @throws IOException
      */
     protected void compareScreen(String identifier) throws IOException {
+        compareScreen(null, identifier);
+    }
+
+    protected void compareScreen(WebElement element, String identifier)
+            throws IOException {
         if (identifier == null || identifier.isEmpty()) {
             throw new IllegalArgumentException("Empty identifier not supported");
         }
@@ -129,7 +136,17 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
         List<File> failedReferenceFiles = new ArrayList<File>();
 
         for (File referenceFile : referenceFiles) {
-            if (testBench(driver).compareScreen(referenceFile)) {
+            boolean match = false;
+            if (element == null) {
+                // Full screen
+                match = testBench(driver).compareScreen(referenceFile);
+            } else {
+                // Only the element
+                match = customTestBench(driver).compareScreen(element,
+                        referenceFile,
+                        BrowserUtil.isIE8(getDesiredCapabilities()));
+            }
+            if (match) {
                 // There might be failure files because of retries in TestBench.
                 deleteFailureFiles(getErrorFileFromReference(referenceFile));
                 break;
@@ -180,6 +197,16 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
         }
     }
 
+    private CustomTestBenchCommandExecutor customTestBench = null;
+
+    private CustomTestBenchCommandExecutor customTestBench(WebDriver driver) {
+        if (customTestBench == null) {
+            customTestBench = new CustomTestBenchCommandExecutor(driver);
+        }
+
+        return customTestBench;
+    }
+
     private void enableAutoswitch(File htmlFile) throws FileNotFoundException,
             IOException {
         if (htmlFile == null || !htmlFile.exists()) {