优秀的编程知识分享平台

网站首页 > 技术文章 正文

使用ImageMagick和Selenium Webdriver进行自动化视觉测试

nanyue 2024-09-01 00:01:51 技术文章 6 ℃

在本文中,我将向您介绍如何使用ImageMagickSelenium WebdriverAShot进行视觉测试自动化。这个工具和框架组合是完全开源的,当您成功完成设置时,您可以开始无需任何费用就可以对它们进行可视化测试。

首先,我想描述这些工具:

Selenium Webdriver:我们将使用webdriver导航,查询和操作网站。

ImageMagick: ImageMagick是我们的图像处理和比较工具。

链接:http://www.imagemagick.org/script/index.php

纯JAVA界面(im4java):http : //im4java.sourceforge.net/

AShot: AShot是我们的Webdriver Screenshot实用工具。我们将使用AShot截图截图。它由 Yandex及其开源开发

链接:https://github.com/yandex-qatools/ashot

逐步安装

步骤1:Selenium Webdriver

如果您不知道如何开始使用Selenium Webdriver,请先阅读本文。

第2步:Visual Studio 2013的Visual C ++可再发行组件包

转到此链接:https : //www.microsoft.com/en-us/download/details.aspx?id=40784并安装它。






第3步:ImageMagick

转至http://www.imagemagick.org/script/binary-releases.php并安装Windows Binary Release,在安装期间选择所有选项并将其安装目录位置设置为系统路径

选择所有选项非常重要。






如何为ImageMagick和Selenium设置项目

测试场景:

- 打开www.kariyer.net

- 添加顶部横幅Cookie不看顶部横幅。

- 如果存在,关闭弹出窗口

- 关闭横幅

- 取消隐藏Uzman Photo的文字区域(“ 21.923???II”部分)

- 悬停在主页上的“UZMAN”部分。


- 等待2秒钟完成图像(CSS)动画。


- 截取此元素的动画照片。

- 在第一次运行时,将它保存到ScreenShots> $ Test_Name文件夹中作为uzmanBaseline.png和uzmanActual.png。

- 第二次运行时,更新uzmanActual.png,并将其与uzmanBaseline.png进行比较,并将差异作为uzmanDiff.png

- 把所有的差异放在“差异”文件夹中。

- 验证他们是否通过了类似的测试。如果没有测试失败。

项目设置:

打开IntelliJ,然后点击文件 - >新建 - >项目 - > Maven

然后,将GroupId和ArtifactId填充为KariyerVisualTest

单击下一步,然后为该项目命名为KariyerVisualTest,然后单击下一步。


之后,我们应该修改我们的pom.xml

始终从https://mvnrepository.com检查库最新版本

对于硒:

XHTML

1

2

3

4

5

<dependency>

<groupId>org.seleniumhq.selenium</groupId>

<artifactId>selenium-java</artifactId>

<version>3.0.1</version>

</dependency>

对于AShot:

XHTML


<dependency>

<groupId>ru.yandex.qatools.ashot</groupId>

<artifactId>ashot</artifactId>

<version>1.5.3</version>

</dependency>

对于IM4Java:

XHTML

<dependency>

<groupId>org.im4java</groupId>

<artifactId>im4java</artifactId>

<version>1.4.0</version>

</dependency>

对于TestNG:

XHTML

<dependency>

<groupId>org.testng</groupId>

<artifactId>testng</artifactId>

<version>6.10</version>

</dependency>

测试代码

在下面的代码中,我尝试写出详细的评论。如果您遇到麻烦,请随时添加评论。我会尽快回复你的问题。

BaseTest类

KariyerVisualTest .java

Java

import com.google.common.io.Files;

import org.apache.commons.io.FileUtils;

import org.im4java.core.CompareCmd;

import org.im4java.core.IMOperation;

import org.im4java.process.ProcessStarter;

import org.im4java.process.StandardStream;

import org.openqa.selenium.*;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.interactions.Actions;

import org.openqa.selenium.support.ui.WebDriverWait;

import org.testng.annotations.BeforeClass;

import org.testng.annotations.BeforeMethod;

import ru.yandex.qatools.ashot.AShot;

import ru.yandex.qatools.ashot.Screenshot;

import javax.imageio.ImageIO;

import java.io.File;

import java.io.IOException;

import java.lang.reflect.Method;

import java.util.Calendar;

import java.util.Date;

import java.util.List;

/**

* Created by onurb on 06-Feb-17.

*/

public class BaseTest {

public WebDriver driver;

public WebDriverWait wait;

public JavascriptExecutor js;

//JSWaiter object

JSWaiter jsWaiter;

//Test name

public String testName;

//Test Screenshot directory

public String testScreenShotDirectory;

//URL of the test website

public String url = "http://www.kariyer.net";

//Main Directory of the test code

public String currentDir = System.getProperty("user.dir");

//Main screenshot directory

public String parentScreenShotsLocation = currentDir + "\\ScreenShots\\";

//Main differences directory

public String parentDifferencesLocation = currentDir + "\\Differences\\";

//Element screenshot paths

public String baselineScreenShotPath;

public String actualScreenShotPath;

public String differenceScreenShotPath;

//Image files

public File baselineImageFile;

public File actualImageFile;

public File differenceImageFile;

public File differenceFileForParent;

//Setup Driver

@BeforeClass

public void setupTestClass() throws IOException {

//Declare Firefox driver

driver = new ChromeDriver();

//Maximize the browser

driver.manage().window().maximize();

//Declare a 10 seconds wait time

wait = new WebDriverWait(driver,10);

//JS Executor

js = (JavascriptExecutor) driver;

//JSWaiter

jsWaiter = new JSWaiter(wait);

//Create screenshot and differences folders if they are not exist

createFolder(parentScreenShotsLocation);

createFolder(parentDifferencesLocation);

//Clean Differences Root Folder

File differencesFolder = new File(parentDifferencesLocation);

FileUtils.cleanDirectory(differencesFolder);

//Go to URL

driver.navigate().to(url);

//Add Cookie for top banner

addCookieforTopBanner();

}

@BeforeMethod

public void setupTestMethod (Method method) {

//Get the test name to create a specific screenshot folder for each test.

testName = method.getName();

System.out.println("Test Name: " + testName + "\n");

//Create a specific directory for a test

testScreenShotDirectory = parentScreenShotsLocation + testName + "\\";

createFolder(testScreenShotDirectory);

//Declare element screenshot paths

//Concatenate with the test name.

declareScreenShotPaths(testName+"_Baseline.png", testName+"_Actual.png", testName + "_Diff.png");

}

//Add Cookie not to see top banner animation

public void addCookieforTopBanner () {

//Get Next Month Last Date for cookie expiration

Calendar calendar = Calendar.getInstance();

calendar.add(Calendar.MONTH, 1);

calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

Date nextMonthLastDay = calendar.getTime();

//Create/Build a cookie

Cookie topBannerCloseCookie = new Cookie.Builder("AA-kobiBannerClosed","4") //Name & value pair of the cookie

.domain("www.kariyer.net") //Domain of the cookie

.path("/") //Path of the cookie

.expiresOn(nextMonthLastDay) //Expiration date

.build(); //Finally build it with .build() call

//Add a cookie

driver.manage().addCookie(topBannerCloseCookie);

}

//Create Folder Method

public void createFolder (String path) {

File testDirectory = new File(path);

if (!testDirectory.exists()) {

if (testDirectory.mkdir()) {

System.out.println("Directory: " + path + " is created!" );

} else {

System.out.println("Failed to create directory: " + path);

}

} else {

System.out.println("Directory already exists: " + path);

}

}

//Close popup if exists

public void handlePopup(String selector) throws InterruptedException {

jsWaiter.waitJS();

List<WebElement> popup = driver.findElements(By.cssSelector(selector));

if(!popup.isEmpty()){

popup.get(0).click();

sleep(200);

}

}

//Close Banner

public void closeBanner () {

jsWaiter.waitJS();

List<WebElement> banner = driver.findElements(By.cssSelector("body > div.kobi-head-banner > div > a"));

if (!banner.isEmpty()) {

banner.get(0).click();

//Wait for 2 second for closing banner

sleep(2000);

}

}

//Unhide an Element with JSExecutor

public void unhideElement (String unhideJS) {

js.executeScript(unhideJS);

jsWaiter.waitJS();

sleep(200);

}

//Move to Operation

public void moveToElement (WebElement element){

jsWaiter.waitJS();

Actions actions = new Actions(driver);

jsWaiter.waitJS();

sleep(200);

actions.moveToElement(element).build().perform();

}

//Take Screenshot with AShot

public Screenshot takeScreenshot (WebElement element) {

//Take screenshot with Ashot

Screenshot elementScreenShot = new AShot().takeScreenshot(driver, element);

/*Screenshot elementScreenShot = new AShot()

.coordsProvider(new WebDriverCoordsProvider())

.takeScreenshot(driver,element);*/

//Print element size

String size = "Height: " + elementScreenShot.getImage().getHeight() + "\n" +

"Width: " + elementScreenShot.getImage().getWidth() + "\n";

System.out.print("Size: " + size);

return elementScreenShot;

}

//Write

public void writeScreenshotToFolder (Screenshot screenshot, File imageFile) throws IOException {

ImageIO.write(screenshot.getImage(), "PNG", imageFile);

}

//Screenshot paths

public void declareScreenShotPaths (String baseline, String actual, String diff) {

//BaseLine, Actual, Difference Photo Paths

baselineScreenShotPath = testScreenShotDirectory + baseline;

actualScreenShotPath = testScreenShotDirectory + actual;

differenceScreenShotPath = testScreenShotDirectory + diff;

//BaseLine, Actual Photo Files

baselineImageFile = new File(baselineScreenShotPath);

actualImageFile = new File(actualScreenShotPath);

differenceImageFile = new File (differenceScreenShotPath);

//For copying difference to the parent Difference Folder

differenceFileForParent = new File (parentDifferencesLocation + diff);

}

//ImageMagick Compare Method

public void compareImagesWithImageMagick (String expected, String actual, String difference) throws Exception {

// This class implements the processing of os-commands using a ProcessBuilder.

// This is the core class of the im4java-library where all the magic takes place.

ProcessStarter.setGlobalSearchPath("C:\\Program Files\\ImageMagick-7.0.4-Q16");

// This instance wraps the compare command

CompareCmd compare = new CompareCmd();

// Set the ErrorConsumer for the stderr of the ProcessStarter.

compare.setErrorConsumer(StandardStream.STDERR);

// Create ImageMagick Operation Object

IMOperation cmpOp = new IMOperation();

//Add option -fuzz to the ImageMagick commandline

//With Fuzz we can ignore small changes

cmpOp.fuzz(10.0);

//The special "-metric" setting of 'AE' (short for "Absolute Error" count), will report (to standard error),

//a count of the actual number of pixels that were masked, at the current fuzz factor.

cmpOp.metric("AE");

// Add the expected image

cmpOp.addImage(expected);

// Add the actual image

cmpOp.addImage(actual);

// This stores the difference

cmpOp.addImage(difference);

try {

//Do the compare

System.out.println ("Comparison Started!");

compare.run(cmpOp);

System.out.println ("Comparison Finished!");

}

catch (Exception ex) {

System.out.print(ex);

System.out.println ("Comparison Failed!");

//Put the difference image to the global differences folder

Files.copy(differenceImageFile,differenceFileForParent);

throw ex;

}

}

//Compare Operation

public void doComparison (Screenshot elementScreenShot) throws Exception {

//Did we capture baseline image before?

if (baselineImageFile.exists()){

//Compare screenshot with baseline

System.out.println("Comparison method will be called!\n");

System.out.println("Baseline: " + baselineScreenShotPath + "\n" +

"Actual: " + actualScreenShotPath + "\n" +

"Diff: " + differenceScreenShotPath);

//Try to use IM4Java for comparison

compareImagesWithImageMagick(baselineScreenShotPath, actualScreenShotPath, differenceScreenShotPath);

} else {

System.out.println("BaselineScreenshot is not exist! We put it into test screenshot folder.\n");

//Put the screenshot to the specified folder

ImageIO.write(elementScreenShot.getImage(), "PNG", baselineImageFile);

}

}

//Sleep Function

public void sleep (int milis) {

Long milliseconds = (long) milis;

try {

Thread.sleep(milliseconds);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

JSWaiter(用于JS和JQuery同步)

import org.openqa.selenium.JavascriptExecutor;

import org.openqa.selenium.support.ui.ExpectedCondition;

import org.openqa.selenium.support.ui.WebDriverWait;

/**

* Created by onurb on 06-Feb-17.

*/

public class JSWaiter {

public WebDriverWait wait;

public JSWaiter (WebDriverWait wait) {

this.wait = wait;

}

public void waitJS () {

//Wait for Javascript to load

ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) driver)

.executeScript("return document.readyState").toString().equals("complete");

//JQuery Wait

ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) driver)

.executeScript("return jQuery.active") == 0);

wait.until(jsLoad);

wait.until(jQueryLoad);

}

}

KariyerVisualTest(测试类)

KariyerVisualTest.java

Java

import org.openqa.selenium.By;

import org.openqa.selenium.WebElement;

import org.testng.annotations.AfterClass;

import org.testng.annotations.Test;

import ru.yandex.qatools.ashot.Screenshot;

/**

* Created by onurb on 28-Aug-16.

*/

public class KariyerVisualTest extends BaseTest {

@Test

public void kariyerUzmanCssTest () throws Exception {

//Handle popup

handlePopup(".ui-dialog-titlebar-close");

//Close banner

closeBanner();

//Declare UZMAN photo section

WebElement uzmanPhotoSection = driver.findElement(By.cssSelector(".item.uzman>a"));

//Unhide Text (It is Changing A lot)

unhideElement("document.getElementsByClassName('count')[0].style.display='none';");

//Move To Operation

moveToElement(uzmanPhotoSection);

//Wait for 2 second for violet color animation

Thread.sleep(2000);

//Take ScreenShot with AShot

Screenshot uzmanScreenShot = takeScreenshot(uzmanPhotoSection);

//Write actual screenshot to the actual screenshot path

writeScreenshotToFolder(uzmanScreenShot, actualImageFile);

//Do image comparison

doComparison(uzmanScreenShot);

}

//Close Driver

@AfterClass

public void quitDriver() {

driver.quit();

}

}

