视觉测试工具箱

视觉测试工具箱

视觉回归测试最常见的情况是使用基线图像进行测试。然而,视觉测试的不同方面也值得讨论。我们将介绍模板匹配(使用OpenCV)、布局测试(使用Galen)和OCR(使用Tesseract),并展示如何将这些工具无缝集成到现有的Appium和Selenium测试中。

我们使用Java(以及OpenCV和Tesseract的Java包装器),但类似的解决方案也可以通过其他技术堆栈实现。

这篇文章是2020年9月在新加坡的Taqelah和2020年Selenium会议期间(以较短的形式)发表的快速演讲的配套文章。有关完整功能的演示和更多详细信息,请参阅
http://www.justtestlah.qa/

我希望这个总结能帮助你选择对你的用例最有影响的工具,并给你一些关于如何将它们集成到你自己的工具箱中的想法。

模板匹配

模板匹配的任务是在当前屏幕上找到给定的图像(模板)。

视觉测试工具箱

Waldo在哪里?

视觉测试工具箱

对于移动测试,Appium在其1.9版本中以图像定位器策略的形式添加了此功能。(更多信息可以在文档和早期教程中找到)其思想是将图像的Base64编码字符串表示传递给WebDriver。

  • 早期教程:https://appiumpro.com/editions/32-finding-elements-by-image-part-1

使用图像定位器(image locator),你可以像任何其他WebElement一样与结果元素交互。例如:

<code>

WebElement

element =

driver.findElementByImage(base64EncodedImageFile);

element.click();

/<code>

<code>By image = MobileBy.image(base64EncodedImageFile);

new

WebDriverWait(driver,

10

).

until

(ExpectedConditions.presenceOfElementLocated(image)).click(); /<code>

开发人员采用的方法是将功能添加到Appium服务器的一部分,并使用OpenCV(这将成为运行Appium服务器的实例的依赖项)来增强实际的图像识别能力。

有趣的是,客户端与服务器之间的流程如下所示:

  1. 从Appium服务器请求截图。
  2. 将屏幕截图和模板都发送到Appium服务器进行匹配。

这感觉并不完美,尤其是如果我们想在同一个屏幕上匹配多个模板。

当我在2018年首次实现模板匹配时(当时还不知道Appium团队已经在开发模板匹配),我也选择了OpenCV,而是在客户端运行了它。使用OpenCV Java包装器,我的代码要点如下所示:

<code>

Mat

result = new Mat(resultRows, resultCols, CvType.CV_32FC1);

templ, result, Imgproc.TM_CCOEFF_NORMED);

MinMaxLocResult

match = Core.minMaxLoc(result);

if

(match.maxVal >= threshold) {

found

}

/<code>

这种方法不需要向上述Appium服务器发出额外的请求。实际上,除了屏幕截图的功能外,它不需要WebDriver的任何功能。它还可以与Selenium和Appium一起使用。也就是说,这也增加了对OpenCV的依赖,这次是对运行测试执行的实例的依赖。

我将以上两种方法(客户端和服务器端执行)都包装到TemplateMatcher接口中,以展示其用法(将其视为PoC)。

你可以在JustTestLah中找到更多详细信息和示例!

  • JTL测试框架:https://justtestlah.qa/#template-matching

布局测试

另一种视觉测试类型涉及验证页面或屏幕的布局。你可以通过图像比较来做到这一点,图像比较也会隐式检查布局。一种更简单的方法是使用像Galen这样的专用布局测试工具(在我看来,这是最被低估的UI测试框架之一)。

Galen使用每个屏幕的规范来定义屏幕上的所有(重要)元素及其大小以及它们之间的绝对或相对位置。

让我们以Google搜索页为例:

视觉测试工具箱

我们可以使用以下规范表示它:

<code>

SEARCH_FIELD

:

below

LOGO

centered

horizontally inside viewport

visible

LOGO

:

above

SEARCH_FIELD

