Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Springのプログラムモデルと動く仕様~テスト編~

 Springのプログラムモデルと動く仕様~テスト編~

2018/03/07のJSUGの資料です
㈱ビッグツリーテクノロジー&コンサルティングの寺島秀樹としての登壇です。

terahide

March 07, 2018
Tweet

More Decks by terahide

Other Decks in Programming

Transcript

  1. 2 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • 設計? • 仕様? • ドキュメント? はじめに 筆者は「設計とは“考えること”であり、アウト プットはその一側面である」と考えている
  2. 3 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    1. 物事をする方法。しかた。やりかた。 「まだほかに仕様があるだろう」 2. 機械類や建築物などの構造や内容。 「仕様の一部を変更する」 仕様とは? https://dictionary.goo.ne.jp/jn/107319/meaning/m0u/ デジタル大辞泉の解説
  3. 4 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    「ユーザの要求を満たすために サービスやシステム、機能などが どのように振る舞うかを 定めたもの」と定義する この場での「仕様」の定義
  4. 5 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    寺島 秀樹(@terahide27) (株)ビッグツリーテクノロジ&コ ンサルティング 所属 SIerを中心に アーキテクト・アジャイルコンサ ルタントとして就業 システムの保守運用から営業支援 まで手広くいろいろやってます CSP/CSPO/CSM TOCfE国際認定ファシリテータ/ アニメ/酒/ラーメン/ 自己紹介
  5. 6 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • テスト駆動開発の話 • アジャイルの話 • すごい話 今日しない話
  6. 7 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • 実際の事例 • テストと仕様とプログラムの話 • 現場で試してみようと思ってる話 (ちょっとだけ) 今日する話
  7. 9 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • 某サービスを運用している現場 • 5週程度のイテレーションでリリースを繰 り返している • 保守を行うチームメンバは12人程度(ほと んどが経験3年目までの若いメンバ) • 自分はインフラのおもりや障害などの調査 を中心にしていて、開発のイテレーション にはあまり関わってなかった 背景
  8. 10 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    「手が足りないからステージング環境 でテストしてください」 「かしこま〜」 ある日
  9. 11 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    テスト仕様書「ユーザの区分がxxで商材のなんたらフラグ となんたらフラグが立っている時になんたら画面でなんた らするとほにゃららがほにゃららで...」 「?」 ユーザの区分がxxなのはわかった。(それ以外のユーザで はどうなるか書いてないけど一旦おいておこう) 「商材のなんたらフラグってどうやって立てるんですか? DB書き換えてええのん?」 「ステージング環境でそんなことしないでください」 「だったらどうやってその状態にするんですか?」(結構 マニアックな機能だった)
  10. 13 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • テストしたい観点は書かれていた • それをテストするための状態にする にはどうすればいいかが書かれてい なかった なにが問題だったか?
  11. 14 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • 操作やその結果に対してはみなさん よく気づく • その操作を行う事前の条件や状態を 忘れがち • e.g. エアコンの設定温度を20度に すると冷たい風がでる。本当? 事前条件を表す?
  12. 15 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • given 事前条件・状態 • when 対象に対する操作をした時 • then どうなるか テンプレート [given]の状態で[when]をすると[then] given - when – then
  13. 17 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    この人ご存知? http://www.startrek.com/database_article/spock
  14. 18 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • JUnitみたいなもん • given - when - then でテストが書ける素晴らし いもの e.g. Spock def test(){ given: "カートにアイテムがある" 商品一覧を開く() カートにいれるby商品ID(1) when: "カートを開く" 商品一覧でカートリンクをクリックする() then: カート画面が表示されている() and: 購入ボタンがクリッカブルである() }
  15. 19 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    プログラマはプログラムを書くのが仕事 我々はプログラマである https://www.lifehacker.jp/2014/12/141210programmer_signs.html
  16. 20 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    プログラムで表現することができれば ドキュメントと違い動かして検証をすることが容易 自動テストを書けば繰り返しの検証もできる 自動テストもまたプログラム 自動テストのプログラムは、もはやテストが目的で はなく、「動く仕様」としての位置づけを求められ る 自動テストは動く仕様である
  17. 22 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    @Test public void test_success1(){…} @Test public void test_success2(){…} 延々と続く・・・ 前みたJUnit
  18. 23 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    @Test public void test(){ load(“xxxData.xls”); actual = sut(); assertWithExcel(actual, “expected.xlsx”); } 前みたJUnit
  19. 25 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    まずはテストメソッドの名前を given - when - then で書くことをしてみよう JUnitでは? @Test public void カートにアイテムがある状態でカートを開くと購入可能である(){ //given 商品一覧でカートにいれるby商品ID(1); //when 商品一覧でカートリンクをクリックする(); //then カート画面が表示されている(); 購入ボタンがクリッカブルである(); }
  20. 26 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    もう少しUnit Testみたいな例 @Test public void 商品がある状態でカートに追加すると購入可能である(){ //given assertThat(itemService.findAll().size(), graterThan(0)); //when Item item = itemService.findById(1); cartService.add(item); //then assertThat(cartService.isPurchasable(), is(true)); }
  21. 27 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    テストで確認したい部分が仕様レベルの話 それをどう実現するか(指定がないならば)の話は隠蔽しても構わない むしろプログラムレベルの話(前述の例ならばDOMの操作など)は積極 的に隠蔽した方がいい 仕様レベルとそれ以外のレベル @Test public void カートにアイテムがある状態でカートを開くと購入可能である(){ //given // 商品一覧ページを開きIDが商品IDの親のtrタグの中の // classがaddCartのリンクをクリックする(プログラムレベルの話) 商品一覧でカートにいれるby商品ID(1); //when // 「カートを開く」とあるが、開き方の指定はなし(操作レベルの話) 商品一覧でカートリンクをクリックする(); //then カート画面が表示されている(); 購入ボタンがクリッカブルである(); }
  22. 28 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    仕様レベルの話を残しそれ以外は他所に委譲する 結果テストのしやすさにつながってくる e.g. プロダクションコードにおける仕様と構造 public CartService{ //購入可能な状態で購入するとカートからアイテムがなくなり購入処理を行う public void purchase(){ if( ! this.isPurchasable()){ throw new IllegalStateException("is not purchasable"); } List<Item> items = this.findAll(); items.stream() .map(i -> toPurchased(i)) .forEach(p -> purchaseService.purchase(p))); this.deleteAll(items); } ・・・
  23. 29 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    つづき // カートにアイテムがあるならば購買処理の購買可能判定を行う public boolean isPurchasable(){ if( this.findAll().isEmpty() ){ return false; } return purchaseService.isPurchasable(); } public List<Item> findAll(){ return cartRepository.findAll(); } public void deleteAll(List<Item> items){ cartRepository.deleteAll(items); } private PurchasedItem toPurchased(Item item){ //snip 商品の特性によってなにやら難しい処理 }
  24. 33 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    自動テストの際にテスト観点以外の依存した部分をMock やStubなどに差し替えることがやりやすくなった • Frameworkなどの親クラスみたいな縛りから解放され た • 依存関係があった場合でも依存性の注入という形で解決 される DI Container がもたらしたもの
  25. 34 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    前述の例 ホワイトボックステスト //購入可能な状態で購入するとカートからアイテムがなくなり購入処理を行う if( ! this.isPurchasable()){ //モックにしてtrue or false を返す throw new IllegalStateException("is not purchasable"); } List<Item> items = this.findAll(); //モックにしてアイテムを2個返す items.stream() .map(i -> toPurchased(i)) // 複雑なことをしていてテストしづらいなら // モックに変えてシンプルにする .forEach(p -> purchaseService.purchase(p))); //モックにして // 2度呼ばれたことを検証する this.deleteAll(items); //モックにして呼ばれたことを検証する
  26. 35 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    状態中心のテスト テストしたい対象の処理前後での状態の変化を検証すること でテストを行う 相互作用中心のテスト テストしたい対象のオブジェクトの相互作用(メッセージの やりとり)を検証することでテストを行う 平たく言うとどのメソッドがどのように何回呼び出されるか 状態中心のテストと相互作用中心のテスト
  27. 36 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    依存部分はモックに変えていくことでテスト観点(仕様)に フォーカスしたテストになる モックに変えた部分はそれぞれ「仕様」があるはずなのでそ れは個別にテストを行う 最終的には依存しないテスト対象はモックに変えずにテスト を行うのでホワイトボックステストとしては充分となる (前述の例だと repository や toPurchased() がその例) 相互作用中心のテスト(私見)
  28. 37 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    前述の例 再掲:ホワイトボックステスト //購入可能な状態で購入するとカートからアイテムがなくなり購入処理を行う if( ! this.isPurchasable()){ //モックにしてtrue or false を返す throw new IllegalStateException("is not purchasable"); } List<Item> items = this.findAll(); //モックにしてアイテムを2個返す items.stream() .map(i -> toPurchased(i)) // 複雑なことをしていてテストしづらいなら // モックに変えてシンプルにする .forEach(p -> purchaseService.purchase(p))); //モックにして // 2度呼ばれたことを検証する this.deleteAll(items); //モックにして呼ばれたことを検証する
  29. 38 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    E2Eのテストやもっと広いシナリオテストのように粒度の 大きい話しから1つのメソッドに対しての粒度の小さい話 しのいずれでも今日の話しは適用できる ただし、仕様の粒度を間違えるとぐちゃぐちゃになるので 要注意(特に粒度の小さい部分) 今日の仕様の話は ・・・
  30. 39 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    粒度の大小に関係なく、テスト対象の使い方をテ ストする (仕様をテストする) 使い方をテストする ・・・
  31. 40 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    e.g. • 北緯なん度、経度なん度の場所に向かい エレベータで何階に行き鍵を取り出しド アを開け靴を脱ぎ冷蔵庫から缶ビールを 取り出してベッドに横になる 粒度の違い
  32. 41 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • プログラマはプログラム書くときの言葉に慣れすぎてい る • 最初に話したテスト仕様書の話しはすごくビジネスから 遠い用語で書かれていた • 特に粒度の小さいテストの場合は要注意 XXフラグみたいなもの
  33. 42 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • ビジネスで使っている言葉で表現しましょう • 難しかったらせめて対象となるものの操作方法(画面と か)で表現しましょう • ただ抽象度の低いホワイトボックステストだとこれも難 しい コツ
  34. 44 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    テスト仕様書はgiven-when-thenのテストで書くように した 結果 • トータルコストは下がった(手戻りが減った) • プログラマの心理的安全が高まった 課題 • メンバによって理解度のバラツキが大きい • 品質は大差ない • テスト工数があがった 実際にやってみた(自プロジェクト)
  35. 45 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    Sound only 自動テストに対する取り組み
  36. 46 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    テスト仕様としていろいろなところに 散らばった仕様を一元管理してトレー ス可能に 今考えてること
  37. 47 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • spockを使って自動テストを記載するプロ ジェクトがちらほらと増えてきた • E2Eの自動テストをうまく活用しているプ ロジェクト • 今後は社内外で今日のような話を通して増 やしていく予定 会社としての取り組み
  38. 49 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • given - when - then • 仕様はビジネスで使う用語で表わそう • 粒度に気をつけて表わそう • プログラムは構造に気をつけよう • 積極的に自動テストに落とそう まとめ
  39. 51 Copyright © 2018 Bigtree Technology&Consulting Ltd. All Rights Reserved.

    • ドキュメンテーションや口伝だとうまく伝わらないもの をどう伝えるかは永遠にテーマだと思う • BDD,ATDDのように検証の方向からのアプローチした りDDDのように設計・実装からアプローチしたりいろい ろな方向から取り組んでいくべき課題と捉えている • なにはともあれプログラムはリーダブルであることが 大前提だと自分は思う • アプローチの一環として今までにはないサービスや開発 形態が今後どんどんでてくるだろうからそういう面でも 注目したいと思っている 所感