0.1 配置开发环境
无论你按照图P-2中的哪条路线来学习这本书,都必须先准备好一套整洁的开发环境。本书后续的内容都假设你已经把这一节里所说的这套开发环境给准备好了。
无论你打算用Go、JavaScript还是Python来学习TDD,都需要按照这一节所说的方法把开发环境配置好。
0.1.1 三种语言共用的配置
0.1.1.1 文件夹结构
创建一个文件夹(也叫作目录),用来存放我们在学习这本书的过程中所写的全部源代码。你要给这个文件夹起个清晰的名称,让你在接下来的几星期里面,一看到这个名字,就知道它里面的东西是做什么用的。比方说,可以起名叫作tdd-project。
在这个文件夹下面建立这样一组子文件夹:
开始写代码之前就得将这些文件夹全都建好,即便你打算每次采用一种语言把这本书学三遍,也还是应该先将这套结构配置好。配置这样一套文件夹结构有下面几个好处:
1.可以分开存放这三种语言的代码,同时又让它们彼此离得比较近。
2.能够让本书中的大多数命令都同时适用于这三种语言的代码。
• 需要指定完整目录名及文件名的命令除外,不过这样的命令比较少。本节就有这样一个例外的命令。
3.能够把某些高级的功能(例如持续集成)同时运用在这三种语言的代码上。
4.与本书示例代码库(https://github.com/saleem/tdd-book-code)的文件夹结构一致。这样能够让你在逐渐扩充代码的过程中与代码库里的示例代码相对照。
接下来的内容会采用TDD Project Root(TDD项目根目录)来指代这个包含所有源代码的根文件夹,也就是刚才说的tdd-project文件夹。这个文件夹里面有三个子文件夹,分别是go、js与py,这三者的名称本身就说明了各自存放的是哪种语言的代码。
TDD Project Root用来指代包含本书全部源代码的文件夹。它是go、js与py这三个文件夹的上级文件夹。
声明一个叫作TDD_PROJECT_ROOT的环境变量,并把它的值设为TDD Project Root文件夹的全路径名[1]。每次开启shell环境之后,只要设置了这个变量,后续执行的所有命令就都能够正确地使用该变量的值来运作(还有一种更好的办法,就是把这条设置环境变量的命令写在.bashrc文件之类的初始化脚本里面,这样每次新开shell时,都会自动设置该变量)。
例如,在笔者的macOS操作系统上,设置TDD_PROJECT_ROOT环境变量所写的全路径就是/Users/saleemsiddiqui/code/github/saleem/tdd-project。
消除重复
每次启动shell时,都需要定义TDD_PROJECT_ROOT环境变量。如果觉得麻烦,可以在适当的配置文件之中做出设置,这样以后就无须重复定义了。具体如何设置取决于你所使用的操作系统及shell。本书使用的是Bash-like shell(类Bash shell),对于这种shell来说,环境变量可以在配置文件中定义,虽然细节或许有所区别,但总之是可以这样做的。比方说,在大多数Linux系统(以及macOS系统)上,都可以把export TDD_PROJECT_ROOT=...这条语句添加在home文件夹的.bashrc文件中(参见https://oreil.ly/SMmFc)。如果你是在Windows系统上使用Git BASH来执行命令,那么可能需要使用.bash_profile文件(参见https://oreil.ly/pkgxg)。本章稍后就会讲到Git BASH的用法。
总之,消除重复肯定是应该的。你要设法通过适当的机制来可靠地定义一套环境变量,让这套环境变量的值能够稳定地出现在你学习本书时所使用的各种shell之中。
0.1.1.2 文本编辑器或集成开发环境
我们需要一个文本编辑器来编辑源代码文件。你还可以选用集成开发环境(Integrated Development Environment, IDE)来编辑源文件,这样能够让你用同一个工具编辑、编译并测试各种语言的代码。具体选用哪种办法可以根据你的喜好而定,你应该选择最适合自己的一种。
附录A详细描述了IDE。
0.1.1.3 shell
我们需要用一个shell(也就是一个命令行解释器)来运行测试、查看输出信息并执行其他任务。与IDE类似,选用哪种shell比较好,也是一个很容易在开发者之间引起激烈争论的话题。这本书假设我们是采用Bash-like shell来输入命令的。几乎所有的类Unix操作系统以及macOS系统,本身都已经装好了Bash shell。
在Windows操作系统上,可以使用名叫Git BASH的shell(参见https://gitforwindows.org/)。Windows 10的Windows Subsystem for Linux(WSL,参见https://oreil.ly/UZ0KU)提供了原生的Bash shell支持,而且还支持其他一些“Linux goodies”(Linux里的好东西)。这两种方式,或者与之类似的其他方式,都可以考虑。当然,你必须从这些方式之中选择一种来运行本书的示例代码。
图0-1显示的是在一个Bash-like shell之中输入命令后所看到的执行结果。
图0-1:为了学习本书中的代码,我们需要使用一个Bash-like shell
0.1.1.4 git
第13章会介绍怎样使用GitHub Actions做持续集成(Continuous Integration, CI)。为了学习那一章的内容,你需要创建自己的GitHub项目并向其中push(推送)代码。
Git是个开源的分布式版本控制系统。GitHub是一个协作式的互联网托管平台,让大家能够在上面分享彼此的项目及其源代码。
Git(https://git-scm.com)是一个免费且开源的分布式版本控制系统。GitHub(https://www.github.com)是一个使用Git的代码分享平台。
为了做持续集成,我们现在需要先做一些准备,另外一些准备工作可以等到第13章再做。现在具体要做的就是把我们的开发环境纳入Git版本控制系统之中。至于如何创建GitHub项目,到了第13章再说。
首先,下载并安装Git版本控制系统(https://git-scm.com/downloads)。这个工具在macOS、Windows以及Linux/Unix系统上都能安装。安装完成之后,请在终端窗口(也就是shell窗口或命令提示符窗口)里输入git--version命令并按回车(Enter)键。你应该会看到Git的回应,如图0-2所示。
图0-2:在shell里输入git--version命令并按回车键,以确认Git安装到位
接下来,我们要在TDD_PROJECT_ROOT之中创建一个新的Git项目。在shell窗口里输入下列命令:
这条命令执行完会输出一段信息,告诉你它已经把TDD_PROJECT_ROOT下面的.git文件夹初始化成了一个空白的Git repository(Git库)。现在,TDD_PROJECT_ROOT目录的结构应该变成了下面这个样子:
.git文件夹是Git用来保存工作信息的地方。我们不需要修改它的内容。
我们在后面几章会编写源代码,而且会定期把这些代码提交到Git库中。我们通过Git CLI(Command Line Interface,命令行界面)来执行该操作。
在本书后续的内容里面,我们会频繁地将修改之后的代码提交到Git库。本书采用这样一个图标来强调这种操作:。
0.1.2 Go
为了学习本书的内容,我们需要安装1.17版本的Go。各种操作系统都能安装这个版本(https://golang.org/dl)。
为了检查Go是否正确地安装到位,你可以在shell里面输入go version命令并按回车键。这会打印出已经安装的Go是什么版本,如图0-3所示。
图0-3:在shell中输入go version命令并按回车键,以验证Go是否能够正常运作
我们还需要设置几个与Go有关的环境变量:
1.名为GO111MODULE的环境变量应设为on。
2.名为GOPATH的环境变量不应把TDD_PROJECT_ROOT或其下任何目录(例如go目录)包含进来。
在shell中执行这样两条命令:
我们需要创建一个最基本的go.mod文件,以便开始撰写代码。请执行下面这两条命令来创建这份文件:
这样会创建出一份名叫go.mod的文件,该文件的内容为:
从现在起,如果要在Go语言的环境下学习本书内容,那么一定要先让shell进入TDD_PROJECT-ROOT里面的go文件夹。
要想学习本书的Go代码,必须先进入 $TDD_PROJECT_ROOT/go文件夹,然后再运行Go命令。
简单说说Go语言的包管理机制
Go语言的包管理机制正在发生剧烈变化。老式的方案是通过GOPATH环境变量来管理,这种方式正在逐渐让位给新的方式,也就是通过go.mod文件来管理。这两种管理方式基本上无法互相兼容。
刚才定义的那两个环境变量和生成的那个极简的go.mod文件,是为了确保Go语言所提供的那套工具能够顺利处理我们的源代码,尤其是我们所创建的包。我们在第5章就要创建Go语言的包。
0.1.3 JavaScript
我们需要使用版本14(代号“Fermium”)或版本16的Node.js来学习本书。这两种版本都可以在Node.js的网站中找到(参见https://nodejs.org/en/download),而且各种操作系统都能够安装。
为了确认Node.js已经正确安装,请在shell里面输入node-v命令并按回车键。这条命令应该会打印出一行消息,告诉你Node.js的版本,如图0-4所示。
图0-4:在shell中输入node-v命令并按回车键,以确认Node.js能够正常运作
0.1.3.1 简单说说Node.js的测试库
Node.js环境里面有许多测试框架。一般来说,这些框架都很适合用来编写测试并执行测试驱动开发。然而本书不打算使用这些框架,而是要用一个名叫assert的NPM包来做断言,并通过一个带有方法的简单类来整理我们所写的测试。这样可以让我们把重点放在TDD的做法和语义上,而不会陷入某个库的语法细节。第6章会更详细地讨论测试。附录B会列举几个测试框架,并解释笔者为什么不打算使用其中任何一个框架。
0.1.3.2 简单说说JavaScript语言的包管理机制
跟测试框架类似,在JavaScript语言中定义包与依赖关系也有许多办法。本书用的是CommonJS方式。第6章会讨论其他三种管理包的办法,前两种是ES6与UMD,笔者会结合代码对它们进行详细解释,第三种是AMD,笔者会简略地介绍这种包管理机制,而不会辅以代码。
0.1.4 Python
我们需要使用3.10版本的Python学习本书,这个版本可以从Python网站下载(参见https://oreil.ly/xNLPa),各种操作系统都能安装。
Python语言在Python 2与Python 3之间发生了很大变化。用旧一些的Python 3(例如3.6版本)来学习这本书的内容或许没有太大问题,但用Python 2来学则不合适。
你的计算机上可能已经安装了Python 2。比方说,许多macOS操作系统(也包括版本号是11的Big Sur系统)都自带Python 2。你没有必要(而且也不建议你)专门为了学习本书而卸载Python 2。你只需要确保在学习本书的时候使用的是Python 3。
为了消除误解,本书明确使用python3来指代这个启动Python 3编程环境时所用的可执行文件。虽然你也可以设法让python命令成为python3的别名或别称(alias),也就是让自己总是可以通过输入python来启动Python 3,但这同样没什么必要。
下面有一种简单的办法可以判断到底应该如何启动Python 3。请在shell里面输入python--version命令并按回车键。如果你看到启动的是Python 3,那意味着以后只要直接输入python就行。如果你看到的是Python 2,那意味着你在执行本书所提到的各种Python命令时,必须明确输入python3。
图0-5演示了一个既装有Python 2又装有Python 3的开发环境。
图0-5:确认本机是否已经安装Python 3,并了解自己应该通过哪个命令启动Python 3(图中所示的情况,意味着必须明确通过python3命令而非默认的python命令来启动Python 3)
应该用Python 3学习本书的代码,不要使用Python 2,因为这些代码无法在Python 2里运行。
图0-6能够帮你很快地记住刚才那几段话所说的意思。
图0-6:这张图会让你很快就记住本书需要的是哪一个版本的Python