Showing 6 Result(s)

レガシーコードからの脱却 まとめ 11.12 – 11.12.1

11.12 実践しよう 11.12.1 テストを仕様として使うための7つの戦略 内容 テストを文書のようにすることで生きた仕様になる。そのための7つの戦略を紹介する。 戦略 説明 テストを文書のように扱えるようにする テストのコードも、マジックナンバーをハードコードせずに意味がわかる変数名にする 意図がはっきりわかるヘルパーメソッドを使う セットアップの処理や、そのほかの機能を独自のヘルパーメソッドでラッピングすることで、個々のテストの重複を排除しつつも、異なるセットアップオプションを用意できるようになる 何が重要なのかを明らかにする 1と似ている。マジックナンバーをハードコードせずに変数で読めるようにして、意図するところをわかるようにする 実装ではなくふるまいをテストする 具体的な実装に合わせてテストするのではなく、テストメソッド名を表すことをテストする。悪い例:testConstructor 。単純すぎる。良い例:testRetrievingValueAfterConstruction 。何をテストしたいのかがわかる。 モックを使ってワークフローをテストする アサーションは値やふるまいをテストできるが、ワークフローやオブジェクト間の相互作用はテストできない。これはモックを使ってテストする。 書きすぎない 微細に記載することは簡単だが、意味が同じテストは重複である。例えば、境界値とその間の値の場合、その間の値のパターンは無尽蔵にあるが、実施するのは1つでよい。それ以外は実施した1つのテストと意味が同じだ。重複したテストは削除する。 正確な例を使う 実際の使われ方を実行することによって、コーディングを開始する前に、矛盾や設計上の問題が明らかになり、早期に対処できる 学び プログラマでない人でも読めるように書くべし 重複は省くべし 相互関係のテストはモックを使うべし ふるまいを明確にテストすべし 学びを活かすアイディア・行動 現場のユニットテストのコーディング規約づくり

レガシーコードからの脱却 まとめ – 11.1 – 11.4

11.1 レッド/グリーン/リファクタリング 内容 テストファースト開発には3つのことなるフェーズがある。 レッド/グリーン/リファクタリング だ。ユニットテストフレームワークの視覚効果が由来する。 レッドテストを失敗「させる」(コンパイルエラーも含まれる)。コンパイルエラーが起きたら「スタブアウト」を作り、テストを失敗させる。 グリーンすべてのテストを成功させる。 リファクタリングコードからリファクタリングし、テストをリファクタリングする 一つのユニットテストを作る中で、この3つのフェーズを繰り返し行っていく。一つのユニットテストというのは、1アサートという意味ではなく、1つのインターフェースに対してかかっている。1インターフェース:複数アサートはあり得る。 11.2 テストコードの例 Parsonという名前と年齢を持つクラスのテストを例にしてテストを解説している。 レッドのフェーズ。クラスが一つも無いところからハッピーパスのテストを書き始める。内容は、Personクラスのコンストラクタに渡した名前と年齢の値がPersonクラスの getName() と getAge() で取得した値と同じかどうかをテストする。クラスは無いのでコンパイルエラーが発生する。 コンパイルエラーのみ解消するために、Personクラスをスタブとしてとして作成してコンパイルエラーの部分を解消。スタブはクイックフィックス機能で作成し、メソッド返却値はダミーのままにすること。テストはコンパイルエラーが解消するので実行すると、返却値がダミーなのでエラーとなる。最初の目的はテストを失敗させることなのでOK。 グリーンのフェーズ。テストが通るようにプロダクトコードを修正する。コンストラクタの引数をメソッドで返すように実装する。 11.3 制約を導入する Personクラスの年齢に負の数を入れると年齢としてはおかしくなるので、そういった不備をなくすために制約を入れる。そういう場合の解説。ここでもテストファーストで書きながら説明している。 Personクラスに最大と最小の定数のテストを書く レッドフェーズ。 Personクラスに最大と最小の定数を記述しコンパイルエラーを出す。 コンパイルエラーをクイックフィックスを使い解消 実行すると失敗するのでレッド完了。 グリーンフェーズ。 Personクラスの最大値、最小値の値を適切に設定して実行。OKとなりグリーン完了。 次にコンストラクタの引数・年齢に最小値より小さい値を入れたらエラーとなるテスト レッドフェーズ 投げられるとOKとなる例外クラスをテストに書いてコンパイルエラーを起こす。 コンパイルエラーの例外クラスはクイックフィックスで作成し、コンパイルエラーを解消。 実行すると失敗するのでレッド完了。 グリーンフェーズ Personクラスのコンストラクタ内で最小値より小さい場合に例外を投げる処理を追加して実行。OKとなりグリーン完了。 次にコンストラクタの引数・年齢に最大値より大きい値を入れたらエラーとなるテスト 最小値のテストと同じ要領で最大値のテストを追加してグリーンまで完了させる。 リファクタリング 最小値と最大値で違う例外を投げるようにしたが、範囲外を表す1つのクラスにした方が使い勝手が良さそうなため、そちらを使うようにする。 11.4 作ったもの 11.2 – 11.3 で作ったものを通しての要点は「テストは仕様であり、テストは不要に重複しないように作る」のがポイントと言っている。 学び テストメソッド名に関する名前重要。何をテストしているかが分かれば、冗長でも構わない。何をテストしているかと仕様がわかることが重要。 コンパイルエラーの解消はクイックフィックスで解消していくことで、コードのタイプミスを減らせる。 レッドのフェーズは、コンパイルエラーからテストを実行して失敗させること。 最大値、最小値などの値よりも定数の名前が重要。境界値は時代の変化に合わせて変わるかもしれないが、重要なのは簡単に変えられるようにしておくこと。 例外をテストする方法。 レッド/グリーン/リファクタリングの3つのフェーズの基本。 テストコードは「失敗をさせ、正しいコードにすることで保証されたものとなる」で、このためにレッド/グリーンのフェーズがある。 …

