我正在使用此article中的信息来使用Firebase模拟器为Firestore构建测试。
仿真器可以正常启动,可以运行测试,但是尽管有SIGKILL(我尝试了其他信号),但测试完成后仍未清除仿真器。
这是我的main_test.go
的样子:
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"syscall"
"testing"
"time"
)
func TestMain(m *testing.M) {
// command to start firestore emulator
cmd := exec.Command("firebase", "emulators:start")
// this makes it killable
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
// we need to capture it's output to know when it's started
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
var result int
defer func() {
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
os.Exit(result)
}()
started := make(chan bool)
go func() {
buf := make([]byte, 512, 512)
for {
n, err := stdout.Read(buf[:])
if err != nil {
if err == io.EOF {
break
}
log.Fatalf("reading stdout %v", err)
}
if n > 0 {
d := string(buf[:n])
// only required if we want to see the emulator output
fmt.Printf("%s", d)
// checking for the message that it's started
if strings.Contains(d, "All emulators ready") {
started <- true
break
}
}
}
}()
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
select {
case <-time.After(10 * time.Second):
log.Fatal("Failed to start the command for 10 seconds")
case err := <-done:
log.Fatalf("------\nCommand has finished unexpectedly with error: %v", err)
case <-started:
fmt.Println("--------")
log.Print("Command started successully... running tests")
}
log.Print("BEFORE running tests")
result = m.Run()
time.Sleep(time.Minute) // to simulate that it take some times to run tests
log.Print("AFTER running tests")
}
go test . -v
的输出看起来不错:
i emulators: Starting emulators: firestore
i firestore: Firestore Emulator logging to firestore-debug.log
i ui: Emulator UI logging to ui-debug.log
┌───────────────────────────────────────────────────────────────────────┐
│ ✔ All emulators ready! View status and logs at http://localhost:4000 │
└────────────────────────────────────────────────────────────--------
2020/10/13 16:20:29 Command started successully... running tests
2020/10/13 16:20:29 BEFORE running tests
testing: warning: no tests to run
PASS
2020/10/13 16:20:29 AFTER running tests
ok go/src/test (cached) [no tests to run]
但是firebase仿真器没有正确清理(如果我再次启动同一命令,则无法抱怨端口4000已被使用)。发现以下过程持续存在:
### snippet from netstat -anp:
tcp 0 0 127.0.0.1:4000 0.0.0.0:* LISTEN 25187/firebase
tcp6 0 0 127.0.0.1:8080 :::* LISTEN 25160/cloud-firesto
### snippet from ps axu:
user 25187 /usr/local/bin/firebase /home/.cache/firebase/emulators/ui-v1.1.1/server.bundle.js
...
user 25160 /home/.cache/firebase/emulators/cloud-firestore-emulator-v1.11.7.jar --launcher_javabase=/usr/local/buildtools/java/jdk11 -Duser.language=en run --host localhost --port 8080 --rules /home/firestore.rules
有什么想法吗? ...或其他有关如何测试我的主要功能(使用Firestore作为后端)的想法?
答案 0 :(得分:0)
简短的回答:执行exec
不会终止子进程。此处有更多详细信息:Why won't Go kill a child process correctly?
根据here中的建议,我决定使用:
firebase emulators:exec "go test"
这将在测试完成后正确清除模拟器。