正文:
3
2
1
Go!
我们将通过编写一个
Countdown
函数来处理这个问题,然后放入 main
程序,所以它看起来这样:
package main func main( { Countdown( }
虽然这是一个非常简单的程序,但要完全测试它,我们需要像往常一样采用迭代的、测试驱动的方法。
所谓迭代是指:确保我们采取最小的步骤让软件可用。
我们不想花太多时间写那些在被攻击后理论上还能运行的代码,因为这经常导致开发人员陷入开发的无底深渊。尽你所能拆分需求是一项很重要的技能,这样你就能拥有可以工作的软件。
下面是我们如何划分工作和迭代的方法:
打印 3
- 打印 3 到 Go!
- 在每行中间等待一秒
先写测试
我们的软件需要将结果打印到标准输出界面。在 DI(依赖注入) 的部分,我们已经看到如何使用 DI 进行方便的测试。
func TestCountdown(t *testing.T { buffer := &bytes.Buffer{} Countdown(buffer got := buffer.String( want := "3" if got != want { t.Errorf("got '%s' want '%s'", got, want } }
如果你对
buffer
不熟悉,请重新阅读前面的部分。我们清楚,我们的目的是让
Countdown
函数将数据写到某处,io.writer就是作为 Go 的一个接口来抓取数据的一种方式。
在
main
中,我们将信息发送到 os.Stdout
,所以用户可以看到 Countdown
的结果打印到终端- 在测试中,我们将发送到
bytes.Buffer
,所以我们的测试能够抓取到正在生成的数据
尝试并运行测试
./countdown_test.go:11:2: undefined: Countdown
为测试的运行编写最少量的代码,并检查失败测试的输出
Countdown 函数
func Countdown( {}
./countdown_test.go:11:11: too many arguments in call to Countdown
have (*bytes.Buffer
want (
编译器正在告诉你函数的问题,所以更正它
func Countdown(out *bytes.Buffer {}
countdown_test.go:17: got '' want '3'
编写足够的代码使程序通过
func Countdown(out *bytes.Buffer { fmt.Fprint(out, "3" }
我们正在使用 fmt.Fprint
传入一个 io.Writer
(例如 *bytes.Buffer
)并发送一个 string
。这个测试应该可以通过。
重构代码
*bytes.Buffer 可以运行,但最好使用通用接口代替。
func Countdown(out io.Writer { fmt.Fprint(out, "3" }