Skip to content

Commit 4d8937d

Browse files
committed
Update 'go test' section for go1.5.
1 parent aecc41c commit 4d8937d

File tree

2 files changed

+59
-67
lines changed

2 files changed

+59
-67
lines changed

0.6.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# go run
22

3+
4+
35
在《Go并发编程实战》的第二章中,我介绍了Go源码文件的分类。Go源码文件包括:命令源码文件、库源码文件和测试源码文件。其中,命令源码文件总应该属于`main`代码包,且在其中有无参数声明、无结果声明的main函数。单个命令源码文件可以被单独编译,也可以被单独安装(可能需要设置环境变量GOBIN)。当然,命令源码文件也可以被单独运行。我们想要运行命令源码文件就需要使用命令`go run`
46

57
`go run`命令可以编译并运行命令源码文件。由于它其中包含了编译动作,因此它也可以接受所有可用于`go build`命令的标记。除了标记之外,`go run`命令只接受Go源码文件作为参数,而不接受代码包。与`go build`命令和`go install`命令一样,`go run`命令也不允许多个命令源码文件作为参数,即使它们在同一个代码包中也是如此。而原因也是一致的,多个命令源码文件会都有main函数声明。
68

79
如果命令源码文件可以接受参数,那么在使用`go run`命令运行它的时候就可以把它的参数放在它的文件名后面,像这样:
810

9-
```go
11+
```bash
1012
hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p ~/golang/goc2p
1113
```
1214

@@ -20,7 +22,7 @@ hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p ~/golang/goc2p
2022

2123
为了更直观的体现出`go run`命令中的操作步骤,我们在执行命令时加入标记`-n`,用于打印相关命令而不实际执行。现在让我们来模拟运行goc2p项目中的代码包helper/ds的命令源码文件showds.go。示例如下:
2224

23-
```go
25+
```bash
2426
hc@ubt:~/golang/goc2p/src/helper/ds$ go run -n showds.go
2527

2628
#
@@ -52,7 +54,7 @@ $WORK/command-line-arguments/_obj/exe/showds
5254

5355
在上面的示例中,我们只是让`go run`命令打印出运行命令源码文件showds.go过程中需要执行的命令,而没有真正运行它。如果我们想真正运行命令源码文件showds.go并且想知道临时工作目录的位置,就需要去掉标记`-n`并且加上标记`-work`。当然,如果依然想看到过程中执行的命令,可以加上标记`-x`。如果读者已经看过之前我们对`go build`命令的介绍,就应该知道标记`-x`与标记`-n`一样会打印出过程执行的命令,但不同的这些命令会被真正的执行。调整这些标记之后的命令就像这样:
5456

55-
```go
57+
```bash
5658
hc@ubt:~/golang/goc2p/src/helper/ds$ go run -x -work showds.go
5759
```
5860

@@ -69,19 +71,21 @@ hc@ubt:~/golang/goc2p/src/helper/ds$ go run -x -work showds.go
6971

7072
由于上述命令中包含了`-work`标记,所以我们可以从其输出中找到实际的工作目录(这里是/tmp/go-build604555989)。有意思的是,我们恰恰可以通过运行命令源码文件showds.go来查看这个临时工作目录的目录树:
7173

72-
hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p /tmp/go-build604555989
74+
```bash
75+
hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p /tmp/go-build604555989
76+
```
7377

7478
读者可以自己试一试。
7579

7680
我们在前面介绍过,命令源码文件如果可以接受参数,则可以在执行`go run`命令运行这个命令源码文件时把参数名和参数值成对的追加在后面。实际上,如果在命令后追加参数,那么在最后执行生成的可执行文件的时候也会追加一致的参数。例如,如果这样执行命令:
7781

78-
```go
82+
```bash
7983
hc@ubt:~/golang/goc2p/src/helper/ds$ go run -n showds.go -p ~/golang/goc2p
8084
```
8185

8286
那么带`-x``-n`标记的命令程序打印的最后一个命令就是:
8387

84-
```go
88+
```bash
8589
$WORK/command-line-arguments/_obj/exe/showds -p /home/hc/golang/goc2p
8690
```
8791

