文章首發(fā)于微信公眾號【軟測小生】
前言:
圖表(Chart)的自動驗(yàn)證是測試自動化的最大挑戰(zhàn)之一拇惋, 而在我們的應(yīng)用程序中,我們有大量的圖表抹剩,接下來將展示我是如何自動化Chart撑帖,或許給你一些新的想法。
Ocular
我將使用Ocular-圖像驗(yàn)證庫! 事實(shí)上澳眷,我創(chuàng)建這個Ocular 庫就是為了這個目的胡嘿。
示例應(yīng)用:
為了更好地解釋,我將創(chuàng)建兩個簡單的HTML文件境蔼,如下所示(我從這個站點(diǎn)獲取HTML) &每個HTML文件包含3個圖表灶平。
這里我們假設(shè)右邊的圖表和左邊的完全一樣伺通。除了收入圖表的1月份數(shù)據(jù)不一樣之外箍土,右邊的圖表幾乎是一樣的。
我的期望是——作為自動化測試的一部分罐监,應(yīng)該報告這種差異吴藻,測試應(yīng)該失敗!
HTML源代碼看起來是這樣的:
現(xiàn)在是時候?yàn)樯厦娴腍TML文件設(shè)計Page對象了:
Page Object:
package com.chart.demo;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import com.testautomationguru.ocular.Ocular;
import com.testautomationguru.ocular.comparator.OcularResult;
public class SampleChartPage {
private WebDriver driver;
private Map<String, String> map;
@FindBy(id = "buyers")
private WebElement buyersChart;
@FindBy(id = "countries")
private WebElement countriesChart;
@FindBy(id = "income") WebElement incomeChart;
// private WebElement incomeChart;
public SampleChartPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
// 頁面對象應(yīng)該包含準(zhǔn)圖像的路徑
// 這些圖像不需要存在
// Ocular如果沒有找到,會創(chuàng)建這些圖像
map = new HashMap<String, String>();
map.put("buyers", "buyers.png");
map.put("countries", "countries.png");
map.put("income", "income.png");
}
public boolean verifyBuyersChart() {
return this.verifyChart(map.get("buyers"), buyersChart);
}
public boolean verifyCountriesChart() {
return this.verifyChart(map.get("countries"), countriesChart);
}
public boolean verifyIncomeChart() {
return this.verifyChart(map.get("income"), incomeChart);
}
// 常用的方法來比較基準(zhǔn)圖像與實(shí)際的某個頁面/特定元素
private boolean verifyChart(String fileName, WebElement element) {
//Path path = Paths.get(fileName); //只為這個方法實(shí)用--baselineTest()
Path path = Paths.get(fileName).toAbsolutePath();//為這兩個方法使用visaul_test_without_any_change()和visaul_test_after_change()
System.out.println(path);
OcularResult result = Ocular.snapshot().from(path) //(1)
.sample().using(driver).element(element) //(2)
.compare(); //(3)
int similarity = result.getSimilarity();
System.out.println("similarity="+similarity);
return result.isEqualsImages();
}
}
我假設(shè)以上page對象是不言自明的弓柱。我在項(xiàng)目中創(chuàng)建了這樣的文件夾沟堡。
- snap文件夾應(yīng)該包含所有的基準(zhǔn)圖像
-
result將包含比較結(jié)果
最初這些文件夾可以是空的。因?yàn)槲覀儾粫心?個圖表網(wǎng)頁元素的圖像(在第一次運(yùn)行時矢空,Ocular將在snap文件夾下創(chuàng)建這些圖像)航罗。
接下來我們開始創(chuàng)建測試用例:
TestNG Test:
在這個testNG測試集中,我有3個測試:
- baseline_test——此測試的目的是首先生成基準(zhǔn)圖像屁药,當(dāng)您第一次運(yùn)行測試時粥血,Ocular將創(chuàng)建基準(zhǔn)圖像。這樣酿箭,您就可以將它用于后續(xù)的任何驗(yàn)證复亏。這個測試總會PASS。
- visual_test_without_any_change ——這里缭嫡,我將調(diào)用相同的HTML文件缔御。因此,Ocular會將圖表與之前測試方法(baseline_test)中創(chuàng)建的基準(zhǔn)圖像進(jìn)行比較妇蛀。這個測試將PASS耕突,因?yàn)槭褂孟嗤臄?shù)據(jù)啟動了相同的HTML笤成,所以圖表將與預(yù)期一樣。
-
visual_test_after_change ——在這個測試中眷茁,我將啟動另一個HTML疹启,其中收入(income)圖表數(shù)據(jù)略有變化。因此蔼卡,Ocular將驗(yàn)證和報告圖片的差異喊崖。
一旦我運(yùn)行baseline_test方法, snap文件夾將包含我們需要的所有圖像!
package com.chart.demo;
import java.nio.file.Paths;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import com.testautomationguru.ocular.Ocular;
public class OcularDemo {
private WebDriver driver;
private SampleChartPage page;
@BeforeSuite
public void ocularConfig() {
//更新Ocular配置
// 設(shè)置基準(zhǔn)圖像的路徑——這個文件夾應(yīng)該存在
// 設(shè)置比較后返回結(jié)果的路徑 - 這個文件夾應(yīng)該存在
Ocular.config()
.snapshotPath(Paths.get(".", "resources/snap"))
.resultPath(Paths.get(".", "resources/result"));
}
@BeforeMethod
public void beforeMethod() {
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@AfterMethod
public void afterMethod() {
driver.quit();
}
// 在這個測試的時候,snap文件是空的. ocular沒有發(fā)現(xiàn)任何基準(zhǔn)圖像.
// 所以O(shè)cular創(chuàng)建了基準(zhǔn)圖像并且對比結(jié)果總是返回True
@Test
public void baselineTest() throws InterruptedException {
driver.get("file:///" + Paths.get("Chart.jsdemo0.html").toAbsolutePath());
Thread.sleep(5000);
page = new SampleChartPage(driver);
Assert.assertTrue(page.verifyBuyersChart());
Assert.assertTrue(page.verifyCountriesChart());
Assert.assertTrue(page.verifyIncomeChart());
}
// 在這個測試中,snap文件包含了基準(zhǔn)圖像.
// 所以O(shè)cular對比了實(shí)際元素獲取的圖像并返回結(jié)果
@Test/*(dependsOnMethods = "baselineTest")*/
public void visaul_test_without_any_change() throws InterruptedException {
driver.get("file:///" + Paths.get("Chart.jsdemo0.html").toAbsolutePath());
page = new SampleChartPage(driver);
Assert.assertTrue(page.verifyBuyersChart());
Assert.assertTrue(page.verifyCountriesChart());
Assert.assertTrue(page.verifyIncomeChart());
}
// snap文件夾下已經(jīng)包含了基準(zhǔn)圖像.
// 所以O(shè)cular對比了實(shí)際元素獲取的圖像并返回結(jié)果
// income圖標(biāo)的數(shù)據(jù)改變了 -所以他將失敗
@Test/*(dependsOnMethods = "visaul_test_without_any_change")*/
public void visaul_test_after_change() throws InterruptedException {
driver.get("file:///" + Paths.get("Chart.jsdemo1.html").toAbsolutePath());
Thread.sleep(5000);
page = new SampleChartPage(driver);
Assert.assertTrue(page.verifyBuyersChart());
Assert.assertTrue(page.verifyCountriesChart());
Assert.assertTrue(page.verifyIncomeChart()); //這里將會失敗雇逞,因?yàn)閿?shù)據(jù)改變了
}
}
對于失敗的測試用例荤懂,差異被高亮顯示,如下所示!!
總結(jié):
大多數(shù)自動化套件通過讀取圖表數(shù)據(jù)來進(jìn)行比較塘砸,如果數(shù)據(jù)與預(yù)期相符节仿,則很難對圖表進(jìn)行實(shí)際驗(yàn)證。但是掉蔬,再看我們上面的例子廊宪,通過Ocular來驗(yàn)證圖表不再是一個大的挑戰(zhàn)! 如果我們通過基準(zhǔn)圖像位置和元素,Ocular比較高亮出差異是很容易的女轿。
這只是局部箭启,希望能夠幫到你,更多內(nèi)容請查看Ocular的源碼蛉迹。
Maven依賴
其中用到的Maven依賴如下:
<!-- https://mvnrepository.com/artifact/com.testautomationguru.ocular/ocular -->
<dependency>
<groupId>com.testautomationguru.ocular</groupId>
<artifactId>ocular</artifactId>
<version>1.0.0.Alpha</version>
</dependency>
Demo HTML網(wǎng)頁獲取
其中該Demo所用到的HTML網(wǎng)頁傅寡,可以到CSDN下載,但是有點(diǎn)惡心要積分北救;
也可關(guān)注微信公眾號軟測小生回復(fù)“ChartDemo”獲取下載鏈接荐操。
下載后解壓使用說明如下圖: