понедельник, 5 мая 2014 г.

Selenium: снятие скриншота элемента

В некоторых ситуациях при написании тестов с использованием селениума появляется желание прикрепить к отчету снимок не целого экрана, а только лишь отдельного элемента.  Разумеется, вариантов, как это сделать - огромное множество. Я , как обычно, решил сделать еще один, свой. Использую его достаточно часто при написании тестов. 
Собственно немного об моем подходе можно прочитать далее.

Алгоритм работы
Сам принцип работы до нельзя прост - берется скриншот всего экрана, далее с помощью стандартных библиотек java по определенным координатам вырезается необходимое изображение. Что с ним делать далее - каждый волен решать сам. В моем случае - я записываю его в файл.

1-ый шаг - снимаем скриншот и преобразовываем его в BufferedImage.
Здесь все достаточно просто :

...
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
....

File screenShot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
BufferedImage screenshotImage = ImageIO.read(screenShot);

....


2-ой шаг - вырезаем по координатам и размерам webElement'а необходимую нам часть:

public static BufferedImage getImageForElement(BufferedImage fullScreenShotImage, WebElement element) {
        ElementCoordinates coordinates = new ElementCoordinates(element);
        int newImageWidth = coordinates.getWidth();
        int newImageHeight = coordinates.getHeight();
        BufferedImage cropped = new BufferedImage(newImageWidth, newImageHeight, fullScreenShotImage.getType());
        Graphics graphics = cropped.getGraphics();
        graphics.drawImage(fullScreenShotImage, 0, 0, newImageWidth,
                newImageHeight, coordinates.getX0(), coordinates.getY0(),
                coordinates.getX1(), coordinates.getY1(), null);
        graphics.dispose();
        return cropped;
    }


Здесь я использую небольшой утилитный класс ElementCoordinates, созданный мною когда то в порыве белой горячки для удобства. Это - ни что иное, как считывание размеров и координат webElement'а.

public class ElementCoordinates {

    private int x0;
    private int x1;
    private int y0;
    private int y1;
    private int width;
    private int height;

    public ElementCoordinates(WebElement element) {
        Dimension elementDimension = element.getSize();
        Point topPoint = element.getLocation();
        this.width = elementDimension.getWidth();
        this.height = elementDimension.getHeight();
        int topX = topPoint.getX();
        int topY = topPoint.getY();
        int lowerX = topX + width;
        int lowerY = topY + height;
        this.x0 = topX;
        this.y0 = topY;
        this.x1 = lowerX;
        this.y1 = lowerY;
    }

    public int getX0() {
        return x0;
    }

    public int getX1() {
        return x1;
    }

    public int getY0() {
        return y0;
    }

    public int getY1() {
        return y1;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
}


3-ий шаг - делаем что захотим с полученным BufferedImage.
Например - записываем его в темповый файл:

public static void main(String[] args) {
        try {
            WebElement element = webDriver.findElement(By.cssSelector("#id"));
   (1)     File screenShot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
   (2)     BufferedImage screenshotImage = ImageIO.read(screenShot);
            BufferedImage croppedImage = ImagesUtils.getImageForElement(screenshotImage, element);
            File file = File.createTempFile("web-auto", "-img");
            ImageIO.write(croppedImage, "png", file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Так же можно заменить строки (1) и (2) на возможно более оптимальные :


byte[] screenShotBytes= ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
BufferedImage screenshotImage = ImageIO.read(new ByteArrayInputStream(screenShotBytes));

Возможные проблемы
Не стоит злоупотреблять. В принципе снятие скриншота - не самая быстрая операция. Хотя что касается вырезания изображений - тут хочется отметить, что операция занимает мало времени(счет в миллисекундах).
Так же советую не снимать все и вся . Подход удобный, но меру тоже нужно знать.


Идеи
В принципе есть мысли попробовать может быть каким-то образом упростить мой подход, а так же попытаться ускорить процесс. Как будет время - попробую.


Автор - Сидельников Михаил
email: sidelnikovmike@gmail.com
Эту и многие другие интересные статьи Вы можете найти на сайте http://perfect-test.com

Комментариев нет:

Отправить комментарий