0.7.md

+49-61
Original file line numberDiff line numberDiff line change
@@ -2,83 +2,71 @@
22

33

44

5-
```go test```命令用于对Go语言编写的程序进行测试。这种测试是以代码包为单位的。当然,这还需要测试源码文件的帮助。关于怎样编写并写好Go程序测试代码,我们会在本章的第二节加以详述。在这里,我们只讨论怎样使用命令启动测试。
5+
`go test`命令用于对Go语言编写的程序进行测试。这种测试是以代码包为单位的。当然,这还需要测试源码文件的帮助。关于怎样编写并写好Go程序测试代码,我们会在本章的第二节加以详述。在这里,我们只讨论怎样使用命令启动测试。
66

7-
```go test```命令会自动测试每一个指定的代码包。当然,前提是指定的代码包中存在测试源码文件。关于测试源码文件方面的知识,我们已经在第二章的第二节中介绍过。测试源码文件是名称以“_test.go”为后缀的、内含若干测试函数的源码文件。测试函数一般是以“Test”为名称前缀并有一个类型为“testing.T”的参数声明的函数.
7+
`go test`命令会自动测试每一个指定的代码包。当然,前提是指定的代码包中存在测试源码文件。关于测试源码文件方面的知识,在我的图书《Go并发编程实战》中有详细介绍。测试源码文件是名称以“_test.go”为后缀的、内含若干测试函数的源码文件。测试函数一般是以“Test”为名称前缀并有一个类型为“testing.T”的参数声明的函数.
88

99
现在,我们来测试goc2p项目中的几个代码包。在使用```go test```命令时指定代码包的方式与其他命令无异——使用代码包导入路径。如果需要测试多个代码包,则需要在它们的导入路径之间加入空格以示分隔。示例如下:
1010

11-
hc@ubt:~$ go test basic cnet/ctcp pkgtool
12-
ok basic 0.010s
13-
ok cnet/ctcp 2.018s
14-
ok pkgtool 0.009s
11+
```bash
12+
hc@ubt:~$ go test basic cnet/ctcp pkgtool
13+
ok basic 0.012s
14+
ok cnet/ctcp 2.014s
15+
ok pkgtool 0.014s
16+
```
1517

16-
```go test```命令在执行完所有的代码包中的测试文件之后,会以代码包为单位打印出测试概要信息。在上面的示例中,对应三个代码包的三行信息的第一列都是“ok”。这说明它们都通过了测试。每行的第三列显示运行相应测试所用的时间,以秒为单位。我们还可以在代码包目录下运行不加任何参数的运行```go test```命令。其作用和结果与上面的示例是一样的。
18+
`go test`命令在执行完所有的代码包中的测试文件之后,会以代码包为单位打印出测试概要信息。在上面的示例中,对应三个代码包的三行信息的第一列都是“ok”。这说明它们都通过了测试。每行的第三列显示运行相应测试所用的时间,以秒为单位。我们还可以在代码包目录下运行不加任何参数的运行`go test`命令。其作用和结果与上面的示例是一样的。
1719

18-
另外,我们还可以指定测试源码文件来进行测试。这样的话,```go test```命令只会执行指定文件中的测试,像这样:
20+
另外,我们还可以指定测试源码文件来进行测试。这样的话,`go test`命令只会执行指定文件中的测试,像这样:
1921

