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
xUnit Test Patterns の序章
Search
takattata
January 11, 2018
Technology
390
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
xUnit Test Patterns の序章
@社内LT大会_12月
※著作権的にアウトそうだったら消します
takattata
January 11, 2018
More Decks by takattata
See All by takattata
What's DDD?
takattata
5
920
Kotlinのコントリビュートに挑戦してみたよ!
takattata
3
300
導入画面を実装したよ
takattata
1
2k
AndroidXに移行しようと`してみた`!
takattata
2
740
Flutterテストことはじめ
takattata
1
860
Flutter
takattata
3
1.6k
ディープリンクを実装した
takattata
1
1.9k
introduce unit testing
takattata
1
600
プロジェクトの1ファイルに単体テストを書いてみた!〜本当にこれで合ってるの…??🤔〜
takattata
0
2.4k
Other Decks in Technology
See All in Technology
小さく始める AI 活用推進 ― 日経電子版 Web チームの事例/nikkei-tech-talk47
nikkei_engineer_recruiting
0
300
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
2k
生成 AI 実践ガイド (概略版) AIガバナンス編
asei
0
110
入門!AWS Blocks
ysuzuki
1
160
Claude Codeをどのように キャッチアップしているか
oikon48
13
8.5k
「勝手に広まる」人気 AI エージェントを爆速で作ろう!(AWS Summit Japan 2026講演資料)
minorun365
PRO
5
1.8k
Flow 不死:AI 時代 DevOps 的不變本質
cheng_wei_chen
2
260
Bucharest Tech Week 2026 - Guardians of the Cloud-Native Galaxy
edeandrea
PRO
0
120
エラーバジェットのアラートのタイミングを考える.pdf
kairim0
0
170
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
3k
Kiro Ambassador を目指す話
k_adachi_01
0
110
200個のGitHubリポジトリを横断調査したかった
icck
0
130
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Building AI with AI
inesmontani
PRO
1
1.1k
Claude Code のすすめ
schroneko
67
230k
Navigating Weather and Climate Data
rabernat
0
220
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
1
200
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Test your architecture with Archunit
thirion
1
2.3k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
730
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
260
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
200
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.7k
Transcript
@takattata xUnit Test Patterns の序章
xUnit xUnitって何があるかご存知ですか?
JUnit(Java) SUnit(Smalltalk) NUnit(.Net) VbUnit(Visual Basic) CUnit(C) CppUnit(C++) PerlUnit(Perl) PyUnit(Python) HUnit(Haskell)
HttpUnit(HTTPによる通信を擬似的に行なう ) HtmlUnit(ウェブブラウザのエミュレータ ) … xUnitでなくても、テストの体系を学べる本 xUnit
Goals, Principles and Smells
The Patterns
脆弱なテスト(Fragile Test)の問題 4つの点において限界があることを知るのは重要 Introduction: Fragile Test Problem
Behavior Sensitivity システムの動作が変更された場合、修正された機能のテストは失敗する可能性が高い Introduction: Fragile Test Problem
Interface Sensitivity UIを介してテスト中のシステム内のビジネスロジックをテストするのは良くない (過去よくあった?) Introduction: Fragile Test Problem
Data Sensitivity テストは既にシステム内にあるデータの観点から定義された test fixture(=pre-conditions, before picture)があ るが、そのデータが変更された場合、多大な努力を払わないとテストは失敗する Introduction: Fragile
Test Problem
Context Sensitivity システム外の状態(デバイスや他アプリ, 日付等)のコンテキストの影響を受けるテストは、コンテキストを制御し ない限り、確定的に繰り返すことが困難 Introduction: Fragile Test Problem
Behavior Sensitivity Interface Sensitivity Data Sensitivity Context Sensitivity →これらを解決する為には、テストのフレームワークを効果的に使用する方法を学ばないといけない Introduction:
Fragile Test Problem
回帰テスト(regression testing) プログラムに手を加えたことによる影響を確認するテスト (=デグレしてないか確認する ) 仕様としてのテスト(tests as specification) TDD この本ではTDDの書き方ではなく、テストがどのようになっているかの観点から説明
test-driven, test-first, test-last開発のどれでも役に立つので、「開発プロセスには無関心」で書いている Introduction: type
Pattern =繰り返し問題に対する解決策 段階がある: 高いレベルの "strategy"パターン →より詳細な "design patterns" →最も詳細な "coding
idioms" へと進むためには、パターン間にリンケージが必要 Introduction: Patterns
Introduction: Patterns 3つのレベルで区別している - “Strategy” level patterns 大きな影響をもたらす Shared Fixture,
Fresh Fixtureを使用することで異なるテストデザインパターンに繋がる - Test “Design” level patterns 特定の機能のテストを書く時, テストロジックをどう整理するかに焦点をあてる ex.) Mock Object patternとか - Test “Coding Idioms” 特定のテストをコーディングする方法, 言語固有のもの
Introduction: Patterns vs Principles vs Smells Principles 選択したパターンはテスト自動化の”ゴール”(テスト自動化で望まれる結果が書かれている)に影響を受ける “ゴール”はパターンを良くすることについての信念体系を体系化する、多くの”原則”によってサポートされている(詳細 については該当の章を参照のこと)
Smells 使ってるパターンが持ってる、起こしがちな問題など
Introduction: Testing Terminology system under test(SUT) 「何をテストしているのか(whatever thing we are
testing)」の略 - unit testsを書く時、テストするクラス、メソッドのこと - customer testsを書く時、アプリ全体か主要なサブシステムのこと
- Unit Testは特定のテストに 関してのみSUT - Unit2 Testを見た時、Unit1 SUTはUnit2 SUTが使用する ため、dependend-on
component(DOC)の役割を する Testing Terminology
Refactoring A Test
Why Refactor Tests? テストは迅速な開発プロセスのボトルネックになるので、リファクタリングをした方が良い 実際に複雑なテストを簡単にする流れを見ながら、生産性の違いを感じてほしい 途中でいくつか重要なsmellsや、それを取り除くためのパターンを出していくよ
A Complex Test ・長い ・コメントが4行も ・ややこしい etc...
test conditionsを見ていこう まずここ、必ずfalseになることを期待しているなら、 Cleaning up the Verification Logic
失敗の呼び出しに変更しよう!直接言うべき これはExtract Method [Fowler]リファクタリング (Martin FowlerのRefactoring Improving the Design of
Existing Codeからメソッド名を引 用)
他にもある 何故こんなにアサーションが必要なんだ?
予想されるオブジェクトを作って、単一のアサーションを使おう これはPreserve Whole Object[Fowler] リファクタリング
でも、待って! なんで if 文がテストに出てくるの? Conditional Test Logic は排除していこう 幸運にも、今回はGuard Assertionが使える
if … else fail() … のところを同じ条件のアサーションに変えるだけ これをもっと短くしたいなら、 Extract Methodリファクタリングを使用して Custom
Assertionを定義しよう こうなる ↓
良き! 次は finallyブロック に注目しよう
そもそもこのコードには致命的な欠陥がある Cleaning up the Fixture Teardown Logic
もしdeleteObjectで失敗したら?のテストがな い! とはいえ、右の様なテストを管理するのはあり 得ない! この問題にはComplex Teardownがある 問題の根本を解決することはできないが、 tearDownメソッドに入れてコードを細分化しよ う
案1: “テスト間で分割されない ”Shared Fixtureを 使うことで、最初にオブジェクトを作らなくて 良くなる が、問題が2つ 1. 共有されたfixtureを介してやり取りす ることで、Unrepeatable
Test, Interacting Tests(不安定なテスト)を 含むtest smellsが多くなる 2. 共有されたfixtureから使われるオブ ジェクトへの参照がMystery Guests になる → 今回は却下
案2: Fresh Fixtureを使う 自動でGCされるメモリ内のfixtureを使う が、問題が1つ 1. 作成するオブジェクトが永続的なもの (DBに保存されているなど )では機能しな い
→ 今回は採用 実現方法: テスト自動化フレームワークに、作成したオブ ジェクトを登録する方法を追加して、削除する
テストクラスに ・オブジェクトを確保しておくリスト ・追加する関数 ・削除する関数 を準備して、使う
良くなった が、まだいける たとえば、変数を初期化する必 要はあるだろうか? これはfinallyブロックのためだっ たから、宣言と初期化を合体さ せよう!
None
Cleaning up the Fixture Setup Extract Methodリファクタリングを使用してCreation Methodを定義しよう オブジェクトを作成して、registerTestObjectを呼び出す関数をそれぞれ作ろう 利点:
読みやすくなる + カプセル化されるからコンストラクタが変更された時にメンテナンスしやすい
まだ問題がいくつかある 1. fixtureが予想している結果とどう関連しているか分かりづらい 2. Hard-Coded Test Dataを使っている (Unrepeatable Test, Interacting
Tests, Test Run Warが起こる可能性が出る ) 解決法: 各テストに固有の値を作って、その値を元にテスト用に作成したオブジェクトで使う (=Anonymous Creation Method) ←今までの引数は関数内に値を移した Addressも → customerで 使いたいだけ createACustomer関数 内でやれば良いね? (Extract Method再び)
これで、テストで検証しているロジックに影響するものだけになった でも、まだ2回繰り返されているハードコーディングされたテストデータがある Replace Magic Number with Symbolic Constantリファクタリングで、 数字の意味を明確にしよう
ついでに、計算が分かりにくいので Introduce Explaining Variableリファクタリングで文書化してみた このコードはTests as Documentationの役割を完全に満たしている(テストの”ゴール”に関わる) The Cleaned Up
Test
Writing More Tests Q: 毎度こんなに色々書くの ?? A: 再利用出来る Test Utility
Methods があるし、 アプリのテストの為に Higher Level Language を定義している 「先ほどの内容をUtilityで書き 換えたけど、2分で書けたよ」