Countdown
という関数を作成します。この関数をmain
プログラム内に配置して、次のようにします。Countdown
関数でどこかにデータを書き込む必要があることはわかっています。io.Writer
は、Goのインターフェースとしてデータをキャプチャするための事実上の方法です。main
でos.Stdout
に送信して、ターミナルに出力されたカウントダウンをユーザーに表示します。bytes.Buffer
に送信して、生成されるデータをテストでキャプチャできるようにします。./countdown_test.go:11:2: undefined: Countdown
Countdown
を定義しますcountdown_test.go:17: got '' want '3'
fm.Fprint
を使用しています。これは、io.Writer
(* bytes.Buffer
など)を受け取り、それにstring
を送信します。テストは成功するはずです。*bytes.Buffer
は機能しますが、代わりに汎用インターフェースを使用する方がよいことはわかっています。main
に結び付けましょう。そうすれば、作業を進めていることを確信できる実用的なソフトウェアができます。end-to-end
で機能するようにします。string
を作成するもう1つの方法ですが、テストに最適な改行などを配置できます。i--
で逆にカウントするfor
ループを使用し、fmt.Fprintln
を使用して、番号と改行文字を続けてout
に出力します。最後にfmt.Fprint
を使用して終わった後「Go!」を送信します。time.Sleep
でこれを実現できます。コードに追加してみてください。Countdown
のすべての新しいテストのテスト実行に4が追加されたことに満足していますか?Sleep
に依存しています。time.Sleep
をモックできる場合は、「実際の」time.Sleep
の代わりにDI dependency injection を使用して、呼び出しをスパイしてアサーションを作成できます。main
で「実際の」Sleeperを使用し、テストで spy sleeper を使用できるようになります。インターフェースを使用することにより、Countdown
関数はこれを意識せず、呼び出し側に柔軟性を追加します。Countdown
関数はスリープ時間の長さに責任を負わないと設計上の決定をしました。 これにより、少なくとも今のところコードが少し単純化されており、関数のユーザーがその眠気を好きなように設定できることを意味します。Sleep()
が呼び出された回数を追跡しているので、テストで確認できます。Sleeper
を受け入れるにはCountdown
を更新する必要がありますmain
はコンパイルできなくなりますtime.Sleep
を呼び出しているため、パスしていません。修正しましょう。Countdown
は各表示の前にスリープする必要があります。Sleep
Print N
Sleep
Print N-1
Sleep
Print Go!
CountdownOperationsSpy
はio.Writer
とSleeper
の両方を実装し、すべての呼び出しを1つのスライスに記録します。このテストでは操作の順序のみを考慮しているため、名前付き操作のリストとして記録するだけで十分です。Countdown
をテストの修正前の状態に戻します。Sleeper
をスパイする2つのテストができたので、テストをリファクタリングして、1つは表示されているものをテストし、もう1つは表示の合間に確実にスリープするようにします。 最後に、最初のスパイは使用されなくなったので削除できます。Sleeper
が構成可能であることは素晴らしい機能です。これは、メインプログラムでスリープ時間を調整できることを意味します。ConfigurableSleeper
の新しいタイプを作成しましょう。duration
を使用し、スリープ関数を渡す方法としてsleep
を使用しています。 sleep
のシグネチャはtime.Sleep
のシグネチャと同じであり、実際の実装でtime.Sleep
を使用して、テストで次のスパイを使用できます。ConfigurableSleeper
で作成されたSleep
メソッドがないことを示す非常に明確なエラーメッセージが表示されます。Sleep
関数が実装されたため、テストに失敗しました。ConfigurableSleeper
のSleep
関数を実装することだけです。ConfigurableSleeper
を使用することです。ConfigurableSleeper
を使用しているので、DefaultSleeper
実装を削除しても安全です。 私たちのプログラムをまとめ、より多くのgeneric任意の長いカウントダウンを備えたスリーパーを用意します。「反復開発を使用する場合?反復開発は、成功させたいプロジェクトでのみ使用する必要があります。」