Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
テーブル駆動テストと状態
Search
Hazumi Ichijo
September 28, 2023
Programming
2.2k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
テーブル駆動テストと状態
https://golangtokyo.connpass.com/event/293636/
Hazumi Ichijo
September 28, 2023
More Decks by Hazumi Ichijo
See All by Hazumi Ichijo
RailsとRidgepoleの マイグレを120倍早くする
hazumirr
0
490
CIを整備してメンテナンスを生成AIに任せる
hazumirr
0
1.5k
病院の情報フローを理解して、 予約〜会計の見え方が変わった話
hazumirr
1
2k
Rubyのコード削除したい時 僕がやること
hazumirr
0
300
オンラインテストしようと思った その日に開始できる環境を目指して
hazumirr
0
1.2k
推薦によるプロダクト改善とマイクロサービスが噛み合った話
hazumirr
2
4.9k
ChatGPTで僕が知っていることまとめ
hazumirr
3
3.2k
プロダクトチームとどう 協業し分析環境を改善するか
hazumirr
2
1.7k
bqv速習会
hazumirr
6
7.3k
Other Decks in Programming
See All in Programming
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
1.3k
Kotlinの15年とServer-Side Kotlin
n_takehata
1
190
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
1.2k
[Dev Group Paris Octobre 26] Agentforce, SIforce, Claudeforce, Slackbot… on s'y retrouve ?
nabondance
0
130
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
400
SODA - FACT BOOK(EN)
sodainc
1
200
Performance Optimization With LLMs
xleitix
0
240
Getting Started with Vibe Coding
miccheng
0
170
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
180
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
5k
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
3
1.7k
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
820
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
6.3k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.2k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
510
Building Applications with DynamoDB
mza
96
7.3k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
730
Unsuck your backbone
ammeep
672
58k
Raft: Consensus for Rubyists
vanstee
143
7.8k
Design in an AI World
tapps
1
380
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
How to train your dragon (web standard)
notwaldorf
96
6.9k
Utilizing Notion as your number one productivity tool
mfonobong
4
630
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Transcript
© 2023 Wantedly, Inc. テーブル駆動テストと状態 golang.tokyo #33 Sep. 28 2023
- Hazumi Ichijo
自己紹介 © 2023 Wantedly, Inc. 一條 端澄 @hazumirr/@rerost 略歴: 2018~
: ウォンテッドリー株式会社 • 2018/04~ 推薦基盤チーム エンジニア • 2021/09~ 推薦チーム プロジェクトマネージャー • 2022/06~ 推薦チーム リーダー 趣味: テトリス・旅行
テーブル駆動テストで悩ましい点 © 2023 Wantedly, Inc. testCase := []struct{ in string
out int }{ { in: "engineer", out: 2, }, } 単語を受け取りその検索結果の件数を返す関数のテ ストの一部
テーブル駆動テストで悩ましい点 © 2023 Wantedly, Inc. testCase := []struct{ in string
out int }{ { in: "engineer", out: 2, }, } 単語を受け取りその検索結果の件数を返す関数のテ ストの一部 テストケースごとにデータを用意しようとすると...
テーブル駆動テストで悩ましい点 © 2023 Wantedly, Inc. testCase := []struct{ in string
before func(sql.DB) out int }{ { in: "engineer", before: func(db sql.DB) error { // ここでテストデータを DBに準備 }, out: 2, }, } よくあるケースとしてはこんな実装 データを生成するのもテストケースごと に管理する
テーブル駆動テストで悩ましい点 テストコードが負債になる • すでにあるテストをどう修正して良いかわからない • かなり似ているが微妙に異なるものが多い • … © 2023
Wantedly, Inc.
テーブル駆動テストで悩ましい点 テストコードが負債になる • すでにあるテストをどう修正して良いかわからない • かなり似ているが微妙に異なるものが多い • … テストケースの記述では「どう作るか」の関心を排除し、「何が状 態として欲しいか」だけに絞りたい
© 2023 Wantedly, Inc.
解決策 © 2023 Wantedly, Inc. testCase := []struct{ in string
state State out int }{ { in: "engineer", state: State{ users: []User{ { OccupationType: "engineer", }, テストケースはここだけ読めばやりたいこと が見えやすくなる 更に、データベースへの接続などのインター フェース変更が容易に
Tips © 2023 Wantedly, Inc. // 文字列を受け取ってUUIDに変換する func GenerateID(id string)
string { return uuid.NewSHA1(uuid.NameSpaceDNS, []byte(id)).String() } func TestSearchCount(t *testing.T) { ... state: State{... { Uid: generateId("User1"), FriendIDs: []string{generateId("User2")}, }, { Uid: generateId("User2"), FriendIDs: []string{generateId("User1")}, … 依存関係を管理したくなった時
Tips © 2023 Wantedly, Inc. デフォルト値を作りたくなった時 // デフォルト値をpropで受け取ったnon null値で上書きしたものを返す関数 func
Merge[T any](t *testing.T, defaultValue, prop T) T { t.Helper() res := new(T) if err := copier.CopyWithOption(&res, defaultValue, copier.Option{...}); err != nil { t.Errorf("Failed to copy default value. err: %v", err) } if err := copier.CopyWithOption(&res, prop, copier.Option{..}); err != nil { t.Errorf("Failed to copy prop value. err: %v", err) } return *res }
まとめ 1. テストケースには「何が状態として欲しいか」のみ記述 2. (自分の観測範囲では)うまく行っている © 2023 Wantedly, Inc.
© 2023 Wantedly, Inc.