centered

horizontally inside viewport

width

< 100% of SEARCH_FIELD/width

visible

SEARCH_BUTTON

:

near

LUCKY_BUTTON 20px left

visible

/<code>

注意,上面使用的是JustTestLah!框架的语法(通过在页面对象的YAML文件中定义的唯一键引用UI元素)。在纯Galen中,这些需要在spec文件的顶部定义:

<code>

@objects

LOGO

id hplogo

SEARCH_FIELD

css input[name=q]

...

/<code>

有多种执行这些检查的方法。我更喜欢将verify方法作为BasePage抽象类的一部分:

<code>

private

T verify() { String baseName =

this

.getClass().getSimpleName(); String baseFolder =

this

.getClass().getPackage().getName().replaceAll(

"\\."

, File.separator); String specPath = baseFolder + File.separator + configuration.getPlatform() + File.separator + baseName +

".spec"

; galen.checkLayout(specPath, locators);

return

(T)

this

; } /<code>

这样,每当我们第一次与屏幕交互时,我们都可以轻松地从测试中调用验证(顺便说一句,我使用类似的方法来集成Applitools进行视觉测试):

<code>

public

class

GoogleSteps

extends

BaseSteps

{

private

GooglePage google; (

"I am on the homepage"

)

public

void

homepage

()

{ google.verify().someAction().nextAction(); } } /<code>

光学字符识别(OCR)

视觉断言的另一种形式是光学字符识别,其首字母缩写为OCR。每当由于某种原因将文本渲染为图像并且无法使用标准测试工具进行验证时,此功能将非常有用。

对于那些使用Selenium进行Web抓取而不是进行测试的用户来说,这可能也很有趣,因为这是网站开发人员采取的反措施之一,以使其变得更加困难。

我们使用Tesseract(一种最初由HP在1980年代开发,目前由Google赞助的OCR工具)。

我们的示例不是最实际的示例,而是要展示Tesseract在检测不同类型的字体方面的强大功能:我们将验证Google徽标是否确实拼写出“ Google”:

<code>

public

class

GooglePage

extends

BasePage

<

GooglePage

>

{

private

OCR ocr; ...

public

String

getLogoText

()

{

return

ocr.getText($(

"LOGO"

)); } }

public

class

GoogleSteps

extends

BaseSteps

{

private

GooglePage google; ... (

"the Google logo shows the correct text"

)

public

void

checkLogo

()

{ assertThat(google.getLogoText()).isEqualTo(

"Google"

); } } /<code>

使用的OCR服务如下所示:

<code>

public

class

OCR

implements

qa

.

justtestlah

.

stubs

.

OCR

{

private

Logger LOG = LoggerFactory.getLogger(OCR

.

class

);

private

TakesScreenshot driver;

private

Tesseract ocr;

public

OCR(Tesseract ocr) {

this

.ocr = ocr; }

public

String getText(WebElement element) {

return

getText(element.getScreenshotAs(OutputType.FILE)); }

public

String getText() {

return

getText(getScreenshot()); }

private

String getText(File file) { LOG.info(

"Peforming OCR on file {}"

, file);

try

{

return

ocr.doOCR(file).trim(); }

catch

(TesseractException exception) { LOG.warn(

"Error performing OCR"

, exception);

return

null

; } }

public

OCR withDriver(WebDriver driver) {

this

.driver = (TakesScreenshot) driver;

return

this

; }

public

OCR withDriver(TakesScreenshot driver) {

this

.driver = driver;

return

this

; }

private

File getScreenshot() {

return

driver.getScreenshotAs(OutputType.FILE); }

public

void setDriver(WebDriver driver) {

this

.driver = (TakesScreenshot) driver; } } /<code>

这要求在运行测试的实例上安装Tesseract。有关完整的源代码和演示,请查看JustTestLah!测试框架。

  • http://www.justtestlah.qa/


分享到:


相關文章: