1. The front-end automated testing of visual test

Front-end automated testing of visual test

image

Front-end test classification

5ad6b227e0634.png

Front-end test is divided into five major direction of the test, which can be divided into many small five direction direction of the test, first briefly introduce the concept in each direction

  1. Interface Style Test

    • Fixed style interface test: the main text for the same area, such as page headers, footers such a structure, the same content area, and the test is generally resolved by contrast shots.
    • Style interface test structure unchanged: the main structure for the same region, such as regional news this type of structure unchanged, changes in the content area, such tests are usually resolved by contrast DOM elements.
    • Computing style testing: major style change for the calculation of the area, such tests are generally resolved by comparing the computed style, but this test is not recommended, because the cost of testing is relatively large.
  2. function test

    • Server data expected test: After mainly for the user to operate in some sort of front-end interface to submit data to the background, the background can return the expected test data
    • Interface function test: After mainly for users operating in some sort of interactive front-end interface, the test can get the desired functionality, interactive interface
  3. Multi-browser testing

    • Multi-browser test: basic interface style testing, functional testing based on up to test different browsers, commonly known compatibility testing.
  4. Performance Testing

    • Time black and white: a user's browser enter the URL to the browser comes along at least 1px screen.
    • The first screen time: the user's browser within the first screen presents all the elements it takes time.
    • Page Return time: the user's browser the first time a non-load all of the elements presented it takes time.
    • The user can operate time (dom ready): Time Site Some features that can be used.
    • Total page download time (onload): site all the resources loaded and available time.
  5. Quality Testing

What kind of projects suitable for automated testing it?

5ae7f3fc745e7.png

As shown above, the real work can not satisfy all the above conditions, the need to make trade-offs, in general, only need to meet the following, we can carry out the project automated test (1. steady demand
does not change frequently .2 Multi the platform runs ergodic combination, a large number of repetitive tasks .3 software maintenance cycle is long, the system under test to develop a viable .4 more standardized, testability strong).:

  1. Demand is stable, does not frequently change

    The biggest challenge is the changing needs of automated testing, and automation script itself will need to modify, extend, debug, to adapt to new functions, if the input-output ratio is too low, then the automated testing has lost its value and significance;

    折中的做法是选择相对稳定的模块和功能进行自动化测试,变动较大、需求变更较频繁的部分用手工测试;

  2. 多平台运行,组合遍历型、大量的重复任务

    测试数据、测试用例、自动化脚本的重用性和移植性较强,降低成本,提高效率和价值;

  3. 软件维护周期长,有生命力

    自动化测试的需求稳定性要求、自动化框架的设计、脚本开发与调试均需要时间,这其实也是一个软件开发过程,如果项目周期较短,没有足够的时间去支持这一过程,那自动化测试也就不需要了;

  4. 被测系统开发较为规范,可测试性强

    主要出于这几点考虑:被测试系统的架构差异、测试技术和工具的适应性、测试人员的能力能否设计开发出适应差异的自动化测试框架;

什么是UI测试

对于界面布局,传统的测试都是由人工对比设计图和产品界面。当界面有修改之后,再由人通过肉眼去检查修改(包括正确的和错误的修改),这样即费时而且测试结果又不稳定,因为人工对比测试存在两个巨坑:1.效率低;2.人的不确定性。对于拥有大量复杂界面的Web应用,界面布局的测试的数量巨大,再加上这两个问题,导致这类应用的界面布局测试/回归测试时间很长,成本很高,所以很多基于Agile(敏捷开发)项目基本不可能在迭代周期内高质量的完成其视觉测试。对于每天做一次,那更是不可能完成的任务。

视觉感知测试/视觉回归测试

为了解决上面提到的各种问题,视觉感知测试孕育而生。它使用传统的对图片进行二进制比较的办法,结合敏捷迭代开发的理念,产生的一种针对界面布局的自动化测试方法。

视觉感知测试

视觉感知测试就是对第一个版本的所有界面进行第一次测试。

视觉感知测试包含以下几个主要的测试步骤:

5ae86eda2a1cc.jpg

需要注意的是!

  1. 配对URL(忽略hostname)

    通过配对URL,对所有的截图按照相同的URL进行分组。当然有时候会出现新的界面,有时候老的界面会被删除。对于新的界面就需要人工进行首次验证测试 。

  2. 像素级别的图形比较

    对于分组之后的截图进行像素级别的比较并生产差别图。有时候为了降噪,可以只对局部关心的组件进行比较。

  3. 人工查看所有不同

    最后通过人工审查差别图报告完成测试。

视觉感知测试结果:

预期(expected) 实际(actual) 比较结果(diff)
1diff

视觉回归测试

我们认为如果一个界面通过第一次的人工验证并发布之后,它就是一个正确的标准界面,并且是包含了人工测试价值的资产。当下一次测试的时候,这部分价值就应该被保留并重用起来,用于减少新的一次测试的时间,从而实现界面的快速回归测试。

视觉回归测试包含以下几个主要的测试步骤:
5aebce31440f0.png

回归和感知测试流程差不多只是差异值要更小一点,并且只有效果图需要替换内容。

视觉自动测试怎么做?

要进行视觉自动测试,有三种方式。

  • 第一种是截屏比对(局部、整页)。
  • 第二种通过JavaScript调用window.getComputedStyle()获取计算后的样式并进行断言。
  • 第三种dom结构对比加css样式对比。

这三种各有明显的优势和不足。 第二种方式强绑定了实现,从而变得可能比较脆弱。 第一种方式离设计太近了,当页面中有可变内容时就会有问题。
第三种方式,无法进行视觉感知测试结果只能进行视觉回归测试和上一版的dom继续比较差异。

我更倾向与第一种截图对比;它的测试基于用户所见而不是用户所见的抽象。当然第三种也是非常好的 page-monitor 有兴趣的朋友可以自行了解。为什么第三种那么好为什么不使用呢?因为上面这个库是基于phantomjs并且它的实现方式过于复杂不适合新手玩玩。

像素对比工具,有哪些?

名称 地址
PhantomCSS https://github.com/HuddleEng/...
GhostStory https://github.com/thingsinja...
Cactus https://github.com/winston/ca...
Needle https://github.com/python-nee...
CSSCritic https://github.com/cburgmer/c...
sikuli http://www.sikuli.org/
Mogo http://mogotest.com/
pixelmatch https://github.com/mapbox/pix...
pixel-diff https://github.com/koola/pixe...

好了介绍了那么多,怎么选一个合适的Headless Browser呢?

Headless Browser???我是视觉测试要无界面浏览器干嘛?

因为有了像素对比工具我们还需要一个浏览器进行截图和设计图进行像素比较。

比较常见出名的几个Headless Browser,有哪些?

名称 内核 地址
Puppeteer Webkit https://github.com/GoogleChro...
PhantomJS Webkit http://phantomjs.org/
SlimerJS Gecko https://github.com/laurentj/s...
TrifleJS IE https://github.com/sdesalas/t...
PhantomJS 基于 Webkit 内核,不支持 Flash 的播放;SlimerJS 基于火狐的 Gecko 内核,支持 Flash播放,并且执行过程会有页面展示。

我们这里呢就只讲Webkit内核的,其他的我就不讲了。

PhantomJS简介:

PhantomJS 是一个基于webkit的JavaScript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码。任何你可以在基于webkit浏览器做的事情,它都能做到。它不仅是个隐形的浏览器,提供了诸如CSS选择器、支持Web标准、DOM操作、JSON、HTML5、Canvas、SVG等,同时也提供了处理文件I/O的操作,从而使你可以向操作系统读写文件等。PhantomJS的用处可谓非常广泛,诸如网络监测、网页截屏、无需浏览器的 Web 测试、页面访问自动化等。

但是 PhantomJS 因为毕竟不是真实的用户浏览器环境,使用起来还是有不少的诟病。之前一直在使用 PhantomJS ,功能虽然够用,不过和在真实的浏览器里面访问的界面来对比差别还是比较大的。

Puppeteer简介:

