Morris's blog

我的瀏覽器自己會動!web e2e test with cypress

2019-07-04

e2e test

  • e2e, means end to end, 指測試一個完整的使用流程,如登入,訂購商品到購物車裡...etc
  • unit test, integration test, e2e test, AB test.....一堆名詞 這些名詞的差別和定義可以看 Will保哥的這篇神文
  • 就算是有畫面的測試,搞IT的人們,也不想要自己動手點來點去,真的懶到最高點惹
  • 寫javascript,驅動一些軟體,讓它操作瀏覽器,做我們人類設定好的assert。
  • 好處:
    1. 可以自動執行
    2. 可以不斷重複執行
    3. 看著瀏覽器自動照著你的意思跑有種拎背就是上帝的感覺 相對於單元測試來說,立即就能感受到的成就感較高。
      I am king of the wold
  • 壞處:
    1. 業務流程一變動,測試就要跟著變,測試也是需要維護的工作量double?

注意一個健康專案裡,單元測試和整合測試加起來的量應該要遠遠超過e2e測試的量才是健康的專案,人們所稱的測試金字塔

modern e2e test framework 大比拼

共同之處:

  • 它們都是based on node.js的軟體
  • 都open source

其他差異:

名稱敘述官網文件完整度有GUI介面多瀏覽器?github
protractorangular官方發展出來的, 建構在selenium之上的軟體不太好是,只要OS裡有,就能用,透過pluging去擴充link
cypresscypress.io公司的產品強,甚至有影片有GUI介面,整合得超好否,目前只支援chrome家族,有說要支援其他的link
puppeteerGoogle推出,headless chrome,適合用來測試網頁執行效能,載入速度。預設不顯示畫面,因為是'headless'否,只支援chrome家族,以後應該也是link

以下開始介紹Cypress...

安裝

  1. project必須要是一個有package.json的專案(npm init過 之類的這樣)
  2. yarn add cypress --save-dev or npm install cypress --save-dev,看要用哪一個。以下將以npm為範例
  3. package.json script區塊加上一個指令
     # in pacaage.json file
      # ...其他設定
      "scripts": {
          # ......其他 npm script
        "test:e2e": "cypress open",
        # script名稱當然是隨意的,重點是內容
        # 其他 npm script
      }
  4. npm run test:e2e,之後就會跑出一個GUI    magic~ cypress_open

如果cypress偵測到沒有它所需要的資料夾的話,在專案資料夾底下會長出

cypress資料夾 跟 cypress.json檔

│──cypress
│  ├── fixtures
│  │   └── example.json
│  ├── integration
│  │   └── example
│  │       └── ....很多範例test.js檔案
│  ├── plugins
│  │   └── index.js
│  └── support
│      ├── commands.js
│      └── index.js
│
├── cypress.json
│
│── ...其他原本就有的檔案, src, node_moduules資料夾之類的
│

cypress/integration資料夾底下就是放我們寫的自動e2e測試腳本,每一個檔案會出現在GUI視窗裡讓你去點來執行,也可以一次跑多個。
cypress/support/command.js裡可以寫測試腳本裡共用的util function。如打api,要登入token...這樣的事   @see_customCommand

如何寫e2e測試

這邊也附上我寫的一個cypress e2e測試範例,並註解一下,相信一定能秒會 link
也可以考慮直接git clone我的todoList example之後跑起來玩玩

    // 讓寫test的時候能讓vscode幫忙自動完成
/// <reference types="Cypress" />

describe('first test', () => {
  it('can open page', () => {
    // 連上 webpack dev server url
    cy.visit('http://localhost:8087')
    // 暫停一下測試執行 讓cy瀏覽器 render一下畫面和套用CSS
    cy.wait(2000)
    // 選取畫面上 第一個 <input />
    const firstInput = cy.get('input:first')
    // 做一個assert( .should ) 這個input 它有`placeholder`屬性 值是 `+ Add Task`
    firstInput.should('have.attr', 'placeholder', '+ Add Task')
    //按下這個input
    firstInput.click()
 
    cy.wait(200)
    // 這時畫面上會打開一個編輯視窗,
    // 再做一個assert 整個document上的 第二個 <input />  會有`placeholder`屬性 值是 `Type Something Here…`
    cy.get('input:nth-child(2)').should('have.attr', 'placeholder', 'Type Something Here…')

    // 按下現在document上的第一個<section /> 底下一層第5個<div /> 底下的 第一個 <a />,它是一個把編輯視窗關閉的 `cancel` button
    cy.get('section:first > div:nth-child(5) > a:first').click()
    // document上的 第一個<input /> 裡的placeholder就應該要變回  `+ Add Task` again
    cy.get('input:first')
      .should('have.attr', 'placeholder', '+ Add Task')
    
  })
})

如果這個測試通過,代表我們的tolist app能夠打開隱藏的編輯視窗,然後按下cancel按鈕後,能夠關閉。 todoList_cypress_test

response