Upgrade to Pro — share decks privately, control downloads, hide ads and more …

テストコードにはテストの意図を込めよう #vstat

テストコードにはテストの意図を込めよう #vstat

706ff501573a736401aa4de5adc88e05?s=128

nihonbuson

July 27, 2022
Tweet

More Decks by nihonbuson

Other Decks in Technology

Transcript

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

  2. 自己紹介 • 風間裕也(ブロッコリー) • 株式会社ビズリーチ(Visionalグループ) プロダクト品質管理部 • 社外活動 ◦ JaSST

    Review実行委員長 ◦ WACATE実行委員 • 執筆活動 ◦ 『Agile Testing Condensed』(翻訳) ◦ 『Testing in DevOps』(翻訳) ◦ 『The BDD Books Discovery』(翻訳) ◦ 『テストコードの注入から始める レガシーコードのリファクタリング』(技術同人誌) SNS上の アイコン
  3. 本発表で話すこと • QAの得意分野を活かして、 テストコードの改善を促す事例を紹介する ◦ 社内外で実際にあった事例を用いて紹介する • 伊藤さんが発表資料の中の 「まだあるリーダブルにするコツ」の1つとして 書いていた以下の部分を詳しく紹介する

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

  5. 3つの立場の人が集まり協調的に要件を確認する Three Amigos People vector created by stories - www.freepik.com

    QA(Tester) 開発者 PO
  6. Three Amigosの得意分野 Three Amigosは得意分野となる注目点が異なる • PO…今回のFeatureで実現したいことに注目 • 開発者…今回のFeatureはどのようにすれば     実現できるかに注目 •

    QA…今回のFeatureが「完成した」と   判断するためには   何を確認すれば良いのかに注目 ※あくまでも得意分野であり、  責任分担している訳ではない
  7. 3つの事例 • 本発表では、QAの得意分野である 「何を確認すれば良いのか」に 注目して行った会話を3つ紹介する ◦ 事例1:分かりやすいメソッド名を考える ◦ 事例2:テストの意図をテストメソッド名に反映する ◦

    事例3:会話を通じてテストの意図を見つけ出す ※本発表では「テストの意図」と表現していますが、  この言葉は、JSTQB(ISTQB)におけるテスト条件のことを指しています。  詳しくは、ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03  を参照してください。
  8. 事例1 分かりやすい テストメソッド名を 考える

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

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

    }
  11. 何を確認したいテスト? 今回のテストって
 何を確認したいん
 ですかね?
 QA 開発者 今回は選んだ
 都道府県によって
 送料が変わることを
 確認したいです!


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

    }
  13. 何を確認したいテスト? これって
 47都道府県
 全てで
 テストする?
 QA 開発者 地方ごとに
 送料が
 変わるのが


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

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

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

    void _中国地方の場合送料が510円{ assertThat(calcShipingCost(“広島県”), is(510)); } ハイレベルテストケース ローレベルテストケース 将来万が一、青森県が統廃合などで 存在しなくなった場合、 東北地方の別の県を選べば良いことが分かる
  17. 伊藤さんも区別して書いている ハイレベルテストケース ローレベルテストケース リーダブルテストコード / #vstat

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

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

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

    _テストその2{ @Test /*氏名:テスト太郎、人数:2名、予約番号:印刷しない*/ public void _テストその3{
  21. テストシナリオをさらに改善する 今回のテストって、
 何を気にしてますかね?
 コメント行に書いてある
 情報量が多くて…
 えっと、自分も情報量が多いなと
 思ってたんですよ!
 実はですね、コードを書く前に
 内容を既に整理はしてまして…
 QA

    開発者
  22. 実はテスト設計書を書いていた

  23. 特別な意図があったのは一部分だけだった @Test /*氏名:テスト太郎、人数:0名、予約番号:印刷する*/ public void _テストその1{ @Test /*氏名:テスト太郎、人数:1名、予約番号:印刷する*/ public void

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

    _テストその2{ @Test /*氏名:テスト太郎、人数:2名、予約番号:印刷しない*/ public void _テストその3{ テストコードを 実装するために 必要になった 入力値
  25. テストの意図をテストメソッド名に込める @Test public void _人数が0名の場合予約できない{ @Test public void _人数が1名の場合予約できる{ @Test

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

    public void _人数が1名の場合予約できる{ } @Test public void _予約番号を印刷しない場合予約できる{
  27. 事例3 会話を通じて テストの意図を 見つけ出す

  28. お題その3 • 題材は自動販売機 • Cucumber + JUnit • 与えられた要求は下記の3つ ◦

    100円硬貨を入れたら 入金額が100円になってほしい ◦ 100円硬貨を入れた後に50円硬貨を入れたら 入金額が150円になってほしい ◦ 1円硬貨は対応しないでほしい
  29. お題を元に作成した結果(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; } }
  30. テストシナリオをさらに改善する Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario:

    入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 入金額確認 Given 自動販売機がある When 1円を入金 Then 0円が入金されている
  31. シナリオ名を変更する Scenario: 入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario:

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

    Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 2回投入時の入金額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている QA 開発者
  33. テストの意図を明確にする 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 開発者
  34. テストの意図を明確にする 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 開発者
  35. テストの意図を明確にする Scenario: 1回投入時の入金額確認 Given 自動販売機がある When 100円を入金 Then 100円が入金されている Scenario:

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

    自動販売機がある When 100円を入金 Then 100円が入金されている Scenario: 複数回投入時の入金加算額確認 Given 自動販売機がある When 100円を入金 And 50円を入金 Then 150円が入金されている Scenario: 使用不可の硬貨投入 Given 自動販売機がある When 1円を入金 Then 0円が入金されている QA 開発者
  37. 数年後、テストの意図が分かるのはどっち? 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円が入金されている
  38. おわりに

  39. おわりに • 今回は、テストメソッド名に着目して、 テストの意図が伝わる改善例をお伝えしました。 • 実際には、テストの意図を確認した結果、 そもそも実装しているテストが 良くない形になっている場合もあります。 ◦ その際はテストメソッド内のリファクタリングや

    テスト設計の作り直しをします。 • 今回は会話から改善する例をお伝えしましたが、 初めからテストプロセスを意識してテストケースを作成 することで、メンテナンス性を高めることができます。
  40. テストプロセス(JSTQBより) テスト 分析 テスト 設計 テスト 実装 テスト 実行 ISTQBテスト技術者資格制度

    Foundation Level シラバス 日本語版 Version 2018V3.1.J03 を参考に作成 何をテスト するか を決定する テストスクリプト やテスト手順を 作成する テストスイート を実行する どのように テストするか を決定する
  41. テストプロセス テスト 分析 テスト 設計 テスト 実装 テスト 実行 何をテスト

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

    するか を決定する テストスクリプト やテスト手順を 作成する テストスイート を実行する どのように テストするか を決定する ここからテストの 意図を込めましょう ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J03 を参考に作成
  43. t_wadaさん作のTDDのサイクルにもある 見てわかるテスト駆動開発より

  44. まとめ • 何を確認したいテストなのか考えることが大切 • 会話を通じてテストの意図を見つけ出すことが可能 • ハイレベルテストケースとローレベルテストケースを 意識してテストメソッド名を考えよう • テストプロセスを活用することで、

    初めからテストの意図を意識でき、 メンテナンス性の高いテストを作成することが可能 • テスト設計を行っておくことで、 テストの意図を整理することが可能
  45. 宣伝

  46. 今年もJaSST Review開催予定! • 秋ごろに開催予定 • 過去には、レビュー中に発生する会話に 着目した発表も存在 ◦ https://www.jasst.jp/archives.html •

    詳細は今後公開予定なので、お楽しみに!
  47. 翻訳書 『Agile Testing Condensed』 • Janet Gregory, Lisa Crispin著 •

    販売:Leanpub • 電子書籍として発売中 • 2019年9月発行 • 2020年4月翻訳版発行 Agileな開発の中で どのようにテストを考えれば良いか について簡潔に書いている一冊 Agile Testing Condensed
  48. 翻訳書 『A Practical Guide to  Testing in DevOps』 • Katrina

    Clokie著 • 風間 裕也、河原田 政典 訳 • 販売:Leanpub • 電子書籍として発売中 • 2017年8月発行 • 2021年8月翻訳版発行 DevOpsにおけるテストについて 事例を交えて紹介した一冊 A Practical Guide to Testing in DevOps
  49. 翻訳書 『The BDD Books - Discovery』 • Gáspár Nagy, Seb

    Rose著 • 販売:Leanpub • 電子書籍として発売中 ◦ もうすぐ物理本を出せるかも? • 2018年2月発行 • 2022年5月翻訳版発行 BDDやATDDにおける、自動化する前の 第1ステップについて書いている一冊 The BDD Books - Discovery
  50. 著書(技術同人誌) 『テストコードの注入から始める  レガシーコードのリファクタリング』 • 販売:Leanpub • 電子書籍として発売中 ◦ ライブコーディングビデオ付き •

    2021年7月発行 テストコードを少しずつ注入しながら、 レガシーコードに立ち向かう方法を、 実際のテストコードを記載しつつ 説明している一冊 テストコードの注入から始める レガシーコードのリファクタリング
  51. 参考:BDDのプロセス 参考:The BDD Books - Discovery

  52. 参考:BRIEFの原則 • Business language(ビジネス言語) • Real data(実際のデータ) • Intention revealing

     (意図を明らかにする) • Essential(必須) • Focused(焦点を絞る) • Brief(簡潔である) 参考:The BDD Books - Formulation
  53. ご清聴 ありがとうございました