prepare func(*testing.T, *UserRepository) input UserInput want User wantErr bool wantList []User }{ // ... { name: "sequential IDs", prepare: func(t *testing.T, repository *UserRepository) { for i := 0; i < 5; i++ { _, err := repository.Create(UserInput{Name: fmt.Sprintf("User%d", i+1)}) if err != nil { t.Fatal(err) } } }, input: UserInput{Name: "Alice"}, want: User{ID: 6, Name: "Alice"}, wantErr: false, wantList: []User{ {ID: 1, Name: "User1"}, {ID: 2, Name: "User2"}, {ID: 3, Name: "User3"}, {ID: 4, Name: "User4"}, {ID: 5, Name: "User5"}, {ID: 6, Name: "Alice"}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := NewUserRepository() if tt.prepare != nil { tt.prepare(t, r) } got, err := r.Create(tt.input) if (err != nil) != tt.wantErr { t.Errorf("UserRepository.Create() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { t.Errorf("UserRepository.Create() = %v, want %v", got, tt.want) } if tt.wantList != nil { if !reflect.DeepEqual(r.List(), tt.wantList) { t.Errorf("UserRepository.List() = %v, want %v", r.List(), tt.wantList) } } }) } } Arrange① Arrange② Arrange③ Act① Act② Act③ Assert① Assert② Assert③ • Arrange, Act, Assertが散らばる • 全テスト項目同じ形を強いられる • より複雑なケースだとさらに難解に… 13 Table-driven testingに見るArrange-Act-Assert