測驗中的惡夢將是誤報。 「一切都會過去!驚人的!」直到未來的某個未知時間,所有地雷一起爆炸,將你的團隊炸入地獄。
測試可能默默失敗的原因有很多。
今天我要講一個很基本的原因:不知道哪些是測驗。
大多數人都是半途而廢地加入 Go 專案的。大多數人透過在現實生活中使用語言來學習語言。
因此,當有人用testify這樣的測試框架來建立專案時,你很可能會認為下面這樣的方法就是測試。
func (suite *ExampleTestSuite) TestExample() { suite.Equal(5, suite.VariableThatShouldStartAtFive) }
然後您加入另一種方法,例如 TestAnotherCase 並發現它有效。您認為您非常清楚什麼是測試。
您所說的「測試」可能與 Go 套件所說的測試不同。
從內建的測試包中,測試可以是以下形式的任何函數
func TestXxx(*testing.T)
當然,由於內建的測試包功能有限,大多數專案都使用 testify/suite 或其他類似的第三方套件作為測試框架。從 testify/suite 的角度來看,什麼是測試?
加入任何以「Test」開頭的方法來新增測試
看,我們對測驗有兩種不同的定義。
使用mockery等工具時,你會閱讀以下內容
您不必再擔心忘記 AssertExpectations 方法呼叫...AssertExpectations 方法已註冊為在測試結束時呼叫
太棒了! 「所以我只需要創建一個模擬,當預期的行為發生時,包就會通知我」。
那就是陷阱。
當mockery在測試結束時說時,它實際上意味著來自testing的定義,而不是來自testify/suite的定義。
因此,當您有以下程式碼時,您將看到 TestA 和 TestB 都通過,即使它們都應該失敗,因為 TestA 中的模擬設定在 TestB 中使用。
package mockandsubtest import ( "fmt" "testing" "github.com/stretchr/testify/suite" ) // Prod code type ExternalService interface { Work() } type Server struct { externalService ExternalService } func NewServer(externalService ExternalService) *Server { return &Server{ externalService: externalService, } } // Test code type ServerSuite struct { suite.Suite ExternalService *MockExternalService Server } func TestServerSuite(t *testing.T) { suite.Run(t, &ServerSuite{}) } // Run before all test cases func (s *ServerSuite) SetupSuite() { s.ExternalService = NewMockExternalService(s.T()) s.Server = Server{externalService: s.ExternalService} } // In this test, Work is set up to be called once but not called func (s *ServerSuite) TestA() { fmt.Println("TestA is running") s.ExternalService.EXPECT().Work().Times(1) } // In this test, Work is called once unexpectedly func (s *ServerSuite) TestB() { fmt.Println("TestB is running") s.Server.externalService.Work() }
運行上述程式碼的結果是
TestA is running TestB is running PASS
事實證明,從測驗和嘲笑的角度來看,只有 TestServerSuite 才被視為測驗。這就是為什麼在 TestServerSuite 末尾呼叫 AssertExpectations 的原因,即使 TestA 和 TestB 是由 testify/suite 內部執行的。
從mockery的角度來看,s.ExternalService預計會被呼叫一次,並且在TestServerSuite的生命週期中實際上會被呼叫一次。所以期望達到了。
有兩種方法可以彌補 testify/suite 和測試之間的差距。
第一種方法是在每個測試方法之前建立一個新的模擬,如下所示。
func (suite *ExampleTestSuite) TestExample() { suite.Equal(5, suite.VariableThatShouldStartAtFive) }
有時,由於多種原因,它在您的專案中並不實用,例如為每個測試案例設定一個伺服器實例太昂貴。然後你可以嘗試另一個方向,即每次測試後手動斷言。
第二個是在每個測試方法的最後加上對 AssertExpectations 的呼叫。例如,在 TearDownTest 中呼叫 AssertExpectations,它在每個測試方法之後執行。
func TestXxx(*testing.T)
以上是揭露 Go 中隱藏的測試陷阱:避免誤報的詳細內容。更多資訊請關注PHP中文網其他相關文章!