Failure to make test suite pass golang "sayHello() used as value" - go

I'm trying to make this test suite pass through the command prompt (hello-world_test.go):
package helloworld
import "testing"
func TestHelloWorld(t *testing.T) {
output := sayHello()
if "Hello, World!" != output {
t.Fatalf("output: %s\nexpected: Hello,World!", output)
}
}
my code is as follows (helloworld.go):
package helloworld
import "fmt"
func sayHello() {
fmt.Println("Hello, World!")
}
and the error code through the command prompt is:
C:\Users\Troy\exercism\go\hello-world\go test -v
# _/C_/Users/Troy/exercism/go/hello-world
.\hello-world_test.go:6: sayHello() used as value
FAIL _/C_/Users/Troy/exercism/go/hello-world [build failed]

I have developed (for this kind of unit test) godbg.Out() and godbg.Err(), two io.Writer which, by default, are os.Stdout and os.Stderr.
That means I no longer use fmt.Println("Hello, World!").
Instead I do:
fmt.Fprintln(Out(), "Hello, World!")
That allows me, when I want to unit test that output (and not having the unit test own output filled with fmt.Println results), to change the default io.Writer with ones dedicated for that test, using the pdbg.SetBuffer() function.
That way, my test becomes:
Convey("Test custom buffer reset on global pdbg", func() {
SetBuffers(nil)
fmt.Fprint(Out(), "test content")
So(OutString(), ShouldEqual, `test content`)
fmt.Fprint(Err(), "err1 cerr")
So(ErrString(), ShouldEqual, `err1 cerr`)
ResetIOs()
fmt.Fprint(Out(), "test2 content2")
So(OutString(), ShouldEqual, `test2 content2`)
fmt.Fprint(Err(), "err2 cerr2")
So(ErrString(), ShouldEqual, `err2 cerr2`)
})
I can now test outputs done on stdout or stderr by replacing (during the unit test only) those writers with my own.
Notes:
I use the goconvey unit test framework here.
the design is still in progress. I might move those writer functions in their own package later on.

Apparently all i had to do to get the original test suite to pass was define the sayHello() function as a string, and return its value "Hello, World!. Also, i made lines 3 and 6 comments, as they do not affect the code directly:
package helloworld
//import "fmt"
func sayHello() string {
//fmt.Println("Hello, World!")
return "Hello, World!"
}
do the comments make the style of the code "tacky"?

Related

Why am I getting "no tests to run" despite having a test function?

Go newbie here, I have written a simple main_test.go file to run some test cases for main.go, when I run go test it says testing: warning: no tests to run
PASS
ok Solution 0.878s
my main.go:
package main
func normalizePhoneNum(phoneNumber string) string {
return ""
}
func main() {
}
main_test.go:
package main
import (
"testing"
)
func testNormalizePhoneNum(t *testing.T) {
testCase := []struct {
input string
output string
}{
{"1234567890", "1234567890"},
{"123 456 7891", "123 456 7891"},
{"(123) 456 7892", "(123) 456 7892"},
{"(123) 456-7893", "(123) 456-7893"},
{"123-456-7894", "123-456-7894"},
{"123-456-7890", "123-456-7890"},
{"1234567892", "1234567892"},
{"(123)456-7892", "(123)456-7892"},
}
for _, tc := range testCase {
t.Run(tc.input, func(t *testing.T) {
actual := normalizePhoneNum(tc.input)
if actual != tc.output {
t.Errorf("for %s: got %s, expected %s", tc.input, actual, tc.output)
}
})
}
}
Can anyone please tell, why it's not running the test cases?
Elementary! See the documentation for the go test command:
A test function is one named TestXxx (where Xxx does not start with a lower case letter) and should have the signature,
func TestXxx(t *testing.T) { ... }
Note that the first letter must be an uppercase T. You must respect this naming convention for test functions or the testing tool will simply ignore them.
Rename your test function to TestNormalizePhoneNum and try running go test again.
Alternatively—and although that is most likely not what you want here—you can force the testing tool to run a "test function" that doesn't adhere to the naming convention by specifying its name (or, more generally, a regular expression that its name matches) in the -run flag:
go test -run=testNormalizePhoneNum

GoLand No Tests Were Run

I have a method that I am testing, and everything seems fine. However, when I run the tests in GoLand, I can see in the output that the tests "PASS" but the test runner says "no tests were run".
Here's the sample method in calculator.go
package calculator
import (
"fmt"
)
type Calculator struct {}
func New() Calculator {
return Calculator{}
}
func (s *Calculator) AddTwoNumbers(num_one, num_two int) int {
fmt.Printf("adding")
return num_one + num_two
}
Here's the test in calculator_test.go:
package calculator
import (
"fmt"
"testing"
)
func Test_Calculator_AddTwoNumbers(t *testing.T) {
// Arrange
calculator := New()
// Act
total := calculator.AddTwoNumbers(1,2)
// Assert
if total != 3 {
msg := fmt.Sprintf("total should have been %d but instead was %d", 3, total)
t.Error(msg)
}
}
What am I doing wrong?
Instead of fmt.Printf(... in AddTwoNumbers try either fmt.Println(... or fmt.Printf("foo\n')
The absence of the newline in the output of your AddTwoNumbers method is is causing the format of the test execution outputs to not have each test in a new line. The test runner is not being able to interpret that a test was run. Adding that newline, keeps a clean output.
I would suggest using to check the verbose output of the test run.
go test -v
-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.

TestMain not run

I have a test package in go which tests some stuff that depend on reading a configuration. I want to read that configuration once before running all tests so I'm trying to use TestMain(m *testing.M):
main.go:
package tests
import (
...
)
var logger = logging.MustGetLogger("tests")
func TestMain(m *testing.M) {
logger.Info("Initializing test suite")
viper.SetConfigName("config")
viper.AddConfigPath("..\\..\\")
err := viper.ReadInConfig()
if err == nil {
os.Exit(m.Run())
} else {
logger.Fatal("Could not read configuration")
}
}
And I have another file in the same directory (and package) with a test.
repository_test.go:
package tests
import (
...
)
func TestCreation(t *testing.T) {
aa := myModule.CreateRepository()
assert.NotNil(t, aa)
}
My problem is that the test fails because the configuration is not read from the file. When I try to debug the test in Gogland a breakpoint inside TestMain is not hit. When I run the tests from command line I don't see any printouts from TestMain.
Is there something special I should do to make it work? From what I read online I understood that if I define TestMain(m *testing.M) then it's going to run just once for the package and that's where I'm supposed to write any setup or teardown code.
TestMain is only executed in test files (suffix _test.go).
Move the function to the repository_test.go file to fix this.
Make sure that the run configuration is set to Package not File in Run | Edit Configurations... | Go Test | Name of your configuration and this should work. If it doesn't, please post the commands the IDE runs to execute the tests.

How can stdout be captured or suppressed for Go(lang) testing?

How can stdout be captured or suppressed for Go testing?
I am trying to teach myself go(lang) testing. In the code below, myshow.LoadPath prints lots of information to stdout (which is a normal side effect). It does however make for very noisy output when I run "go test" Is there a way to suppress or capture stdout?
For comparison, I'm thinking about something like this from the python world. http://pytest.org/latest/capture.html#captures
package slideshow_test
import (
"os"
"testing"
"github.com/golliher/go-hpf/slideshow"
)
func setupTest() {
myshow := slideshow.Slideshow{Name: "This is my show"}
myshow.LoadPath("..")
}
func TestStub(t *testing.T) {
if true == false {
t.Fail()
}
}
func TestMain(m *testing.M) {
setupTest()
os.Exit(m.Run())
}
os.Stdout which is used by the fmt.Printf and others is just a variable. So you can overwrite it at any time and restore it back when necessary. https://golang.org/pkg/os/#pkg-variables
To suppress the output during the test I use the following code. I fixes output as well as logging. After test is done it resets the output streams.
func TestStartStowWrongCommand(t *testing.T) {
defer quiet()()
...
}
func quiet() func() {
null, _ := os.Open(os.DevNull)
sout := os.Stdout
serr := os.Stderr
os.Stdout = null
os.Stderr = null
log.SetOutput(null)
return func() {
defer null.Close()
os.Stdout = sout
os.Stderr = serr
log.SetOutput(os.Stderr)
}
}
The output can be suppressed
by running the tests with go test .:
$ go help test
Go test runs in two different modes: local
directory mode when invoked with no package arguments (for example,
'go test'), and package list mode when invoked with package arguments
(for example 'go test math', 'go test ./...', and even 'go test .').
In local directory mode, go test compiles and tests the package
sources found in the current directory and then runs the resulting
test binary. In this mode, caching (discussed below) is disabled.
After the package test finishes, go test prints a summary line showing
the test status ('ok' or 'FAIL'), package name, and elapsed time.
In package list mode, go test compiles and tests each of the packages
listed on the command line. If a package test passes, go test prints
only the final 'ok' summary line. If a package test fails, go test
prints the full test output. If invoked with the -bench or -v flag, go
test prints the full output even for passing package tests, in order
to display the requested benchmark results or verbose logging.
Not exactly what you are asking for but still might be helpful.
You can use t.Log (http://golang.org/pkg/testing/#T.Log) and t.Logf (http://golang.org/pkg/testing/#T.Logf) methods in the test method. The output will be printed only if the test fails or the -test.v flag is set.
I also would suggest to use log package to print to the console in myshow.LoadPath. Then you can disable (or capture) the output in the test by setting custom writer using log.SetOutput

golang testing method after each test: undefined: testing.M

I am trying to repeat example from golang testing
package main
import (
"testing"
)
func TestSomeTest(t *testing.T) {}
func TestMain(m *testing.M) { // cleaning after each test}
I want TestMain function to run after every test.
Running command go test
And the compiler says
./testingM_test.go:9: undefined: testing.M
So how to clean after executing every test?
Check you go version output: this is for go 1.4+ only.
The testing package has a new facility to provide more control over running a set of tests. If the test code contains a function
func TestMain(m *testing.M)
that function will be called instead of running the tests directly.
The M struct contains methods to access and run the tests.
You can see that feature used here:
The introduction of TestMain() made it possible to run these migrations only once. The code now looks like this:
func TestSomeFeature(t *testing.T) {
defer models.TestDBManager.Reset()
// Do the tests
}
func TestMain(m *testing.M) {
models.TestDBManager.Enter()
// os.Exit() does not respect defer statements
ret := m.Run()
models.TestDBManager.Exit()
os.Exit(ret)
}
While each test must still clean up after itself, that only involves restoring the initial data, which is way faster than doing the schema migrations.

Resources