An Interest In:
Web News this Week
- April 25, 2024
- April 24, 2024
- April 23, 2024
- April 22, 2024
- April 21, 2024
- April 20, 2024
- April 19, 2024
Unit testing Stdout in Go
Figuring out how to unit test functions that print to the terminal can be something of a daunting task. Thankfully, it's actually pretty simple due to the magic of interfaces in Go!
This post is going to be short and sweet on how to test output by capturing it in a bytes.Buffer
. Below, I have a function that accepts a string, prints out a statement, and then returns.
func SayHello(w io.Writer, name string) { fmt.Fprintf(w, "Hi, my name is %s
", name)}
The critical component of this function is the io.Writer
interface variable being passed in. Because it is an interface, this function will accept any data type that implements the method Write(b []byte) (n int, err error)
.
This interface is implemented in the io
package and the entire code can be seen here. Most importantly, here is the code below for the interface:
type Writer interface { Write(p []byte) (n int, err error)}
So how do we print out this function to the terminal? We pass in os.Stdout
, which has its own Write method! This can be seen here.
To print this out to our terminal, just add the following in the main()
function.
func main() { SayHello(os.Stdout, "Shannon")}
Now, we can move onto unit testing this specific function, which just outputs a name and greeting. In order to test it, we need to capture its output and then turn it into a string from a slice of bytes. To do this, we'll utilize the bytes.Buffer
struct, which has a Write method to satisfy the Writer interface.
Here is the full test code in order to compare these:
func TestSayHello(t *testing.T) { tt := []struct { description string name string expect string }{ {"Empty", "", "Hi, my name is
"}, {"Name1", "Shannon", "Hi, my name is Shannon
"}, {"Name2", "Shug", "Hi, my name is Shug
"}, } for _, tc := range tt { t.Run(tc.description, func(t *testing.T) { var output bytes.Buffer SayHello(&output, tc.name) if tc.expect != output.String() { t.Errorf("got %s but expected %s", output.String(), tc.expect) } }) }}
You'll notice that we are declaring a Buffer here: var output bytes.Buffer
and then passing that buffer into the SayHello function. However, we are actually passing in the address of the buffer. This is due to the Buffer method for Write being a pointer receiver, which can be seen here.
And that's it! Run go test -v
to see that all tests pass, and you have successfully captured the output of a command in order to unit test the output without actually returning the string value.
Original Link: https://dev.to/lucassha/unit-testing-stdout-in-go-1jd
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To