22+
```bash
2023
hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go
21-
# command-line-arguments
22-
./envir_test.go:20: undefined: GetGoroot
23-
./envir_test.go:34: undefined: GetAllGopath
24-
./envir_test.go:74: undefined: GetSrcDirs
25-
./envir_test.go:76: undefined: GetAllGopath
26-
./envir_test.go:83: undefined: GetGoroot
27-
FAIL command-line-arguments [build failed]
28-
29-
我们看到,与指定源码文件进行编译或运行一样,命令程序会为指定的源码文件生成一个虚拟代码包——“command-line-arguments”。但是,测试并没有通过。但其原因并不是测试失败,而是编译失败。对于运行这次测试的命令程序来说,测试源码文件envir_test.go是属于代码包“command-line-arguments”的。并且,这个测试源码文件中使用了库源码文件envir.go中的函数。可以,它却没有显示导入这个库源码文件所属的代码包,这当然会引起编译错误。如果想解决这个问题,我们还需要在执行命令时加入这个测试源码文件所测试的那个源码文件。示例如下:
30-
31-
hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go envir.go
32-
ok command-line-arguments 0.008s
24+
# command-line-arguments
25+
./envir_test.go:25: undefined: GetGoroot
26+
./envir_test.go:40: undefined: GetAllGopath
27+
./envir_test.go:81: undefined: GetSrcDirs
28+
./envir_test.go:83: undefined: GetAllGopath
29+
./envir_test.go:90: undefined: GetGoroot
30+
FAIL command-line-arguments [build failed]
31+
```
32+
33+
我们看到,与指定源码文件进行编译或运行一样,命令程序会为指定的源码文件生成一个虚拟代码包——“command-line-arguments”。但是,测试并没有通过。但其原因并不是测试失败,而是编译失败。对于运行这次测试的命令程序来说,测试源码文件envir_test.go是属于代码包“command-line-arguments”的。并且,这个测试源码文件中使用了库源码文件envir.go中的函数。但是,它却没有显示导入这个库源码文件所属的代码包。这显然会引起编译错误。如果想解决这个问题,我们还需要在执行命令时加入这个测试源码文件所测试的那个源码文件。示例如下:
34+
35+
```bash
36+
hc@ubt:~/golang/goc2p/src/pkgtool$ go test envir_test.go envir.go
37+
ok command-line-arguments 0.010s
38+
```
3339

34-
现在,我们故意使代码包```pkgtool```中的某个测试失败。现在我们再来运行测试:
40+
现在,我们故意使代码包`pkgtool`中的某个测试失败。现在我们再来运行测试:
3541

36-
hc@ubt:~$ go test basic cnet/ctcp pkgtool
37-
ok basic 0.010s
38-
ok cnet/ctcp 2.015s
39-
--- FAIL: TestGetSrcDirs (0.00 seconds)
40-
envir_test.go:85: Error: The src dir '/usr/local/go/src/pkg' is incorrect.
41-
FAIL
42-
FAIL pkgtool 0.009s
42+
```bash
43+
hc@ubt:~$ go test basic cnet/ctcp pkgtool
44+
ok basic 0.010s
45+
ok cnet/ctcp 2.015s
46+
--- FAIL: TestGetSrcDirs (0.00 seconds)
47+
envir_test.go:85: Error: The src dir '/usr/local/go/src/pkg' is incorrect.
48+
FAIL
49+
FAIL pkgtool 0.009s
50+
```
4351

44-
我们通过以上示例中的概要信息获知,测试源码文件中envir_test.go的测试函数```TestGetSrcDirs```中的测试失败了。在包含测试失败的测试源码文件名的那一行信息中,紧跟测试源码文件名的用冒号分隔的数字是错误信息所处的行号,在行号后面用冒号分隔的是错误信息。这个错误信息的内容是用户自行编写的。另外,概要信息的最后一行以“FAIL”为前缀。这表明针对代码包pkgtool的测试未通过。未通过的原因在前面的信息中已有描述。
52+
我们通过以上示例中的概要信息获知,测试源码文件中envir_test.go的测试函数`TestGetSrcDirs`中的测试失败了。在包含测试失败的测试源码文件名的那一行信息中,紧跟测试源码文件名的用冒号分隔的数字是错误信息所处的行号,在行号后面用冒号分隔的是错误信息。这个错误信息的内容是用户自行编写的。另外,概要信息的最后一行以“FAIL”为前缀。这表明针对代码包pkgtool的测试未通过。未通过的原因在前面的信息中已有描述。
4553

4654
一般情况下,我们会把测试源码文件与被测试的源码文件放在同一个代码包中。并且,这些源码文件中声明的包名也都是相同的。除此之外我们还有一种选择,那就是测试源码文件中声明的包名可以是所属包名再加“_test”后缀。我们把这种测试源码文件叫做包外测试源码文件。不过,包外测试源码文件存在一个弊端,那就是在它们的测试函数中无法测试被测源码文件中的包级私有的程序实体,比如包级私有的变量、函数和结构体类型。这是因为这两者的所属代码包是不相同的。所以,我们一般很少会编写包外测试源码文件。
4755

