FAQ
Dear Gophers,

I've run into a weird problem with my integration test. My integration
tests are obviously very domain specific but ill try to explain what
happens, Each test basicly looks like the following (pseudo code):

Test case(s):
func TestInstallHook(t *testing.T) {

         // This creates a temporary database session (mgo)
         db, clean := sh.TempMongo(t, "", "test")

         //this closes the database session and empties the collections
defer clean("user", "project")

         <inserts some test data into mongodb>

         //this creates a 'controller', that is a struct with several
http.Handlerfunc functions and holds a
         //dedicated (goji) mux
c := NewController(db, <other dependencies>)

         //the following creates a request, and calls the mux with the
request with a new httptest recorder
rec := AssertPOST(t, c.Mux(), <assertions> )


         <finally assert the data in the database>
}

AssertPost calls the HandlerFunc like this:
// web.Handler implements the http.Handler interface
func AssertRequestResponse(t *testing.T, mux web.Handler, r *http.Request) {
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, r)

         <assertion code>
}



The controller just does some basic database operations using the mgo
session that was pass in as a dependency:
func (ctrl *Controller) InstallHook(c web.C, w http.ResponseWriter, r
*http.Request) {

         data := <deserialize request body>

err := ctrl.DB.C("project").UpdateId(p.Id, bson.M{"$set":
bson.M{"hookedto": data.url}})

         <error handling, serialization and response writing>

}


So the thing that seems to be happening is that when I increase the number
test that run the .*clean()* method (that empties the collections and
closes the test session) -- of some other test - is run while another test
case is still reading from the database. Hence, sometimes tests randomly
fail (because data that should be there isn't)

Hints:
- If I comment the clean method the problem goes away (obvious, since data
is no longer removed from the db)
- The more tests I run the greater the chance (i.e go test ./... instead of
go test ./hook_ctrl)
- The longer the controller takes to create its requests the bigger the
chance this happens
- I get no weird errors from my mongodb

Considering these hints it seems to be that the tests are racing for
database data... But I cant figure out why this happens:
- Tests aren't run in parallel by default right?
- As far as i can tell there are no go-routines involved whatsoever (at
least in my domain code)
- Tests might run quicker then mongodb could handle but shouldn't the
driver (and thus the test) wait for the database queries to complete?

Hopefully someone might provide me with some hints. Even if its just hints
towards a way of debugging this better.

Kind regards,

Ad van der Veer



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Advanderveer at Aug 31, 2014 at 7:18 am
    Although I didn't manage to find prove in the Go CMD source code (If
    someone can confirm this would be great) it seems that the individual test
    binaries that are created for each package may run simultaneously (in
    different threads?). So if your integration tests are dependant on a
    resource of which its state is outside the compiled code it may cause race
    conditions. So in my case I could create separate databases for each tested
    package or make sure the tests always run after each other by using some
    shell script that looks like:

    go test ./package_a
    go test ./package_b
    go test ./package_c

    I went with this option as it was the quickest to implement


    On Friday, August 29, 2014 7:00:46 PM UTC+2, advand...@gmail.com wrote:

    Dear Gophers,

    I've run into a weird problem with my integration test. My integration
    tests are obviously very domain specific but ill try to explain what
    happens, Each test basicly looks like the following (pseudo code):

    Test case(s):
    func TestInstallHook(t *testing.T) {

    // This creates a temporary database session (mgo)
    db, clean := sh.TempMongo(t, "", "test")

    //this closes the database session and empties the collections
    defer clean("user", "project")

    <inserts some test data into mongodb>

    //this creates a 'controller', that is a struct with several
    http.Handlerfunc functions and holds a
    //dedicated (goji) mux
    c := NewController(db, <other dependencies>)

    //the following creates a request, and calls the mux with the
    request with a new httptest recorder
    rec := AssertPOST(t, c.Mux(), <assertions> )


    <finally assert the data in the database>
    }

    AssertPost calls the HandlerFunc like this:
    // web.Handler implements the http.Handler interface
    func AssertRequestResponse(t *testing.T, mux web.Handler, r *http.Request)
    {
    rec := httptest.NewRecorder()
    mux.ServeHTTP(rec, r)

    <assertion code>
    }



    The controller just does some basic database operations using the mgo
    session that was pass in as a dependency:
    func (ctrl *Controller) InstallHook(c web.C, w http.ResponseWriter, r
    *http.Request) {

    data := <deserialize request body>

    err := ctrl.DB.C("project").UpdateId(p.Id, bson.M{"$set":
    bson.M{"hookedto": data.url}})

    <error handling, serialization and response writing>

    }


    So the thing that seems to be happening is that when I increase the number
    test that run the .*clean()* method (that empties the collections and
    closes the test session) -- of some other test - is run while another test
    case is still reading from the database. Hence, sometimes tests randomly
    fail (because data that should be there isn't)

    Hints:
    - If I comment the clean method the problem goes away (obvious, since data
    is no longer removed from the db)
    - The more tests I run the greater the chance (i.e go test ./... instead
    of go test ./hook_ctrl)
    - The longer the controller takes to create its requests the bigger the
    chance this happens
    - I get no weird errors from my mongodb

    Considering these hints it seems to be that the tests are racing for
    database data... But I cant figure out why this happens:
    - Tests aren't run in parallel by default right?
    - As far as i can tell there are no go-routines involved whatsoever (at
    least in my domain code)
    - Tests might run quicker then mongodb could handle but shouldn't the
    driver (and thus the test) wait for the database queries to complete?

    Hopefully someone might provide me with some hints. Even if its just hints
    towards a way of debugging this better.

    Kind regards,

    Ad van der Veer


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Advanderveer at Sep 1, 2014 at 7:11 am
    Wow, thank you for providing the definite answer! I didn't expect the
    parral flag of the build to effect the parallel nature of running the tests.
    On Sunday, August 31, 2014 4:25:54 PM UTC+2, rjeczalik wrote:
    On 31 August 2014 09:16, <advand...@gmail.com <javascript:>> wrote:

    Although I didn't manage to find prove in the Go CMD source code (If
    someone can confirm this would be great) it seems that the individual test
    binaries that are created for each package may run simultaneously (in
    different threads?).

    Your tests are being executed in:

    http://golang.org/src/cmd/go/test.go#L513

    And run in parallel by:

    http://golang.org/src/cmd/go/build.go#L736

    Depending on the value of -parallel flag, which by default is set to:

    http://golang.org/src/cmd/go/build.go#L122

    Basing on the above you could simplify your build rules from:
    go test ./package_a
    go test ./package_b
    go test ./package_c

    I went with this option as it was the quickest to implement
    to

    go test -p 1 ./...

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedAug 29, '14 at 5:00p
activeSep 1, '14 at 7:11a
posts3
users1
websitegolang.org

1 user in discussion

Advanderveer: 3 posts

People

Translate

site design / logo © 2022 Grokbase