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

magefile: added combined test coverage support for mage test:all #2235

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

kartikaysaxena
Copy link
Contributor

Fixes #1348 mage test:all now generates combined coverprofile aggregated into coverage.txt

Signed-off-by: Kartikay <[email protected]>
@kartikaysaxena kartikaysaxena requested a review from a team as a code owner February 4, 2025 21:19
testArgs := append([]string{
"test",
"-covermode=atomic",
"-coverprofile=coverage.txt",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this overwrite the coverage.txt file when each individual test suite runs? Can you try running mage test:all and ensure it combines the coverage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the approach, now each test writes to a different file and removes those files in the end, go tool cover -html=coverage.txt now shows
Screenshot 2025-02-06 at 12 25 43 AM

@@ -210,3 +223,45 @@ func run(dir string, env map[string]string, stdout, stderr io.Writer, cmd string
err = c.Run()
return sh.CmdRan(err), sh.ExitStatus(err), err
}

func sanitizePath(path string) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend hashing the path here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@vroldanbet vroldanbet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the PR enables coverage by default on all, whereas before it was opt in. Do we have concerns that would add overhead on the inner loop? Or is the overhead negligible?

@kartikaysaxena kartikaysaxena force-pushed the mage-test-coverage branch 2 times, most recently from 4fb47db to 7498752 Compare February 10, 2025 22:12
@kartikaysaxena
Copy link
Contributor Author

Seems like the PR enables coverage by default on all, whereas before it was opt in. Do we have concerns that would add overhead on the inner loop? Or is the overhead negligible?

I used time mage test:all to check and the overhead was costing over a minute, followed the pattern for other targets for generating coverage reports which was earlier in UnitCover, now we have a dedicated test:allcover for this, is this correct? Would love the feedback and any improvements further if necessary

}
defer f.Close()

args := []string{"run", "github.com/wadey/gocovmerge@latest"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use go tool covdata merge, see https://go.dev/doc/build-cover

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems we need to build a binary for this for specifying the -cover flag before the tests which would generate the files(tests should be carried on the same binary?)

@@ -210,3 +221,40 @@ func run(dir string, env map[string]string, stdout, stderr io.Writer, cmd string
err = c.Run()
return sh.CmdRan(err), sh.ExitStatus(err), err
}

func hashPath(path string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to hash the path? I'd keep it simpler by generating a UUID as suffix

func (t Test) AllCover() error {
ds := Testds{}
c := Testcons{}
mg.Deps(t.UnitCover, t.IntegrationCover, t.SteelthreadCover, t.ImageCover, t.AnalyzersCover,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems like a lot of duplication that would lead to drift w.r.t to All() method. Ideally All and AllCover invoke `all(coverage bool)

return err
}

for _, file := range files {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why deleting the tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was for deleting individual coverage files after merging them. reverting

"-tags", "ci,docker,datastoreconsistency",
"-timeout", "10m",
"-run", fmt.Sprintf("TestConsistencyPerDatastore/%s", datastore))
if coverage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all this if coverage blocks could be refactored to avoid all the duplication - e.g. a function that takes the args and the coverage bool, and returns the args with the appended parameters.


func (Testds) spanner(coverage bool) error {
args := []string{"-tags", "ci,docker", "-timeout", "10m"}
if coverage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of duplication: this coverage if statement should be handled inside datastoreTest

func (Test) image(coverage bool) error {
mg.Deps(Build{}.Testimage)
args := []string{"-tags", "docker,image"}
if coverage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be moved into goDirTest, otherwise it leads to a lot of duplication

@@ -43,27 +53,75 @@ func (Test) unit(coverage bool) error {
fmt.Println("running unit tests")
args := []string{"-tags", "ci,skipintegrationtests", "-race", "-timeout", "10m", "-count=1"}
if coverage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be moved into goTest, otherwise it leads to a lot of duplication

}

// SteelthreadCover Runs the steelthread tests and generates a coverage report
func (t Test) SteelthreadCover() error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's annoying we end up with proliferation of commands just to have with/without coverage versions of them. Calling mage leads to a very long list that starts to become not very user friendly.

I know mage supports arguments in commands, but not if it supports commands with arguments and default values, could you investigate?

Signed-off-by: Kartikay <[email protected]>
@kartikaysaxena
Copy link
Contributor Author

Utilised uuid instead, also passed the bool through a context to goDirTest and goDirTestWithEnv, now works like mage test:all -cover=true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mage test:all should produce a combined code coverage result
3 participants