Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
テーブル駆動テストと状態
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
440
CIを整備してメンテナンスを生成AIに任せる
hazumirr
0
1.5k
病院の情報フローを理解して、 予約〜会計の見え方が変わった話
hazumirr
1
1.9k
Rubyのコード削除したい時 僕がやること
hazumirr
0
290
オンラインテストしようと思った その日に開始できる環境を目指して
hazumirr
0
1.1k
推薦によるプロダクト改善とマイクロサービスが噛み合った話
hazumirr
2
4.8k
ChatGPTで僕が知っていることまとめ
hazumirr
3
3.1k
プロダクトチームとどう 協業し分析環境を改善するか
hazumirr
2
1.7k
bqv速習会
hazumirr
6
7.3k
Other Decks in Programming
See All in Programming
LLMは4年分のCompose移行を再現できるのか?実プロダクト279件のXMLで探る自動化の境界線
makun
0
440
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
940
自分的「カンファレンスの楽しみ方」
syumai
0
190
Deep dive into the select statement (GopherCon UK)
jespino
0
170
Intent as Code
shoppingjaws
2
230
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
760
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
100
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
0
390
Webの地図
yosuke_furukawa
PRO
1
450
AIエージェント時代のコードレビューを設計する
nogu66
6
2.6k
What We Talk About When We Talk About XP
m_seki
2
390
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
170
Featured
See All Featured
Optimizing for Happiness
mojombo
378
71k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
260
Become a Pro
speakerdeck
PRO
31
6.2k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
430
Marketing to machines
jonoalderson
1
5.7k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.1k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
We Are The Robots
honzajavorek
0
350
Git: the NoSQL Database
bkeepers
PRO
432
67k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
The Cult of Friendly URLs
andyhume
79
7k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
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.