1.3 第一个失败的测试
我们先来做清单里的第一个功能:
首先,编写一个失败的测试,这就是RGR环中的第一个环节:红。
1.3.1 Go
在go文件夹里新建一个名叫money_test.go的文件,然后我们就来编写第一个测试:
❶包声明。
❷引入testing包,后面的t.Errorf需要用到这个包。
❸这是我们的测试方法,该方法必须以Test开头,并拥有一个*testing.T型的参数。
❹这是个用来表示“USD 5”(5美元)的结构体,目前还不存在Dollar结构体。
❺调用有待接受测试的方法,也就是Times方法,该方法目前并不存在。
❻将实际值与我们所期望的值相对比。
❼确保该测试会在期望值与实际值不符时失败。
这个测试函数包含许多为了做测试而必须要写的样板代码。
package main这样一条声明用来表示其后的所有代码都是main包的一部分。如果想编写可单独执行的Go程序,那么必须这样做。包管理(https://oreil.ly/yvh3S)是Go语言中一个较为复杂的功能。我们会在第5章详细讨论。
接下来,我们用import语句引入testing包。后面的单元测试需要使用该包。
单元测试函数(即TestMultiplication函数)是这段代码的主要内容。我们在该函数中声明了一个实体,用来表示“USD 5”。我们还创建了一个名叫fiver的变量,并把这个amount字段为5的结构体设为该变量的初始值(或者说,我们用这个amount字段为5的结构体来初始化该变量)。然后,我们将fiver与2相乘〔并用变量tenner来表示结果〕。我们希望相乘的结果是10美元,也就是说,tenner变量的amount字段必定等于10。如果不是这样,就打印一条格式整齐的错误消息,以显示实际的值(无论这个值是多少,我们都把它写在这条消息之中)。
我们在TDD Project Root文件夹中用go test-v .命令运行测试,大家应该会看到下面这样的错误:
这条信息说得很明白:我们写的测试失败(FAIL)了。到这里,我们就完成了TDD的第一步,也就是写一个失败的测试。
go test-v.命令用来运行当前文件夹中的测试,go test-v ./...命令[1]用来运行当前文件夹与各个子文件夹中的测试。-v选项(或者说开关)的意思是,打印详尽的输出信息。
1.3.2 JavaScript
在js文件夹中新建名叫test_money.js的文件,然后开始编写我们的第一个测试用例:
❶引入assert包,稍后的断言语句需要用到这个包。
❷创建一个表示“USD 5”的对象。目前还不存在这种Dollar对象。
❸调用有待接受测试的方法,也就是times方法。该方法目前并不存在。
❹通过strictEqual断言语句来对比实际值与我们所期望的值。
用JavaScript语言做测试时,几乎没有那种为了做测试而必须编写的样板代码,我们只需要用一行require语句把名为assert的NPM包引入就行了。
这行代码之后的三行代码是用来做测试的。我们创建一个表示5美元的对象,将其乘以2,并期望相乘的结果是10。
ES2015新增了用来声明变量的let关键字(https://oreil.ly/jBMPk)与用来声明常量的const关键字(https://oreil.ly/GfYQ5)。
我们在TDD Project Root目录下用node js/test_money.js运行测试,会看到像如下这样开头的一段错误信息:
太棒了!我们已经写好了第一个失败的测试用例。
node file.js这样的命令用来运行名为file.js的JavaScript代码文件并输出运行结果。我们在本书中也采用这种格式的命令来运行测试。
1.3.3 Python
在py文件夹中新建名为test_money.py的文件,并开始编写我们的首个测试:
❶引入unittest包,后面要写的TestMoney类需要以该包中的TestCase类为超类。
❷这是我们自己的测试类,该类必须是unittest.TestCase类的子类。
❸测试方法的名称必须以test开头。
❹这是个用来表示“USD 5”(5美元)的对象。当前还不存在这种Dollar对象。
❺调用有待接受测试的times方法,该方法目前并不存在。
❻用assertEqual语句对比期望值与实际值。
❼按惯例编写__main__结构,以确保这个TestMoney类〔所在的test_money.py文件〕能够单独作为一个脚本运行。
为了用Python语言做测试,我们必须通过import关键字引入unittest包,并创建一个TestCase类的子类,还需要定义一个名称以test开头的函数。另外,为了让我们的测试类〔所在的test_money.py文件〕可以作为单独的程序运行,需要按照Python的惯例书写__main__结构(参见https://docs.python.org/3/library/__main__.html),以便在单独运行〔而不是作为其他脚本的一部分来运行〕test_money.py时,能够触发unittest.main()函数〔以启动测试〕。
这个测试函数(即testMultiplication函数)描绘我们期望代码如何运作。我们定义名为fiver的变量,并将其初始化为一个我们想要的对象,该对象应是Dollar类的实例(当然,目前这个类还不存在)。我们构造该对象时,向构造器传入5作为参数。然后,我们把fiver与2相乘,并将结果保存在tenner变量中。最后,我们期望tenner的amount应该是10。
我们在TDD_PROJECT_ROOT文件夹中,用python3 py/test_money.py-v命令运行这段代码时,会看到含有下列信息的错误:
好,我们已经把第一个失败的测试给写出来了!
python3 file.py-v格式的命令用来运行名为file.py的Python代码。-v的意思是显示详尽的输出信息。我们会采用这种格式的命令来运行本书的测试。