Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_helpers.go should be named helpers_test.go #580

Closed
tebeka opened this issue Apr 7, 2016 · 20 comments
Closed

test_helpers.go should be named helpers_test.go #580

tebeka opened this issue Apr 7, 2016 · 20 comments
Assignees
Labels

Comments

@tebeka
Copy link
Contributor

tebeka commented Apr 7, 2016

test_helpers.go is built with the package. It should be built only when testing which means it should have the suffix _test.go. One side effect is that is that by test_helpers.go using httptest every program that uses gin gets -httptest.serve flag.

package main

import (
    "flag"
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    rtr := gin.Default()
    rtr.GET("/", func(ctx *gin.Context) {
        ctx.String(http.StatusOK, "Hi")
    })
    flag.Parse()
    rtr.Run(":8080")
}

Now run the program with --help and you'll see:

$ go run /tmp/t.go --help
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /                         --> main.main.func1 (3 handlers)
Usage of /tmp/go-build903640301/command-line-arguments/_obj/exe/t:
  -httptest.serve string
        if non-empty, httptest.NewServer serves on this address and blocks
exit status 2
$
@javierprovecho
Copy link
Member

@tebeka thank you for noticing this, merging #581

javierprovecho added a commit that referenced this issue Apr 9, 2016
Rename to conform with test files naming (closes #580)
@roylou
Copy link
Contributor

roylou commented Apr 13, 2016

There's a need to name it as test_helpers.go not helpers_test.go. Unit test on a package using gin will need to create test context. By renaming it to helpers_test.go CreateTestContext() becomes private.

Since CreateTestContext() refers to private methods, package user now can't create his own test context.

@javierprovecho
Copy link
Member

@roylou i didn't know that, there is any resource I can check?

By renaming it to helpers_test.go CreateTestContext() becomes private.

Even when the first letter of the function name is capital?

@roylou
Copy link
Contributor

roylou commented Apr 14, 2016

@javierprovecho unfortunately I couldn't find any web resource. This is by self exploration.

If you run "go test" of the following foo_test.go:

package foo

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

func TestCreateContext() {
    c, w, r := gin.CreateTestContext()
    fmt.Println(c, w, r)
}

It'll complain
./foo_test.go:9: undefined: gin.CreateTestContext

@tebeka
Copy link
Contributor Author

tebeka commented Apr 15, 2016

Maybe move this to "github.com/gin-gonic/gin/test" package then? This way people will be able to use it in testing but it won't show up by application code using gin?

@roylou
Copy link
Contributor

roylou commented Apr 15, 2016

This unfortunately won't work. CreateTestContext() invokes some of gin's private function. Putting it out of github.com/gin-gonic/gin will block private function accessibility.

I think exposing -httptest.serve flag is a worthy trade-off given today's golang rule. Your program already shows 100+ flags depending on the number of third-party libs. 90% of them you don't really care. Adding a test flag into those 90% isn't ideal but tolerable to me.

@tebeka
Copy link
Contributor Author

tebeka commented Apr 15, 2016

I disagree. I think we should find a cleaner API and make it work.

@alienscience
Copy link

The merge of #581 has broken a my tests because they relied on CreateTestContext(). Is there a workaround?

alienscience added a commit to alienscience/gin that referenced this issue Apr 16, 2016
This reverts commit 2fd607b.

CreateTestContext() should work again
@roylou
Copy link
Contributor

roylou commented Apr 17, 2016

Seems there's trade off between API cleanness and testibility. Please let me know if there's better way to maintain testibility. Without CreateTestContext(), I'll need to really start a fake http server instead of testing against my gin router function.

@nickmiller-wf
Copy link

I too am missing the existence of this function. The fact that gin handlers only need to take a Context is part of what attracted me to it. The lack of an easy way to create a context for testing purposes seems like a regression to me.

@alienscience
Copy link

alienscience commented Aug 17, 2016

I am guessing from the lack of interest in this issue, that application code that uses gin remains untestable?

@tebeka
Copy link
Contributor Author

tebeka commented Aug 17, 2016

IMO we should revert to the old state where CreateTestContext is exposed until we find a better/cleaner way to do it. Any objections?

@alienscience
Copy link

That would be good for me - thanks.

@tebeka
Copy link
Contributor Author

tebeka commented Aug 18, 2016

Created #688

@andreynering
Copy link
Contributor

You can use gin's ServeHTTP function to simulate a request:

func getGinRouter() *gin.Engine {
    r := gin.Default()
    r.Post("/", func (c *gin.Context) { c.String(200, "Hello") })
    return r
}

func newTestContext(method, path string) (w *httptest.ResponseRecorder, r *http.Request) {
    w = httptest.NewRecorder()
    r, _ = http.NewRequest(method, path, nil)
    r.PostForm = url.Values{}
    return
}

func TestIndex(t *testing.T) {
    w, r := newTestContext("POST", "/")
    r.PostForm.Add("a_param", "a_value")
    getGinRouter().ServeHTTP(w, r)
    assert.Equal(t, 200, w.Code)
    assert.Equal(t, "Hello", w.Body.String())
}

I only miss the ability to access gin's context inside my tests. Otherwise, it works very well.

A section about how to write tests with Gin would be important for new users.

@yehezkielbs
Copy link

yehezkielbs commented Sep 20, 2016

Why not make CreateTestContext() to receive a http.ResponseWriter object?

func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) {
    r = New()
    c = r.allocateContext()
    c.reset()
    c.writermem.reset(w)
    return
}

When testing, create a new httptest.NewRecorder() and pass it to CreateTestContext()

w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)

This means test_helpers.go doesn't need to import net/http/httptest

@yehezkielbs
Copy link

Please consider the PR #707

@xiaods
Copy link

xiaods commented Nov 8, 2016

any update on it? need this exported func CreateTestContext

@jonmchan
Copy link

jonmchan commented Nov 15, 2016

I also need CreateTestContext to test my handler independent of the http router/application. Any updates?

@appleboy
Copy link
Member

appleboy commented Dec 5, 2016

Hi all, already fixed by #707

@appleboy appleboy closed this as completed Dec 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants