rillig / gobco

Measure branch coverage of golang tests
62 stars 12 forks source link

Allow for user defined TestMain() #4

Closed KantarBruceAdams closed 5 years ago

KantarBruceAdams commented 5 years ago

If a user defines their own TestMain then gobco fails with:

multiple definitions of TestMain

I notice that writeGobcoTestGo() creates a gobco_test.go whose sole purpose is to add the running of gobcoPrintCoverage(@listAll@)

I think this is okay but some allowance is needed for the case where a user defines their own test main. Perhaps we require a go:generate to generate the call to gobcoPrintCoverage() in there test main and/or have a build flag (e.g. / +build gobco) to distinguish running under gobco from normal go test as both should work.

For example if I have:

package main

import (
    "flag"
    "os"
    "testing"
)

func TestMain(m *testing.M) {
    CmdLineVerbose = flag.Bool("verbose", false, "verbosity of tests")
    flag.Parse()
    os.Exit(m.Run())
}

As a workaround I could have my TestMain in a file by itself (main_test.go) as in:


// +build !gobco

package main

import (
    "flag"
    "os"
    "testing"
)

func TestMain(m *testing.M) {
    flag.Parse()
    os.Exit(m.Run())
}

With a separate file (e.g. flags_test.go) for things which would otherwise be in TestMain() for example:

package main

import (
    "flag"
)

var CmdLineVerbose *bool

func init() {
    CmdLineVerbose = flag.Bool("verbose", false, "verbosity of tests")
}

and then run gobco -tags gobco

I don't find this solution particularly elegant. This might break for a more complicated TestMain()

An alternative might be for gobco to have an option to not generate its own TestMain but instead to provide a hook via //go:generate or something similar.

rillig commented 5 years ago

What if gobco simply inserted its function call as the very first statement of the existing TestMain? That should work for all cases I can imagine right now. Since gobco rewrites the existing code anyway, this is not a big deal.

KantarBruceAdams commented 5 years ago

That sounds like the right way to go, except it should be last statement as later statements may be invoking tests.

rillig commented 5 years ago

In the end I decided to inspect the code of the existing TestMain function and to rewrite it a bit.

The most common TestMain implementations call os.Exit directly, and right before this call happens, gobco persists the coverage data. I expect this to be the right solution for most practical cases.

Please have a look whether it meets your requirements.

KantarBruceAdams commented 2 years ago

Returning to this after a long time yes your implemention works as required