WEB自動化-03-Cypress 測試框架概述

3 Cypress 測試框架概述

3.1 Cypress 默認文件結構

    在Cypress安裝完成後,其生成的默認文件目錄如下所示:

3.1.1 Fixtures

    Fixture又稱之爲測試夾具,通常配合cy.fixture命令使用,主要用於存儲測試用例的外部靜態數據。其默認位置位於cypress\fixtures中,也可以根據需要配置到其他目錄。 Fixtures裏面的靜態數據通常存儲在json文件中,而這部分數據通常是某個網絡請求對應的響應部分,如HTTP狀態碼和返回值等。Fixture的應用場景通常爲,當測試需要對某些外部接口進行訪問並依賴於其返回值時,可以使用fixture而無需訪問這些接口。

3.1.2 測試文件

    測試文件就是對應的測試用例,一般位於cypress\integration中,也可以根據需要配置到另一個目錄中,通常爲js文件,在Cypress中其他命令格式爲:fileName.spec.js,支持的文件類型如下所示:

  • .js
  • .jsx
  • .coffee
  • .cjsx

3.1.3 Plugins

    在Cypress中,測試代碼是運行瀏覽器裏面,提供了更加可靠的測試體驗,但也存在明顯的缺點,使得與瀏覽器之外進行通信更加困難。爲解決這個問題,Cypress提供了一些插件,可以修改或擴展Cypress的內部行爲。插件一般位於cypress\plugins,在每個測試文件運行之前,Cypress會自動加載該目錄中的index.js文件。

3.1.4 Support

    支持文件一般位於目錄cypress\support中,可以根據需要放置在其他目錄中,其主要功能是放置可複用配置項,如底層通用方法、全局默認配置等。在每個測試文件運行前,Cypress會自動加載該目錄中的index.js文件。

    使用方法也非常簡單,僅需要在cypress\support\index.js文件中添加beforeEach()函數即可。示例如下所示:

beforeEach( function (){
  cy.log(`Current Enviroment is ${JSON.stringfy(Cypress.env())}`)
 }
)

3.2 核心概念

3.2.1 核心參數配置

    在第一次打開Cypress Test Runner後,cypress.json將會創建,目錄與Cypress同級。該文件主要用於保存所有支持的自定義配置,在配置了錄製和測試項目後,則projectId將會被保存至cypress.json文件中。

用戶可以通過參數來定義所使用的配置文件,參數爲--config-file

3.2.1.1 全局配置項

    以下爲Cypress支持的常用自定義的全局配置及其默認值,如下所示:

配置項 默認值 描述
baseUrl null URL前綴,通常與命令cy.visit()/cy.request()結合使用
clientCertificates [] 客戶端證書選項數組
env {} 環境變量設置選項,任何支持的值均可
numTestsKeptInMemory 50 在內存中保存的快照和命令數據等數量,在運行測試時,若內存佔用太高,可以減少該值
port null Cypress使用的端口號,默認隨機產生
redirectionLimit 20 在出現錯誤前,允許應用程序在測試運行時重定向的數量
reporter spec 在Cypress運行時使用的的reporter
reporterOptions null reporter支持的配置選項
watchForFileChanges true 用於監測文件變化,若有變化,則自動重新運行該用例

3.2.1.2 超時

    超時是Cypress中的核心概念,所以必須瞭解,常見的超時參數如下所示:

配置項 默認值 描述
defaultCommandTimeout 4000 命令默認超時時間,單位爲ms
execTimeout 60000 在cy.exec()執行期間,等待系統命令完成執行的超時時間,單位爲ms
taskTimeout 60000 在cy.task()執行期間,等待任務完成執行的超時時間,單位爲ms
pageLoadTimeout 60000 在等待頁面加載或cy.visit()/cy.go()/cy.reload()等命令觸發其他頁面加載事件的超時時間,單位爲ms,網絡請求受限於操作系統
requestTimeout 5000 在執行cy.wait()命令時,請求超時時間,單位爲ms
responseTimeout 30000 在執行命令cy.request()/cy.wait()/cy.fixture()/cy.getCookie()/cy.getCookies()/cy.setCookie()/ cy.clearCookie()/ cy.clearCookies/cy.screenshot()時的響應超時時間,單位爲ms
slowTestThreshold 10000 | 250 在Cypress run期間,運行較慢的測試用例在reporter中將會以桔黃色顯示,通過該參數可進行單獨設置E2E和組件測試超時時間,E2E默認超時時間爲 10000ms,而組件測試爲250ms,單位爲ms

3.2.1.3 目錄和文件

    Cypress支持自定義目錄和文件,如下所示:

配置項 默認值 描述
downloadsFolder cypress/downloads 在測試期間,默認的文件下載目錄
fileServerFolder root project folder 向服務器發送的應用程序文件目錄
fixturesFolder cypress/fixtures fixture默認目錄,可更改默認值爲false來禁用
ignoreTestFiles *.hot-update.js 在運行期間,需要忽略的測試用例
integrationFolder cypress/integration 測試用例所在目錄
pluginsFile cypress/plugins/index.js Plugins所在目錄,可更改默認值爲false來禁用
screenshotsFolder cypress/screenshots 在測試用例運行失敗或cy.screenshot()命令觸發截圖,用於保存這些截圖的目錄
supportFile cypress/support/index.js 在測試加載之前要加載的文件
testFiles **/. 要加載的測試文件
videosFolder cypress/videos 在Cypress run運行期間,用於保存video的目錄

