2 回答

TA貢獻1810條經驗 獲得超5個贊
您的代碼需要進行一些重構以使其可測試。目前您無法真正測試代碼,因為代碼中的函數不返回任何內容。在單元測試中,您調用一個函數并驗證它的輸出(一般來說)。
因此,為了使您的代碼可測試,您必須在單獨的函數中重構代碼的某些部分。我將向您展示閏年的示例:
//main.go
func IsLeapYear(date time.Time) bool {
if date.Year() % 400 == 0 {
return true
}
return date.Year()%4 == 0 && date.Year()%100 != 0
}
在您的測試文件中:
//main_test.go
type dateTest struct {
date time.Time
expect bool
}
var dateTests = []dateTest{
// your test data
}
func TestIsLeapYear(t *testing.T){
for _, tc := range dateTests {
result := IsLeapYear(tc.data)
assert.Equal(t, tc.expect, result)
}
}

TA貢獻1825條經驗 獲得超6個贊
關于您更新的代碼:
我將從我給您的最重要的一條建議開始: 停止忽略錯誤!檢查錯誤對于調試 Go 代碼和運行程序絕對至關重要。請記住,與 Javascript 等許多高級語言不同,Go 沒有例外。您對錯誤返回的檢查是您必須捕獲這些錯誤的唯一機會。
例如:
json.Unmarshal(byteValue, &users)
如果 json 無效,該行將返回錯誤。你應該檢查一下。查找您使用的每個庫函數的文檔,但您沒有記住 - 我會 - 并確保您正在使用這些錯誤消息。
好的,讓我們看看你傳遞給什么IsLeapYear
:
jsonFile, err := os.Open("users.json") ... IsLeapYear("users.json")
當你到達時,IsLeapYear
你已經過了需要文件名的地步。您已經打開了該文件并將其值解組為一個Users
結構。因此,您當然不需要將文件名傳遞給它。
讓我強調一下 Pim 向您展示的一些您沒有忠實遵循的內容:
func IsLeapYear(date time.Time) bool
IsLeapYear
Pim檢查一個日期這一事實很重要。您的測試用例是需要單獨檢查的單獨日期。但是您 IsLeapYear
會遍歷整個日期列表。您無法提供要檢查的特定日期。您的閏年還希望收到多個日期,但您只返回一個bool
,因此單個返回值不可能告訴您閏年檢查您可能已經過去的多個日期的結果。
按照 Pim 的建議IsLeapYear
- 它應該只有一個參數,并且應該是time.Time
. 名字和姓氏不相關,IsLeapYear
因此不需要傳遞。 IsLeapYear
不需要解析日期 - 它們的格式與您在 json 中存儲數據的方式有關,并且與它們所代表的日期是否是閏年無關。
瞄準 10-20 行功能。
我提出這個建議的原因是,長函數幾乎總是做太多事情,這表明您需要重構函數以更好地匹配算法的組件。讓我們將您的代碼分解為偽代碼以更好地反映您的算法:
從 json 文件中讀取用戶
對于每個用戶:
打印用戶信息
打印閏年消息
如果生日是今天,打印用戶信息和生日信息
否則打印不是生日信息
從預期格式解析其日期
如果是閏年生日
否則打印用戶信息而不是生日信息
從中我們可以確定我們可能編寫的一些函數:
func ReadUsersFromJson(filename string) (*Users, err)
func ParseUserDateString(date string) (time.Time, error)
func IsLeapYear(date time.Time) bool
func PrintUserInfo(u User)
func IsTodaysDate(date time.Time) bool
這些功能中的每一個都非常簡單明了,而且只做一件事。它們中的每一個都可以依次進行測試。你的一般測試方法很常見:寫一個完整的輸入列表(和預期的輸出- 你錯過了那部分),然后遍歷列表,將每個輸入傳遞給正在測試的函數,并驗證它的結果是你的預期的。
因為ReadUsersFromJson
您可能有一個tests/
目錄,其中包含您測試的一些 json 文件。您可以使用有效和無效的 json 測試成功和錯誤情況。
同樣,ParseUserDateString測試數據可能類似于:
struct ParseUserDateStringTestData {
input string
expected time.Time
exp_err_msg string
}
然后你可以在那里測試成功和失敗的案例。其余的功能依此類推。
一旦所有的功能都被編寫和測試了,這只是一個將所有功能組裝在一起的問題Birthday()。
func Birthday() {
users, err := ReadUsersFromJson("users.json")
if err != nil {
panic(fmt.Errorf("Failed to read from Json: %w", err))
}
for _, user := range users.Users {
if d, err := ParseUserDateString(user.Date); err != nil {
panic(fmt.Errorf("Date %s could not be parsed: %w", user.Date, err))
} else if IsLeapYear(d) {
PrintUserInfo(user)
fmt.Printf("Leap year message!")
if IsTodaysDate(d) {
fmt.Printf("birthday message!")
} else {
fmt.Printf("Not birthday message!")
}
} else {
fmt.Printf("Not leap year message!")
}
}
}
它恰好出現在 20 行,而且它在做什么也很清楚。您會注意到,自從我編寫它以來,PrintUserInfo它刪除了Birthday. 當然,這種重復使函數更難閱讀和管理。
如果您編寫像我列出的那樣的函數,并測試所有這些函數,那么您的程序應該可以很好地結合在一起。請注意,main()或Birthday()不需要編寫來測試其他功能。在編寫函數時測試它們是一個好主意,以免最終積壓大量測試,并灌輸對您編寫的代碼的信心。
一個例子:
if date.Day() == time.Now().Day() {
我不認為那正在做你認為它正在做的事情。 Day()實際上是月份的日期,所以你實際上只是說,日期的日期與今天的日期是同一天嗎?任何一個月Day()的 29 日都與 2 月 29 日相同。測試將證明是否是這種情況,然后您可以稍后依賴該功能。同樣,ParseUserDateString測試數據可能類似于:
struct ParseUserDateStringTestData {
input string
expected time.Time
exp_err_msg string
}
然后你可以在那里測試成功和失敗的案例。其余的功能依此類推。
一旦所有的功能都被編寫和測試了,這只是一個將所有功能組裝在一起的問題Birthday()。
func Birthday() {
users, err := ReadUsersFromJson("users.json")
if err != nil {
panic(fmt.Errorf("Failed to read from Json: %w", err))
}
for _, user := range users.Users {
if d, err := ParseUserDateString(user.Date); err != nil {
panic(fmt.Errorf("Date %s could not be parsed: %w", user.Date, err))
} else if IsLeapYear(d) {
PrintUserInfo(user)
fmt.Printf("Leap year message!")
if IsTodaysDate(d) {
fmt.Printf("birthday message!")
} else {
fmt.Printf("Not birthday message!")
}
} else {
fmt.Printf("Not leap year message!")
}
}
}
它恰好出現在 20 行,而且它在做什么也很清楚。您會注意到,自從我編寫它以來,PrintUserInfo它刪除了Birthday. 當然,這種重復使函數更難閱讀和管理。
如果您編寫像我列出的那樣的函數,并測試所有這些函數,那么您的程序應該可以很好地結合在一起。請注意,main()或Birthday()不需要編寫來測試其他功能。在編寫函數時測試它們是一個好主意,以免最終積壓大量測試,并灌輸對您編寫的代碼的信心。
一個例子:
if date.Day() == time.Now().Day() {
我不認為那正在做你認為它正在做的事情。 Day()實際上是月份的日期,所以你實際上只是說,日期的日期與今天的日期是同一天嗎?任何一個月Day()的 29 日都與 2 月 29 日相同。測試將證明是否是這種情況,然后您可以稍后依賴該功能。
- 2 回答
- 0 關注
- 129 瀏覽
添加回答
舉報