4856
**关于标记**
4957

50-
```go test```命令的标记处理部分是庞大且繁杂的,以至于使Go语言的开发者们不得不把这一部分的逻辑从```go test```命令程序主体中分离出来并建立单独的源码文件。因为```go test```命令中包含了编译动作,所以它可以接受可用于```go build```命令的所有标记。另外,它还有很多特有的标记。这些标记的用于控制命令本身的动作,有的用于控制和设置测试的过程和环境,还有的用于生成更详细的测试结果和统计信息。
58+
`go test`命令的标记处理部分是庞大且繁杂的,以至于使Go语言的开发者们不得不把这一部分的逻辑从`go test`命令程序主体中分离出来并建立单独的源码文件。因为`go test`命令中包含了编译动作,所以它可以接受可用于`go build`命令的所有标记。另外,它还有很多特有的标记。这些标记的用于控制命令本身的动作,有的用于控制和设置测试的过程和环境,还有的用于生成更详细的测试结果和统计信息。
5159

52-
可用于```go test```命令的两个比较常用的标记是```-i```和标记```-c```。这两个就是用于控制```go test```命令本身的动作的标记。详见下表。
60+
可用于`go test`命令的几个比较常用的标记是`-c``-i``-o`。这两个就是用于控制`go test`命令本身的动作的标记。详见下表。
5361

5462
表0-6 ```go test```命令的标记说明
55-
<table class="table table-bordered table-striped table-condensed">
56-
<tr>
57-
<th width=25%>
58-
标记名称
59-
</th>
60-
<th>
61-
标记描述
62-
</th>
63-
</tr>
64-
<tr>
65-
<td>
66-
-c
67-
</td>
68-
<td>
69-
生成用于运行测试的可执行文件,但不执行它。
70-
</td>
71-
</tr>
72-
<tr>
73-
<td>
74-
-i
75-
</td>
76-
<td>
77-
安装/重新安装运行测试所需的依赖包但不编译和运行测试代码。
78-
</td>
79-
</tr>
80-
</table>
81-
82-
上述这两个标记可以搭配使用。搭配使用的目的就是让```go test```命令既安装依赖包又编译测试代码,但不运行测试。也就是说,让命令程序跑一遍运行测试之前的所有流程。这可以测试一下测试过程。需要注意的是,在加入```-c```标记后,命令程序在编译测试代码并生成用于运行测试的一系列文件之后会把临时工作目录及其下的所有内容一并删除。如果想在命令执行结束后再去查看这些内容的话,我们还需要加入```-work```标记。
83-
84-
除此之外,```go test```命令还有很多功效各异的标记。但是由于这些标记的复杂性,我们需要结合测试源码文件进行详细的讲解。所以我们把这些内容放在了本章的第二节中。
63+
64+
标记名称 | 标记描述
65+
------------ | -------------
66+
-c | 生成用于运行测试的可执行文件,但不执行它。这个可执行文件会被命名为“pkg.test”,其中的“pkg”即为被测试代码包的导入路径的最后一个元素的名称。
67+
-i | 安装/重新安装运行测试所需的依赖包,但不编译和运行测试代码。
68+
-o | 指定用于运行测试的可执行文件的名称。追加该标记不会影响测试代码的运行,除非同时追加了标记`-c``-i`
69+
70+
上述这几个标记可以搭配使用。搭配使用的目的可以是让`go test`命令既安装依赖包又编译测试代码,但不运行测试。也就是说,让命令程序跑一遍运行测试之前的所有流程。这可以测试一下测试过程。注意,在加入`-c`标记后,命令程序会把用于运行测试的可执行文件存放到当前目录下。
71+
72+
除此之外,`go test`命令还有很多功效各异的标记。但是由于这些标记的复杂性,我们需要结合测试源码文件进行详细的讲解。所以我们在这里略过不讲。如果读者想了解相关详情,请参看《Go并发编程实战》的第5章。

0 commit comments

Comments
 (0)