Slide 1

Slide 1 text

もう少しテストを書きたいんじゃ〜 第173回 PHP勉強会@東京 Hideki Kinjyo GitHub: o0h / X: @o0h_ [公開用]

Slide 2

Slide 2 text

つい先日! 
 愛知県の某イベントで発表をしてきました  

Slide 3

Slide 3 text

お題: 
 『テスト書いた方が 
 開発が早いじゃん』を解き明かす 話したこと: テストがない環境で、テストを書きたい人ができること 
 テストを書くとこんな風に役立つよ〜のポイント  

Slide 4

Slide 4 text

こんな会話がありました ※ 一部改変   発表を聴きました〜 トテモウレシイ 
 アリガトウ

Slide 5

Slide 5 text

こんな会話がありました ※ 一部改変   会社ではテストまだ書けてい ないので、試してみたいかも ワ、ウレシイ 
 アリガトウ

Slide 6

Slide 6 text

こんな会話がありました ※ 一部改変   ただ、機会があってテストを ちょっと書いた時に どんな検査をすればいいの? で手が止まっちゃって !

Slide 7

Slide 7 text

「テスト的なものに取り組む動機」と 
 「テストを書き始めるための裏道」を 
 与えることは出来た ・・・・が!   今回(名古屋)の発表で

Slide 8

Slide 8 text

「テストを書けていない」人が 
 「自信や興味を持ってテストを書いてみる」に まだ届いていない!   自分が目指していた世界

Slide 9

Slide 9 text

ということで、 
 「テストを書く時の観点」の話 
 をリベンジだと思って話します  

Slide 10

Slide 10 text

本日のテーマ 🙅 テスト自体の「保守性」観点での品質の求め方 🙆 テストケースを考える際のコツ、観点 ⇓ ちょっとだけ「テストを書く」のに自信がつくように!  

Slide 11

Slide 11 text

本日のゴール テストケースを 
 気ままに増やせる/減らせるようになろう!  

Slide 12

Slide 12 text

自己紹介 • 金城秀樹 / きんじょうひでき • GitHub: @o0h / 𝕏 : @o0h_ • 好きなFWはCakePHP • アイコンは美味しい鮭親子丼の写真です • 最近はPodcastをやっています • ハッシュタグ: #readlinefm  

Slide 13

Slide 13 text

