色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

淺析單測在商家前端業務中的實踐

OSC開源社區 ? 來源:得物技術 ? 2023-01-12 10:28 ? 次閱讀

1

背景

商家系統是提供給得物商家在得物平臺上可以穩定運營的服務抓手,前端代碼也伴隨著系統的發展而不斷壯大。這樣將導致文檔卻更新不及時,最后想再通過這些文檔回溯業務邏輯也非常困難。

且若代碼結構上沒有關注,動輒就會產出一個大幾千行的文件,人員交替維護的時候很難理清里面的邏輯,維護非常困難。

2

前端單測的難點

為解決上述痛點,早在單測之前,團隊上已經做了一些其他事情來使文檔更清晰、代碼質量更高,如寫需求系分文檔、通過整潔架構(The clean architecture)對代碼進行分層、code review等等。但這些其實都只是外在的約束,只有內在的代碼能真正經得住單測的推敲,才能更好的保障我們的代碼質量。

但目前現狀是前端大部分情況下都沒有接觸到單測,僅在組件庫或工具類的項目里有一些。這并不代表業務項目中前端就無法單測, 而是因為一些客觀原因,導致前端在單測上的投入相對較少。

前端開發的內容比較雜,一個需求不僅僅是功能函數的編寫,還有UI的展示、dom交互的綁定等等,且若想單測完全覆蓋,將包含非常多的內容,對業務前端來說成本太高。

前端UI框架層出不窮,在業務開發的時候,依賴框架也很容易將代碼邏輯和UI等完全耦合在一起,導致一個文件上千行,很難對這種代碼找到單測的切入點。

單測上手本身就有一定的門檻,要寫出可維護性高的單測更不簡單,會讓不熟悉的人望而卻步。

3

單測即文檔

鑒于上面的第一個難點,前端涉及的內容太雜,我們肯定無法給所有的代碼覆蓋單測,去測到代碼的各個角落。再結合上我們自己本身的痛點(文檔更新不及時,人員輪轉成本高),因此以“單測即文檔”為目標,我們只用覆蓋業務邏輯上的單測即可,只關注業務流程的銜接,通過用例將業務流程講清楚,對于單測的分支覆蓋率也不做強硬的要求。

Use Cases

因此,要在團隊落地單測的第一步即是識別出實現業務邏輯的代碼模塊。若在較早的時候,想找到這個切入點可能還真沒有什么好的方法,因為全是幾千行的大文件,且邏輯和UI都耦合在一起。 正如前面所說,在單測推行前,我們已經做了一些代碼準備工作。得益于“整潔架構”的推行,在開發需求的同時,已逐漸在對代碼進行解耦重構,其核心就是依據各部分代碼作用的不同將其拆分成不同的層次,在各層次間制定了明確的依賴原則,達到與框架無關與外部服務無關并可測試的目的。

78a80d70-85ec-11ed-bfe3-dac502259ad0.png

經過分層后,我們將業務邏輯主要都落在了usecase這一層,在我們的代碼結構上,它的作用是將業務流程串聯起來,且它僅依賴entities(主要對服務端返回數據做適配和檢查)層,邏輯獨立不會因為依賴框架或UI的變化而無法運行。

相較于后端服務,前端應用通常并不會承載如計算、存儲等實實在在的業務邏輯,同時由于現在微服務架構的流行,前端應用往往會承擔很重的膠水邏輯,即將各個微服務的邏輯串聯在一起,從而跑通業務流程。

因此,前端在編寫usecase的時候,我們會更注重主子函數的拆分,讓主usecase更純粹的去描述業務流程,而將部分具體的實現拆分到子函數中去實現。

/*
    usecase聚焦流程的描述,諸如url鏈接拼接、活動期查詢等具體邏輯都拆分到了其他的模塊中
*/
async function exportActivityLog({count, formValues}: {count: number;formValues: LogData}) {
  if (count > 5000) {
    message.error('導出文件數量不得超過5000!')
    return
  }
  const res = await checkIsDuringTheEventApi()
  if (res.isDuring) {
    message.error('活動期間,功能暫不可用,如有疑問聯系運營');
    return
  }
  const url = generateDownloadUrl({ formValues })
  downloadExcelFile(url)
}


