mirror of
https://github.com/golang/go
synced 2024-11-18 11:14:39 -07:00
cmd/go, testing: streamline direct use of test binaries
Before: $ go test -c -cover fmt $ ./fmt.test -test.covermode=set PASS coverage: 65.1% of statements in strconv $ After: $ go test -c -cover fmt $ ./fmt.test PASS coverage: 65.1% of statements in strconv $ In addition to being cumbersome, the old flag didn't make sense: the cover mode cannot be changed after the binary has been built. Another useful effect of this CL is that if you happen to do $ go test -c -covermode=atomic fmt and then forget you did that and run benchmarks, the final line of the output (the coverage summary) reminds you that you are benchmarking with coverage enabled, which might not be what you want. $ ./fmt.test -test.bench . PASS BenchmarkSprintfEmpty 10000000 217 ns/op BenchmarkSprintfString 2000000 755 ns/op BenchmarkSprintfInt 2000000 774 ns/op BenchmarkSprintfIntInt 1000000 1363 ns/op BenchmarkSprintfPrefixedInt 1000000 1501 ns/op BenchmarkSprintfFloat 1000000 1257 ns/op BenchmarkManyArgs 500000 5346 ns/op BenchmarkScanInts 1000 2562402 ns/op BenchmarkScanRecursiveInt 500 3189457 ns/op coverage: 91.4% of statements $ As part of passing the new mode setting in via _testmain.go, merge the two registration mechanisms into one extensible mechanism (a struct). R=r CC=golang-dev https://golang.org/cl/11219043
This commit is contained in:
parent
4419d7e53c
commit
ccc4553491
@ -744,7 +744,6 @@ control the execution of any test:
|
||||
|
||||
-cover
|
||||
Enable coverage analysis.
|
||||
TODO: This feature is not yet fully implemented.
|
||||
|
||||
-covermode set,count,atomic
|
||||
Set the mode for coverage analysis for the package[s]
|
||||
@ -754,18 +753,18 @@ control the execution of any test:
|
||||
count: int: how many times does this statement run?
|
||||
atomic: int: count, but correct in multithreaded tests;
|
||||
significantly more expensive.
|
||||
Implies -cover.
|
||||
Sets -cover.
|
||||
|
||||
-coverpkg pkg1,pkg2,pkg3
|
||||
Apply coverage analysis in each test to the given list of packages.
|
||||
If this option is not present, each test applies coverage analysis to
|
||||
the package being tested. Packages are specified as import paths.
|
||||
Implies -cover.
|
||||
The default is for each test to analyze only the package being tested.
|
||||
Packages are specified as import paths.
|
||||
Sets -cover.
|
||||
|
||||
-coverprofile cover.out
|
||||
Write a coverage profile to the specified file after all tests
|
||||
have passed.
|
||||
Implies -cover.
|
||||
Sets -cover.
|
||||
|
||||
-cpu 1,2,4
|
||||
Specify a list of GOMAXPROCS values for which the tests or
|
||||
|
@ -139,18 +139,18 @@ control the execution of any test:
|
||||
count: int: how many times does this statement run?
|
||||
atomic: int: count, but correct in multithreaded tests;
|
||||
significantly more expensive.
|
||||
Implies -cover.
|
||||
Sets -cover.
|
||||
|
||||
-coverpkg pkg1,pkg2,pkg3
|
||||
Apply coverage analysis in each test to the given list of packages.
|
||||
The default is for each test to analyze only the package being tested.
|
||||
Packages are specified as import paths.
|
||||
Implies -cover.
|
||||
Sets -cover.
|
||||
|
||||
-coverprofile cover.out
|
||||
Write a coverage profile to the specified file after all tests
|
||||
have passed.
|
||||
Implies -cover.
|
||||
Sets -cover.
|
||||
|
||||
-cpu 1,2,4
|
||||
Specify a list of GOMAXPROCS values for which the tests or
|
||||
@ -1040,6 +1040,10 @@ type testFuncs struct {
|
||||
Cover []coverInfo
|
||||
}
|
||||
|
||||
func (t *testFuncs) CoverMode() string {
|
||||
return testCoverMode
|
||||
}
|
||||
|
||||
func (t *testFuncs) CoverEnabled() bool {
|
||||
return testCover
|
||||
}
|
||||
@ -1201,8 +1205,12 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts
|
||||
|
||||
func main() {
|
||||
{{if .CoverEnabled}}
|
||||
testing.CoveredPackage({{printf "%q" .Tested}}, {{printf "%q" .Covered}})
|
||||
testing.RegisterCover(coverCounters, coverBlocks)
|
||||
testing.RegisterCover(testing.Cover{
|
||||
Mode: {{printf "%q" .CoverMode}},
|
||||
Counters: coverCounters,
|
||||
Blocks: coverBlocks,
|
||||
CoveredPackages: {{printf "%q" .Covered}},
|
||||
})
|
||||
{{end}}
|
||||
testing.Main(matchString, tests, benchmarks, examples)
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ var usageMessage = `Usage of go test:
|
||||
-benchmem=false: print memory allocation statistics for benchmarks
|
||||
-benchtime=1s: passes -test.benchtime to test
|
||||
-cover=false: enable coverage analysis
|
||||
-covermode="set": passes -test.covermode to test if -cover
|
||||
-covermode="set": specifies mode for coverage analysis
|
||||
-coverpkg="": comma-separated list of packages for coverage analysis
|
||||
-coverprofile="": passes -test.coverprofile to test if -cover
|
||||
-cpu="": passes -test.cpu to test
|
||||
@ -115,6 +115,7 @@ var testFlagDefn = []*testFlagSpec{
|
||||
func testFlags(args []string) (packageNames, passToTest []string) {
|
||||
inPkg := false
|
||||
outputDir := ""
|
||||
testCoverMode = "set"
|
||||
for i := 0; i < len(args); i++ {
|
||||
if !strings.HasPrefix(args[i], "-") {
|
||||
if !inPkg && packageNames == nil {
|
||||
@ -208,12 +209,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
|
||||
passToTest = append(passToTest, "-test."+f.name+"="+value)
|
||||
}
|
||||
}
|
||||
if testCover {
|
||||
if testCoverMode == "" {
|
||||
testCoverMode = "set"
|
||||
}
|
||||
passToTest = append(passToTest, "-test.covermode", testCoverMode)
|
||||
}
|
||||
|
||||
// Tell the test what directory we're running in, so it can write the profiles there.
|
||||
if testProfile && outputDir == "" {
|
||||
dir, err := os.Getwd()
|
||||
|
@ -22,30 +22,23 @@ type CoverBlock struct {
|
||||
Stmts uint16
|
||||
}
|
||||
|
||||
var (
|
||||
coverCounters map[string][]uint32
|
||||
coverBlocks map[string][]CoverBlock
|
||||
)
|
||||
var cover Cover
|
||||
|
||||
var (
|
||||
testedPackage string // The package being tested.
|
||||
coveredPackage string // List of the package[s] being covered, if distinct from the tested package.
|
||||
)
|
||||
|
||||
// RegisterCover records the coverage data accumulators for the tests.
|
||||
// Cover records information about test coverage checking.
|
||||
// NOTE: This struct is internal to the testing infrastructure and may change.
|
||||
// It is not covered (yet) by the Go 1 compatibility guidelines.
|
||||
func RegisterCover(c map[string][]uint32, b map[string][]CoverBlock) {
|
||||
coverCounters = c
|
||||
coverBlocks = b
|
||||
type Cover struct {
|
||||
Mode string
|
||||
Counters map[string][]uint32
|
||||
Blocks map[string][]CoverBlock
|
||||
CoveredPackages string
|
||||
}
|
||||
|
||||
// CoveredPackage records the names of the packages being tested and covered.
|
||||
// RegisterCover records the coverage data accumulators for the tests.
|
||||
// NOTE: This function is internal to the testing infrastructure and may change.
|
||||
// It is not covered (yet) by the Go 1 compatibility guidelines.
|
||||
func CoveredPackage(tested, covered string) {
|
||||
testedPackage = tested
|
||||
coveredPackage = covered
|
||||
func RegisterCover(c Cover) {
|
||||
cover = c
|
||||
}
|
||||
|
||||
// mustBeNil checks the error and, if present, reports it and exits.
|
||||
@ -63,13 +56,13 @@ func coverReport() {
|
||||
if *coverProfile != "" {
|
||||
f, err = os.Create(toOutputDir(*coverProfile))
|
||||
mustBeNil(err)
|
||||
fmt.Fprintf(f, "mode: %s\n", *coverMode)
|
||||
fmt.Fprintf(f, "mode: %s\n", cover.Mode)
|
||||
defer func() { mustBeNil(f.Close()) }()
|
||||
}
|
||||
|
||||
var active, total int64
|
||||
for name, counts := range coverCounters {
|
||||
blocks := coverBlocks[name]
|
||||
for name, counts := range cover.Counters {
|
||||
blocks := cover.Blocks[name]
|
||||
for i, count := range counts {
|
||||
stmts := int64(blocks[i].Stmts)
|
||||
total += stmts
|
||||
@ -89,5 +82,5 @@ func coverReport() {
|
||||
if total == 0 {
|
||||
total = 1
|
||||
}
|
||||
fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), coveredPackage)
|
||||
fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
|
||||
}
|
||||
|
@ -122,8 +122,7 @@ var (
|
||||
|
||||
// Report as tests are run; default is silent for success.
|
||||
chatty = flag.Bool("test.v", false, "verbose: print additional output")
|
||||
coverMode = flag.String("test.covermode", "", "cover mode: set, count, atomic; default is none")
|
||||
coverProfile = flag.String("test.coverprofile", "", "write a coveraage profile to the named file after execution")
|
||||
coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
|
||||
match = flag.String("test.run", "", "regular expression to select tests and examples to run")
|
||||
memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
|
||||
memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
|
||||
@ -489,6 +488,10 @@ func before() {
|
||||
if *blockProfile != "" && *blockProfileRate >= 0 {
|
||||
runtime.SetBlockProfileRate(*blockProfileRate)
|
||||
}
|
||||
if *coverProfile != "" && cover.Mode == "" {
|
||||
fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
// after runs after all testing.
|
||||
@ -520,7 +523,7 @@ func after() {
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
if *coverMode != "" {
|
||||
if cover.Mode != "" {
|
||||
coverReport()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user