Try   HackMD

React Testing Library


React Testing Library 是什麼?

React Testing Library 是一套 DOM Testing Library 工具,希望我們能更關注在用戶的使用操作上,因此提供許多在模擬使用者查詢 DOM 節點的方法,讓開發者針對 DOM 與使用者的操作行為進行測試。

但是 React Testing Library 本身無法運行測試,以及測試是否有通過,需仰賴 Jest 的協作。並且可與 Jest 搭配在不透過瀏覽器的情況下模擬使用者的操作行為(e.g. 點擊按鈕、下拉選單)。

  • 常用方法:
    • Type of Query:getBy, queryBy, findBy
    • Multiple Elements:getAllBy, queryAllBy, findAllBy
    • 渲染 React 元件:render, screen, getBy

初始設定

如果是使用 create-react-app 建立的專案,通常在建立時就會幫你安裝好 React Testing Library 套件。
可以在 package.json 檔案裡找到:

"dependencies": {
    ...
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",
     "@testing-library/user-event": "^13.5.0",
    ...
}

jest-dom, user-event 皆為在測試時會一起使用的輔助工具。

若專案中沒有 create-react-app 套件,也可以自行執行 npm 指令進行安裝。

npm install --save-dev @testing-library/react

撰寫流程

使用React Testing Library 搭配來撰寫測試時,我們可以針對程式碼結構進行思考,如何渲染、模擬行為、驗證結果是否符合預期。

  1. 可以先使用 render 呈現我們要測試的元件
  2. 找到該元件中元素的所在位子
  3. 觀察或模擬使用者在該元素上的操作行為
  4. 搭配 jest 函式庫來導入方法
  5. 驗證結果是否和預期相同

常見使用方法:

React Testing Library 提供很多方法可以讓我們像使用者一樣選取網頁上的 DOM 元素,讓我們在測試時更切合實際。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • getBy

    • 在沒有匹配到(No Match)或是匹配到多個(1 + Match)的情況下,都會報錯(throw)。
    • 不適用於一開始不會顯示的情況。
      • e.g. 某些元素需要在用戶有操作的情況下才會顯示的情形。
  • getAllBy

    • 可以選取多個匹配的元素
    • 匹配到一個(1 Match)、多個(1 + Match)⇒ 回傳 Array
  • findBy

    • 可用來處理非同步、或一開始不會顯示在頁面上,需執行對應動作重新渲染後才會顯示的畫面。
  • findAllBy

    • 與 getAllBy一樣可以選取多個匹配的元素,適合用來選取非同步操作後顯示的元素。
  • queryBy

    • 適用於比對是否沒有某個元素

    • 沒有比對到元素時不會報錯,而是會回傳 null

    • 因不會直接報錯,不建議拿來選取存在的元素

    • 適合與 not 一起搭配使用

      ​​​​​​​​expect(screen.queryByRole('button')).not.toBeInTheDocument();
      
  • queryAllBy

    • 適合用在比對是否沒有某個元素
    • 沒有匹配的情況下會回傳空陣列

如何選取:

  • ByText

    • 尋找 document 內符合的文字內容
  • ByRole:(需注意套件設定的 Role)

    • 可以透過標籤的角色去尋找想要的元素,角色可以透過此方式去觀看:

      • 叫出開發者工具後在 Elements 底下原先預設 Styles 的地方點擊最右側小箭頭 >> 圖示後選取 Accessibility

        Image Not Showing Possible Reasons
        • The image file may be corrupted
        • The server hosting the image is unavailable
        • The image path is incorrect
        • The image format is not supported
        Learn More →

      • 選取對應的 element 後底下會顯示 Role 角色!

        Image Not Showing Possible Reasons
        • The image file may be corrupted
        • The server hosting the image is unavailable
        • The image path is incorrect
        • The image format is not supported
        Learn More →

      • 以按鈕舉例可以這樣選取:

        ​​​​​​​​​​​​screen.getByRole('button');
        
      • 如果有多顆按鈕的情況,可以在按鈕上添加 aria-label 屬性後透過 name 去指定:

        ​​​​​​​​​​​​ <button aria-label='first-button'>第一顆按鈕</button>
        
        ​​​​​​​​​​​​// 透過 aria-label 指定名稱
        ​​​​​​​​​​​​screen.debug(screen.getByRole('button', { name: /first-button/i }));
        

      這邊透過 Antd 的素材庫去舉例,也要特別提醒,如果是透過套件去渲染的元件,套件可能會有多個層級,此時要特別留意要做測試的層級,按照 Select 舉例該 input 可能包在很內層,input 內也有去設定 role 角色:

      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →

  • ByLabelText

    • 尋找 label 屬性的文字內容。
  • ByPlaceholderText

    • 尋找 Placeholder 屬性的文字內容。
  • ByDisplayValue

    • 尋找 value :如 input 、 select 等等的顯示值。
  • ByAltText

    • 尋找 img 標籤的 Alt 屬性。
  • ByTitle

    • 尋找有設定 title 屬性的元素。
  • ByTestId

    • 可以找出 data-testid 屬性,data-testid 要提前埋在標籤內:
      ​​​​​​​​<div data-testid="test" />
      
      ​​​​​​​​// 選取埋藏的 id 
      ​​​​​​​​screen.getByTestId('test');
      

選取之前須先觀看頁面上可供選擇的元素

  • screen.debug()

    • 能幫我們印出現有的 DOM 元素,讓我們更方便去選去元素,也可以帶入參數,帶入參數後可單獨印出該元素。
    ​​​​// 會帶出所有目前頁面上的 dom 元素
    ​​​​screen.debug()
    ​​​​
    ​​​​// 帶入參數選取想看的 dom 元素
    ​​​​screen.debug(screen.getByText('test'));