Showing 84 Result(s)

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

10.10.1 優れた受け入れテストのための7つの戦略 内容 受け入れテストは、開発者に何を作る必要があるのか、何がいちばん重要なのか、いつ終わるのかを教えてくれる。機能がどうなると終わるのかを知ることで、開発者が作りすぎるのを防ぐことになる。 ここでは10章(10.1.1)で伝えた内容で「受け入れテスト」について実際にどうやって実践する、有効な7つの戦略を説明している。 戦略 補足 作っているものが何に役立つのか明確にする そのまんま 誰が何のために何をしたいのかを知る そのまんま 受け入れ基準を自動化する ? エッジケース、例外、代替パスを表す ? 例示を使って具体化し、矛盾を一掃する ? 受け入れ基準とふるまいの分離 ? 各テストを一意にする ? 学び まだよくわからない。 要勉強。

レガシーコードからの脱却 まとめ – 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つのフェーズの基本。 テストコードは「失敗をさせ、正しいコードにすることで保証されたものとなる」で、このためにレッド/グリーンのフェーズがある。 …

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

11 プラクティス7 テストでふるまいを明示する 内容 テストによって動くものと動かないものがすぐにわかる。これは開発の原動力を大きく影響を及ぼす。 ケイパー・ジョーンズは「開発者の時間の半分以上が、過去にやった仕事の手直しに費やされている」と言っている。例えば、不具合の原因が2箇所による複合的な要因の場合、その原因を特定するのは非常に時間がかかるが、ありえる。この手直しに時間がかかっていることが、テスト駆動開発を行う理由だ。 マネージャーがテスト駆動開発する時間を持てないというのは、以下のループとなっているためだ。 テスト駆動開発をしていないから、問題の原因の特定に時間がかかる 問題の原因の特定に時間をかけすぎてるから、テスト駆動開発を学習する時間がとれない このループになっているのであれば、ここから降りなければならない。 テストは具体的な要件であり、メソッドの使い方を正しくフォーカスすることができる。これは実装を良くするためや、問題をとりのぞくために非常に効果がある。 学び ほとんどの時間を読む時間、調査する時間に費やしているという事実 テスト駆動開発をしていないからテスト駆動開発ができないループに入っている場合、なんとかしてそのループを抜け出なければならない 学びを活かすアイディア・行動 テストコードの目的のための事前知識整理

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

10.11 本章のふりかえり 内容 正しいユニットテストの書き方で書けば、コードのリファクタリングのサポートをしてくれて「CLEAN」なコードにつながる。 テスト駆動開発は正しく行わないと、保守可能な効果はなくなる。 学び 内容の通り 学びを活かすアイディア・行動 特になし

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

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

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

10.8 テスト駆動開発をチームに広める 内容 テスト駆動開発の正しいやり方を身につける唯一の方法なんてものは存在しないが、まずは、良い共通理解を形成するところから始める。 テスト駆動開発導入にあたって足かせになるのは、経営者と開発者それぞれ異なったテスト駆動開発に対する負の先入観。これらを統一した共通認識にするところから始める必要がある。 10.9 テストに感染する 開発者の最初の大きな課題は最初にテストを書くことが不快だということだ。なぜ不快かというと、実装を集中して書くことを訓練してきたからだ。その習慣をやめて最初にテストを書くようになるまで長い時間がかかる。 開発者は「目的」と「やり方」の世界を行き来するが、まず「作るものは何か」(目的)から始めるべきだ。それがインターフェイスであり、テストだ。 まず、呼び出すメソッドの外観、名前、入力パラメーター、戻り値を明らかにする。それから「どうやって作るか」に焦点を合わせる。 一直線にプロダクションコードを書くという習慣をやめれば、自然にテストファーストに考えられる。この現象を、テスト駆動開発の初期提案者の1人エリック・ガンマ氏が「テストに感染し始めた」と言った。 学び チームに導入したければ、経営者、開発者はそれぞれの観点でメリット、デメリットを整理して共通認識になるように準備する必要がある。 テストを最初に書く違和感の直し方は、「作るものは何か?」(外観、名前、入力パラメータ、戻り値)を明確にし、そのテストを書くところから始めよう。 最初にテストを書く習慣が開発者にはない。 学びを活かすアイディア・行動 テスト駆動開発のメリデメの整理。経営観点と開発観点。 テストコードの目的の事前知識整理

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

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

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

