Slide 1

Slide 1 text

テストコードには テストの意図を 込めよう ブロッコリー @nihonbuson

Slide 2

Slide 2 text

自己紹介 ● 風間裕也(ブロッコリー) ● 株式会社ビズリーチ(Visionalグループ) プロダクト品質管理部 ● 社外活動 ○ JaSST Review実行委員長 ○ WACATE実行委員 ● 執筆活動 ○ 『Agile Testing Condensed』(翻訳) ○ 『Testing in DevOps』(翻訳) ○ 『The BDD Books Discovery』(翻訳) ○ 『テストコードの注入から始める レガシーコードのリファクタリング』(技術同人誌) SNS上の アイコン

Slide 3

Slide 3 text

本発表で話すこと ● QAの得意分野を活かして、 テストコードの改善を促す事例を紹介する ○ 社内外で実際にあった事例を用いて紹介する ● 伊藤さんが発表資料の中の 「まだあるリーダブルにするコツ」の1つとして 書いていた以下の部分を詳しく紹介する

Slide 4

Slide 4 text

Three Amigos という考えと QAの得意分野

Slide 5

Slide 5 text

3つの立場の人が集まり協調的に要件を確認する Three Amigos People vector created by stories - www.freepik.com QA(Tester) 開発者 PO

Slide 6

Slide 6 text

Three Amigosの得意分野 Three Amigosは得意分野となる注目点が異なる ● PO…今回のFeatureで実現したいことに注目 ● 開発者…今回のFeatureはどのようにすれば     実現できるかに注目 ● QA…今回のFeatureが「完成した」と   判断するためには   何を確認すれば良いのかに注目 ※あくまでも得意分野であり、  責任分担している訳ではない

Slide 7

Slide 7 text

3つの事例 ● 本発表では、QAの得意分野である 「何を確認すれば良いのか」に 注目して行った会話を3つ紹介する ○ 事例1:分かりやすいメソッド名を考える ○ 事例2:テストの意図をテストメソッド名に反映する ○ 事例3:会話を通じてテストの意図を見つけ出す ※本発表では「テストの意図」と表現していますが、  この言葉は、JSTQB(ISTQB)におけるテスト条件のことを指しています。  詳しくは、ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03  を参照してください。

Slide 8

Slide 8 text

事例1 分かりやすい テストメソッド名を 考える

Slide 9

Slide 9 text

お題その1 都道府県の項目についてテストする場合、 どんな値を使ってテストしますか?

Slide 10

Slide 10 text

何を確認したいテスト? @Test public void _青森県の場合{ } @Test public void _広島県の場合{ }

Slide 11

Slide 11 text

何を確認したいテスト? 今回のテストって
 何を確認したいん
 ですかね?
 QA 開発者 今回は選んだ
 都道府県によって
 送料が変わることを
 確認したいです!
 @Test public void _青森県の場合{ } @Test public void _広島県の場合{ }

Slide 12

Slide 12 text

何を確認したいテスト? @Test public void _青森県の場合送料が1000円{ } @Test public void _広島県の場合送料が510円{ }

Slide 13

Slide 13 text

何を確認したいテスト? これって
 47都道府県
 全てで
 テストする?
 QA 開発者 地方ごとに
 送料が
 変わるのが
 確認できれば
 OK!
 @Test public void _青森県の場合送料が1000円{ } @Test public void _広島県の場合送料が510円{ }

Slide 14

Slide 14 text

意図が伝わるテストメソッド名の例 @Test public void _東北地方の場合送料が1000円{ assertThat(calcShipingCost(“青森県”), is(1000)); } @Test public void _中国地方の場合送料が510円{ assertThat(calcShipingCost(“広島県”), is(510)); }

Slide 15

Slide 15 text

意図が伝わるテストメソッド名の例 @Test public void _東北地方の場合送料が1000円{ assertThat(calcShipingCost(“青森県”), is(1000)); } @Test public void _中国地方の場合送料が510円{ assertThat(calcShipingCost(“広島県”), is(510)); } ハイレベルテストケース ローレベルテストケース

Slide 16

Slide 16 text

意図が伝わるテストメソッド名の例 @Test public void _東北地方の場合送料が1000円{ assertThat(calcShipingCost(“青森県”), is(1000)); } @Test public void _中国地方の場合送料が510円{ assertThat(calcShipingCost(“広島県”), is(510)); } ハイレベルテストケース ローレベルテストケース 将来万が一、青森県が統廃合などで 存在しなくなった場合、 東北地方の別の県を選べば良いことが分かる

Slide 17

Slide 17 text

伊藤さんも区別して書いている ハイレベルテストケース ローレベルテストケース リーダブルテストコード / #vstat

Slide 18

Slide 18 text

事例2 テストの意図を テストメソッド名に 反映する

Slide 19

Slide 19 text

お題その2 以下の画像は座席順番待ちシステムの入力画面です。 この店では、最大4名まで予約できます。 氏名は10文字まで入力可能であり、入力必須です。 この入力画面を用いて、順番待ちの登録が できるかどうかのテストを考えてください。

