Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test os.exit scenarios in Go

Given this code

func doomed() {   os.Exit(1) } 

How do I properly test that calling this function will result in an exit using go test? This needs to occur within a suite of tests, in other words the os.Exit() call cannot impact the other tests and should be trapped.

like image 625
mbrevoort Avatar asked Oct 06 '14 21:10

mbrevoort


People also ask

What does OS exit do in Golang?

An exit code or an exit status is a number returned by a program to indicate whether a program has successfully executed or encountered an error. Typically, an exit code of 0 means that the program executes successfully. Any other numerical value between 1 and 125 (golang) shows the program encountered an error.

How do I test my go code?

At the command line in the greetings directory, run the go test command to execute the test. The go test command executes test functions (whose names begin with Test ) in test files (whose names end with _test.go). You can add the -v flag to get verbose output that lists all of the tests and their results.


1 Answers

There's a presentation by Andrew Gerrand (one of the core members of the Go team) where he shows how to do it.

Given a function (in main.go)

package main  import (     "fmt"     "os" )  func Crasher() {     fmt.Println("Going down in flames!")     os.Exit(1) } 

here's how you would test it (through main_test.go):

package main  import (     "os"     "os/exec"     "testing" )  func TestCrasher(t *testing.T) {     if os.Getenv("BE_CRASHER") == "1" {         Crasher()         return     }     cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")     cmd.Env = append(os.Environ(), "BE_CRASHER=1")     err := cmd.Run()     if e, ok := err.(*exec.ExitError); ok && !e.Success() {         return     }     t.Fatalf("process ran with err %v, want exit status 1", err) } 

What the code does is invoke go test again in a separate process through exec.Command, limiting execution to the TestCrasher test (via the -test.run=TestCrasher switch). It also passes in a flag via an environment variable (BE_CRASHER=1) which the second invocation checks for and, if set, calls the system-under-test, returning immediately afterwards to prevent running into an infinite loop. Thus, we are being dropped back into our original call site and may now validate the actual exit code.

Source: Slide 23 of Andrew's presentation. The second slide contains a link to the presentation's video as well. He talks about subprocess tests at 47:09

like image 73
Timo Reimann Avatar answered Oct 03 '22 00:10

Timo Reimann