pom.xml中:

pom.xml

XHTML

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>KariyerVisualTest</groupId>

<artifactId>KariyerVisualTest</artifactId>

<version>1.0-SNAPSHOT</version>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<source>1.8</source>

<target>1.8</target>

</configuration>

</plugin>

</plugins>

</build>

<dependencies>

<dependency>

<groupId>org.seleniumhq.selenium</groupId>

<artifactId>selenium-java</artifactId>

<version>3.0.1</version>

</dependency>

<dependency>

<groupId>org.testng</groupId>

<artifactId>testng</artifactId>

<version>6.10</version>

</dependency>

<dependency>

<groupId>org.im4java</groupId>

<artifactId>im4java</artifactId>

<version>1.4.0</version>

</dependency>

<dependency>

<groupId>ru.yandex.qatools.ashot</groupId>

<artifactId>ashot</artifactId>

<version>1.5.3</version>

</dependency>

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.5</version>

</dependency>

</dependencies>

</project>

的testng.xml

testNG.xml

XHTML

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Kariyer Visual Automation with IM4JAVA Selenium AShot">

<test name="RunTest" preserve-order="true">

<classes>

<class name="KariyerVisualTest" />

</classes>

</test>

</suite>

GitHub链接https://github.com/swtestacademy/VisualAutomationImageMagickSelenium

检测结果:

第一次运行:


二次运行(正面情况):



第三轮(负面情况):

我也想告诉你失败的案例。我用照片编辑器打开uzmanBaseline并添加一些形状并保存。之后,我重新运行测试,并得到了低于结果。测试失败,并突出显示了无与伦比的部分。

在开始测试之前,我对“uzmanBasline.png”进行了以下修改


然后,我运行测试并得到以下结果:



Tags:

最近发表
标签列表