Puppeteer是Chrome团队开发的一个Node库。它提供了一个高级API来控制无头或完整的Chrome。它通过使用Chrome无界面模式 (Headless Chrome )和DevTools协议的组合来实现这一点。它使用一个更上层的API来封装其功能,让用户界面测试自动化变得轻而易举。
人们基于Chrome DevTools协议开发了一系列Google Chrome工具。你在浏览器中点击更多工具 ->开发工具,打开的就是DevTools。DevTools协议是DevTools的动力基础,我们现在可以使用Chrome中的DevTools来做更多的事情。

好了简介讲完了,我们来对比一下这两个Headless Browser的区别。

截图比较
代码:

PhantomJS:

var page = require('webpage').create();

page.viewportSize = { width: 400, height: 400 };
page.open("http://localhost:8899/VS", function(status) {
    if (status === "success") {
        page.render("a.jpg");

    } else {
        console.log("Page failed to load.");
    }
    phantom.exit(0);
});

Puppeteer:

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://localhost:8899/VS');

    await page.setViewport({ width: 400, height: 400 })

    //保存图片
    const images = await page.screenshot({ path: 'VS.jpg', fullPage: true, omitBackground: true });

    //关闭浏览器
    await browser.close();

})();
Puppeteer PhantomJS Chrome浏览器
5ab35f3ecea48.jpg 5ab23225073a2.jpg 5ab361e464d76.png

浏览器效果(大图):

5ab232251f25b.png

好了看到这里已经可以分别出来胜负了。

使用puppeteer进行视觉感知测试

我们来做一个简单的dome

我们这里拿掘金来做一个视觉感知测试的例子。

1.首先创建项目名字就叫“PerceptionTest”把。

2.安装依赖

安装Puppeteer

npm install puppeteer --save

像素对比工具我就选我最常用的blink-dif了

npm install blink-diff --save

3.依赖安完了我们来创建一个js文件“app.js”

4.加载依赖

const puppeteer = require('puppeteer'),//无头浏览器
    BlinkDiff = require('blink-diff'),//像素对比
    imgUrl = __dirname + "/blink-diff_img/";//图片目录

5.使用puppeteer进行截图

(async () => {
    //创建puppeteer
    const browser = await puppeteer.launch({ headless: true });
    //new 一个新的tab页面
    const page = await browser.newPage();
    //设置浏览器的尺寸
    await page.setViewport({ width: 1920, height: 945 });
    //打开url
    await page.goto('https://juejin.im/');
    //保存截图
   await page.screenshot({ path: imgUrl + 'Screenshots.png', fullPage: true });
  
    //关闭浏览器
    await browser.close();
})();

6.分析页面找到要替换的内容

Why do you want to replace the contents of it, because we are testing UI testing refers to the interface to match the style rather than the contents inside, if you do not replace what's inside that pixel comparison tool more out similarities certainly very low. So we asked to replace the content, content to let the full unity, we go more accurate to compare the differences.

Well, we analyze the content to be replaced.

5aeb1fa0de449.png

To replace reads as follows:

  1. title
  2. label
  3. Author
  4. release time
  5. Read Times
  6. List Pictures

7. Replace content

puppeteer provides a very rich api, api called page.evaluate which there can be inserted into a js page.

 await page.evaluate(async () => {

        //列表
        var Lists = document.querySelectorAll("div.feed.welcome__feed > ul > li > div > a > div");
        Lists.forEach(function (element, index, array) {

            element.querySelector("a.title").innerHTML = "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试";

            //替换标签
            element.querySelector("ul > li.item.category > span").innerHTML = "测试";

            //替换作者
            element.querySelector("ul > li.item.username.clickable > div > a").innerHTML = "测试";

            //替换发布时间
            element.querySelector("div.info-row.meta-row > ul > li:nth-child(3)").innerHTML = "9999天前";

            //替换发布时间
            element.querySelector("div.info-row.meta-row > ul > li:nth-child(4)").innerHTML = "99999999999 次阅读";

            //列表图片
            if (element.querySelectorAll("div.lazy.thumb.thumb.loaded").length==1) {
                element.querySelector("div.lazy.thumb.thumb.loaded").style.background = "#fdedc9";
            } else {
                var loaded=document.createElement("div");
                loaded.className=" lazy thumb thumb loaded";
                loaded.style.background = "#fdedc9";
                loaded.setAttribute("data-v-b2db8566","");
                loaded.setAttribute("data-v-009ea7bb","");
                loaded.setAttribute("data-v-f2ca14b0","");
                element.appendChild(loaded);
            }
        });

    });

