Let's Go Testing › Profiling test coverage
Previous · Contents · Next
Chapter 14.8.

Profiling test coverage

A great feature of the go test tool is the metrics and visualizations that it provides for test coverage.

Go ahead and try running the tests in our project using the -cover flag like so:

$ go test -cover ./...
ok  	snippetbox.alexedwards.net/cmd/web	0.022s	coverage: 46.1% of statements
?   	snippetbox.alexedwards.net/internal/assert	[no test files]
ok  	snippetbox.alexedwards.net/internal/models	1.081s	coverage: 6.5% of statements
?   	snippetbox.alexedwards.net/internal/models/mocks	[no test files]
?   	snippetbox.alexedwards.net/internal/validator	[no test files]
?   	snippetbox.alexedwards.net/ui	[no test files]

From the results here we can see that 46.1% of the statements in our cmd/web package are executed during our tests, and for our internal/models package the figure is 6.5%.

We can get a more detailed breakdown of test coverage by method and function by using the -coverprofile flag like so:

$ go test -coverprofile=/tmp/profile.out ./...

This will execute your tests as normal and — if all your tests pass — it will then write a coverage profile to a specific location (in our case /tmp/profile.out).

You can then view the coverage profile by using the go tool cover command like so:

$ go tool cover -func=/tmp/profile.out
snippetbox.alexedwards.net/cmd/web/handlers.go:15:		    home			        0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:31:		    snippetView		        92.9%
snippetbox.alexedwards.net/cmd/web/handlers.go:56:		    snippetCreate		    0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:82:		    snippetCreatePost	    0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:126:		    userSignup		        100.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:132:		    userSignupPost		    88.5%
snippetbox.alexedwards.net/cmd/web/handlers.go:192:		    userLogin		        0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:198:		    userLoginPost		    0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:256:		    userLogoutPost		    0.0%
snippetbox.alexedwards.net/cmd/web/handlers.go:277:		    ping			        100.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:17:		    serverError		        0.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:27:		    clientError		        100.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:34:		    notFound		        100.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:38:		    newTemplateData		    100.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:47:		    render			        58.3%
snippetbox.alexedwards.net/cmd/web/helpers.go:79:		    decodePostForm		    50.0%
snippetbox.alexedwards.net/cmd/web/helpers.go:108:		    isAuthenticated		    75.0%
snippetbox.alexedwards.net/cmd/web/main.go:31:			    main			        0.0%
snippetbox.alexedwards.net/cmd/web/main.go:95:			    openDB			        0.0%
snippetbox.alexedwards.net/cmd/web/middleware.go:11:		secureHeaders		    100.0%
snippetbox.alexedwards.net/cmd/web/middleware.go:27:		logRequest		        100.0%
snippetbox.alexedwards.net/cmd/web/middleware.go:35:		recoverPanic		    66.7%
snippetbox.alexedwards.net/cmd/web/middleware.go:55:		requireAuthentication	16.7%
snippetbox.alexedwards.net/cmd/web/middleware.go:78:		noSurf			        100.0%
snippetbox.alexedwards.net/cmd/web/middleware.go:90:		authenticate		    38.5%
snippetbox.alexedwards.net/cmd/web/routes.go:12:		    routes			        100.0%
snippetbox.alexedwards.net/cmd/web/templates.go:23:		    humanDate		        100.0%
snippetbox.alexedwards.net/cmd/web/templates.go:40:		    newTemplateCache	    83.3%
snippetbox.alexedwards.net/internal/models/snippets.go:31:	Insert			        0.0%
snippetbox.alexedwards.net/internal/models/snippets.go:61:	Get			            0.0%
snippetbox.alexedwards.net/internal/models/snippets.go:98:	Latest			        0.0%
snippetbox.alexedwards.net/internal/models/users.go:36:		Insert			        0.0%
snippetbox.alexedwards.net/internal/models/users.go:68:		Authenticate		    0.0%
snippetbox.alexedwards.net/internal/models/users.go:100:	Exists			        100.0%
total:								                        (statements)		    38.1%

An alternative and more visual way to view the coverage profile is to use the -html flag instead of -func.

$ go tool cover -html=/tmp/profile.out

This will open a browser window containing a navigable and highlighted representation of your code, similar to this:

14.08-01.png

It’s easy to see exactly which statements get executed during your tests (colored green) and which are not (highlighted red).

You can take this a step further and use the -covermode=count option when running go test like so:

$ go test -covermode=count -coverprofile=/tmp/profile.out ./...
$ go tool cover -html=/tmp/profile.out

Instead of just highlighting the statements in green and red, using -covermode=count makes the coverage profile record the exact number of times that each statement is executed during the tests.

When viewed in the browser, statements which are executed more frequently are then shown in a more saturated shade of green, similar to this:

14.08-02.png