3.2.1.4 截圖

配置項 默認值 描述
screenshotOnRunFailure true 測試用例運行失敗後將進行截圖
screenshotsFolder cypress/screenshots 在測試用例運行失敗或cy.screenshot()命令觸發截圖,用於保存這些截圖的目錄

3.2.1.5 視頻

配置項 默認值 描述
videoCompression 32 設置視頻的壓縮比,設置爲false關閉壓縮或0~51,數字越低,視頻質量越好,文件越大
videosFolder cypress/videos 在Cypress run運行期間,用於保存video的目錄
video true 是否啓用視頻功能
videoUploadOnPasses true 是否啓用在用例運行通過後,上傳視頻至Dashboard,僅適用於錄製項目,如果關閉該功能,則僅上傳運行失敗的視頻

3.2.1.6 視圖

配置項 默認值 描述
viewportHeight 660 測試視圖下待測試應用程序的默認高度,單位爲pixels,可使用cy.viewport()命令覆蓋
viewportWidth 1000 測試視圖下待測試應用程序的默認寬度,單位爲pixels,可使用cy.viewport()命令覆蓋

更多自定義選項,可查閱官方文檔,地址爲:https://docs.cypress.io/guides/references/configuration

3.2.1.7 命令行

    除了使用配置文件進行配置以外,也可以使用命令行進行設置以下各個參數,如下所示:

cypress open --config pageLoadTimeout=30000,baseUrl=https://www.surpass.com
cypress run --config integrationFolder=tests,videoUploadOnPasses=false

3.2.1.8 Cypress.config()

    除了直接在cypress.json文件中更改配置之外,也可以通過Cypress.config()去獲取或覆蓋某些配置項。其基本使用方法如下所示:

// 獲取所有config信息
Cypress.config()
// 獲取指定config信息
Cypress.config(name)
// 更改指定config信息
Cypress.config(name,value)
// 設置多個config項
Cypress.config(object)

    示例代碼如下所示:

describe("測試Cypress.config",function(){
   it("獲取defaultCommandTimeout",function(){
       cy.log(`defaultCommandTimeout value is:${Cypress.config("defaultCommandTimeout")}`)
       // 設置參數選項值
       Cypress.config("defaultCommandTimeout",99999)
       cy.log(`defaultCommandTimeout value is:${Cypress.config("defaultCommandTimeout")}`)
   })
})

    運行結果如下所示:

3.2.2 用例結構

    Cypress是建立在MochaChai之上,因此同時支持Chai的BDDTDD兩種風格。如果你熟悉JavaScript風格的代碼,那麼在Cypress中寫測試用例是很容易上手的。

Mocha是一款適用於Node.js和瀏覽器的測試框架,可使用異步測試變得簡單靈活。

    Cypress的測試風格繼承於Mocha,提供了describe()context()it()specify()四個關鍵字,對於一條可執行的測試而言,必須包含以下兩個組成部分:

  • describe()context()等效,均表示一個測試套件或測試集
  • it()specify()等效,均表示一個測試用例

    示例如下所示:

describe('我是一個測試集', () => {
    it('測試用例-1', () => {
        expect(1+2).to.eq(3)
    });
    it('測試用例-2', () => {
        expect(3-2).to.eq(1)
    });
    it('測試用例-3', () => {
        expect(3*2).to.eq(5)
    });
});

    最終的運行結果如下所示:

更多測試用例的組織和編寫會在後續詳細講解

3.2.3 重試機制

    重試是Cypress一個非常重要的功能,在瞭解重試的概念後,有助於寫出更加健壯的測試。

3.2.3.1 命令和斷言

    命令斷言是兩種在Cypress中測試常用的兩種方法,示例如下所示:

/// <reference types="cypress" />

describe('', () => {
    let baseUrl="https://example.cypress.io/todo"
    it('測試用例-1', () => {
        // 一個命令 visit
       cy.visit(baseUrl);
       // 一個命令 get,一個斷言 should
       cy.get(".header input").should("have.class","new-todo");
       // 三個命令 get 和 type
       cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
        // 一個命令 get,一個斷言 should
       cy.get('.todo-list li').should('have.length', 4);
    });

});

    最終的運行結果如下所示:

    讓我們一起來看看最後一行的命令和斷言,如下所示:

 cy.get('.todo-list li').should('have.length', 4);

    以上命令和斷言,是通過cy.get()命令查找頁面的DOM,在找到與選擇器匹配的元素,然後進行斷言嘗試,而現在很多WEB應用幾乎都是異步的。以最後一行代碼爲例,Cypress不能在查詢DOM元素(todo-list)的同時又去檢查其元素個數是否爲4個。因此在出現以下情況,就會出現問題,如下所示:

  • 1.當運行命令或斷言時,應用程序沒有更新DOM時,怎麼辦?
  • 2.當運行命令或斷言時,應用程序正在等待後端返回響應,而頁面暫時沒有結果時,怎麼辦?
  • 3.當運行命令或斷言時,應用程序正在進行密集計算,而導致頁面顯示未及時更新時,怎麼辦?

    以上幾種情況,在測試過程中非常常見,一般處理辦法在斷言前,設置一個等待時間,但這個等待時間,在不同環境中還不能完全統一,還是會導致經常出錯。而Cypress處理這種問題,則非常智能,如下所示:

