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

「質」のいいユニットテストを書くためのプラクティス / practices to write better unit test

「質」のいいユニットテストを書くためのプラクティス / practices to write better unit test

#phperkaigi 2019での発表資料です。
応用編は https://speakerdeck.com/hgsgtk/think-deep-unit-test-practical-problem にて

Kazuki Higashiguchi

March 29, 2019
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Technology

Transcript

  1. © - BASE, Inc.
    「質」のいいユニットテストを
    書くためのプラクティス
    . . #phperkaigi - @hgsgtk

    View Slide

  2. © - BASE, Inc.
    このトークの全体図

    View Slide

  3. © - BASE, Inc.
    このトークの⽬標
    「初級者」から「中級者」へ

    View Slide

  4. © - BASE, Inc.
    想定する「初級者」
    • ユニットテストフレームワークの⽂法がわかる
    • ⼀通りユニットテストを書いた
    • どういうテストが良いかわからない

    View Slide

  5. © - BASE, Inc.
    ユニットテストについて話すこと
    考え⽅と実践 - 「How Testing?」
    ⽬的 - 「Why Testing?」
    まとめ - 「That’s why Testing」

    View Slide

  6. © - BASE, Inc.
    ⾃⼰紹介
    東⼝和暉 (Kazuki
    Higashiguchi)
    Twitter / GitHub : @hgsgtk
    サーバーサイドエンジニア
    BASE BANK, Inc. / Dev Division

    View Slide

  7. © - BASE, Inc.
    ユニットテストについて話すこと
    考え⽅と実践 - 「How Testing?」
    ⽬的 - 「Why Testing?」
    まとめ - 「That’s why Testing」

    View Slide

  8. © - BASE, Inc.
    「費⽤対効果の⾼い」
    このトークでの「質」 の定義

    View Slide

  9. 費⽤対効果?🤔

    View Slide

  10. 我々はなぜ
    ユニットテストを書くのか?

    View Slide

  11. © - BASE, Inc.
    なぜユニットテストを書くのか
    • 品質向上、バグを防ぎたい?
    • テストによるドキュメンテーション?
    • 設計改善の指標?

    View Slide

  12. © - BASE, Inc.
    根本的な理由は
    コスト削減

    View Slide

  13. © - BASE, Inc.
    コスト削減の指標
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS

    View Slide

  14. © - BASE, Inc.
    ユニットテストによるコスト削減
    ⼿動ユニットテストのコスト
    ドキュメンテーションコスト
    設計改善によるメンテナンスコスト
    ⽋陥の早期発⾒による修正コスト
    デバッグコスト

    View Slide

  15. © - BASE, Inc.
    ユニットテストの作成‧維持コスト
    新規テスト作成コスト
    テスト実⾏時間の待ちコスト
    既存テスト維持コスト
    ⾃動テストのためのCI維持コスト
    ユニットテストの学習コスト

    View Slide

  16. © - BASE, Inc.
    コスト削減の指標
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  17. © - BASE, Inc.
    「テストの経済性」
    • 『xUnit Test Patterns』より
    「テストの経済性」
    • 最初は、⾃動化テストの学習‧
    実践コストによってコストが嵩

    • 徐々に落ち着いてきて、テスト
    による節約コストも増えてくる
    • 結果として、コストは相殺され
    ていく
    ref: https://qiita.com/hgsgtk/items/
    00daa278516d1995dac6

    View Slide

  18. © - BASE, Inc.
    テストの⾮経済性
    • 維持コストが⾼いテストがテス
    ト⾃⾝のコストが上げていく
    • 可読性が悪い
    • 修正頻度が多い
    • 修正が難しい
    • テストによる節約コストも少な
    い効果の薄いテスト
    • 結果的にトータルコストが増⼤
    していく
    ref: https://qiita.com/hgsgtk/items/
    00daa278516d1995dac6

    View Slide

  19. © - BASE, Inc.
    コスト削減の指標
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    >

    View Slide

  20. © - BASE, Inc.
    まとめ:⽬的 - 「Why Testing?」
    • 根本的な⽬的はコスト削減
    • xUTPの「テストの経済性」
    • 費⽤対効果の⾼いユニットテストを⽬指す

    View Slide

  21. © - BASE, Inc.
    まとめ:⽬的 - 「Why Testing?」
    「⽬的」

    View Slide

  22. ここで⼀旦CM

    View Slide

  23. © - BASE, Inc.
    BASEのプロダクトについて
    ネットショップ作成サービス
    「BASE」
    ショッピングアプリ
    「BASE」
    価値の交換をよりシンプルにし、
    世界中の⼈々が最適な経済活動を⾏えるようにする。
    MISSION

    View Slide

  24. © - BASE, Inc.

    View Slide

  25. はい

    View Slide

  26. © - BASE, Inc.
    ユニットテストについて話すこと
    考え⽅と実践 - 「How Testing?」
    ⽬的 - 「Why Testing?」
    まとめ - 「That’s why Testing」

    View Slide

  27. © - BASE, Inc.
    費⽤対効果の良いテストを書くために、
    何を意識するべきか
    ユニットテストの「考え⽅」

    View Slide

  28. © - BASE, Inc.
    ユニットテストの「考え⽅」
    「考え⽅」

    View Slide

  29. © - BASE, Inc.
    ユニットテストの「実践」
    「実践」

    View Slide

  30. 意図を伝えるテスト

    View Slide

  31. © - BASE, Inc.
    意図を伝えるテスト

    View Slide

  32. © - BASE, Inc.
    意図を伝えるテスト
    • テストはメンテナンスされていく
    • 読み⼿にとって理解しやすくメンテナンスしやすいテ
    ストへ

    View Slide

  33. © - BASE, Inc.
    主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  34. © - BASE, Inc.
    Test as Documentation
    意図を伝えるテスト

    View Slide

  35. © - BASE, Inc.
    このメソッドはどういう仕様?
    public function canUse(int $user_id): bool
    {
    $user = $this->User->findById($user_id);
    if (empty($user)) {
    return false;
    }
    if (!$user->isProhibit()) {
    return false;
    }
    if ($user->status === 7) {
    return false;
    }
    return true;
    }

    View Slide

  36. © - BASE, Inc.
    ユニットテストがない場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • 動作コードを読んで理解する
    • もしあれば、ドキュメント(単体仕
    様書など)を読む
    • 実際に動かして理解する
    • それでもわからない場合は、作成者
    に聞きに⾏く

    View Slide

  37. © - BASE, Inc.
    ユニットテストがない場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • 動作コードを読んで理解する
    • もしあれば、ドキュメント(単体仕
    様書など)を読む
    • 実際に動かして理解する
    • それでもわからない場合は、作成者
    に聞きに⾏く
    よくあるケース
    • 複雑なコードでひと⽬ではわからない
    • 意図通りなのかわからない

    View Slide

  38. © - BASE, Inc.
    ユニットテストがない場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • 動作コードを読んで理解する
    • もしあれば、ドキュメント(単体仕
    様書など)を読む
    • 実際に動かして理解する
    • それでもわからない場合は、作成者
    に聞きに⾏く
    よくあるケース
    • そもそもない
    • メンテナンスされてなくて古い

    View Slide

  39. © - BASE, Inc.
    ユニットテストがない場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • 動作コードを読んで理解する
    • もしあれば、ドキュメント(単体仕
    様書など)を読む
    • 実際に動かして理解する
    • それでもわからない場合は、作成者
    に聞きに⾏く
    よくあるケース
    • その対象だけを動かすのが難しい
    • 動かすための前準備に時間がかかる
    • 繰り返し実⾏するのが⼿間

    View Slide

  40. © - BASE, Inc.
    ユニットテストがない場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • 動作コードを読んで理解する
    • もしあれば、ドキュメント(単体仕
    様書など)を読む
    • 実際に動かして理解する
    • それでもわからない場合は、作成者
    に聞きに⾏く
    よくあるケース
    • そもそも作成者が現場にいない
    • 作成者も覚えてない

    View Slide

  41. © - BASE, Inc.
    ユニットテストがある場合
    ΤϯδχΞ
    このメソッド何をし
    てくれるんだろう?
    • ユニットテストを読んで理解する
    • ユニットテストを実⾏して理解する
    • 動作コードを読んで理解する
    • 要件を知るためのドキュメントを読む
    • (それでもわからない場合)作成者に聞
    きに⾏く

    View Slide

  42. © - BASE, Inc.
    テストを読んで仕様を理解する
    /**
    * @param int $user_id
    * @param bool $expected
    *
    * @see StatusChecker::canUse()
    * @dataProvider dataProvider_canUse
    */
    public function test_canUse(int $user_id, bool $expected)
    {
    $checker = new StatusChecker();
    $this->assertSame($expected, $checker->canUser($user_id));
    }
    /**
    * @return array
    */
    public function dataProvider_canUse(): array
    {
    return [
    ‘௨ৗϢʔβʔ͸ར༻Մೳͱ൑ఆ’ => [1, true],
    ‘Ϣʔβʔ͕ଘࡏ͠ͳ͍৔߹͸ར༻ෆՄͱ൑ఆ’ => [9999, false],
    ‘ېࢭϢʔβʔͷ৔߹͸ར༻ෆՄͱ൑ఆ’ => [2, false],
    ‘Ϣʔβʔ͕཭୤Ϣʔβʔͷ৔߹͸ར༻ෆՄͱ൑ఆ’ => [3, false],
    ];
    }

    View Slide

  43. © - BASE, Inc.
    テストを実⾏して理解する⽅法について

    View Slide

  44. © - BASE, Inc.
    Simple Test
    Test as Documentation

    View Slide

  45. © - BASE, Inc.
    このテストは何をしている?
    public function testConditional()
    {
    $Flight = new EagerFlight();
    $Flight->setNumber(1);
    if ($Flight->number === 1) {
    $this->assertTrue($Flight->cancel());
    } else if ($Flight->number === 2) {
    $this->assertTrue($Flight->cancel2());
    }
    if ($Flight->airline_code === 'special') {
    $this->assertSame(2, $Flight->number);
    }
    }

    View Slide

  46. © - BASE, Inc.
    Simple Test
    • テストは読み書きする上でシンプルであるべき
    • ⼩さいテスト
    • 1回につき”ひとつのこと”をテストする
    • 重点を置くべきは、「テストを書くこと」ではなく
    「テストをすること」

    View Slide

  47. © - BASE, Inc.
    Name to Convey Intent
    Test as Documentation

    View Slide

  48. © - BASE, Inc.
    このテストはどういうパターン?
    /**
    * @param int $user_id
    * @param bool $expected
    *
    * @see StatusChecker::canUse()
    * @dataProvider dataProvider_canUse
    */
    public function test_canUse(int $user_id, bool $expected)
    {
    $checker = new StatusChecker();
    $this->assertSame($expected, $checker->canUser($user_id));
    }
    /**
    * @return array
    */
    public function dataProvider_canUse(): array
    {
    return [
    [1, true],
    [9999, false],
    [2, false],
    [3, false],
    ];
    }

    View Slide

  49. © - BASE, Inc.
    Name to Convey Intent
    • 意図、期待値を伝えるための命名‧ラベリング
    • 読み⼿に伝わる “ドキュメント” を⽬指す

    View Slide

  50. © - BASE, Inc.
    テストを改善する
    /**
    * @param int $user_id
    * @param bool $expected
    *
    * @see StatusChecker::canUse()
    * @dataProvider dataProvider_canUse
    */
    public function test_canUse(int $user_id, bool $expected)
    {
    $checker = new StatusChecker();
    $this->assertSame($expected, $checker->canUser($user_id));
    }
    /**
    * @return array
    */
    public function dataProvider_canUse(): array
    {
    return [
    ‘௨ৗϢʔβʔ͸ར༻Մೳͱ൑ఆ’ => [1, true],
    ‘Ϣʔβʔ͕ଘࡏ͠ͳ͍৔߹͸ར༻ෆՄͱ൑ఆ’ => [9999, false],
    ‘ېࢭϢʔβʔͷ৔߹͸ར༻ෆՄͱ൑ఆ’ => [2, false],
    ‘Ϣʔβʔ͕཭୤Ϣʔβʔͷ৔߹͸ར༻ෆՄͱ൑ఆ’ => [3, false],
    ];
    }

    View Slide

  51. © - BASE, Inc.
    振り返り:主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  52. テストを独⽴させる

    View Slide

  53. © - BASE, Inc.
    テストを独⽴させる

    View Slide

  54. © - BASE, Inc.
    主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  55. © - BASE, Inc.
    SUTに対して疎結合
    テストを独⽴させる

    View Slide

  56. © - BASE, Inc.
    SUTに対して疎結合

    View Slide

  57. SUT?🤔

    View Slide

  58. © - BASE, Inc.
    SUT - Sytem Under Test
    • テストしている対象を⽰す
    • ユニットテストの場合、テスト対象のクラス‧メ
    ソッドなど
    • 書籍『xUnit Test Patterns: Refactoring Test
    Code』で登場する⽤語
    https://www.amazon.co.jp/dp/ /ref=cm_sw_r_tw_dp_U_x_Y kJCb EX F

    View Slide

  59. © - BASE, Inc.
    SUTとテストクラスの関係性

    View Slide

  60. © - BASE, Inc.
    SUTとテストクラスの関係性
    • CartTestクラスはCartクラスに依存している
    • クラス間の密結合はメンテナンスしていく上で弊害
    になりうる
    • テストクラス‧SUT間もそれは同様

    View Slide

  61. © - BASE, Inc.
    テストがSUTに密結合する弊害
    • SUTの変更に敏感に反応してテストが落ちる
    • ex. Private methodの実装変更
    • SUTの内部実装を変えるたびに、テストを修正する
    • 壊れやすいテスト
    • 維持コストを抑えるために疎結合を意識する

    View Slide

  62. © - BASE, Inc.
    Test Public Method
    SUTに対して疎結合

    View Slide

  63. © - BASE, Inc.
    Test Public Method
    • SUTをブラックボックスとして⾒る
    • ブラックボックスの外から⾒える Public Method に
    対してテストするのが Better
    • 逆を返すと、Private Methodはテストしない⽅が
    Better
    • ブラックボックスの外から⾒えない

    View Slide

  64. © - BASE, Inc.
    尺度:Methodの “安定度”
    • Public Method
    • 外部から使⽤される想定を持つ
    • 変更の頻度が少ない、“安定”している
    • Private Method
    • 外部から使⽤される想定はない
    • 責務の “不安定” さ
    • 変更の頻度が⾼い、 “不安定”

    View Slide

  65. © - BASE, Inc.
    Do Not Test Private Method
    • 変更の頻度が⾼い Private Method
    • → テストの修正の頻度も⾼くなる
    • →メンテナンスコストの増⼤
    • Private Methodは、同⼀クラスのPublic Methodに
    よって使⽤される
    • → Public Testのテストでカバーできる

    View Slide

  66. © - BASE, Inc.
    IF YOU CAN, Do Not Test Private Method
    • 現実の “レガシーコード” を⽬の前にするとテストし
    たいときはある
    • Private methodを切り出していくのが Better
    • それも苦しい時には、リファクタリングの障壁をへら
    すために、テストを書く選択肢もひとつある

    View Slide

  67. © - BASE, Inc.
    Isolate SUT from others
    SUTに対して疎結合

    View Slide

  68. © - BASE, Inc.
    突然テストが落ちるようになりました、なぜ?
    public function test_canUse(int $user_id, bool $expected)
    {
    $search = CloudSearchWrapper::factory();
    $search->conditions()
    ->keyword(‘test’, ‘title’)
    ->sort(‘list_order asc’);
    $search->documentBatch($this->addJson());
    sleep(3);
    $result = $search->search($search->conditions()->query());
    }

    View Slide

  69. © - BASE, Inc.
    Isolate SUT from others
    • SUTを他のソフトウェア(外部システム)から隔離す

    • 依存している場合
    • 外部システムの動作変更‧状態に応じて、テストが
    突然落ちる
    • Dependency Injectionなどの技法の活⽤
    • 依存しているオブジェクトをTest Doubleに置き換
    える

    View Slide

  70. © - BASE, Inc.
    テスト間の独⽴
    テストを独⽴させる

    View Slide

  71. © - BASE, Inc.
    テスト間の独⽴

    View Slide

  72. © - BASE, Inc.
    テスト間の独⽴性
    • テストが相互依存‧順序依存する場合、 “独⽴性”が
    ない状態
    • “独⽴性” がない弊害
    • テストが通ったり落ちたりする
    • 「ローカルでは通るがCIでは通らないことがある」
    • 不安定なテスト

    View Slide

  73. © - BASE, Inc.
    順序依存するテスト

    View Slide

  74. © - BASE, Inc.
    順序依存するテスト

    View Slide

  75. © - BASE, Inc.
    Depend in Fixture properly
    テスト間の独⽴

    View Slide

  76. © - BASE, Inc.
    Depend in Fixture properly
    • データベースを⽤いるテストを⾏う場合 Fixture を⽤
    いる
    • 全テストケースで共有する 共有されたFixture
    • 共有しているためテストの追加‧変更に影響を受ける

    View Slide

  77. © - BASE, Inc.
    共有されたFixture
    Standard Fixture

    View Slide

  78. © - BASE, Inc.
    共有されたFixture
    Standard Fixture

    View Slide

  79. © - BASE, Inc.
    共有されたFixture
    TestE追加のためにFixtureを変更した
    Standard Fixture

    View Slide

  80. © - BASE, Inc.
    “Standard Fixture”
    • “We reuse the design of the test fixture
    across the many tests.
    • 複数のテストケースでフィクスチャレコード定義
    を共有する戦略
    Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ
    / Chapter 18. Test Strategy Patterns

    View Slide

  81. © - BASE, Inc.
    共有されたFixtureのMerit/Demerit
    • Merit
    • 共通のマスター系テーブルであれば、⼀回の
    Fixture作成で済む
    • Demerit
    • テスト間の独⽴性が損なわれる
    • エッジケースのテストのやりにくさ

    View Slide

  82. © - BASE, Inc.
    テストケース専⽤Fixture
    • テストケースごとに⽤意するFixture (Minimal
    Fixture)
    • テスト間の独⽴性の向上
    • ex. Laraval => Factory‧Faker

    View Slide

  83. © - BASE, Inc.
    共有 & 専⽤ Fixture
    • 2つの戦略を組み合わせて使う
    Standard Fixture

    View Slide

  84. © - BASE, Inc.
    Fixtureに適切に依存する
    • 全テストで共有することが有益なケース
    • 基本となるFixtureを定義
    • ex. 「通常のユーザー」
    • 使いみちが限定されるエッジケースのテスト
    • テストケース専⽤Fixtureを⽤意する
    • ex. 「利⽤禁⽌になったユーザー」

    View Slide

  85. © - BASE, Inc.
    Tear Down Global Changes
    テスト間の独⽴

    View Slide

  86. © - BASE, Inc.
    Tear Down Global Changes
    • テストがグローバルな状態変化を⽣み出す場合
    • $_SERVERの書き換え
    • Session状態の更新
    • トランザクション
    • テスト時間 (timecop使⽤の場合など)
    • 他のテストに影響を及ぼす
    • テスト‧SUTの状態変化に応じてtearDownしておく

    View Slide

  87. © - BASE, Inc.
    振り返り:主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  88. 重複を最⼩限に

    View Slide

  89. © - BASE, Inc.
    重複を最⼩限に

    View Slide

  90. © - BASE, Inc.
    主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  91. © - BASE, Inc.
    DRY in Test Code
    重複を最⼩限に

    View Slide

  92. © - BASE, Inc.
    DRY in Test Code
    • DRY (Don’t Repeat Yourself)は、テストコードにお
    いても同じく意識
    • テストコードの可読性を上げる
    • フレームワーク‧カスタムのTest Utilityの活⽤によ
    り、より意図を語るテストへ

    View Slide

  93. © - BASE, Inc.
    振り返り:主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  94. テスト容易な設計

    View Slide

  95. © - BASE, Inc.
    重複を最⼩限に

    View Slide

  96. © - BASE, Inc.
    主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  97. © - BASE, Inc.
    テスト容易な設計
    • テストコードに対する意識‧改善では、費⽤対効果の
    ⾼いテストは実現できない
    • プロダクションコードのテスタビリティの向上‧改善
    が必要

    View Slide

  98. © - BASE, Inc.
    TDD
    テスト容易な設計

    View Slide

  99. © - BASE, Inc.
    TDD - Test-Drive Development
    • プログラム開発⼿法のひとつ
    • 「動作するきれいなコード」をゴールとする
    • Red-Green-Refactor のサイクルを回す
    • 最初に Red にするため、テストファーストで進める

    View Slide

  100. © - BASE, Inc.
    TDDとテスト容易性
    • テストファーストによって、テスト容易性が強制され

    • テストから先に書くため、基本的な⽋陥はテスト実⾏
    によって気がつくことができる
    • テスト実⾏だけで実装中のコードをデバッグできる

    View Slide

  101. © - BASE, Inc.
    TDDによるテスト容易性の強制について
    https://speakerdeck.com/hgsgtk/tesutokaxin-iwojie-jue-surutesutoqu-dong-kai-fa-falseahuroti-at-phpkanhuarensuxian-tai-2019

    View Slide

  102. © - BASE, Inc.
    振り返り:主に期待する効果
    Ϣχοτςετ
    ʹΑΔ
    ίετ࡟ݮ
    Ϣχοτςετ
    ͷ
    ࡞੒ɾҡ࣋ίετ
    VS
    • खಈϢχοτςετͷίετ
    • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ
    • υΩϡϝϯςʔγϣϯίετ
    • σόοάίετ
    • ઃܭվળʹΑΔϝϯςφϯείετ
    • ৽نςετ࡞੒ίετ
    • طଘςετҡ࣋ίετ
    • ςετ࣮ߦ࣌ؒͷ଴ͪίετ
    • ࣗಈςετͷͨΊͷCIҡ࣋ίετ
    • Ϣχοτςετͷֶशίετ

    View Slide

  103. © - BASE, Inc.
    まとめ:考え⽅と実践 - 「How Testing?」
    • コスト削減を達成するための「考え⽅」
    • 考え⽅に基づいた「実践」によって、効果を得る

    View Slide

  104. © - BASE, Inc.
    ユニットテストについて話すこと
    考え⽅と実践 - 「How Testing?」
    ⽬的 - 「Why Testing?」
    まとめ - 「That’s why Testing」

    View Slide

  105. © - BASE, Inc.
    良いテストを書くのは難しい
    • 「テストを書く」ことは⽐較的簡単
    • 費⽤対効果の⾼いテストを書くのは難度が上がる
    • 費⽤対効果の⾼いテストを⽬指すのは、考えて実践し
    ていく必要がある

    View Slide

  106. © - BASE, Inc.
    費⽤対効果を⾼めるには
    “テストにコストがかかることの解決⽅法は、テストを
    やめることではありません。うまくなることです。”
    Sandi Metz. オブジェクト指向設計実践ガイド 〜Rubyでわかる 進化しつづける柔軟なアプリケーションの育て⽅
    https://gihyo.jp/book/2016/978-4-7741-8361-9

    View Slide

  107. Enjoy Happy
    Testing Life 👋

    View Slide

  108. © - BASE, Inc.
    補⾜:参考書籍
    『xUnit Test Patterns: Refactoring Test Code』
    https://www.amazon.co.jp/dp/ /
    ref=cm_sw_r_tw_dp_U_x_Y kJCb EX F
    『オブジェクト指向設計実践ガイド 〜Rubyでわかる 進化しつづける柔
    軟なアプリケーションの育て⽅』
    https://gihyo.jp/book/ / - - - -

    View Slide

  109. © - BASE, Inc.
    補⾜:関連資料
    xUnit Test Patternsから学ぶ12個のユニットテストの原則
    https://qiita.com/hgsgtk/items/a a d d b d
    xUnit Test Patternsから学ぶユニットテストの6つの⽬指すべきゴール
    https://qiita.com/hgsgtk/items/ daa d dac
    xUnit Test Patternsから学ぶテストアンチパターン
    https://speakerdeck.com/hgsgtk/testing-anti-pattern-learned-in-xunit-test-
    pattern
    ユニットテスト初⼼者を脱するために⾝につけたいN個のこと
    https://speakerdeck.com/hgsgtk/n-points-to-get-out-of-unit-test-beginner-
    number-phpstudy

    View Slide

  110. © - BASE, Inc.
    補⾜:関連資料
    テストが⾟いを解決するテスト駆動開発のアプローチ
    https://speakerdeck.com/hgsgtk/tesutokaxin-iwojie-jue-surutesutoqu-dong-
    kai-fa-falseahuroti-at-phpkanhuarensuxian-tai-
    PHPバージョンアップと決済リプレイスを⽀えたユニットテスト
    https://speakerdeck.com/hgsgtk/phpbaziyonatuputojue-ji-ripureisuwozhi-
    etayunitutotesuto-number-phpcon
    テストを書いたことがないエンジニアがテストを書けるようになるまで
    やったこと
    https://speakerdeck.com/hgsgtk/tesutowoshu-
    itakotokanaiensiniakatesutowoshu-keruyouninarumateyatutakoto-at-
    phpkanhuarensuguan-xi-

    View Slide