レガシーコードからの脱却 まとめ – 10.10.2

10.10.2 優れたユニットテストのための7つの戦略 内容 ユニットテストのための大切な7つの観点を説明している。 戦略 補足 呼び出し側の視点に立つ 呼び出し側は何を必要としているのか、何を渡す必要があるのか。 テストを使ってふるまいを表す 仕様がわかるドキュメントになるようにわかりやすく書く。テストを最新に保つことが、ドキュメントを最新に保つことになる。 新しい違いを生み出すテストだけ書く テストは一意にする。観察可能なテストにして無駄なテストをなくす。 失敗したテストにパスするためのコードのみを書く まず失敗するコードを書き、テストが通るコードに書き直す。このルールに則った場合に「テストが通ったら正しい」という保証になる。 テストを使って、ふるまいを作る ハッピーパスから作るにしろ、例外からにしろ、テストから作る コードをリファクタリングする 反復開発する場合、保守性は重要だからリファクタリングをして保守可能な状態にする テストをリファクタリングする 実装に依存したテストではなくふるまいを表したテストを書いていなければ不要に修正する必要はない。ただし、テストもコードであるため保守可能な状態にしないとコード品質に影響する可能性がある。 学び テストはコードだという認識。保守可能な状態にリファクタリングする必要がある。 テストはふるまいを表すべき。実装に依存したかたちにしてしまうと不要に修正する必要の可能性が出てくるし、そうなると保守できなくなる。 テストは仕様を表す最新のドキュメント。実行することでプログラムが正しいことを表すため、仕様がわかるように書くことで、最新のドキュメントとなる。メソッドコメントのように変更し忘れがなくなる。 学びを活かすアイディア・行動 現場のユニットテストのコーディング規約づくり

レガシーコードからの脱却 まとめ – 10.7

10.7 テスト駆動開発は失敗することがある 内容 テスト駆動開発はスキルであり、スキルが十分に習得されていないと、開発者の負荷になり、プロジェクトの進行は遅くなる。それが原因でプロジェクトが失敗するというように判断したのなら、テスト駆動開発をやめるのが正しい。 開発者が対応できないときは、開発者に新しい学習曲線の負担をかけるべきではない。テスト駆動開発を続けてプロジェクトを失敗させ倒産するか、テスト駆動開発をやめるかの選択に直面しているなら、テスト駆動開発をやめることはいちばん確実で正しい。リリースの準備ができているなら、テスト駆動開発の導入に挑戦する必要はない。 テスト駆動開発の間違った会社の例 とある会社ではコードの品質、「CLEAN」なコード、優れた開発原則は導入できていたにもかかわらず、テストの運用がうまくいかなかった。 テストが冗長コードをクリーンにするのに1日、テストをクリーンにするのに1週間かかっていた。原因はテストコードもコードであると見直しておらず、テストの冗長性が非常に高くなっていたため。 インターフェースではなく実装に依存したテストインターフェイスに対してテストするのではなく、実装に対してテストをしていたため、コードのクリーンアップをしようとしたときに、テストをクリーンアップするのが困難だった。 ユニットテストの書き方が違うテストを実行するためにOracleに接続していて、モックを使っておらず実際のDBに接続していたため時間がかかっていた。 テストの量を不要に増やした彼らはQAの立場で「テストが多ければ良いテストだ」と考え、あまりにも多くのテストを書いていた。上記の要因を踏まえ、大量の運用できないテストを作っていた。 学び テスト駆動開発はスキルであり、習得が必要。習得には負荷がかかるので導入は計画的にしなければいけない。 負荷が高すぎたり、間違ったやり方で工数が上がりすぎては本末転倒。 学びを活かすアイディア・行動 ユニットテストのコーディング規約づくり失敗するとどうなるかを書く。

レガシーコードからの脱却 まとめ – 10.0

