Skip to content

Instantly share code, notes, and snippets.

@satokitty
Created June 17, 2013 11:39
Show Gist options
  • Save satokitty/5796287 to your computer and use it in GitHub Desktop.
Save satokitty/5796287 to your computer and use it in GitHub Desktop.
TDD Meet up, at 2013/06/17.

TDDMeetUp 2013/06/17

テストがしにくい領域におけるTDD

  • 元のコードにテストコードが0

    • 200k行なのにテストないとか・・・
  • 自社製Webフレームワーク使ってる

  • Godオブジェクトが居る

  • 【レガシーコード対策】リフレクションを使って仕様化する

    • いずれ捨てる
  • イベントループ的なの

    • ケースを切り分けて考える
    • 例えば300回回したときにどうなるか、とかは別に考える必要がある。
  • 性能試験

    • Gatling(http://gatling-tool.org/)
      • 結合試験でも使っている。パラメータを変えれば性能試験の出来上がり。
    • JMeter
    • xUnit
  • 異常系

    • GatlingやJMeterで実際的に落とす
    • リフレクションなどを使って落とすケースを作り出す
    • ハードウェア的に落とす
      • テスト内で設定ファイルを書き換えるようにしておいて、ネットワークエラーを起こすなど
  • 耐久テスト

    • xUnit
    • Scala
  • 期待結果が人に依存する試験

    • 担当者とプロダクトオーナーの認識の齟齬
    • 期待結果 / 仕様が曖昧
    • 定量化できればいけるケースもある
      • その時点で曖昧さは無い

TDDしづらい領域を先に考えておく事で、TDDしやすい方向へ持っていく事が出来る。

TDDとプログラミングパラダイム

  • クラスベースのOOP言語で書かれた書籍が多い。他のパラダイムに置けるTDDとは?

    • C
    • Javascript
    • Haskell
    • Scala
    • F#
  • Javascript

    • 最近はテストフレームワークが出揃ってきていて、何とかなる
  • Haskell

    • コンパイルが通れば大体動くから、あんまりテストコード書かない
      • 他の関数型言語でも大体同じ。Haskell, OCamlは型で表現できる内容が豊かなので、コンパイル通れば大体OK。
        • F#はちょっと違う。
      • 何のためにテストしているのか? -> 値を確認するため。
      • 型は値よりも抽象的な概念で、Haskell, OCamlは型を用いて記述する。型に齟齬がなければ、大体において想定通りになる。
        • コンパイラが保証している範囲であればテストを書く必要は無い。
        • ただし、テストが必要ないという事ではない。
  • TDDがやりやすいかどうか ≒ 言語にどれだけ習熟しているかどうか

  • TDDはあくまでプログラマが考えるためのフレームワーク

  • 関数型言語は設計がやりやすい。

    • TDDでサポートできている外部設計については、型によってサポートされる。
    • 関数型言語におけるTDDは、設計ではなく試験に比重がよる。
  • 静的型付言語においては、テストを一行書く前に、まず型から書き始める。

    • Javaにおける型とはインターフェイス
    • Haskell, OCaml, F#などはより複雑な型を宣言できる。面倒くさい記述も少ない。"型が軽い"。
  • 言語が前提としているパラダイムを変更してTDDする意味があるのか?

    • TDD for Embedded Cは、いわゆるCスタイルでTDDするのではなく、オブジェクト指向的な設計の仕方をしましょうと書いてある。
    • JavaにおけるTDDの書籍では、OOPベースの書籍しかない。他のパラダイムで説明しているものは無い。
    • わざわざ別のパラダイムで考える必要は無いのでは?
    • TDD for Embedded CはC言語でオブジェクト指向設計を学ぼう、という趣旨に思える。それにTDDくっつけただけのよーな。
  • TDDとWモデルの関係

    • TDD, BDDはテストコードで仕様を表現する
    • ではテストコードだけが仕様?テストコードだけでソフトウェアを読み解けるか?
    • コード以外のレイヤの仕様や要求が存在している。
    • Wモデルにおいて、前段階の定義が次の段階のテストの入力になっているのは、それ。
    • 前段階の仕様からテストを書いて、同時に同じレイヤの設計をする事でテストファーストに出来る。
  • ATDD

    • ある機能について実装している間はずっとRedになる。
    • 開発者のマシンでAcceptance Testをやるのは非効率的?
      • CI環境だけでATをやって開発者のマシンではやらない、という方法も。
    • ATはなるべく早くGreenにする(そのためであればモックを大量に使う)
      • GOOS的なやりかた
  • モックの功罪

    • 嫌い
      • 面倒くさい
      • バグを作り込みやすい
        • TDDの自殺(http://d.hatena.ne.jp/kyon_mm/20121223/1358326642)
        • テスト通ってるのにモックが間違っている、とか
        • 複雑すぎるモックを書かないこと。ドメインごとに許容される複雑さ(モックの行数とか)を定義する。
      • 仕様変更に対応させるのにコストがかかる
        • モックをメンテさせようとするから困難になる
    • 好き
      • 作るのが難しいオブジェクト
        • このテストは結合テストでやっちゃうのも一つの手
      • 腐敗防止層
      • 使い捨てのモック

良いTDDとは何か?

  • 良いTDD

    • 仕様変更がしやすい状態を提供し続けている
    • 良いコードを書けるようにする == ダメなコードを許さない
      • TDDはObject Oriented Excerciseのようなもの
      • 想定されたパラダイム以外のコードを書かない
      • 想定されていないコードを書かない
      • UnitTestにおいては、良いシグネチャが良いコードを保証する
      • ATDDにおけるTDDが良いコードを育てているとは?何を見てそういえるか?
        • ATDDで悪いコードを防げているか?
        • 防げているのであれば良いATDDと言えるし、良いコードになるフォースが無いのであれば良いATDDとは言えない
      • TDDは品質保証をしている
        • ここで言っている品質とは、「保守性をあげる」ということ
  • 悪いTDD

    • 思ったタイミングで色が変わらない
      • ちゃんと狙ったタイミングでRedにならなかったりすると、積み上げてきたテストへの信頼がなくなってしまう
      • どこまで戻ればこのテストは信頼できるのだろうか?
    • テストレベルと合っていないassertの数
      • UnitTestなのに複数のassertが存在している
  • 利用と現実の狭間

    • オブジェクト指向でやっていくと、オーバーヘッドが発生する
      • パフォーマンスに非常にシビアな場面だと、それすらも惜しい
      • その場合には汚いコードを書かざるを得ない...
    • そういった場面では、まさにデザインパターンの登場
      • ストラテジパターンなんかはアルゴリズムを切り替えるためにある。
        • 切り出しておいて必要になればパフォーマンスの高い実装に切り替えれば良いだけ
    • 最初は綺麗なコードを書けば良い
      • パフォーマンスを意識するのは最後の最後
        • Effective C++では、最後の最後まで局所最適化はするな、と言われている
        • 最適化は全体を計測してから

TDDが失敗しているとは?

カバレッジをどの程度意識するか?

  • コードカバレッジなんて必要ない
  • 考えるべきカバレッジは「仕様カバレッジ」
    • 自分たちが作っているソフトウェアで重要なのは「仕様を満たしているか」であってコードではない
  • 無いよりはあった方がいいよね、程度
    • 気にするくらいなら仕様を満たしているかどうかを考えろ

DBアクセスは是か非か

  • やった方が良い
    • 単体で本番と同様にSQLを発行して動作を確認している人はどれだけ居るか?
    • 性能の問題だったりとか発覚したときにやりやすいよね
    • やるんだったら、本番と同じDBを使うのが良い
      • 使えるSQL違うし
      • テスト用のスキームを作っておいた方が良い
        • 並列実行可能性の保証
  • やらない理由
    • 遅くなるから
    • 準備が面倒くさい

どれくらい信用するのがTDDか?

  • TDDで出来上がってきた成果物をどれだけ信頼するのか?
    • そのテストは本当に正しいと、どうやって保証するのか?
    • 誰がそのテストをレビューするのか?
  • ありがちなのは、TDDやってるくらい意識高い人なら良いんじゃね?って考え方
  • TDDのプロセス監視
    • 自動コミットさせて、Red-Green-Refactoringの切り替わりタイミングを見る
    • ファイル変更検知→コンパイル→コンパイル成功であればテスト実行→結果(Red or Green)をコミットコメントにして自動コミット
      • Redの時間が長い → タスクが大きすぎる
      • RefactoringもしていないのにGreenの時間が長い → 何かが間違っている。変な進め方をしている。
    • 手動コミットするのは、ブランチに対して何かをするときだけ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment