Skip to content

Integration test code coverage: Add support for merging additional coverage files that were created before the test run completed.  #3611

@saborrie

Description

@saborrie

Is your feature request related to a problem? Please describe.
As well as unit tests, my Go applications will often have a few integration tests that don't call functions from my package, but instead build it into a binary and then execute the binary. I would like these tests to be picked up by vscode-go for reporting and displaying code coverage

Describe the solution you'd like
Go has support in go build to add the -cover option, which will create binaries that report coverage based on the GOCOVERDIR environment variable. Integration tests would create this as an additional coverage file, rather than being added to the one output from the test run itself, which is triggered by vscode-go.

I would like vscode-go to include an additional option such as go.additionalCoverageFiles. I could set this option to a directory such as /tmp/my_go_integration_test_coverage, and then vscode-go can look in that directory after each test run for additonal coverage files, and if found merge them into the main coverage file that was output by the test run.

Describe alternatives you've considered
I have tried to do the merge myself, such as in TestMain, but the main coverage file doesn't exist until after the tests exit, to there is nothing to merge.

Example

// main.go
package main

import (
	"os"
	"fmt"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Please provide a command")
		os.Exit(1) // we can't unit test this behaviour because it exits, an exit causes unit tests to fail
	}
	fmt.Println("Ok")
}
// main_test.go
package main_test

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"testing"
)

var binaryName = "/tmp/my_go_binary_for_integration_testing"
var coverageDir = "/tmp/my_go_integration_test_coverage"

func TestMain(m *testing.M) {
	cmd := exec.Command("go", "build", "-cover",  "-o", binaryName, "./main.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		fmt.Printf("failed to build binary: %v", err)
		os.Exit(1)
	}

	exitCode := m.Run()

	os.Remove(binaryName)

	os.Exit(exitCode)
}

func TestShouldExitWithCode1WhenNoArgProvided(t *testing.T) {
	var stdout, stderr bytes.Buffer
	cmd := exec.Command(binaryName)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	
	// we can set the coverage directory for the instrumented binary when we execute it
	cmd.Env = []string{"GOCOVERDIR="+coverageDir}

	// Run the command
	err := cmd.Run()

	if err == nil {
		t.Fatalf("expected error from exit code 1, got nil")
	}
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    External

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions