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
protractor angular官方發展出來的, 建構在selenium之上的軟體 不太好 是,只要OS裡有,就能用,透過pluging去擴充 link
cypress cypress.io公司的產品 強,甚至有影片 有GUI介面,整合得超好 否,目前只支援chrome家族,有說要支援其他的 link
puppeteer Google推出,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