最新国产AV资源网_亚洲熟女AV天堂五月天_中文字幕丶东京热_中文字幕乱码免费高清视频

Hi,您好,歡迎來到西安盛圖軟件科技有限公司!

干貨分享|在 Go 語言單元測試中如何解決文件依賴問題

發(fā)布時間:2023-08-14 10:45:33

現(xiàn)如今的 Web 應(yīng)用程序往往采用 RESTful API 接口形式對外提供服務(wù),后端接口直接向前端返回 HTML 文件的情況越來越少,所以在程序中操作文件的場景也變少了。不過有些時候還是需要對文件進(jìn)行操作,比如某個 API 接口需要返回應(yīng)用程序的 ChangeLog,那么這個接口就可以通過讀取項(xiàng)目的 CHANGELOG.md 文件內(nèi)容,將其發(fā)送給前端。


在編寫單元測試時,文件就成了被測試代碼的外部依賴,本文就來講解下測試過程中如何解決文件外部依賴問題。

獲取 ChangeLog 程序示例

假設(shè)我們有一個函數(shù),可以讀取項(xiàng)目的 ChangeLog 信息并返回。


程序代碼實(shí)現(xiàn)如下:


package main
import (  "io"  "os")
var (  version        = "dev"  commit         = "none"  builtGoVersion = "unknown"  changeLogPath  = "CHANGELOG.md")
type ChangeLogSpec struct {  Version        string  Commit         string  BuiltGoVersion string  ChangeLog      string}
func GetChangeLog() (ChangeLogSpec, error) {  data, err := os.ReadFile(changeLogPath)  if err != nil {    return ChangeLogSpec{}, err  }
 return ChangeLogSpec{    Version:        version,    Commit:         commit,    BuiltGoVersion: builtGoVersion,    ChangeLog:      string(data),  }, nil}



GetChangeLog 函數(shù)實(shí)現(xiàn)比較簡單,首先從 changeLogPath 文件路徑中讀取 ChangeLog 內(nèi)容,然后結(jié)合程序版本號、COMMIT 信息、Go 版本號一起組裝成 ChangeLogSpec 結(jié)構(gòu)體,并返回。

使用臨時文件測試

現(xiàn)在,我們要對 GetChangeLog 函數(shù)進(jìn)行單元測試。


可以發(fā)現(xiàn),GetChangeLog 函數(shù)內(nèi)部依賴了 changeLogPath 文件路徑,然后從中讀取內(nèi)容。所以,在編寫測試時,我們要考慮 changeLogPath 文件如何指定。


我們最先想到的就是指定 changeLogPath 文件的真實(shí)路徑。但是,這可能會存在問題,比如本地環(huán)境和 CI 環(huán)境下 changeLogPath 文件路徑不同,那么在編寫測試代碼時,就要考慮根據(jù)不同的測試環(huán)境執(zhí)行不同邏輯。所以,這種方式不應(yīng)該成為首選方案。


不過,我們可以換種思路,Go 語言提供了 os.CreateTemp 方法,可以創(chuàng)建一個臨時文件。那么,我們就可以考慮在測試函數(shù)開始時創(chuàng)建一個臨時文件來保存 ChangeLog,然后為 changeLogPath 變量賦值為臨時文件路徑,測試代碼執(zhí)行完成后刪除臨時文件,這樣就能夠解決單元測試中依賴外部文件的問題。


按照這個思路,編寫的單元測試代碼如下:


func TestGetChangeLog(t *testing.T) {  // 創(chuàng)建臨時文件  // 第一個參數(shù)傳 "",表示在操作系統(tǒng)的臨時目錄下創(chuàng)建該文件  // 文件文件名會以第二個參數(shù)作為前綴,剩余的部分會自動生成,以確保并發(fā)調(diào)用時生成的文件名不重復(fù)  f, err := os.CreateTemp("", "TEST_CHANGELOG")  assert.NoError(t, err)  defer func() {    _ = f.Close()    // 盡管操作系統(tǒng)會在某個時間自動清理臨時文件,但主動清理是創(chuàng)建者的責(zé)任    _ = os.RemoveAll(f.Name())  }()
 changeLogPath = f.Name()
 data := `# ChangelogAll notable changes to this project will be documented in this file.`  _, err = f.WriteString(data)  assert.NoError(t, err)
 expected := ChangeLogSpec{    Version:        "v0.1.1",    Commit:         "1",    BuiltGoVersion: "1.20.1",    ChangeLog: `# ChangelogAll notable changes to this project will be documented in this file.`,  }
 actual, err := GetChangeLog()  assert.NoError(t, err)  assert.Equal(t, expected, actual)}