8. Blink-Diff pixel comparison

const diff = new BlinkDiff({
        imageAPath: imgUrl + 'example.png', // 设计图
        imageBPath: imgUrl + 'Screenshots.png',//页面截图
        //低于其中差异的像素数/ p(默认值:500) - 百分比阈值:1 = 100%,0.2 = 20%
        threshold: 0.02, // 1% threshold
        imageOutputPath: imgUrl + 'Diff.png'//Diff路径
    });

    diff.run(function (error, result) {
        if (error) {
            throw error;
        } else {
            console.log(diff.hasPassed(result.code) ? '通过' : '失败');
            console.log('总像素:' + result.dimension);
            console.log('发现:' + result.differences + ' 差异.');
        }
    });

Complete code:

const puppeteer = require('puppeteer'),
    BlinkDiff = require('blink-diff'),
    imgUrl = __dirname + "/blink-diff_img/";

(async () => {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();
    await page.setViewport({ width: 1920, height: 945 });
    await page.goto('https://juejin.im/');



    await page.evaluate(async () => {

        //列表
        var Lists = document.querySelectorAll("div.feed.welcome__feed > ul > li > div > a > div");
        Lists.forEach(function (element, index, array) {

            element.querySelector("a.title").innerHTML = "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试";

            //替换标签
            element.querySelector("ul > li.item.category > span").innerHTML = "测试";

            //替换作者
            element.querySelector("ul > li.item.username.clickable > div > a").innerHTML = "测试";

            //替换发布时间
            element.querySelector("div.info-row.meta-row > ul > li:nth-child(3)").innerHTML = "9999天前";

            //替换发布时间
            element.querySelector("div.info-row.meta-row > ul > li:nth-child(4)").innerHTML = "99999999999 次阅读";

            //列表图片
            if (element.querySelectorAll("div.lazy.thumb.thumb.loaded").length==1) {
                element.querySelector("div.lazy.thumb.thumb.loaded").style.background = "#fdedc9";
            } else {
                var loaded=document.createElement("div");
                loaded.className=" lazy thumb thumb loaded";
                loaded.style.background = "#fdedc9";
                loaded.setAttribute("data-v-b2db8566","");
                loaded.setAttribute("data-v-009ea7bb","");
                loaded.setAttribute("data-v-f2ca14b0","");
                element.appendChild(loaded);
            }
        });

    });

    await page.screenshot({ path: imgUrl + 'Screenshots.png', fullPage: true });

    const diff = new BlinkDiff({
        imageAPath: imgUrl + 'example.png', // 设计图
        imageBPath: imgUrl + 'Screenshots.png',//页面截图
        threshold: 0.02, // 1% threshold
        imageOutputPath: imgUrl + 'Diff.png'//Diff路径
    });

    diff.run(function (error, result) {
        if (error) {
            throw error;
        } else {
            console.log(diff.hasPassed(result.code) ? '通过' : '失败');
            console.log('总像素:' + result.dimension);
            console.log('发现:' + result.differences + ' 差异.');
        }
    });


    //关闭puppeteer
    await browser.close();
})();

Difference map

Differences No difference
5aeb373a1fa34.png 5aeb3773ec472.png

git complete code

git complete code: HTTPS: //github.com/my07ke/Per ...

Well, information on how funeral, please listen next time decomposition.

5aebd8bbb1762.gif

Click on the link to join a group chat [front-end | WEB | CSS | Javascript | HTML]: ? HTTPS: //jq.qq.com/ _wv = 1027 & k ...

reference:

On the UI test automation

Visual Perception Test

Guess you like

Origin www.cnblogs.com/baimeishaoxia/p/11933947.html