How to discard printouts when running tests - go

Using Go 1.11 I have a function that prints a label above a user input. This is fine and works but when I have started to write the test for this function it prints out this label when running the tests.
I have also use log.Print but then in the test file adding the following
func init() {
log.SetOutput(ioutil.Discard)
}
This stops the log.Print from being displayed when running the tests. So how do I get it to do the same for any fmt.Println?
UPDATE
I thought I would post the func that I am testing and how I set up,
func checkLoop(loopCount int) int {
var input int
var ok bool
for !ok {
fmt.Printf("Input %d :: ", loopCount)
ok, input = takeInput()
}
return input
}
So takeInput() only takes the users input, using fmt.Scan and checks it to see if its within a set range I want. So it returns a bool and if its false it will re-use the label to check what input number it is.

Either you're testing on a wrong level or you're testing a wrong thing, let me explain.
If it's for some reason valuable for you to test that
your function prints something and also accepts user input,
then go ahead and do end-to-end testing for it—that is, also test
that it prints what it's expected to print, and once it does that, submit it some canned input and then verify it processes it the way you expect it to.
I don't know your code but supposedly you should stop
using fmt.P* family of functions—which imply using os.Std{in|out|err} and write the functions forming the core of your code accepting io.Reader and io.Writer interfaces and
call them from the top-level code passing them os.Stdin and os.Stderr etc.
Then, when testing, it will be easy to pass these functions
stub (or mock) values which also satisfy the said interfaces.
(The fmt package supports formatted printing using the fmt.FP* family of functions, where that F is a historical artefact meaning "file" and allows you to pass it any value implementing io.Writer.)
Another possibility is that what you explained looks like
a code smell: a function concerned with processing some input
data has no business printing any labels anywhere.
So it well may be that you instead should split your function
at least in two: the "outer" one prompts the user and reads the data, and the second accepts the data and processes it.
You then test the second one.

For example,
discard_test.go:
package main
import (
"fmt"
"os"
"syscall"
"testing"
)
func printLabel(label string) {
fmt.Println(label)
}
func TestDiscardLabel(t *testing.T) {
defer func(stdout *os.File) {
os.Stdout = stdout
}(os.Stdout)
os.Stdout = os.NewFile(uintptr(syscall.Stdin), os.DevNull)
printLabel("Discard:")
}
func TestPrintLabel(t *testing.T) {
printLabel("Print:")
}
Output:
$ go test discard_test.go -v
--- PASS: TestDiscardLabel (0.00s)
=== RUN TestPrintLabel
Print:
--- PASS: TestPrintLabel (0.00s)
PASS
$

fmt.Printf use the os.Stdout so you can simply:
os.Stdout = nil
fmt.Println("Hello Gopher!")
or more elegant:
os.Stdout,_ = os.Open(os.DevNull)
fmt.Println("Hello Gopher!")
Hope this help

Related

How do I write a go Test function for something that reads from stdin?

I have go test code similar to this:
func TestRollback(t *testing.T) {
store := NewStore()
// do some stuff
err := store.Rollback()
// checks
}
The problem is store.Rollback() has a prompt read from the stdin for y or n
How do I send "y" to the test process when running go test -v --run TestRollback
The difficulty in testing your Rollback method stems from hardcoding its dependency on singleton os.Stdin.
Tinkerer's answer is viable but, because it mutates that package-level variable, it doesn't lend itself to running tests in parallel.
A preferable alternative (IMO) consists in using an interface. Testing often rhymes with interface, in Go. Here, because os.Stdin satisfies the io.Reader interface, you could parameterise your Store type with an io.Reader passed to your factory function:
type Store struct {
// other fields, omitted here
in io.Reader
}
func NewStore(in io.Reader) *Store {
store := Store {
// other fields, omitted here
in: in,
}
return &store
}
Then, in your test functions, you could use a concrete type that satisfies io.Reader and is easily configurable, such as a *strings.Reader:
func TestRollback(t *testing.T) {
// arrange
in := strings.Reader("-- put contents of stdin here --")
store := NewStore(in)
// act
err := store.Rollback()
// assert
// ...
}
The following can redirect stdin temporarily.
rd,wr,err := os.Pipe()
saved := os.Stdin
os.Stdin = rd
... Test code feeds wr ...
os.Stdin = saved

Reading from stdout pipe once ready in golang