復(fù)制代碼


我們首先通過 os.CreateTemp("", "TEST_CHANGELOG") 創(chuàng)建了一個臨時文件,然后將 data 內(nèi)容寫入臨時文件作為 ChangeLog,再然后將臨時文件名稱 f.Name() 賦值給 changeLogPath,之后就可以調(diào)用 GetChangeLog 函數(shù)進(jìn)行測試了。


對于程序版本號、COMMIT 信息、Go 版本號這幾個變量,因?yàn)槎际侨肿兞?,所以也屬于外部依賴?/p>


對于全局變量的依賴,我們可以在 init 函數(shù)中對其進(jìn)行初始化,這樣就相當(dāng)于在測試環(huán)境中固定了這幾個變量的值,便于測試。


func init() {  version = "v0.1.1"  commit = "1"  builtGoVersion = "1.20.1"}


筆記:你也可以在 TestMain 函數(shù)中對其進(jìn)行初始化。


使用 go test 來執(zhí)行測試函數(shù):


$ go test -v -run="TestGetChangeLog$"     === RUN   TestGetChangeLog--- PASS: TestGetChangeLog (0.00s)PASSok      github.com/jianghushinian/blog-go-example/test/file     0.562s


測試通過。

使用 Go embed 測試

以上我們介紹了使用臨時文件的方式來解決被測試函數(shù)依賴外部文件的問題。


不過我們在測試中提供的 ChangeLog 內(nèi)容不多:


  data := `# ChangelogAll notable changes to this project will be documented in this file.`


為了讓單元測試更加可靠,你也許想測試 ChangeLog 內(nèi)容比較多的情況下,GetChangeLog 函數(shù)能否正常工作。


我們可以編寫一個真實(shí)的 CHANGELOG.md 文件,存放于 testdata/CHANGELOG.md 路徑下:


# Kubernetes v0.1.1
## 主要特性和改進(jìn)
- 添加了一些新的主要特性和改進(jìn)。
## 重要變更
- 這里列出了對現(xiàn)有功能的重要變更。
## API 變更
- 在 API 中進(jìn)行的重要變更和更新。
## 已知問題
- 列出了已知的問題和限制。
## Bug 修復(fù)
- 修復(fù)了以下已知 Bug。
## 改進(jìn)和優(yōu)化
- 對現(xiàn)有功能進(jìn)行了改進(jìn)和優(yōu)化。
## 安全性更新
- 列出了安全性方面的更新和修復(fù)。
## 已棄用功能
- 列出了已被棄用的功能。
## 警告和提醒
- 列出了需要注意的警告和提醒事項(xiàng)。
## 社區(qū)貢獻(xiàn)者
- 致謝并列出了為此版本做出貢獻(xiàn)的社區(qū)成員。
更詳細(xì)的信息可以查閱 Kubernetes 官方文檔和發(fā)布說明。


此時,我們可以使用 Go 提供的 embed 技術(shù)來將文件內(nèi)容嵌入到 Go 變量中。

embed []byte

embed 可以實(shí)現(xiàn)在 Go 程序編譯時,直接將文件內(nèi)容嵌入到 Go 變量。embed 目前支持嵌入兩種基礎(chǔ)類型的變量,分別是 []bytestrings。嵌入這兩種類型變量方式相同,本小節(jié)就像大家演示下如何通過將文件嵌入 []byte 變量的方式來編寫 GetChangeLog 函數(shù)的單元測試。


GetChangeLog 函數(shù)編寫的單元測試代碼如下:


package main
import (  _ "embed"  "os"  "testing"
上一篇:低代碼,更利好前端研發(fā)的紅海
下一篇:盛圖科技|在 2023 年及以后可以改善企業(yè)業(yè)務(wù)的五種軟件

歡迎登錄盛圖科技

歡迎注冊盛圖科技

已有賬號,立即登錄