Upgrade to Pro — share decks privately, control downloads, hide ads and more …

カバレッジ95%以上を実現した テストコードの書き方

yudppp
April 21, 2018

カバレッジ95%以上を実現した テストコードの書き方

Battle Conference U30 ( https://bcu30.jp/ )で話した時の資料です

より安心して使っていただくために、これまでどうしても超えられなかった95%の壁を越えるための挑戦についてと今後のテスト方針について

yudppp

April 21, 2018
Tweet

More Decks by yudppp

Other Decks in Technology

Transcript

  1. σΟϨΫτϦߏ੒ . ├── application │ └── usecase - usecase ├──

    domain │ ├── entity - domain entity(simple struct only) │ ├── repository - domain repository(interface only) │ └── service - domain service ├── infrastructure │ └── persistence │ └── rdb - implement domain repository └── interfaces └── api ├── internal │ ├── handler - http handler │ ├── http_utils - http utils │ └── middleware - http server middleware └── server.go - http server endpoint
  2. DI͢Δ type UserRepository interface { GetByID(ctx context.Context, id uint64) (*User,

    error) } 
 type userService struct { repo UserRepository } func NewUserService(repo UserRepository) UserService { return &userService{ repo: repo, } }
 
 func (u *userService) GetByID(ctx context.Context, id uint64) (*User, error) { … }
  3. ϞοΫԽͯ͠ςετ import ( "context" "testing" "github.com/golang/mock/gomock" ... ) func TestUserServiceGetByID(t

    *testing.T) { ... ctrl := gomock.NewController(t) defer ctrl.Finish() mockRepo := mock.NewMockUserRepository(ctrl) mockRepo.EXPECT().GetByID(c.context, c.id).Return(c.mockuser, nil) service := NewUserService(mockRepo) actual, err := GetByID(c.context, c.id) ... }
  4. SQL΋ϞοΫԽ import ( "regexp"
 sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1" ) func TestGetByID(t *testing.T)

    { … query := `SELECT …` rows := sqlmock.NewRows(columns) rows = rows.AddRow(expextRow…) mock.ExpectQuery(query).WillReturnRows(rows)
 repo := NewUserRepository(mockDB) actual, err := repo.GetByID(c.context, c.id) … }
  5. TableDrivenTests func TestSquare(t *testing.T) { cases := []struct{ expect int

    input int
 }{{1,1},{4,2}} for _, c := range cases { actual := Square(c.input) if actual != c.expect { t.Errorf("Square(%q) == %q, want %q",
 c. input, actual, c.expect, ) } } }
  6. ͲͪΒͷํ͕ྑ͍ίʔυͰ͠ΐ͏͔ if (A || B || C) { return errors.New("something")

    } return nil if (A) { return errors.New("something1") } if (B) { return errors.New("something2") } if (C) { return errors.New("something3") } return nil
  7. ӈΛྑ͍ͱ͍ͯ͠·͢ if (A || B || C) { return errors.New("something")

    } return nil if (A) { return errors.New("something1") } if (B) { return errors.New("something2") } if (C) { return errors.New("something3") } return nil
  8. ϥΠϯΧόϨοδ $ go test -cover `go list ./... | grep

    -v mock` ok .../application/usecase coverage: 97.8% of statements ? .../domain/entity [no test files] ? .../domain/repository [no test files] ok .../domain/service coverage: 96.2% of statements ok …/infrastructure/persistence/rdb coverage: 100.0% of statements ok .../interfaces/api/internal/handler coverage: 94.7% of statements ok .../interfaces/api/internal/middleware coverage: 95.1% of statements …
  9. ࢒Γͷ5%ʹ͍ͭͯ cookie, err := r.Cookie("cookie_name") if err != nil {

    if err == http.ErrNoCookie { h.ServeHTTP(w, r) return } w.WriteHeader(http.StatusInternalServerError) return }
  10. Puppeteer w $ISPNF%FW5PPMT։ൃνʔϜ͕ग़ͨ͠044 w )FBEMFTT$ISPNF w $ISPNFͷΈ͔͠ಈ͔ͳ͍ w /PEF+4Ͱಈ͘ w

    IUUQTHJUIVCDPN(PPHMF$ISPNFQVQQFUFFS w IUUQTUSZQVQQFUFFSBQQTQPUDPN