I'm facing with a weird golang issue. The following code will clarify:
package main
import (
"os/exec"
"io"
"fmt"
"os"
)
var (
pw io.WriteCloser
pr io.ReadCloser
)
func main() {
term := exec.Command("/bin/sh")
// Get stdin writer pipe
pw, _ = term.StdinPipe()
pr, _ = term.StdoutPipe()
term.Start()
run("cd ~")
pwd := run("pwd");
// Do something with pwd output
...
term.Wait()
}
func run(c string) string {
io.WriteString(pw, fmt.Sprintln(c))
buf := make([]byte, 32 * 1024)
pr.Read(buf)
return string(buf)
}
I'd like to run some commands in a shell env and read their output. There's no problem on write/run command but it seems that there're some limitations while reading:
you can't know if a command doesn't output anything or not;
there's no way to check if stdout is ready to be read or not.
The pr.Read(dest) method will block the code flow until something is read from stdout. As said, the goal is to read sequentially (without using a go routine and/or an infinite loop). This means that if we send a cd command the func end is never reached.
Setting the non-block flag through unix.SetNonblock on stdout file descriptor seems to solve the above issue but you can't know prior if it's ready or not and an error saying "resource temporary not available" is returned from .Read call.
As Cerise Limón mentioned go functions whould be the way to go here, since these sorts of interactive scripting exercises are traditionally done with expect.
You can wrap the the parrellel execution into a library to it might still look like sequencial code, so this might be helpful: https://github.com/ThomasRooney/gexpect
From the readme:
child, err := gexpect.Spawn("python")
if err != nil { panic(err) }
child.Expect(">>>")
child.SendLine("print 'Hello World'")
child.Interact()
child.Close()

Compare Go stdout to file contents with testing package [duplicate]

I have a simple function I want to test:
func (t *Thing) print(min_verbosity int, message string) {
if t.verbosity >= minv {
fmt.Print(message)
}
}
But how can I test what the function actually sends to standard output? Test::Output does what I want in Perl. I know I could write all my own boilerplate to do the same in Go (as described here):
orig = os.Stdout
r,w,_ = os.Pipe()
thing.print("Some message")
var buf bytes.Buffer
io.Copy(&buf, r)
w.Close()
os.Stdout = orig
if(buf.String() != "Some message") {
t.Error("Failure!")
}
But that's a lot of extra work for every single test. I'm hoping there's a more standard way, or perhaps an abstraction library to handle this.
One thing to also remember, there's nothing stopping you from writing functions to avoid the boilerplate.
For example I have a command line app that uses log and I wrote this function:
func captureOutput(f func()) string {
var buf bytes.Buffer
log.SetOutput(&buf)
f()
log.SetOutput(os.Stderr)
return buf.String()
}
Then used it like this:
output := captureOutput(func() {
client.RemoveCertificate("www.example.com")
})
assert.Equal(t, "removed certificate www.example.com\n", output)
Using this assert library: http://godoc.org/github.com/stretchr/testify/assert.
You can do one of three things. The first is to use Examples.
The package also runs and verifies example code. Example functions may include a concluding line comment that begins with "Output:" and is compared with the standard output of the function when the tests are run. (The comparison ignores leading and trailing space.) These are examples of an example:
func ExampleHello() {
fmt.Println("hello")
// Output: hello
}
The second (and more appropriate, IMO) is to use fake functions for your IO. In your code you do:
var myPrint = fmt.Print
func (t *Thing) print(min_verbosity int, message string) {
if t.verbosity >= minv {
myPrint(message) // N.B.
}
}
And in your tests:
func init() {
myPrint = fakePrint // fakePrint records everything it's supposed to print.
}
func Test...
The third is to use fmt.Fprintf with an io.Writer that is os.Stdout in production code, but bytes.Buffer in tests.
You could consider adding a return statement to your function to return the string that is actually printed out.
func (t *Thing) print(min_verbosity int, message string) string {
if t.verbosity >= minv {
fmt.Print(message)
return message
}
return ""
}
Now, your test could just check the returned string against an expected string (rather than the print out). Maybe a bit more in-line with Test Driven Development (TDD).
And, in your production code, nothing would need to change, since you don't have to assign the return value of a function if you don't need it.

Go: abstract iterable

