Reputation: 27
I want to get test coverage of a REST service written in Go. I am spawning REST service through a goroutine, then making HTTP requests using rest client, and reviewing the HTTP responses.
Tests are passing successfully but go test -cover
returns 0% test coverage.
Is there a way to get the actual test coverage of all the packages used inside the go lang REST service.
my test file: main_test.go
import (
"testing"
)
// Test started when the test binary is started. Only calls main.
func TestSystem(t *testing.T) {
go main() // Spinning up the go lang REST server in a separate go routine.
http.Post("https://localhost/do_something")
}
my output:
go test -cover main_test.go
ok command-line-arguments 0.668s coverage: 0.0% of statements
Upvotes: 0
Views: 915
Reputation: 27
Thanks all for your reply. I am able to get the coverage by -coverpkg. Not sure what exactly solved the issue below are couple of changes which worked for me as suggested by @Flimzy 1. Moved REST server Initialization code from main to a function. and then in test case starting the REST server within go routine and gracefully terminating it by sending a message to channel
channel := make(chan error) // create a channel will listen for error
go func(channel chan error) {
inithandler.InitRestServer(channel, )
_ = <-channel // terminate the channel
}(channel)
http.Post("https://localhost/do_something") // call the endpoint and resp verification
.
.
channel <- errors.New("stop")
trigger test with -coverpkg
go test main_test.go -cover -coverpkg ./...
Upvotes: 1
Reputation: 3547
This could not be a complete answer covering all cases.
It's an attempt to explain how it could be possible to get zero coverage from what OP explained.
Tests are passing successfully but go test -cover returns 0% test coverage.
go main()
inside Test
-functionhttp.Post
to service without checks for errors and that response is not nil
http.Post
http.Post
are not checked For first problem:
time.Sleep
after go main()
For second problem:
Take a look at such Test-function:
func TestPost(t *testing.T) {
var b bytes.Buffer
http.Post("http:/inexistent.com/inexistent-url", "", &b)
t.Log("No problems!")
}
This test will always pass. Because it tests non-existense of panics only.
To make this test more correct:
func TestPost(t *testing.T) {
var b bytes.Buffer
if _, err:= http.Post("http:/inexistent.com/inexistent-url", "", &b); err!=nil{
t.Errorf("http.Post : %v", err)
}
http.Post
resultsUpvotes: 1
Reputation: 274
Regardless of the root cause, I think there’s an issue with your general approach here.
I would suggest that some of what you’re testing here isn’t your code and you shouldn’t bother. You don’t need to actually test the http protocol and http package, right?
So the way I’ve handled this in the past is to break apart my the meaningful code that I want to test out of the http handler functions. The http handlers should only be responsible for validating input, calling the actual business logic, and then formatting output.
Once you’ve broken apart your code this way, you can directly call your meaningful functions from your tests. Your http handler functions should be so simple that there is no place for bugs to lurk.
Don’t seek 100% test coverage. Test what matters.
Upvotes: -1