10.0 まずテストから書く 内容 テスト駆動開発(TDD)は死んでしまったと主張する人たちもいる。良いアイデアに見えるものの実際には多くのテストや、実装に依存するテストがかえって負担になってしまうという「テストによるダメージ」となりうまくいっていないという理由で。テストファースト開発を行う利点は、既存のコードを変更するときにサポートを得られることであるが、いつテストを書くのをやめるべきかわからないときに、不必要に多くのテストを書くことになったり、実装依存のテストを書くことになったりと、「テストによるダメージ」が発生する。こうなるとテストの変更が難しくなり、変更しやすさの手助けになるどころか負担となり、コードの変更は困難になり時間がかかるようになる。 しかし、テストを仕様と捉えることで、必要なテストが明確になる。 テスト駆動開発を正しく使用する方法と、落とし穴があることを伝えている。 学び テスト駆動開発を間違って行うと負担になる。正しく使うためには仕組みの理解が必要だ。 不必要に多くのテストや実装依存のテストは 学びを活かすアイディア・行動 テスト駆動開発のノウハウ整理 現場のテストコードのコーディング規約づくり

レガシーコードからの脱却 まとめ – 11.5 – 11.9

11.5 テストは仕様だ 内容 11.2-4までの中で、3つのアサーションを定義した。 1から200までの値が必要で、MINIMUM_AGE – 1もしくは0を渡した場合は例外がスローされる 有効値はMINIMUM_AGE以上MAXIMUM_AGE以下である。この場合は、エラーなしで戻り値を返す MAXIMUM_AGE + 1もしくは201を渡した場合は例外がスローされる これらの3つはすべて独立しており、同じ理由では失敗しない。そしてすべてが通らないとOKにならない。このテストコードは独立した3つの要件そのものである。通常の要求のドキュメントが最新かどうかは担保するのがむずかしいが、テストは実行すればOKかNGがわかるため、OKが出れば最新だし、NGが出るのであれば最新ではない。 11.6 完全であれ ふるまいを書くときは常にテストを先に書く。そうすることで、完全で漏れのないテストスイートが出来上がる。そうすれば最終的には品質が劇的に向上する。 テスト駆動開発をすればテスト容易性とコード品質が上がるが、テスト用意性が高いからといってQAも同時にやればいいというわけではない。テスト駆動開発と同時にQAをやろうとすると、たぶん、QAのためにとても多くのテストを書く羽目になる。最悪、コードがぐちゃぐちゃになり、あとから直しにくくなる。 QAの役割は、開発の段階で考えていないようなケースについても確実にカバーできるようにすることだから、開発者はまずふるまいを作ることに集中しよう。そしてQAで発生したものは必要に応じてあとからクリーンアップする。その方が遥かに効率が良い。 マネジメント側がQAをテスト駆動開発を含めるように言い出した場合、QA(システムが停止する可能性のある箇所の調査、非機能要件の検討、その他)は、テスト駆動開発には含めずに、後でやり、必要に応じて修正するほうが、コードが良い保守性になりやすいと言ったほうが良い。 11.7 テストを一意にする テストファースト開発は設計方法論であり、テストが一意になる設計をしながら進めるためのものだ。 良いテストの基準は テストが未知の理由ではなく既知の理由で失敗すること テストは一意であること であるが、テストに重複を許すと、何かの失敗で複数の失敗が起き、以下の理由で著しくスピードが下がる。 すべての失敗が本当に同じ原因で落ちているかどうかを調べなければいけなくなる リファクタリング箇所が多くなる 11.8 コードをテストでカバーする コードカバレッジ(テスト網羅率)は100%以外は意味がどんどん薄れる。 テストを仕様として書き、テストが難しい仕様はテストができるように設計を工夫する必要がある。難易度が高い、且つテストできなくない状態を続けることは、コード品質が低いことを意味し、後の負債となる。 11.9 バグにはテストがない すべてのバグはテストがないゆえに存在する。 テスト駆動開発を用いてバグを修正するには、まずバグを再現させるような失敗するテストを書く。次に、テストがグリーンに変わるように、バグを修正する。 そのため、すべての仕様に対して理論上はテストがあるようになる。 学び テストコードはプログラムの正しさを検証するとともに、仕様ドキュメントである必要がある。 テストコードは運用していかないと効果を発揮しない。 ドキュメントをテストコードによって表現するスキルが必要だ。 QAとテスト駆動開発は同時にやるとコードの保守性が悪くなる可能性が高い。 テスト駆動開発では機能要件にフォーカスし、非機能要件にはフォーカスしないほうが効率が良い。 テストは一意となるようにしなければ、開発効率がかなり落ちる。 テストを一意にするということはふるまいを一意にするということ コードカバレッジは100%を基準とするべし。信憑性がなくなる。 テストがしづらい仕様が設計のしどころ バグはテストしなかったから顕在化した テスト出来ない箇所は設計の問題がある可能性があるから見直す必要がある 学びを活かすアイディア・行動 現場のユニットテストのコーディング規約づくり テストコードの目的のための事前知識整理 エッジケースを含めたふるまいがテストに網羅されているかチェックする必要がある 業務要件のフローとスマホ独自の中断操作をかけ合わせたケースで考える必要もある