调试某个go test程序的时候,需要实现confirm/approve
功能:
测试完testCase1
之后(或者说是某个断点),用户输入yes
,执行下一个case
,输入no
, 则退出整个测试。
下意识的觉得这个很好实现,调用fmt.Scan
应该就OK了。
但是写的时候才发现,go test
会强制重定向os.Stdin = /dev/null
忽略所有的 stdin输入,
所以没法使用 fmt.Scan
来等待键盘(用户)的输入:
1
2
3
4
5
| // fmt.Scan reads from os.Stdin, which is set to /dev/null when testing.
// Tests should be automated and self-contained anyway, so you don't want
// to read from stdin.
// Either use an external file, a bytes.Buffer, or a strings.Reader and
// call scan.Fscan if you want to test **the literal** `scan` Function.
|
解决方案#
可以参考事件驱动,使用named pipes
来实现confirm/approve
功能:
消费者#
先写一个消费者的函数readPipe
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
for i := 0; i < 6; i++ {
readPipe(i)
}
}
func readPipe(i int) {
f, err := os.Open("pipe")
if err != nil {
log.Fatalln(err)
}
defer f.Close()
reader := bufio.NewScanner(f)
for reader.Scan() {
fmt.Println(i, reader.Text())
}
}
|
然后在测试的case里调用readPipe
函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| package main
import (
"fmt"
"testing"
)
func TestCase1(t *testing.T) {
fmt.Println("testing test case 1")
fmt.Println("test case 1 tested")
readPipe(1)
}
func TestCase2(t *testing.T) {
fmt.Println("testing test case 2")
fmt.Println("test case 2 tested")
readPipe(2)
}
func TestCase3(t *testing.T) {
fmt.Println("testing test case 3")
fmt.Println("test case 3 tested")
readPipe(3)
}
|
生成者#
创建pipe
,然后往pipe里写数据,就可以触发(unblock
)消费者进程。
1
2
3
| ➜ ~ mkfifo pipe
➜ ~ ls -alh pipe
prw-r--r-- 1 r staff 0B 4 24 16:32 pipe
|
写入数据:
1
2
3
| ➜ ~ date > pipe
➜ ~ date > pipe
➜ ~ date > pipe
|
调试的结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
| ➜ ~ go test
testing test case 1
test case 1 tested
1 2020年 4月24日 星期五 16时31分50秒 CST
testing test case 2
test case 2 tested
2 2020年 4月24日 星期五 16时31分59秒 CST
testing test case 3
test case 3 tested
3 2020年 4月24日 星期五 16时32分08秒 CST
PASS
ok abc 36.016s
|