前回との比較(ターゲット) • 前回(#phpcon_nagoya)の発表は 
 「まだテストを書き始められていない」人向け • 今回の発表は 
 「書き始めたけど、いまいち自信がない・ふわふわしている」人向け  

Slide 14

Slide 14 text

本題に入る前に • 同日に名古屋であった、こちらの発表も素敵でした! • 勇気づけられる資料なので紹介です  

Slide 15

Slide 15 text

おしながき 1. 基礎編 2. 頭の体操編 3. まとめ  

Slide 16

Slide 16 text

1. 基礎編 2. 頭の体操編 3. まとめ

Slide 17

Slide 17 text

1. 基礎編 
 => 単体テストを考える際のヒント(技法) 2. 頭の体操編 3. まとめ

Slide 18

Slide 18 text

この章は? テストケース考えるときに、 
 どんな引き出しがあるんだろう? を広げるために薄く広く用語を並べます  

Slide 19

Slide 19 text

(・・・の前に) そもそもテストって何なんだ、の話

Slide 20

Slide 20 text

テストの基本 「事前条件」「入力」「結果」「事後条件」をセットで考える • これらが「何をテストするの?」の軸ということに • ケースが考えにくい時は、 
 いったん、日本語でこれらを考えるのも手助けになるはず  

Slide 21

Slide 21 text

テストの基本 この4つの「バリエーション」「網羅性」を考えられた時が 
 「テストに自信を持てる」時になるはず。 
 特に次の2点に着目して考えるのがスタート地点(※個人の意見です) • 「何が動けばOKか」 = 結果 • 「どんな動かし方が考えられるか」 = 入力 
  

Slide 22

Slide 22 text

テストの基本 テストは何をしてくれるのか?を定義すると・・・ • 🙆 テストとは「欠陥があることを証明するもの」 • 🙅 テストとは「欠陥がないことを証明するもの」 すなわち、「書かれた範囲で何かを証明する」だけ。 
 「○○がない」ことを証明はできない => 「こういう欠陥があるのではないか?」というマインドで取り組む  

Slide 23

Slide 23 text

テストを『知る』入口となる色々

Slide 24

Slide 24 text

出力値ベース・テスト [文献] 単体テストの考え方/使い方 (6章) • 何らかの入力をして、その出力(戻り値) を検査する • 対象のオブジェクトや関連オブジェクト が、状態を持たない(変化しない)場合に 使える • これが1番シンプルで便利と思って良さ そう   

Slide 25

Slide 25 text

状態ベース・テスト [文献] 単体テストの考え方/使い方 (6章) • 何らかの操作を行い、対象の状態を検査 する • ファイルへの書き込みやDBのデータ更新 も、この範疇 • 「計算して結果を直接返す」ことが出来 ないが、「結果が何処か別の所で観察で きる」場合などに使う   

Slide 26

Slide 26 text

コミュニケーション・ベース・テスト [文献] 単体テストの考え方/使い方 (6章) • テスト対象から、その協力オブジェクト への入力を検査する • 結果を返してもくれないし、かつ影響 (変更)を観測できない場合に使う • モックやスパイ等のテクニックが必要   

Slide 27

Slide 27 text

制御フローテスト [文献] はじめて学ぶソフトウェアのテス ト技法 (10章) • 制御フロー(分岐経路)を整理して、その フローを通るように検査する • いわゆる「◯◯カバレッジ」を意識する やり方で、テストケースを充実させる   ᶃ ᶄ ᶅ

Slide 28

Slide 28 text

◯◯カバレッジ • プログラムを実行した際に、 
 その処理を通った(cover)箇所の割合(-age) • ソースコードの行単位だったり、分岐単位だったり、色々なレベルが あります • 以前にPHPUnitの機能を絡めて発表した資料 があるので、引用してイメージを共有します • Line Coverage • Branch Coverage • Path Coverage  

Slide 29

Slide 29 text

Line Coverage 行単位で通ったコード(の割合)   実行される

Slide 30

Slide 30 text

Branch Coverage 「分岐」単位で通ったコード(の割合)   実行される 実行されない

Slide 31

Slide 31 text

Branch Coverage 「分岐」単位で通ったコード(の割合)   実行される 実行される

Slide 32

Slide 32 text

Path Coverage 「経路」単位で通ったコード(の割合)   4つのパス(=分岐の組み合わせ)が生まれる

Slide 33

Slide 33 text

比較すると?   Line Coverageを100%にするのは、どれでもOK OR OR OR

Slide 34

Slide 34 text

Branch Coverageを100%にするのは、$cの判定まで行く必要がある 
 それさえあればOK 比較すると?   OR

Slide 35

Slide 35 text

Path Coverageを100%にするのは、すべて必要 
 (※1番下って必要?については説明しません!) 比較すると?   AND AND AND

Slide 36

Slide 36 text

カバレッジとテスト • 必ずしも「ちゃんと測定する」「数字を気にする」とならなくても • なんとなく「そういう観点があるんだな」を知って • 自分がテストを良くする際の発想のヒントに使える!!(はず

Slide 37

Slide 37 text

同値クラステスト [文献] はじめて学ぶソフトウェアのテス ト技法 (3章) • 「違う値だけど意味が同じ」ものを削っ て、テストケースを減らす   開始日 終了日 2025-02-10 2025-03-10 この区間は 
 どれをとっても 
 「同じ意味」

Slide 38

Slide 38 text

境界値テスト [文献] はじめて学ぶソフトウェアのテス ト技法 (4章) • 「意味の境目」に着目して、テストケー スを増やす • 境界線の「内側」「ぴったり」「外側」 の値を使ってテストする   開始日 終了日 2025-02-10 2025-03-10 変わり目に沿って 
 検査をする

Slide 39

Slide 39 text

ディシジョンテーブルテスト [文献] はじめて学ぶソフトウェアのテスト技法 (5章) • 「入力」「出力」のバリエーションを表形式で整理し、組み合わせの 漏れをなくす • 1列 = 1ケースとして扱う   έʔε1 έʔε2 έʔε3 έʔ ೖྗ Ωϟϯϖʔϯظؒத y y y ݶఆ඼ n y n Ωϟϯϖʔϯର৅Ձ֨ Ҏ্ Ҏ্ ະຬ ظ଴ Ձ֨ -10% ±0% ±0% ϙΠϯτ 5% 5% 3%

Slide 40

Slide 40 text

ペアワイズ法 • 効率的に「無駄な組み合わせ」を減らす方法 • デシジョンテーブルを全うにやりすぎると、組み合わせが増えすぎる • 「PICT」というツールが有名 • これを使うとがーーーーーっと減らせる • Emacsで便利に使えるらしいので、Emacs を使いましょう!  

Slide 41

Slide 41 text

三角測量 [文献] テスト駆動開発(3章) • 1つの視点で「成功すること」もしくは 「失敗したこと」を検査した後に、別の 視点でテストするで確かさを高める   A 1視点だけだと、ブレる 2視点で座標を確定する A B

Slide 42

Slide 42 text

ブラックボックステスト • 内部実装の知識に頼らずに実施するテスト • 例えば「シグニチャ(引数や返り値、phpdocの内容など)」や「仕様書」 に沿ってテストケースを作成する  

Slide 43

Slide 43 text

ホワイトボックステスト • 内部実装の知識に頼って実施するテスト • 例えば「コードカバレッジを高める(行カバレッジやブランチカバレッ ジetc)」ようなテストケースを作成する  

Slide 44

Slide 44 text

1. 基礎編 2. 頭の体操編 3. まとめ

Slide 45

Slide 45 text

このテスト、よさそう? • 機能: 指定されたIDのユーザーを消す • テスト: • id=1を入力して、操作を実行する • ユーザー(id=1)が消えていることを確認する  

Slide 46

Slide 46 text

このテスト、よさそう? • 機能: 指定されたIDのユーザーを消す • テスト: • id=1を入力して、操作を実行する • ユーザー(id=1)が消えていることを確認する   この世界で最も美しいクエリ───

Slide 47

Slide 47 text

このテスト、よさそう? • 機能: 指定されたIDのユーザーを消す • テスト: • id=1を入力して、操作を実行する • ユーザー(id=1)が消えていることを確認する   DELETE FROM user;

Slide 48

Slide 48 text

そのテスト、駄目そう • 機能: 指定されたIDのユーザーを消す • テスト: • id=1を入力して、操作を実行する • ユーザー(id=1)が消えていることを確認する • テスト2[三角測量]: • ユーザー(id=2)が消えていないことを確認する • 取りうるIDは「指定されたID」か「指定されていないID」だけなので、 
 それらの同値クラスを代表する値を1つずつ確かめられていればOK  

Slide 49

Slide 49 text

こんなテスト、どうする? • 機能: 入力されたメッセージを、世界中の市役所に送信する • テスト: • メッセージを実際に入力して • 「送信されたかな」を確認する • 問題: • 「世界中の市役所が壊れていたら」という挙動を確認できない • 「テストのために市役所を壊滅させよう」なんて出来ないので   テスト対象 クラス 世界市役所 
 クライアント

Slide 50

Slide 50 text

こんなテスト、どうする? • 機能: 入力されたメッセージを、世界中の市役所に送信する • テスト: • メッセージを実際に入力して • 「送信されたかな」を確認する • 問題: • 「世界中の市役所が壊れていたら」という挙動を確認できない • シナリオ1: 入力が正しく、送信先も正常な場合、成功   テスト対象 クラス 世界市役所 
 クライアント ココがOK ココもOK

Slide 51

Slide 51 text

こんなテスト、どうする? • 機能: 入力されたメッセージを、世界中の市役所に送信する • テスト: • メッセージを実際に入力して • 「送信されたかな」を確認する • 問題: • 「世界中の市役所が壊れていたら」という挙動を確認できない • シナリオ1: 入力が正しく、送信先も正常な場合、成功 • シナリオ2: 入力が正しくなくて、失敗   テスト対象 クラス 世界市役所 


Slide 52

Slide 52 text

こんなテスト、どうする? • 機能: 入力されたメッセージを、世界中の市役所に送信する • テスト: • メッセージを実際に入力して • 「送信されたかな」を確認する • 問題: • 「世界中の市役所が壊れていたら」という挙動を確認できない • シナリオ1: 入力が正しく、送信先も正常な場合、成功 • シナリオ2: 入力が正しくなくて、失敗 • シナリオ3: 入力が正しく、送信先が異常な場合、???   テスト対象 クラス 世界市役所 
 クライアント ココがOK ココがNG

Slide 53

Slide 53 text

こんなテスト、どうする? • 機能: 入力されたメッセージを、世界中の市役所に送信する • テスト: • メッセージを実際に入力して • 「送信されたかな」を確認する • 問題: • 「世界中の市役所が壊れていたら」という挙動を確認できない • シナリオ1: 入力が正しく、送信先も正常な場合、成功 • シナリオ2: 入力が正しくなくて、失敗 • シナリオ3: 入力が正しく、送信先が異常な場合、???   これも 
 「要素」×「状態」 
 で洗い出せる

Slide 54

Slide 54 text

こんなテスト、ダミーオブジェクトを使う • モックとかスタブとか • 「もし、こうなったら?」を 
 ハリボテ化する • これらは、 
 テストを簡単にするための方法 • 簡単 = テストの実装をシンプルに • 簡単 = テストの意図をわかりやすく   テスト対象 クラス 世界市役所 
 クライアント ココがOK ココがNG スタブ!

Slide 55

Slide 55 text

参考: こんなテスト、ダミーオブジェクトを使う • 「なるほど〜〜」ってなりやすのでオススメの資料 • 混乱されがちな「モックとは?スタブとは?」を解説する内容です が、コミュニケーション・ベース・テストの意義についても感じら れると思います  

Slide 56

Slide 56 text

カバレッジの練習 こんな仕様で実装したつもりです • お弁当とお茶の合計金額を返す • お弁当1個777円 • お茶1本120円 • お弁当を2つ以上買うと、お茶が1本無料 • お茶が無料になるのは最大1本まで  

Slide 57

Slide 57 text

カバレッジの練習 • Lineでカバレッジを見ると 
 どうなりますか?  

Slide 58

Slide 58 text

カバレッジの練習 • Lineで見てみるとこうなる①  

Slide 59

Slide 59 text

カバレッジの練習 • Lineで見てみるとこうなる②  

Slide 60

Slide 60 text

カバレッジの練習 • Lineで見てみるとこうなる③  

Slide 61

Slide 61 text

カバレッジの練習 • テストでカバーできているのは? • Branchでみてみる場合  

Slide 62

Slide 62 text

カバレッジの練習 • テストでカバーできているのは? • Branchでみてみる場合①  

Slide 63

Slide 63 text

カバレッジの練習 • テストでカバーできているのは? • Branchでみてみる場合②  

Slide 64

Slide 64 text

カバレッジの練習 • テストでカバーできているのは? • Branchでみてみる場合③  

Slide 65

Slide 65 text

カバレッジの練習 カバレッジだけで見えてこないもの 
 => まだ欠陥があるかも 例: • お弁当2つ以上でお茶が全部無料になる バグ • あらゆる条件でお茶が無料にならない バグ • あらゆる条件でお茶が1本無料になるバ グ  

Slide 66

Slide 66 text

1. 基礎編 2. 頭の体操編 3. まとめ

Slide 67

Slide 67 text

これが言いたい テストは場数!!!!  

Slide 68

Slide 68 text

これが言いたい 書いてみる 読んでみる やっていきましょう!!  

Slide 69

Slide 69 text

更に学習するために • こうした話を深ぼるには「ソフトウェアテスト技法」で調べると◎ • 『ソフトウェアテスト技法練習帳』(技術評論社)などもオススメ • テスト的な感覚や「仕様や期待する挙動をコードに落とす」の感覚を 磨くには、『テスト駆動開発』の写経を真面目にやってみるのもオス スメです • よく使うフレームワークの機能や仕様を「テストコードから読み解い てみる」のも非常にオススメ • cloneして手元で「もうあるテストを書き換えて・壊して動かしてみる」のも学 びが深まります!  

Slide 70

Slide 70 text

おしまい! お付き合いいただき ありがとうございました!!

Slide 71

Slide 71 text

参考書籍 • Vladimir Khorikov 著ほか. 単体テストの考え方/使い方, マイナビ出 版, 2022.12, (Compass Programming). 978-4-8399-8172-3. • リー・コープランド 著ほか. はじめて学ぶソフトウェアのテスト技 法, 日経BP社, 2005.11. 4-8222-8251-1. • Kent Beck 著ほか. テスト駆動開発, オーム社, 2017.10. 978-4-274- 21788-3.