function generateDownloadUrl() {
  // 省略
}
因此,對usecase層寫單測,正是我們要找的最好切入點,其既能滿足我們將業務文檔進行補充,同時又能有單測模塊的產出,保障我們的代碼質量和程序的穩定性。

4

單測實踐

在識別出要覆蓋單測的代碼模塊之后,下一步自然就是落地單測用例。

前面已說過,寫單測本身就有一定的門檻,但既然要寫就應寫可維護性和穩定性高的單測。否則代碼稍微一重構,單測崩了;或代碼真崩了的時候,單測卻沒又通過了。

根據前面的描述可以看出,我們對于用例的可讀性(文檔性)和穩定性有極高的訴求,對于用例所測試的邏輯范圍要求不高,這個準則對于后續的單測用例的設計取舍會有很大的影響。

4.1 用例設計

首先我們需要確定設計用例的切入點,目前單測社區內比較流行的模式無非TDD和BDD兩種: TDD:測試驅動開發,偏向于去測到函數的各個功能運行的結果是否符合預期,由于是通過先寫用例去驅動業務邏輯的實現,因此用例的設計往往更偏技術實現。 BDD:行為驅動開發,流程上是TDD模式的一種分支,區別在于在構思用例的時候更多的是以用戶行為(user story)的角度去考慮。

7928282a-85ec-11ed-bfe3-dac502259ad0.png

關于兩者更多的區別,大家可以網上查閱到更多的資料,這里就不再贅述。為了我們單測的穩定可維護性,且以文檔為導向的我們,自然是選用了BDD的模式,只測業務行為邏輯,不關注功能函數的輸出正確與否(這塊目前可在自測和測試兄弟團隊那邊幫忙保障)。這樣除非業務流程發生變更,否則代碼一般的重構或調整都不會影響到單測的運行,不會造成單測的雪崩。

4.2 用例結構

在用例結構上,為了配合“單測即文檔”的初衷并更好的配合BDD,我們在社區常見的AAA(Arrange-Act-Assert)和GWT(Given-When-Then)兩種結構之間選擇了后者。

無論AAA還是GWT最終都會形成一個三段式的用例結構,其區別仍然在于AAA的構思更傾向于技術實現,GWT更傾向于業務流程。雖然結構一樣,但設計出來的用例內容會有很大區別。

Given-When-Then

Given:一個上下文,指定和準備測試的預設

When:進行一系列操作,即所要執行的操作

Then:得到可觀察的結果,即需要檢測的斷言

我們根據GWT的提供了單測的基本模板,供組內同學寫單測時直接使用。

function init() {
  const checkIsDuringTheEventApi = jest.fn();
  const downloadExcelFile = jest.fn();
  const exportActivityLog = buildMakeExportActivityLog({checkIsDuringTheEventApi, downloadExcelFile})


  return {
    checkIsDuringTheEventApi,
    downloadExcelFile,
    exportActivityLog
  }
}


