$30 off During Our Annual Pro Sale. View Details »

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

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

nihonbuson

July 27, 2022
Tweet

More Decks by nihonbuson

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. 何を確認したいテスト?
    今回のテストって

    何を確認したいん

    ですかね?

    QA
    開発者
    今回は選んだ

    都道府県によって

    送料が変わることを

    確認したいです!

    @Test
    public void _青森県の場合{
    }
    @Test
    public void _広島県の場合{
    }

    View Slide

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

    View Slide

  13. 何を確認したいテスト?
    これって

    47都道府県

    全てで

    テストする?

    QA
    開発者
    地方ごとに

    送料が

    変わるのが

    確認できれば

    OK!

    @Test
    public void _青森県の場合送料が1000円{
    }
    @Test
    public void _広島県の場合送料が510円{
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. テストシナリオをさらに改善する
    今回のテストって、

    何を気にしてますかね?

    コメント行に書いてある

    情報量が多くて…

    えっと、自分も情報量が多いなと

    思ってたんですよ!

    実はですね、コードを書く前に

    内容を既に整理はしてまして…

    QA
    開発者

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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;
    }
    }

    View Slide

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

    View Slide

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

    『入金額確認』になってますね。

    同じ名前はどうかと思うので

    変えたほうが良い気がしてます。

    なるほど。

    そしたらこんな感じですかね。

    (テストシナリオを編集する)

    QA
    開発者

    View Slide

  32. シナリオ名を変更する
    すべてシナリオ名が

    『入金額確認』になってますね。

    同じ名前はどうかと思うので

    変えたほうが良い気がしてます。

    なるほど。

    そしたらこんな感じですかね。

    (テストシナリオを編集する)

    Scenario: 1回投入時の入金額確認
    Given 自動販売機がある
    When 100円を入金
    Then 100円が入金されている
    Scenario: 2回投入時の入金額確認
    Given 自動販売機がある
    When 100円を入金
    And 50円を入金
    Then 150円が入金されている
    Scenario: 使用不可の硬貨投入
    Given 自動販売機がある
    When 1円を入金
    Then 0円が入金されている
    QA
    開発者

    View Slide

  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
    開発者

    View Slide

  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
    開発者

    View Slide

  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
    開発者

    View Slide

  36. テストの意図を明確にする
    ということは、気にしているのは

    2回投入の金額ではなく、

    複数回の投入時の加算

    なんですね。

    あー、確かにそうですね。

    (テストシナリオを編集する)

    Scenario: 1回投入時の入金額確認
    Given 自動販売機がある
    When 100円を入金
    Then 100円が入金されている
    Scenario: 複数回投入時の入金加算額確認
    Given 自動販売機がある
    When 100円を入金
    And 50円を入金
    Then 150円が入金されている
    Scenario: 使用不可の硬貨投入
    Given 自動販売機がある
    When 1円を入金
    Then 0円が入金されている
    QA
    開発者

    View Slide

  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円が入金されている

    View Slide

  38. おわりに

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  45. 宣伝

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide