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

Support running multiple tests per commit #27

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Conversation

mhagger
Copy link
Owner

@mhagger mhagger commented Jan 2, 2025

This is a riff on #24. Thanks to @hlovdal for that contribution, from which I borrowed heavily!

Compared to that PR, I have tried to make the new output more consistent and informative without being overwhelming. But I also went through most of the implementation again and revised it quite a bit. I preserved the authorship of commits that retained the flavor of the original even though they are somewhat transformed; @hlovdal let me know if you have any objections!

With this change, you can run multiple tests at the same time by feeding multiple test names to the --test (or -t or --tests) option, like

git test run --test=test1,test2 commit1..commit2

This checks out the commits as before, one by one, but for each commit it runs all of the specified tests. If any of the tests fail, the commit is considered bad. The good/bad status is recorded for each (commit, test) pair, in Git notes named after the individual tests.

The stdout is changed somewhat; now each line has a third field explaining which test failed; for example,

3d9ec13248e904ef0279b54450a5c89f211d2174^{tree} bad (test1:bad)

There is one such line per (commit, test) pair.

git test results, when applied to multiple tests, outputs one line per commit of the form

ca061fd40c0759fa02a756ae527dc4e172d4837f^{tree} bad (test1:known-bad test2:good)
5c2c8173f7cc866a6eb160f8222a1a7695d730b9^{tree} bad (test1:bad test2:good)

The stderr should mostly be self-explanatory. If a commit is found to be bad, the bad commit and its log messages are printed out as usual. But now, the header says what tests failed and what their individual return codes were:

*******************************************************************************
BAD COMMIT 5c2c8173f7cc866a6eb160f8222a1a7695d730b9: (failing:test1:retcode=1,test2:bad:retcode=13)

commit 5c2c8173f7cc866a6eb160f8222a1a7695d730b9 (HEAD, origin/multi-tests-v2, multi-tests-v2)
[...]

The last thing output is the overall success or failure of all tests over all commits so that it's obvious whether everything was OK or whether there was a problem:

!!! 4 TESTS FAILED !!!

One other change is that, if --keep-going is specified, then git-test doesn't try to set its own exit code based on the exit code of the last failing test. This didn't seem like a useful feature, since multiple tests might have failed. But if --keep-going is not specified, then the old behavior is preserved: the exit code of git-test is the same as that of the test that failed (if any).

@hlovdal if you are interested to give this a try, let me know what you think. Since you've obviously used this kind of functionality before, you might notice if something important is missing or inconvenient.

@motlin
Copy link

motlin commented Jan 2, 2025

Thanks for writing this! I've been trying it out and my initial impression is that it works great. The only thing I've noticed so far is that it's slightly awkward to use --keep-going for both:

  • continue to additional commits if one failed
  • continue to additional tests if one failed

I usually don't want to proceed to the next commit, since I'm going to have to amend the commit and rerun tests anyway.

However, I will often want to proceed to the next test, when one is for unit tests and the other is a linter, and they are fairly independent.

@mhagger
Copy link
Owner Author

mhagger commented Jan 2, 2025

@motlin: Thanks for the comment! That makes sense as a way of working.

It would be fairly easy to add another option, but I hate piling on new options if there's a way around it. I wonder if it would be better if all tests run against a commit even if an earlier test fails (i.e., even without --keep-going), and there is no way to get "stop after very first failing subtest"?

If you think that separate options are really needed, do you have a suggestion for what to call them?

(For the sake of argument, there is yet another mode that would possibly make sense: When a particular test fails for a commit, then stop running that test for any subsequent commits, while continuing to run all of the other tests against that and subsequent commits. But I doubt that's useful enough to be worth implementing.)

@motlin
Copy link

motlin commented Jan 2, 2025

I think you'll want to keep --keep-going unchanged, so I was thinking about names like --fail-on-first-test or --all-tests, but I'm not sure.

I had an experiment that I never got working that takes every (commit,sha) pair, creates a git worktree for it, and runs the test in the worktree. I wanted it to support parallelism across commits, and it would have had the behavior you're talking about, where it would be possible for the linter test to pass on say 5 commits before the unit tests are even up to the 3rd commit.

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.

3 participants