背景:在測試頁面的時候,經常會遇到css變更或者某個組件有變更,但是下意識的只會在乎當前頁面是否符合整體產品使用而不會去對比曾經的版本,甚至根本不會回歸。所以誕生了Visual Testing,該測試方法能夠幫助回歸測試(當然,這里的回歸肯定只包含老舊區)。
我所使用的視覺測試是集成在cypress上的,所以視覺測試也是一種輔助E2E的測試方法。
一:首先,需要安裝視覺測試包
直接 npm install --save-dev cypress-image-snapshot,安裝完成后會在package.json中看到包名以及版本。
二:在[root]/plugins/index.js中加包并定義方法
const {
????addMatchImageSnapshotPlugin,
} =require('cypress-image-snapshot/plugin');
導出全局方法名
module.exports = (on, config) => {
????addMatchImageSnapshotPlugin(on, config);
}
三:在[root]/support/commamd.js中引入方法
import {addMatchImageSnapshotCommand }from 'cypress-image-snapshot/command';
addMatchImageSnapshotCommand({
????failureThreshold:0.03,
? ? customDiffConfig: {threshold:0.1 },
? ? failureThresholdType:'percent',
? ? capture:'viewport'
});
四:最后就可以在用例中使用該方法了
以下是官方所提供的使用方法,在用例的方法中添加配置,會覆蓋全局配置。
// addMatchImageSnapshotPlugin
addMatchImageSnapshotPlugin(on,config);
//addMatchImageSnapshotCommand
addMatchImageSnapshotCommand();
addMatchImageSnapshotCommand(commandName);
addMatchImageSnapshotCommand(options);
addMatchImageSnapshotCommand(commandName,options);
//matchImageSnapshot.matchImageSnapshot();
.matchImageSnapshot(name);
.matchImageSnapshot(options);
.matchImageSnapshot(name,options);
// ---or---cy.matchImageSnapshot();
cy.matchImageSnapshot(name);
cy.matchImageSnapshot(options);
cy.matchImageSnapshot(name,options);
該方法官方推薦是使用在斷言之后。
五:第一次運行該代碼,會在cypress/snopshot/${spec.name}中生成一個baseImage
六:再次運行該代碼,如果兩次截圖不一致,會在cypress/snopshot/${cypress.spec.name}/__diff_output__中生成一個diffImage。
下圖就是diff圖,左邊為baseImage,右邊為本次運行時截圖。中間就是diff圖片。
七:參數
Updating snapshots
Run Cypress with?--env updateSnapshots=true?in order to update the base image files for all of your tests.
Preventing failures
Run Cypress with?--env failOnSnapshotDiff=false?in order to prevent test failures when an image diff does not pass.
八:diffImage加入報告
這個也是琢磨了很久才搞出來的辦法,肯定不是最優的,但這是我當前能想到的辦法了。。
方法還是跟上一篇文章一樣,需要使用到addContext方法并且配合pipeline歸檔使用。但是這個diffimages的相對路徑還有一點不一樣,不知道則呢么去獲取,只能通過捕獲到錯誤消息去替換路徑獲得diff圖片的相對路徑。如果有更好的辦法,可以評論一下哦。
在[root]/support/index.js中加入全局方法。
Cypress.on('test:after:run', (test, runnable) => {
????if (test.state ==='failed') {
// Build image path
????????if(test.err.message.includes('See diff')) {
// If the test failed due to cypress-image-snapshot the message will always be the same and the plugin gives you in the message the url of the path
? ? ? ? ? ? const linuxDiffImages = test.err.parsedStack[1].message.replace('See diff for details: ', '').split("/").slice(-5).join("/");
? ? ? ? ? ? const diffImages = test.err.parsedStack[1].message.replace('See diff for details: ', '').split("/").slice(-6).join("/");
? ? ? ? ? ? if(navigator.userAgent.indexOf("Linux")>0){
????????????????addContext({test}, {
????????????????????title:'diffImage',
? ? ? ? ? ? ? ? ? ? value:`${Cypress.env("jobUrl")}` +"lastSuccessfulBuild/artifact/" + `${linuxDiffImages}`
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }else {
????????????????addContext({test}, {
????????????????????title:'diffImage',
? ? ? ? ? ? ? ? ? ? value:`/${diffImages}`
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }
????????}
????}
});
pipeline
使用pipeline歸檔這個diff圖片的時候,遇到了一個問題。
(先交代下背景:cypress/snapshots/${cypress.spec.name}文件夾中存在baseImage,所以我不會去刪除snapshots文件夾)
所以在開始歸檔前,我使用了fileExists去判斷__diff_output__文件夾是否存在,但是該文件夾又是存在于${cypress.spec.name}中的,所以就要寫成
?if(fileExists('cypress/snapshots/**/__diff_output_') == true){
? ??`````code`````
}
但是fileExists不支持通配符,只能指定死文件夾(**代表無論這里有多少層,*代表僅一層)。所以fileExists方法就不可用,只能換成findFiles方法。該方法會返回一個list,所以我這里通過判斷這個list的長度來確定是否存在diff圖片,如果存在的話,則歸檔所有的.diff.png圖片
// fileExists不支持通配符
script{
? ????def files=findFiles excludes:'',glob:'cypress/snapshots/**/*.diff.png'
????????echo"${files}"
????? if("${files.size()}" != "0"){
????????echo"---------------存在diff失敗用例截圖,開始歸檔---------------"
????????archiveArtifactsartifacts:'cypress/snapshots/**/*.diff.png'
????}
}
報告
生成了測試報告后,就可以在用例步驟里看到diffImage圖片了