Suppose I want to have a method that should either return a chan or a slice. For example, I need a chan if I want to "follow" a file as new lines come, and a slice if I just want to read and return existing lines.
In both cases I will only have to iterate through this return value. Here is an abstract example in Python (which has nothing to do with files but sort of shows the idea):
def get_iterable(self):
if self.some_flag:
return (x for x in self.some_iterable)
return [x for x in self.some_iterable]
def do_stuff(self):
items = self.get_iterable()
for item in items:
self.process(item)
Now, I have a difficulty doing this in Go. I suppose I should look for something like an "iterable interface" which I should return, but I failed to google up some ready-to-use solutions (sorry if it's just my poor googling skills).
What is the best way to do what I want? Or, maybe, the whole design is "bad" for Go and I should consider something else?
Or, maybe, the whole design is "bad" for Go and I should consider something else?
While you could build some interface on top of the types so that you can deal with them as if they were the same I would say it's a poor choice. The far simpler one is to take advantage of multiple return types and define your func with chan myType, []myType, error for it's return then just use 3 way if-else to check for error, followed by chan or slice. Read of the channel like you normally would, iterate the slice like you normally would. Put the code that does work on myType in a helper method so you can call it from both control flows.
My money says this is no more code and it's also far more straight forward. I don't have to read through some abstraction to understand that I have a channel and the inherit complications that come along with it (chan and a slice are incongruous so trying to model them the same sounds like a nightmare), instead you just have an extra step in the programs control flow.
I'm kinda late to the party, but if you really need some "abstract iterable", you could create an interface like this:
type Iterable interface {
Next() (int, error)
}
(Inspired by sql.Rows.)
Then, you could use it like this:
for n, err := iter.Next(); err != nil; n, err = iter.Next() {
fmt.Println(n)
}
For iteration I usually follow pattern found in sql.Rows and bufio.Scanner. Both have a next-equivalent function returning bool, indicating whether next item has been successfully fetched. Then there's a separate method to access the value and error. This pattern lets you write very clean for loops without complex conditions (and without using break or continue statements) and moves error handling outside of the loop.
If you were to abstract your line input, you could for example create an interface like this:
type LineScanner interface {
Scan() bool
Text() string
Err() error
}
This would give you and abstract line source reader. As a bonus, by using exactly these method names you would make bufio.Scanner instantly implementing your interface, so you could use it along with your own types, for example tail-like reader mentioned in your question.
Fuller example:
package main
import (
"bufio"
"fmt"
"strings"
)
type LineScanner interface {
Scan() bool
Text() string
Err() error
}
func main() {
var lr LineScanner
// Use scanner from bufio package
lr = bufio.NewScanner(strings.NewReader("one\ntwo\nthree!\n"))
// Alternatively you can provide your own implementation of LineScanner,
// for example tail-like, blocking on Scan() until next line appears.
// Very clean for loop, isn't it?
for lr.Scan() {
// Handle next line
fmt.Println(lr.Text())
}
// Check if no error while reading
if lr.Err() != nil {
fmt.Println("Error:", lr.Err())
}
}
http://play.golang.org/p/LRbGWj9_Xw

go how to check if a function exists

Is there any way to check if a func exists in Go?
In PHP I might do something like
if(function_exists('someFunction')) {
//...
}
but I have not been able to figure out how to do this in Go
Any help on this will be greatly received.
A little more context on what you're trying to do would help.
As you note in your own comment, if you try to call a function Go checks at compile-time if the function exists, most of the times.
One exception that comes to my mind is when you use interface{} and you want to check that a method exists before calling it. For this you can use type checks.
Example:
package main
import "fmt"
// a simple Greeter struct
// with a Hello() method defined
type Greeter struct {
Name string
}
func (m *Greeter) Hello() string {
return "hello " + m.Name
}
var x interface{}
func main() {
x = Greeter {Name:"Paolo"} // x is a interface{}
g,ok := x.(Greeter) // we have to check that x is a Greeter...
if ok {
fmt.Println(g.Hello()) // ...before being able to call Hello()
}
}
Another scenario I can think of is that you're creating your own tool for Go that requires parsing go files before compiling them. If so, Go provides help in the for of the parser package
There's no way to do that (and for good!). The reason is that Go is a compiled language and does not support loadable modules (yet, at least) so functions can't come and go at runtime, and hence whether or not a top-level function exists, you know by defintion: if a given source file imports a package containing the function of interest1, that function is visible in this source file. Or this function is declared in the same package this source file belongs to and hence it's also available. In all the other cases the function is not available. Note that a function might be compiled in the program but still not visible in a given source file while compiling, so the whole definition of visibility as you put it does not exist in Go.
On the other hand you might want some generality. Generality in Go is achieved via interfaces. You might define an interface and then require a type to implement it. Checking that a type implements an interface is done via a neat trick.
An update from 2021-12-29.
The support for loadable modules was added in Go 1.8 in the form of the plugin package and has since then matured to support most mainline platforms except Windows.
Still, this solution is not without problems—for instance, see #20481.
1Without renaming that module to nothing, but let's not touch this for now.
Provided your thing is an interface value, type assert, something like this:
if Aer, ok := thing.(interface{MethodA()}); ok {
Aer.MethodA()
}
If thing is a struct, assign it to an interface variable first,
because type assertions only work on interface values.
It wouldn't hurt to define a named interface instead of using the
nonce one, but for simple cases like this it's not worth it.
Recently I had a need for figuring out if a struct has a particular function or not.
Here is another way using reflection :
package main
import (
"fmt"
"reflect"
)
type FuncRegistry struct {}
func (fr FuncRegistry) Hi() {
fmt.Println("function Hi")
}
func (fr FuncRegistry) Hello() {
fmt.Println("function Hello")
}
func functionExists(obj interface{},funcName string) bool {
mthd := reflect.ValueOf(obj).MethodByName(funcName)
if mthd.IsValid() {
fmt.Printf("Function '%s' exists \n",funcName)
return true
}
fmt.Printf("Function '%s' does not exist\n",funcName)
return false
}
// Main function
func main() {
var fr FuncRegistry
functionExists(fr,"Hi")
functionExists(fr,"Hello")
functionExists(fr,"Fail")
}
This sounds a lot like a XY problem. Please tell what you are trying to do. As far as I know, this is something you can't really do the same way as in PHP.
However, you could create a map with function names as keys. Add the functions there manually or generate the contents by parsing the source files before the compilation or at run time. Parsing the source seems like a dirty hack though.

Resources