Golang 첫 Unit 테스트 #golang

17549 단어 5testunittesttesting
이전 기사 ( Golang 및 Line Notify를 사용하여 API의 인증서 만료 확인 )를 만들었지만 이번에는 단위 테스트를 추가합니다.

Golang의 단위 테스트란?



철저히 조사한 느낌이라면, 다음과 같은 느낌으로 만들어 보면 좋을 것 같습니다.
  • 테스트 할 코드와 동일한 계층 구조에 넣습니다 (표준 패키지가 동일한 구조로 되어 있음)
  • testing 패키지 사용
  • 테스트를위한 함수 접두사에 "Test"를 붙이십시오
  • Assert 가 준비되어 있지 않기 때문에, 스스로 조건을 기재한다
    (테스트 케이스를 실패시키고 싶을 때는 「testing.T.Error」나 「testing.T.Fatal」을 이용한다)
  • testing.T.Error : 이후의 처리를 계속해서 실행하는
  • testing.T.Fatal : 이후의 처리가 실행되지 않는다


  • 테스트 코드 기재



    테스트 대상 코드



    apichecker.go
    package main
    
    import (
        "flag"
        "fmt"
        "io/ioutil"
        "log"
        "net/http"
        "net/url"
        "strings"
        "time"
    )
    
    func main() {
        var endpoint = flag.String("endpoint", "", "check target Endpoint URL")
        var lineToken = flag.String("token", "", "LINE notify token")
        flag.Parse()
    
        var apiResult = getAPI(*endpoint)
        var result = postLINE(*lineToken, apiResult)
    
        fmt.Printf("LINE Post result [%t]\n", result)
    }
    
    func getAPI(endpoint string) string {
        if endpoint == "" {
            log.Println("not endpoint")
            return "not endpoint"
        }
    
        var result = ""
        resp, err := http.Get(endpoint)
        if err != nil {
            result = fmt.Sprintf("NG\n%s", err)
        } else {
            defer resp.Body.Close()
            expire := "-"
            if len(resp.TLS.PeerCertificates) > 0 {
                expireUTCTime := resp.TLS.PeerCertificates[0].NotAfter
                expireJSTTime := expireUTCTime.In(time.FixedZone("Asia/Tokyo", 9*60*60))
                expire = expireJSTTime.Format("06/01/02 15:04")
            }
            result = fmt.Sprintf("OK (expire=%s)\n%s", expire, endpoint)
        }
    
        return result
    }
    
    func postLINE(token string, message string) bool {
        if token == "" {
            log.Println("not token")
            return false
        } else if message == "" {
            log.Println("not text")
            return false
        }
    
        data := url.Values{"message": {message}}
        r, _ := http.NewRequest("POST", "https://notify-api.line.me/api/notify", strings.NewReader(data.Encode()))
        r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
        resp, err := http.DefaultClient.Do(r)
        if err != nil {
            log.Println(err)
            return false
        }
        defer resp.Body.Close()
        _, err = ioutil.ReadAll(resp.Body)
        if err != nil {
            log.Println(err)
            return false
        }
    
        return true
    }
    

    getAPI 테스트 코드 작성



    동일한 패키지이므로 private 함수도 테스트 할 수있어 편리합니다.
    다음 패턴 테스트 케이스 준비
  • 매개 변수 오류
  • 성공적으로 실행 완료
  • 인증서 오류

  • apichecker_test.go
    package main
    
    import (
        "regexp"
        "testing"
    )
    
    func TestGetAPI_パラメーターエラー(t *testing.T) {
        if getAPI("") != "not endpoint" {
            t.Error("failed validation check")
        }
    }
    
    func TestGetAPI_正常(t *testing.T) {
        r := regexp.MustCompile("OK \\(expire=[0-9]{2}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}\\)\nhttps://www.yahoo.co.jp")
        if !r.MatchString(getAPI("https://www.yahoo.co.jp")) {
            t.Error("function format error")
        }
    }
    
    func TestGetAPI_証明書エラー(t *testing.T) {
        r := regexp.MustCompile("NG\n.+")
        if !r.MatchString(getAPI("https://www.yahoo.jp")) {
            t.Error("function format error")
        }
    }
    

    테스트 실행


    $ go test .
    ok      github.com/ynozue/apichecker    0.684s
    

    CI에도 적용



    구성 파일에 테스트 실행 추가



    travis.yaml
    language: go
    
    install:
     - go get -u golang.org/x/tools/cmd/goimports
     - go get -u github.com/golang/lint/golint
    
    script:
     - go vet ./...
     - diff <(goimports -d .) <(printf "")
     - diff <(golint ./...) <(printf "")
     - go test .
    

    수정된 내용을 Git으로 Push




    $ go vet ./...
    
    
    The command "go vet ./..." exited with 0.
    $ diff <(goimports -d .) <(printf "")
    
    
    The command "diff <(goimports -d .) <(printf "")" exited with 0.
    $ diff <(golint ./...) <(printf "")
    
    
    The command "diff <(golint ./...) <(printf "")" exited with 0.
    $ go test .
    ok      github.com/ynozue/apichecker    2.600s
    
    
    The command "go test ." exited with 0.
    

    Appendix


  • 소스 코드
  • 좋은 웹페이지 즐겨찾기