Slide 20

Slide 20 text

何かをテストしたい気持ちは分かるけど… @Test /*氏名:テスト太郎、人数:0名、予約番号:印刷する*/ public void _テストその1{ @Test /*氏名:テスト太郎、人数:1名、予約番号:印刷する*/ public void _テストその2{ @Test /*氏名:テスト太郎、人数:2名、予約番号:印刷しない*/ public void _テストその3{

Slide 21

Slide 21 text

テストシナリオをさらに改善する 今回のテストって、
 何を気にしてますかね?
 コメント行に書いてある
 情報量が多くて…
 えっと、自分も情報量が多いなと
 思ってたんですよ!
 実はですね、コードを書く前に
 内容を既に整理はしてまして…
 QA 開発者

Slide 22

Slide 22 text

実はテスト設計書を書いていた

Slide 23

Slide 23 text

特別な意図があったのは一部分だけだった @Test /*氏名:テスト太郎、人数:0名、予約番号:印刷する*/ public void _テストその1{ @Test /*氏名:テスト太郎、人数:1名、予約番号:印刷する*/ public void _テストその2{ @Test /*氏名:テスト太郎、人数:2名、予約番号:印刷しない*/ public void _テストその3{ 本当に確認したい 入力値

Slide 24

Slide 24 text

特別な意図があったのは一部分だけだった @Test /*氏名:テスト太郎、人数:0名、予約番号:印刷する*/ public void _テストその1{ @Test /*氏名:テスト太郎、人数:1名、予約番号:印刷する*/ public void _テストその2{ @Test /*氏名:テスト太郎、人数:2名、予約番号:印刷しない*/ public void _テストその3{ テストコードを 実装するために 必要になった 入力値

Slide 25

Slide 25 text

テストの意図をテストメソッド名に込める @Test public void _人数が0名の場合予約できない{ @Test public void _人数が1名の場合予約できる{ @Test public void _予約番号を印刷しない場合予約できる{

Slide 26

Slide 26 text

Nestedを用いてテストの意図を整理する @Nested class _予約できる人数は1名以上4名以下 { @Test public void _人数が0名の場合予約できない{ @Test public void _人数が1名の場合予約できる{ } @Test public void _予約番号を印刷しない場合予約できる{

Slide 27

Slide 27 text

事例3 会話を通じて テストの意図を 見つけ出す

Slide 28

Slide 28 text

お題その3 ● 題材は自動販売機 ● Cucumber + JUnit ● 与えられた要求は下記の3つ ○ 100円硬貨を入れたら 入金額が100円になってほしい ○ 100円硬貨を入れた後に50円硬貨を入れたら 入金額が150円になってほしい ○ 1円硬貨は対応しないでほしい

Slide 29

Slide 29 text

お題を元に作成した結果(JUnitは割愛) Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 1円を入金 Then 0円が入金されている public class VendingMachine { int currentMoney = 0; public void insertCoin(int money) { if (money == 50 || money==100) { currentMoney += money; } } public int getCurrentMoney() { return currentMoney; } }

Slide 30

Slide 30 text

テストシナリオをさらに改善する Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 1円を入金 Then 0円が入金されている

Slide 31

Slide 31 text

シナリオ名を変更する Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 1円を入金 Then 0円が入金されている すべてシナリオ名が
 『入金額確認』になってますね。
 同じ名前はどうかと思うので
 変えたほうが良い気がしてます。
 なるほど。
 そしたらこんな感じですかね。
 (テストシナリオを編集する)
 QA 開発者

Slide 32

Slide 32 text

シナリオ名を変更する すべてシナリオ名が
 『入金額確認』になってますね。
 同じ名前はどうかと思うので
 変えたほうが良い気がしてます。
 なるほど。
 そしたらこんな感じですかね。
 (テストシナリオを編集する)
 Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 2回投入時の入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている QA 開発者

Slide 33

Slide 33 text

テストの意図を明確にする Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 2回投入時の入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている なるほど。ちなみに、
 2つ目のテストの意図って
 なんですかね?
 コインを1回だけではなく、
 2回投入した時にも
 ちゃんと動くか確認したい
 という意図です。
 QA 開発者

Slide 34

Slide 34 text

テストの意図を明確にする Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 2回投入時の入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている なるほどー。
 そしたら『2回投入時』と
 書いていますが、
 3回目はどうなるのでしょうか?
 3回目は2回目と同じく、
 加算されていく仕組みなので、
 ロジック上は大丈夫です。
 QA 開発者

Slide 35

Slide 35 text

テストの意図を明確にする Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 2回投入時の入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている ということは、気にしているのは
 2回投入の金額ではなく、
 複数回の投入時の加算
 なんですね。
 あー、確かにそうですね。
 (テストシナリオを編集する)
 QA 開発者

Slide 36

Slide 36 text

テストの意図を明確にする ということは、気にしているのは
 2回投入の金額ではなく、
 複数回の投入時の加算
 なんですね。
 あー、確かにそうですね。
 (テストシナリオを編集する)
 Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 複数回投入時の入金加算額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている QA 開発者

Slide 37

Slide 37 text

数年後、テストの意図が分かるのはどっち? Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 1円を入金 Then 0円が入金されている Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 複数回投入時の入金加算額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている

Slide 38

Slide 38 text

おわりに

Slide 39

Slide 39 text

おわりに ● 今回は、テストメソッド名に着目して、 テストの意図が伝わる改善例をお伝えしました。 ● 実際には、テストの意図を確認した結果、 そもそも実装しているテストが 良くない形になっている場合もあります。 ○ その際はテストメソッド内のリファクタリングや テスト設計の作り直しをします。 ● 今回は会話から改善する例をお伝えしましたが、 初めからテストプロセスを意識してテストケースを作成 することで、メンテナンス性を高めることができます。

Slide 40

Slide 40 text

テストプロセス(JSTQBより) テスト 分析 テスト 設計 テスト 実装 テスト 実行 ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03 を参考に作成 何をテスト するか を決定する テストスクリプト やテスト手順を 作成する テストスイート を実行する どのように テストするか を決定する

Slide 41

Slide 41 text

テストプロセス テスト 分析 テスト 設計 テスト 実装 テスト 実行 何をテスト するか を決定する テストスクリプト やテスト手順を 作成する テストスイート を実行する どのように テストするか を決定する ここを 注力しがち ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03 を参考に作成

Slide 42

Slide 42 text

テストプロセス テスト 分析 テスト 設計 テスト 実装 テスト 実行 何をテスト するか を決定する テストスクリプト やテスト手順を 作成する テストスイート を実行する どのように テストするか を決定する ここからテストの 意図を込めましょう ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03 を参考に作成

Slide 43

Slide 43 text

t_wadaさん作のTDDのサイクルにもある 見てわかるテスト駆動開発より

Slide 44

Slide 44 text

まとめ ● 何を確認したいテストなのか考えることが大切 ● 会話を通じてテストの意図を見つけ出すことが可能 ● ハイレベルテストケースとローレベルテストケースを 意識してテストメソッド名を考えよう ● テストプロセスを活用することで、 初めからテストの意図を意識でき、 メンテナンス性の高いテストを作成することが可能 ● テスト設計を行っておくことで、 テストの意図を整理することが可能

Slide 45

Slide 45 text

宣伝

Slide 46

Slide 46 text

今年もJaSST Review開催予定! ● 秋ごろに開催予定 ● 過去には、レビュー中に発生する会話に 着目した発表も存在 ○ https://www.jasst.jp/archives.html ● 詳細は今後公開予定なので、お楽しみに!

Slide 47

Slide 47 text

翻訳書 『Agile Testing Condensed』 ● Janet Gregory, Lisa Crispin著 ● 販売:Leanpub ● 電子書籍として発売中 ● 2019年9月発行 ● 2020年4月翻訳版発行 Agileな開発の中で どのようにテストを考えれば良いか について簡潔に書いている一冊 Agile Testing Condensed

Slide 48

Slide 48 text

翻訳書 『A Practical Guide to  Testing in DevOps』 ● Katrina Clokie著 ● 風間 裕也、河原田 政典 訳 ● 販売:Leanpub ● 電子書籍として発売中 ● 2017年8月発行 ● 2021年8月翻訳版発行 DevOpsにおけるテストについて 事例を交えて紹介した一冊 A Practical Guide to Testing in DevOps

Slide 49

Slide 49 text

翻訳書 『The BDD Books - Discovery』 ● Gáspár Nagy, Seb Rose著 ● 販売:Leanpub ● 電子書籍として発売中 ○ もうすぐ物理本を出せるかも? ● 2018年2月発行 ● 2022年5月翻訳版発行 BDDやATDDにおける、自動化する前の 第1ステップについて書いている一冊 The BDD Books - Discovery

Slide 50

Slide 50 text

著書(技術同人誌) 『テストコードの注入から始める  レガシーコードのリファクタリング』 ● 販売:Leanpub ● 電子書籍として発売中 ○ ライブコーディングビデオ付き ● 2021年7月発行 テストコードを少しずつ注入しながら、 レガシーコードに立ち向かう方法を、 実際のテストコードを記載しつつ 説明している一冊 テストコードの注入から始める レガシーコードのリファクタリング

Slide 51

Slide 51 text

参考:BDDのプロセス 参考:The BDD Books - Discovery

Slide 52

Slide 52 text

参考:BRIEFの原則 ● Business language(ビジネス言語) ● Real data(実際のデータ) ● Intention revealing  (意図を明らかにする) ● Essential(必須) ● Focused(焦点を絞る) ● Brief(簡潔である) 参考:The BDD Books - Formulation

Slide 53

Slide 53 text

ご清聴 ありがとうございました