describe('spec', () => {
  it('test', () => {
    // Given  準備用例所需的上下文
    const { checkIsDuringTheEventApi, downloadExcelFile, exportActivityLog } = init();


    // When 調用待測的函數
    exportActivityLog()


    // Then  斷言
    expect('expect')
  })
})
對于一些校驗簡單模型的用例,通過init函數做一層封裝就夠用了。但對于業務邏輯比較復雜,字段比較多的模型,直接利用原生數據進行初始化對用例的可讀性并不友好。
describe('spec', () => {
  it('個人賣家未發貨的訂單,允許進行取消操作', () => {
    // Bad case: 依賴字段較多,這樣手動去創造字段數據可讀性并不友好
    // 若case較多,這些字段要手動構建多次
    action({
      status: Status.待發貨,
      merchantType: MerchantType.個人賣家,
      // ...還有一些其他必傳字段
    })
  })
}
對于這種復雜場景,我們傾向于使用builder模式來構造數據,在較小的開發成本下保障用例的可讀性和可維護性。

describe('spec', () => {
    it('個人賣家未發貨的訂單,允許進行取消操作', () => {
        // Good case:通過builder實現邏輯的復用和信息的聚焦
        const order = new OrderBuilder()
          .status("待發貨")
          .merchantType("個人賣家")
          .build()


        action(order)


    })
})

4.3 用例描述

既然是要作為文檔使用,那用例描述上也顯得至關重要了。相比TDD對功能函數的單測,我們描述完全于GWT的用例結構對應(When時常會被省略掉),我們并不關心具體的技術實現細節,更多的是描述的這個業務的行為流程,思考函數最終想做什么,達到什么目的。基于意圖,把被測函數當做黑盒,不用關注其中間的實現細節,究竟生成了什么臨時變量、循環了幾次、有什么判斷等,而是通過用例描述將業務流程講清楚。

describe('導出活動日志', () => {
  it('導出時,先查詢當前活動狀態,若狀態是未在進行中,則執行導出操作', () => {
    // 省略...
  })
  it('導出時,若導出數量大于5000條,將不允許導出', () => {
    // 省略...
  })
})

上面是導出活動日志的一個操作,可以看出,用例的描述不會像測功能函數那樣精簡(入參是a,調用了啥函數必須返回b之類),但是將導出活動時,相應的調用流程和條件描述了出來,這樣其他人在接手這塊業務時,通過這個用例就能清楚知道在導出活動日志時需求上有些什么限制以及要做的操作。

4.4 用例斷言

在確定好用例的設計思路和結構之后,我們在用例的校驗內容上也做了一些取舍。針對社區上主導的經典測試(Classical)和模擬測試(Mockist)兩大陣營,結合“單測即文檔“的理念,我們對于業務流程的驗證訴求非常強烈,因此選擇了后者。

Classical風格是盡可能的使用真實對象和函數,讓函數以及依賴都真實的執行;相對的,Mockist是想盡辦法去mock,主張將所調用的被測函數全部mock。存在即合理,兩個派各有利弊,并不存在一定誰好誰差。

要對用到的函數進行mock,在保證用例可維護性的前提下(比如不mock文件路徑),我們需要對函數的依賴關系進行整理。得益于團隊整潔架構的落地,目前應用的usecase層都已經通過依賴倒置對依賴關系做了很好的管理(usecase只依賴entity)。

export default function buildMakeExportActivityLog({checkIsDuringTheEventApi,downloadExcelFile}) {
  async function exportActivityLog({count,formValues}) {
    if (count > 5000) {
      message.error('導出文件數量不得超過5000!')
      return
    }
    const res = await checkIsDuringTheEventApi()
    if (res.isDuring) {
      message.error('活動期間,功能暫不可用,如有疑問聯系運營');
      return
    }
    const url = generateDownloadUrl({ formValues })
    downloadExcelFile(url)
  }
}


// index.ts
import {checkIsDuringTheEventApi} from '@/services/activity'
import {downloadExcelFile} from '@/utils'
import buildMakeExportActivityLog from './makeExportActivityLog'


export const exportActivityLog = buildMakeExportActivityLog({cancel,printSaleTicket})
可以看到checkIsDuringTheEventApi以及downloadExcelFile這兩個函數最終作為參數傳入到實際的函數中,他們一個將會去發起請求,一個是會調用window的方法進行下載,通過依賴倒置就能方便我們對其進行模擬,在單測時就不會去真實執行這兩個函數。
function init() {
  const checkIsDuringTheEventApi = jest.fn();
  const downloadExcelFile = jest.fn();
  const exportActivityLog = buildMakeExportActivityLog({checkIsDuringTheEventApi, downloadExcelFile})
  return {
    checkIsDuringTheEventApi,
    downloadExcelFile,
    exportActivityLog
  }
}
usecase中時常會有依賴的函數要去發起請求,在單測時我們不會去真實去發起這個請求,因此對于這類函數,我們都應mock掉,這樣可保障我們用例的速度和穩定性。當然實際在寫單測中,我們也不應該成為一個完全的mockist,無休止的進行mock,更好的方式是兩者結合,否則濫用mock反而會導致單測寫起來會更繁瑣(因為要去mock所有調用的函數實現或場景),而且真實代碼寫起來也會很別扭(所有外部函數都依賴倒置)。

一個用例正確與否,最終依賴的是最后的斷言,那對我們來說該怎樣進行斷言呢,如前面一直強調的一樣,我們測的是邏輯行為,因此需斷言的是某個行為的是否執行或者是否達到了什么目的。結合前面的mock,我們可對函數的調用情況進行捕獲,針對上面發起取消退款的函數,斷言的例子如下:

describe('導出活動日志', () => {
  it('導出時,先查詢當前活動狀態,若狀態是未在進行中,則執行導出操作', () => {
    // 省略...
    expect(downloadExcelFile).toBeCalled()
  })


  it('導出時,若導出數量大于5000條,將不允許導出', () => {
    // 省略...
    expect(downloadExcelFile).not.toBeCalled();
  })
})

如上,斷言的內容不是函數的實現細節,如參數是否正確,而是只斷言行為是否執行,它能盡量保證做到若代碼重構后,單測用例在不修改的情況下依然能健壯的運行,其只依賴需求的變更而做更改。同時為了維護用例的穩定性,單個用例我們通常僅執行一次斷言(單一職責),斷言的內容嚴格和描述的“Then”部分對應。

5

結語

商家以“單測即文檔”的理念為落地方向,在代碼設計以及用例的構思、結構、斷言、描述等環節都做了一定取舍,最終在用例的書寫成本、穩定性、可讀性等各個方面取得了相對較好的平衡。

目前組內各個項目已逐漸沉淀了幾百個用例,團隊內相互支援或自己回顧時,通過這些用例就能知道這塊邏輯在做什么事,在修改這些需求時通過測試用例也能盡快知道基本的業務邏輯,有了單測的保障,改起代碼來更有底氣,代碼結構上,也更加的合理。在大家逐漸熟悉單測后,后續更會慢慢做到功能函數、UI等的單測覆蓋,大家一起來保障商家前端業務的穩定發展。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 邏輯電路
    +關注

    關注

    13

    文章

    494

    瀏覽量

    42641
  • TDD
    TDD
    +關注

    關注

    1

    文章

    121

    瀏覽量

    38204
  • BDD
    BDD
    +關注

    關注

    0

    文章

    6

    瀏覽量

    7536

原文標題:單測在商家前端業務中的實踐

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    基于電信業務的程序設計課程改革探索與實踐

    【摘要】:本文針對我國大學程序設計課程教學存在的問題,以通信工程專業為背景,提出將專業知識與程序設計課程相結合的改革思路,指出根據專業特點優化課程教案、豐富課堂案例的方法,介紹了電信業務硬件平臺
    發表于 04-24 10:06

    GMTC 大前端時代前端監控的最佳實踐

    系統。(這時候你就會想)要是能知道用戶報了什么錯就好了。別怕,打開阿里云前端監控的【訪問明細】搜索用戶ID,直接可以看到該用戶訪問過程,到底報了什么錯。有時候拿到了用戶報錯時的基本信息,也知道用戶
    發表于 07-04 16:12

    高線性度芯片射頻前端解決方案

    終端設備(如手機和PMP)越來越講究輕薄小巧的今天,芯片RF(射頻)前端終端應用市場上的前景越來越受到歡迎。可是,與數字電路不同,
    發表于 06-25 07:26

    OpenHarmony例模式實踐

    概念在軟件世界里面,實例是一個非常重要的概念。比如一個國家只有一個主席/總統/...一支軍隊只有一個最高統帥一個班級只有一個班主任...OpenHarmony實踐OpenHarmony是如何實現
    發表于 09-15 09:27

    國產射頻前端芯片

    AT2402E 是一款應用于無線通信的集成收發功能的射頻前端芯片,芯片 內部集成了所需要的射頻電路模塊,集成度非常高,主要包括功率放大器(PA), 低噪聲放大器(LNA),收發模式切換的開關
    發表于 02-02 15:16

    業務規則管理電信網管系統的應用

    主要介紹業務規則及業務規則管理的概念,討論了業務規則管理系統的基本原理,實踐一個簡單的業務規則管理系統并應用于電信網絡管理系統
    發表于 06-19 11:57 ?17次下載

    Ku波段接收前端抗干擾方法淺析

    Ku波段接收前端抗干擾方法淺析,下來看看。
    發表于 07-29 19:05 ?6次下載

    高通宣布與谷歌、hTC、三星和索尼移動射頻前端業務方面展開合作

    射頻前端對終端用戶對其設備的移動體驗至關重要,并能夠促進移動行業的未來發展。過去的一年,高通射頻前端領域可謂動作頻頻,經過一系列的合作,如今終于迎來一波重要的合作伙伴。今天CES的
    的頭像 發表于 01-10 16:22 ?4510次閱讀

    web前端開發實踐的目錄推薦

    本文檔的主要內容詳細介紹的是web前端開發實踐的目錄推薦。
    發表于 01-31 08:00 ?0次下載

    淺析風速傳感器氣象監測的重要作用

    淺析風速傳感器氣象監測的重要作用
    發表于 11-03 17:25 ?12次下載

    淺析高壓放大器絕緣電阻電痕腐蝕程度分析的應用

    淺析高壓放大器絕緣電阻電痕腐蝕程度分析的應用
    發表于 01-14 10:00 ?5次下載

    淺析質構儀還原劑對熟化陳米品質影響研究的應用

    淺析質構儀還原劑對熟化陳米品質影響研究的應用
    發表于 01-18 09:20 ?4次下載

    淺析低功耗應用克服低IQ挑戰

    淺析低功耗應用克服低IQ挑戰
    發表于 02-10 09:56 ?2次下載

    加快部署 5G 基站的最佳實踐:RF 前端大規模 MIMO 入門

    加快部署 5G 基站的最佳實踐:RF 前端大規模 MIMO 入門
    的頭像 發表于 12-26 10:16 ?1808次閱讀
    加快部署 5G 基站的最佳<b class='flag-5'>實踐</b>:RF <b class='flag-5'>前端</b>大規模 MIMO 入門

    前端大數據產品的應用背景和應用原理

    ? 導讀: 本文由梯度科技前端研發部高級開發工程師賀信撰寫,主要介紹如何基于前沿開源的前端技術方案實現微前端大數據平臺中的應用落地,并對所取得的應用效果進行剖析。主要包括以下幾個方面
    的頭像 發表于 08-14 15:18 ?1313次閱讀
    微<b class='flag-5'>前端</b><b class='flag-5'>在</b>大數據產品<b class='flag-5'>中</b>的應用背景和應用原理
    主站蜘蛛池模板: 嫩草国产福利视频一区二区| 精品午夜久久影视| 国产精品一区二区三区四区五区| 免费果冻传媒2021在线观看| 在线播放毛片| 久久久久久久久久毛片精品美女| 亚洲精品高清AV在线播放| 国产精品一区二区欧美视频| 色哟哟tv| 国产伦精品一区二区免费 | 国产h视频在线观看网站免费| 内射老妇BBX| WRITEAS塞红酒瓶| 秋霞鲁丝片Av无码| 成人区在线观看免费视频 | 欧美xx69| 成 人 色综合| 天天狠狠色噜噜| 国产在线观看免费| 亚洲色 图| 理论片午午伦夜理片久久| 98国产精品人妻无码免费| 欧美伦理片第7页| 国产精品高潮呻吟AV久久96| 小黄鸭YELLOWDUCK7596| 黑色丝袜美女被网站| 又紧又大又爽精品一区二区 | 久久99精品国产麻豆婷婷| 中文成人在线| 欧美一区二区三区久久综| 国产成人mv 在线播放| 亚洲乱色视频在线观看| 毛片大全网站| 大迪克黑人异族| 亚洲欧美日韩国产手机在线| 久久视热频国只有精品| jaPanesmature儿母| 香艳69xxxxx有声小说| 猫咪最新破解版下载| 丰满的寡妇hd高清在线观看| 亚洲免费久久|