antd-pro1.0使用jest對react組件進行單元測試

前言

基於React+Ant Design(如下用Antd表示)的項目,在對於本身封裝的,或者基於Antd封裝的公共組件的自動化測試技術的選型和實踐。前端

背景

隨着前端項目愈來愈大,業務邏輯日益繁雜,協同開發的同事也愈來愈多,迭代頻繁,許多頁面有一些類似的功能,會複用一些組件,這些組件被剝離出來,通常放在component文件夾下,你們共同維護,這時會出現一些常見問題:react

  • 從代碼層面看,咱們必須保證當前組件的質量,即當前業務的正常使用
  • 在新需求下,舊組件若是能知足新需求50%以上的功能,應當升級舊組件知足新需求,同時兼容舊業務
  • 除該組件Owner以外第二人,在修改組件的過程當中,避免由於對代碼的不熟悉,改出BUG
  • 一個組件多個頁面複用,修改後的測試迴歸任務重

單元測試的好處

  • 測試用例代碼跟項目代碼徹底分離,可是能檢驗當前組件的質量、健壯性,保證業務可以正常使用
  • 下降項目多處使用的公共組件修改後,測試迴歸任務重(改一處測多處)的問題
  • 減小沒必要要的console.log或者debug,提高維護體驗
  • 對開發人員來講,寫測試用例能夠適量提高對代碼實現的理解

銘記:測試不是最終目的,儘量在開發階段有意識地提升代碼質量、規避問題。後端

React項目單元測試框架Jest

  • 源自Facebook,Jest的一個理念是提供一套完整集成的零配置測試體驗,開箱即用。
  • 包含單元測試運行器、斷言庫、Mock庫
  • 內置代碼覆蓋率報告
  • 能夠與TypeScript一同使用

jest針對爲實現某些業務邏輯而封裝的函數,設定多種可能的輸入,判斷是否準確地返回了指望值框架

當前管理平臺的簡單示例

1.測試對象:

側邊菜單欄組件(./src/componets/SiderMenu.js)中使用到的數據和邏輯處理函數輸入輸出表現ide

2.測試前分析:

業務角度分析:這是一個按權限展現的多級側邊主菜單欄。(權限方面須要測試及後端人員進行)
組件實現分析:根據後端提供的數據作菜單展現,若是存在多級數據就多級展現,同時可基於菜單實現路由映射。(jest單元測試)函數

3.肯定測試對象用到的數據和邏輯處理函數

如下兩個文件中包含並導出了咱們的測試對象組件SiderMenu使用到的函數
**js文件1:./src/componets/_utils/pathTools.js**單元測試

// /userinfo/2144/id => ['/userinfo','/useinfo/2144,'/userindo/2144/id']
export function urlToList(url) {
  const urllist = url.split('/').filter(i => i);
  return urllist.map((urlItem, index) => {
    return `/${urllist.slice(0, index + 1).join('/')}`;
  });
}

js文件2:./src/componets/SiderMenu.js測試

......
......
/**
 * 遞歸扁平化數據
 * [{path:string},{path:string}] => [path,path2]
 * @param  menu
 */
export const getFlatMenuKeys = menu =>
  menu.reduce((keys, item) => {
    keys.push(item.path);
    if (item.children) {
      return keys.concat(getFlatMenuKeys(item.children));
    }
    return keys;
  }, []);

/**
 * 根據paths查找全部匹配的菜單的keys
 * @param  flatMenuKeys: [/abc, /abc/:id, /abc/:id/info]
 * @param  paths: [/abc, /abc/11, /abc/11/info]
 */
export const getMenuMatchKeys = (flatMenuKeys, paths) =>
  paths.reduce(
    (matchKeys, path) =>
      matchKeys.concat(flatMenuKeys.filter(item => pathToRegexp(item).test(path))),
    []
  );
......
......

4.編寫測試用例

在測試組件目錄下添加.test.js文件,運行jest將會自動識別並執行.test.js結尾的文件進行測試。ui

jest提供的定義測試的一些方法:

  • describe: 定義一個測試套件(test suite)
  • it: 定義一個測試(test)
  • beforeEach: 定義一個回調函數在每一個測試以前執行
  • expect: 執行一個斷言
  • jest.fn(): 創造一個mock函數
    ..................

測試用例:SlideMenu.test.jsurl

// 導入待測試的三個函數
import { urlToList } from '../_utils/pathTools';
import { getFlatMenuKeys, getMenuMatchKeys } from './SiderMenu';

// 先mock一個測試的菜單欄數據做爲參數
const menu = [
  {
    path: '/dashboard',
    children: [
      {
        path: '/dashboard/name',
      },
    ],
  },
  {
    path: '/userinfo',
    children: [
      {
        path: '/userinfo/:id',
        children: [
          {
            path: '/userinfo/:id/info',
          },
        ],
      },
    ],
  },
];

// 傳入mock的數據給getFlatMenuKeys獲得的輸出爲flatMenuKeys
const flatMenuKeys = getFlatMenuKeys(menu);

// 測試getFlatMenuKeys返回的結果是否符合咱們的預期
describe('test convert nested menu to flat menu', () => {
  it('simple menu', () => {
    expect(flatMenuKeys).toEqual([
      '/dashboard',
      '/dashboard/name',
      '/userinfo',
      '/userinfo/:id',
      '/userinfo/:id/info',
    ]);
  });
});

// 測試菜單匹配 模擬多種可能的輸入是否符合指望(多種輸入對應的輸出是否符合預期)
describe('test menu match', () => {
  // 簡單的一級菜單應該返回對應的一個一級菜單結果
  it('simple path', () => {
    expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboard'))).toEqual(['/dashboard']);
  });
  // 錯誤或不存在的路徑應該返回[]
  it('error path', () => {
    expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboardname'))).toEqual([]);
  });
  // 二級菜單應該返回對應的全部菜單keys
  it('Secondary path', () => {
    expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboard/name'))).toEqual([
      '/dashboard',
      '/dashboard/name',
    ]);
  });
  // 存在參數的路徑應該返回對應的預期
  it('Parameter path', () => {
    expect(getMenuMatchKeys(flatMenuKeys, urlToList('/userinfo/2144'))).toEqual([
      '/userinfo',
      '/userinfo/:id',
    ]);
  });
  // 三級帶參數路徑
  it('three parameter path', () => {
    expect(getMenuMatchKeys(flatMenuKeys, urlToList('/userinfo/2144/info'))).toEqual([
      '/userinfo',
      '/userinfo/:id',
      '/userinfo/:id/info',
    ]);
  });
});

5.測試操做:

// 由於當前項目是基於roadhog、roadhog將Jest已經隱藏
yarn roadhog test ./src/componets/SiderMenu
// 若是是普通react項目使用jest須要安裝
yarn jest test ./src/componets/SiderMenu

更多功能待完善....

相關文章
相關標籤/搜索