10.6 テスト可能なコードを書く 内容 テスト駆動開発をやっていないし、やりたくもないマネージャーに対して納得させた言葉。 テストファースト開発するかどうかは気にしないが、テスト可能なコードを書くかどうかを気にする。テスト駆動開発はそうするための方法だ。 テスト駆動開発はテストファーストでテストを書くため、自然とテスト可能なコードになる。 うまくいかない状況というのは、設計の問題があって考え直すべきであることを示している。テスト駆動開発は、難易度のダイヤルを持つようなものだ。詰まってしまったときには、いつでも「哀れになるほど簡単」にセットして、そこで少し自信をつけてから難易度を上げる。これを自分自身でコントロールしていくのだ。 このようにして、うまく進めなければ謙虚に前に戻り、設計し直し、最後にはよいテストとテスト可能なコードを作る。 学び テスト可能なコードかどうかが重要。 テスト駆動開発はテストファーストでテストを書くため、自然とテスト可能なコードになる。 間違ったなら、素直に認めて前に戻ろう。 学びを活かすアイディア・行動 テストコードの目的の事前知識整理

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

10.4 テスト駆動開発はすばやいフィードバックをもたらす 内容 ソフトウェアを開発するいちばん安価な方法は、最初からバグが発生しないようにすることだ。次に安価な方法は、あとで別のチームが修正するのではなく、発見したらすぐに同じ人または同じチームによって修正することだ。 一連の刺激と反応のトランザクションが精神に定着するためには、刺激に対してすばやい反応を続けることが必要だと、ある生物学者は示している。この生物学的観点でも、バグを生んだ本人がすぐ治すのが早いということになる。 そして、テスト駆動開発はすばやいフィードバックをもたらしてくれる。 10.5 テスト駆動開発はリファクタリングをサポートする コードがテストによってサポートされている場合は、リファクタリングが安全にできる。何かを間違えたらテストが失敗してすぐに教えてくれるからだ。 リファクタリングが必要なシーン 視野が狭くなっていると命名が少しずさんになる傾向がある。 ふるまいを実装している最中に、何に命名をする必要があるかわからなくなることがある。 アジャイルはリファクタリングしながら進むと効率的 アジャイル開発では、すべてを最初から理解しようとせず、反復的にソフトウェアを「間違いながら」「設計しながら」作ることが許されており、そのほうがはるかに効率的。そうするためにはリファクタリングしながら進むのは必須で、そのためにはテストが常にサポートしてくれる環境が必要。 学び 記憶を定着させるには反復練習が必要。 レガシーの匂いがするコードは対処を先延ばしにしないようにしないと、レガシーコードを作った本人がいなくなる可能性がある。レガシーコードが残ると拡張しづらいシステムになるので、レガシーコードはなるべくリアルタイムで修正する。 レガシーコードを産まないようにするにはテスト駆動開発とペアプロすると、正しく進んでいくのがよいのではないか。 リファクタリングにはテストを担保するものが常に横にある必要がある リファクタリングは開発中が一番コストをかけずにできる 学びを活かすアイディア・行動 現場にテスト駆動開発をシフトさせる。どうすればいいか。。 現場のリファクタリング計画のためにリファクタリング内容に紐づく修正ファイル対象の一覧を作る。案件があるときに、合わせて修正を検討する。

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

10.3 良いテストを書く 内容 テスト駆動開発として実践されている「テストファースト開発」と「テストアフター開発」を紹介し、多くの開発者やマネージャーは「テストアフター開発」によって、テスト駆動開発に対するネガティブな誤解を生んでいることを説明している。 テストファースト開発 説明 小さな機能のテストを書いてから、その機能を実装するやり方。 メリット テストの観点(外部からの観察)と、コードの観点(内部からの観察)を行き来することで、フィードバックをもらいながら堅実に進められる。 最初にテストを書くことで、常に100%のコードカバレッジが確保できる。 失敗したテストに合格するようにコードを書くため、テスト可能なコードが書けていることを保証してくれる。 デメリット テストを書くスキルの習得が要る テストアフター開発 説明 コードを書いてからテストを書く。(著者がそう呼んでいる) メリット 自動化された回帰テストを好きなときに作って実行できる。 デメリット コードを書いたあとにテストを書くのは、かなりの再設計、コードをクリーンアップが必要であることがほとんど。結局、テスト可能なコードを最初に作成するほうが楽。 この実態を前提に、多くのマネージャーと開発者は、テスト駆動開発に対し、テストアフター開発のイメージを持ち「やたら手がかかる」というような先入観を持っている。 テストファースト開発では、テストアフター開発のデメリットを防ぐことができる。 すべてのテストを先に書いてから、実装する方法もある。この方法にはいくつかの利点があるのは事実だが、テストファースト開発で得られる頻繁なフィードバックのほうが大きな利点である。著者はすべてのテストを先に書いてから実装する方法はテスト駆動開発とは考えていない。 10.3.1 テストではない テストは二重の役割を果たしているということを説明している。 1つは、仮説であり、ふるまいの仕様。 もう1つは、回帰テストが常に用意されていて実行され、コードが期待したように機能していることを検証すること コードを書く前に書いているユニットテストはテストではなく仮説。サービスの呼び出し方法と期待する戻り値の仮説を立てている。つまり、どうなったら完成するのかの仮説を立てている。 次に、テストに合格するコードを書いたら実際のテストになる。なんらかのふるまいを実行して検証したから。 そしてこの検証機能はソフトウェアの寿命が来るまで以下の価値を提供し続ける。 影響を与える可能性のあるものは何も変わっていないことを保証する コードが期待したように動くことを保証する 10.3.2 ふるまいの集合体 ユニットとはふるまいの単位で独立した検証可能なふるまいのこと。つまり、どのように使ってどのような結果になるかを検証できるふるまいのこと。ふるまいを表すために、常に必要最小限のテストを書くことが重要。 多くの開発者は「ユニットテスト」の「ユニット」と言う言葉を、メソッド、クラス、モジュール、関数などのような実体を指すものと勘違いするが、違う。この勘違いのため、新しいクラスやメソッドを作るたびに新しいテストを作成し、コードの成長とともに多くのテストを追加することで、肥大化するのではないかと心配したり、実際に追加してしまう。 テストファーストのメリットは、必要に応じてあとから簡単にコードをクリーンアップできるようにすることだ。ユニットの単位を勘違いして、コードをクリーンアップするときに、不要なテストを増やしてしまうと、自動回帰テストを持つことの価値の大部分を失ってしまう。 「ユニット」が表現するのはふるまいだ。ふるまいが変わらないなら、テストを変える必要はない。 「ユニットテスト」は「すべてのクラスやメソッドがテストを持つべき」ではなく「あらゆる観察可能なふるまいが、それに紐づくテストを持つべき」である。「あらゆる観察可能なふるまい」=「すべてのクラスやメソッド」というわけではない。 学び 実際にテストアフター開発が起きているからネガティブな先入観が生まれる。では、なぜテストアフター開発をしてしまうのか。要因は、大きく2つ。 傲慢。ほとんどの開発者はテスト可能でないコードを書いてしまう前提を認識していない。 無知。テストファースト開発が習得が必要なスキルだということを知らない。 間違った認識、無知は失敗を生み、ネガティブな先入観を生む。 テストファーストで書くテストは、実際のコードまで書いて、テストとなる。テストだけの時点では、ふるまいの仕様を表す仮説である。 自動回帰テストの環境がないと効果が薄いように感じる。 ユニットとは観察可能なふるまいの単位である。 ユニットの単位を明確にして不要なテストを増やしてはいけない。 学びを活かすアイディア・行動 テストコードの目的のための事前知識準備 現場の回帰テスト環境作り ユニットの単位の深堀り 現場のテストコードのコーディング規約づくり