I'm writing a test framework and would like to put examples in my documentation. For maintainability, I'd like to have these examples tested but I can't figure out how.
Ideally, I would like a tested example which looks like:
func TestFoo(t *testing.T) {
f := mytestframework.FromT(t)
// code using f
}
Wrapping the above snippet in func ExampleFoo() { } doesn't work as function definitions can't be nested (this is a syntax error).
I've tried putting this in a separate example_test.go file, however godoc will mistake this for a test file, as according to the go.dev blog, on whole-file examples (emphasis my own):
A whole file example is a file that ends in _test.go and contains exactly one example function, no test or benchmark functions, and at least one other package-level declaration.
I've looked at the docs for Go's doc package, but I couldn't figure out whether this was useful to me.
I could just paste the example as a markdown code block into documentation somewhere, but then this wouldn't be tested and could quietly go out of date in future.
Is there any way to have example tests tested, or at least type-checked?
As designed, the testing package doesn't support executable examples using *testing.T. Currently by definition whole file examples must not include Test* functions.
The best option is simply adding the example code as an indented block to the package or function documentation. This is how the testing package provides example documentation
// Using test framework:
//
// func TestFoo(t *testing.T) {
// framework(t)
// }
Another option would be to use Example functions and declare the test function as an anonymous function
func ExampleTesting() {
_ = func(t *testing.T) {
framework(t)
}
}
Related
In my code there are various types of functions with a lot of user defined parameters and return types. Most of them run in parallel as go routines. In order to be able to efficiently debug them, I want to add labels.
I went through this link on using profile labels, find go routines during debugging.
However, if I do it the way they've mentioned, ie. call the desired function inside pprof.Do, then this would mean that I would have to add this redundant piece of code everywhere.
Old code:
go executeMeAsGoRoutine(arg1 sometype, arg2 sometype)
New Code based on the links above:
go func(args1 type1, args2 type2, args3 type3, args4, type4) {
labels := pprof.Labels("some label", "some more label", "args1",strconv.Itoa(int(100)))
pprof.Do(context.Background(), labels, func(_ context.Context) {
//function that was to be called.
executeMeAsGoRoutine(arg1, arg2, arg3, arg4)// Use args1 or args2
})
}(page, i)
However most of my functions have different arguments and custom return types. If I were to enhance each go routine I will have to repeat the above code everywhere. Wherever, I am calling go runThisFunctionInGoRoutine(), I'll also have to add outer anonymous go routine, followed by pprof.Labels, followed by pprof.Do everywhere. This will lead to a lot of unnecessary code repetiton. There are already so many places where there are different go routines created.
I was hoping if I could make a generic function that would WRAP the go routine creation call as well as label creation and then does pprof.Do for me.
Can someone suggest how to do that? The source of problem is that the functions that should run as go routines are different and have different arguments.
I envision some api like:
makeGoRoutineWithLabel(labels string, functionToRun, argumentsToSupply).
NOTE: functionToRun is different each time with argumentsToSupply being different as well.
Can anyone suggest how to do this without repeating the code? A generic go routine creation wrapper which also provides a provision to add labels along.
Instead of go createGoRoutine, its something like createAGoRoutineWithLabels.
I'm setting up some integration testing, which I'm doing in a separate test package to my src code. This is done to prevent circular dependencies. Unit tests are not stored here, they are stored alongside the files they are testing.
My golang project hierarchy looks like:
cmd
public
...
testing/
main_test.go
database_test.go
in main_test.go, I plan to initialise the connections to external dependencies, such as my test database.
package tests
type Database struct {
...
}
var DB Database
func TestMain(m *testing.M){
SetUpDatabase()
exitCode := m.Run()
os.Exit(exitCode)
}
database_integration_test.go
func Test(t *testing.T) {
tests := []struct {
title string
run func(t *testing.T)
}{
{"should make query", testQuery},
}
for _, test := range tests {
t.Run(test.title, func(t *testing.T) {
test.run(t)
})
}
}
func testQuery(t *testing.T) {
var r result.Result
err := DB.database.DoQuery("").Decode(&r)
if err != nil {
t.Errorf(err.Error())
t.Fatal()
}
}
This setup works when I run it, however, I would like to add build tags to these files, or the type: // +build integration
However, as soon as I use the build tag, the database_integration_test.go file cannot see the initalised Database type. How can I stop this? Also as a side note, should I change the name of main_test.go. I only called it that due to main being the standrd entry point.
Firstly, Regarding this:
Also as a side note, should I change the name of main_test.go. I only
called it that due to main being the standard entry point.
I think it is confusing to name it as main_test.go as it might indicate that you are testing the main function in this file (according to golang convention)
Secondly, Regarding this:
However, as soon as I use the build tag, the
database_integration_test.go file cannot see the initialised Database
type. How can I stop this?
A Build Constraint or also known as Build Tag is used to include or exclude files in a package during a build process. With this, we can build different types of builds from the same source code.
So if you are not seeing the Database Type initialized then most probably the definition of the Database Type and the integration test are tagged with different build tags. Make sure they are present in the same build tags. Also, I think you can use more than one build tag to label a file. So you can try that as well.
For more details on the Build Tags check out the following article by Dave Cheney here
You could simply add a flag to your TestMain:
var isIntegration bool
func init() {
flag.StringVar(&isIntegration, "mytest.integration", "Set flag to set up DB for integration tests")
}
func TestMain(t *testing.M) {
SetUpDatabase(isIntegration)
//etc...
}
Then just simply have the SetUpDatabase call different, unexported, functions based on whether or not the argument is true or false. That'd be a quick way to get the behaviour, without having to much about with custom build constraints. Especially considering you're running tests, not building the application as-such.
As far as renaming main_test.go is concerned: I don't see why you'd need to change it. It does what it says on the tin. When someone else wants to see how the tests are structured/run, or what possible flags have been added, it's a lot easier to just check the directory and look for a main_test.go file (along with init.go, that'd be first file I'd look for). Any other name like setup_integration_test.go, integration_setup_test.go, integration_start_test.go, ... is just going to muddy the waters.
I am doing some web develoment using the go programming language using the package html/template. At some point of the code, I need to call the function template.ParseFiles(...) so I can create a template from those files ad then execute it using temp.Execute(w,data). I would like to know if it is better to create the template on each request or to do it once in the main and declare a global variable.
Right now I do it on each request on my handle functions, like most tutorials do. However, I don't know If I'm wasting resources by doing it on each request instead of having them as global variables.
This is how it looks on each request
func ViewStats(w http.ResponseWriter, r *http.Request) {
//Get stuff from db and put them in data
//...
//return data to user
tmp, err := template.ParseFiles("views/guest-layout.html",
"views/stats.html")
if err != nil {
fmt.Println(err)
} else {
tmp.Execute(w,data)
}
}
I would like to know if this is better:
var temp1 template.Template
func main() {
temp1, err = template.ParseFiles("file1","file2")
//...
}
As usual: It depends.
But first some nuance:
You should never do template parsing (or anything else interesting) in your main() function. Instead, your main() function should call methods (or a single method) that kicks off the chain of interesting things in your program.
Go doesn't have globals, so it's not actually an option to store your parsed templates in a global variable in the first place. The closest Go has to global variables is package variables. You could store your parsed templates in a package variable in the main package, but this is also bad form, as your main package (except for tiny, trivial programs), should just be an entry point, and otherwise nearly empty.
But now, on to the core of your question:
Should you parse templates per request, or per run?
And here it depends.
If you have templates that change frequently (i.e. during development, when you're constantly editing your HTML files), once per request can be best.
But this is far less efficient than just parsing once, so in production, you may wish to parse the templates once on startup only. Then you can store the templates in a package variable, or better, in a struct that is initialized at runtime. But I leave that to you.
But what may be best is actually a bit of a compromise between the two approaches. It may be best to load your templates at start-up, and re-load them occasionally, either automatically (say, every 5 minutes), or watch your filesystem, and reload them whenever the on-disk representation of the templates changes.
How to do this is left as an exercise for the reader.
I'm trying to do something that seems like it should be trivial until I read up and now it seems like it should be really complex. ;-)
I've knocked up a test pattern to illustrate:
http://play.golang.org/p/Re88vJZvPT
At the most basic I'm trying to have a function that can read data from a channel and spit it out on another one. Easy. The test does this as long as you use the pusher function shown.
However the problem with this is that doing it this way I would need a different pusher function for each type of data I want to push through it.
Now I've done similar things in the past with an empty interface as nothing in the pusher code cares about what's in the data structure. What I can't figure out is when I'm dealing with channels of an un-cared-about data structure.
To illustrate the concept of what I'm trying to achieve please see the function pusher_naive_generic.
However that doesn't work either so more reading up implied the way to do it was making use of reflection and finally you see my pusher_reflect_generic function(obviously this won't achieve the same intended function as the others it's showing where I got to before getting stuck).
Which still fails because I can't get from an interface that contains a chan to the structure read from that chan.
Hopefully the code makes more sense of what I'm trying to achieve than my words actually do. I can make all of this work by explicitly coding for every type, but what I can't figure out how to do is code it for any future type.
If I have understood your question correctly, then this might be the solution:
http://play.golang.org/p/xiDO7xkoW4
func forwardChannel(i interface{}, o interface{}) {
it, ot := reflect.TypeOf(i), reflect.TypeOf(o)
if it != ot {
panic("forwardChannel: both arguments must be of the same type")
}
iv, ov := reflect.ValueOf(i), reflect.ValueOf(o)
for {
v, k := iv.Recv()
if !k {
break
}
ov.Send(v)
}
ov.Close()
}
Note that Recv, Send and Close panic if i and o are not channels.
I am essentially trying to walk through a folder of html files. I want to embed them into the binary file and be able to parse them upon request for template execution purposes. (Please excuse me if im not wording this properly).
Any ideas, tips, tricks or better way of accomplishing this is much appreciated.
// Template Files
type TempFiles struct {
Files map[string]string
}
// Loop through view files and load them
func LoadTempFiles() {
t := new(TempFiles)
// Load template files
filepath.Walk("application/views", func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
content, _ := ioutil.ReadFile(path)
t.Files[path] = string(content)
}
return nil
})
}
func ViewTemp(w http.ResponseWriter, path string) {
t := new(TempFiles)
temp, err := template.New().Parse(t.Files[path])
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
temp.Execute(w, nil)
}
}
I do this with most of my Go web apps. I use go-bindata to auto-generate Go source code from all the files I want to embed and then compile them into the binary.
All this is done automatically during build.
One downside is that the current go build tools do not offer a way to hook into the build process, so I use a Makefile for this purpose. When the makefile is invoked, it runs go-bindata to generate the sources for all necessary files, then usually performs some additional code generation bits and bobs (notably, creating a Go source file which lists all the embedded files in a map.. A Table of Contents if you will). It then proceeds to compile the actual program.
This can become a little messy, but you only have to set it all up once.
Another downside, is that the use of a Makefile means the software is not compatible with the go get command. But since most of my web apps are not meant to be shared anyway, this has not been a problem so far.
When it comes to debugging/developing such an application, there is another issue that arises from embedding the static web content: I can't just edit an HTML or CSS file and refresh the browser to see its effects. I would have to stop the server, rebuild it and restart it with every edit. This is obviously not ideal, so I split the Makefile up into a debug and release mode. The release mode does what I described above. The debug mode, however, wil not actually embed the static files. It does generate source files for each of them, but instead of having them contain the actual file data, it contains a stub which simply loads the data from the filesystem.
As far as the server code is concerned, there is no difference in the generated code. All it does is call a function to fetch the contents of a given static file. It does not care whether that content is actually embedded in the binary, or if it's loaded from an external source. So the two build modes are freely interchangeable.
For example, the same generated function to fetch static file content in release and debug mode would look as follows:
Release mode:
func index_html() []byte {
return []byte {
....
}
}
Debug mode:
func index_html() []byte {
data, err := ioutil.ReadFile("index.html")
...
return data
}
The interface in both cases is identical. This allows for easy and care-free development and debugging.
Another tool to consider: Another recent good tool comes from esc: Embedding Static Assets in Go (GitHub repo)
a program that:
can take some directories and recursively embed all files in them in a way that was compatible with http.FileSystem
can optionally be disabled for use with the local file system for local development
will not change the output file on subsequent runs
has reasonable-sized diffs when files changed
is vendoring-friendly
Vendoring-friendly means that when I run godep or party, the static embed file will not change.
This means it must not have any third-party imports (since their import path will be rewritten during goimports, and thus different than what the tool itself produces), or a specifiable location for the needed third-party imports.
It generates nice, gzipped strings, one per file.
There is a simple flag to enable local development mode, which is smart enough to not strip directory prefixes off of filenames (an option in esc that is sometimes needed).
The output includes all needed code, and does not depend on any third-party libraries for compatibility with http.FileSystem.
I made a package that makes switching between debug and production easier. It also provides an http.FileSystem implementation, making it easy to server the files. And it has several ways of adding the files to the binary (generate go code, or append as zip).
https://github.com/GeertJohan/go.rice
Go now has builtin support for this:
package main
import (
"embed"
"os"
)
//go:embed *.html
var content embed.FS
func main() {
b, e := content.ReadFile("index.html")
if e != nil {
panic(e)
}
os.Stdout.Write(b)
}
https://golang.org/pkg/embed