[Go] Unit testing Go code
- Vanilla Go includes Testing
- A test is a file with
suffix_test.go
- You define functions with prefix
Test
and with an special signature receiving a*testing.T
arguement - The function inside calls methods of
T
- You can create subtests as goroutines
- You use the CLI with
go test
- TableDrivenTest Design Pattern
- Fuzzing since 1.19
Fuzzing: Automated testing that manipulates inputs to find bugs. Go fuzzing uses coverage guidance to find failures and is valuable in detecting security exploits and vunlnerabilities.
Code:
查看代码
package api
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"project/data"
)
const apiUrl = "https://cex.io/api/ticker/%s/USD"
// add * to struct in return type is a pattern
// because if you want to return nil from the function
// without *, it doesn't compile
func GetRate(currency string) (*data.Rate, error) {
if len(currency) < 3 {
return nil, fmt.Errorf("3 characteres minimu; %d received", len(currency))
}
upCurrency := strings.ToUpper(currency)
res, err := http.Get(fmt.Sprintf(apiUrl, upCurrency))
if err != nil {
return nil, err
}
var cexResp CEXResponse
if res.StatusCode == http.StatusOK {
// Wait all stream have been readed
bodyBytes, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
errJson := json.Unmarshal(bodyBytes, &cexResp)
if errJson != nil {
return nil, errJson
}
} else {
return nil, fmt.Errorf("status code received: %v", res.StatusCode)
}
rate := data.Rate{Currency: upCurrency, Price: float32(cexResp.Ask)}
return &rate, nil
}
Test:
package api_test
import (
"testing"
"project/api"
)
func TestApiCallWithEmptyCurrency(t *testing.T) {
_, err := api.GetRate("")
if err == nil {
t.Error("error was not found")
}
}