在實際運行時,如果cy.get()命令之後的斷言通過,則認爲該命令成功執行。如果失敗,則cy.get()命令將重新查詢應用程序的DOM,再進行斷言。如果失敗,則再次執行cy.get()命令查詢DOM,再進行斷言。依此類推,直至斷言成功或cy.get()命令超時爲止。

    正是因爲Cypress的這種自動重試功能避免了在測試代碼中出現硬編碼的等待。使測試代碼更加健壯。

3.2.3.2 多重斷言

    在日常測試中,有時候需要對一個數據進行多次斷言,Cypress提供一種方法叫多重斷言,其定義爲:單個命令後跟多個斷言。在斷言時,Cypress將按順序重試每個命令,即當第一個斷言通過後,在進行第二個斷言時仍會重試第一個斷言。當第一和第二個斷言都通過後,在進行第三個斷言,仍然會重試第一和第二個斷言,依此類推。來看看以下示例:

/// <reference types="cypress" />

describe('多重斷言示例', () => {
    let baseUrl="https://example.cypress.io/todo";
    it('演示用例-1', () => {
        cy.visit(baseUrl);
        cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
        cy.get('.todo-list li')
        .should('have.length',4)
        .and(($li) => {
            expect($li.get(2).textContent,'first item').to.equal('todo A')
            expect($li.get(3).textContent,'second item').to.equal('todo B')
           });
    });
});

.and()斷言是.should()的別名,它是.should()的自定義回調函數,包含兩個expect()斷言。

    最終的運行結果如下所示:

    上面代碼共有三個斷言,分別是should和兩個expect。在測試過程中,如果第二個斷言失敗了,則第三個斷言不會執行,如果第二個斷言執行通過,整個命令還未超時,在執行第三個斷言前,會再次重試第一個和第二個斷言。

    修改代碼使得第二個斷言出現失敗,代碼如下所示:

/// <reference types="cypress" />

describe('多重斷言示例', () => {
    let baseUrl="https://example.cypress.io/todo";
    it('演示用例-1', () => {
        cy.visit(baseUrl);
        cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
        cy.get('.todo-list li')
        .should('have.length',4)
        .and(($li) => {
            expect($li.get(2).textContent,'first item').to.equal('toda A')
            expect($li.get(3).textContent,'second item').to.equal('todo B')
           });
    });
});

    在第二個斷言運行失敗後,第三個斷言則不會被執行。在執行命令超時後,會在運行頁面顯示第一個斷言執行成功,第二個斷言執行失敗,如下圖所示:

3.2.3.3 重試條件

    Cypress並不會重試所有命令。當命令可能改變待測應用程序的狀態時,則將不會進行重試操作(例如.click()命令)。Cypress僅會重試查詢DOM的命令,例如cy.get()、.find()、.contains()等等。

如果需要查詢更多重試的命令,可查閱API文檔中Assertions文檔https://docs.cypress.io/guides/references/assertions

    重試的超時時間默認爲4s,也可通過defaultCommandTimeout進行設置。

3.2.3.3.1 增加超時時間

    我們也可以通過修改所有命令的超時時間,例如,將全局的默認超時時間設置爲10s,如下所示:

cypress run --config defaultCommandTimeout=10000

    以上這種方式可以修改全局的超時時間,但不推薦。相反,我們可以通過設置單個命令的超時時間{ timeout: ms },而更加靈活的控制各個命令的超時時間,示例如下所示:

/// <reference types="cypress" />

describe('多重斷言示例', () => {
    let baseUrl="https://example.cypress.io/todo";
    it('演示用例-1', () => {
        cy.visit(baseUrl,{timeout:1000});
        cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
        cy.get('.todo-list li')
        .should('have.length',4)
        .and(($li) => {
            expect($li.get(2).textContent,'first item').to.equal('toda A')
            expect($li.get(3).textContent,'second item').to.equal('todo B')
           });
    });
});

    以上代碼,設置訪問網站的超時時間爲1s,運行結果如下所示:

3.2.3.3.2 禁用重試

    如果將超時時間設置爲0,其本質上是禁用重試機制,示例如下所示:

cy.get('.new-todo',,{timeout:0}).type('todo A{enter}').type('todo B{enter}');

原文地址:https://www.jianshu.com/p/55819e173a5d

本文同步在微信訂閱號上發佈,如各位小夥伴們喜歡我的文章,也可以關注我的微信訂閱號:woaitest,或掃描下面的二維碼添加關注:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章