-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: testing: add testing.T.Volatile to exempt test functions from result caching #67568
Comments
related #23799 |
I still agree with my old comment #23799 (comment): some marker is fine but the default behavior of 'go test' should still be to cache things. We could have 'go test -volatile' to explicitly rerun volatile tests even when the result is cached from last time, but I think that's indistinguishable from -count=1. |
Also reading the Mastodon thread it seems like the first thing to understand is https://hachyderm.io/@elan@publicsquare.global/112481172747959065. That has nothing to do with volatile tests. |
I posted https://hachyderm.io/@rsc/112491348314936122 over on Mastodon about the potential build/test cache misbehavior. |
This proposal has been added to the active column of the proposals project |
Making this require a command line option feels strange to me, because a testing being volatile is a property of the test, rather than a property of the test run or a personal preference of the person running the test suite. Relying on a cached result of a volatile test is a mistake. I could imagine a compromise where volatile tests don't run at all by default; e.g. perhaps I have some prior art of something similar to that in some of the software I maintain in my dayjob: we have some integration tests that access external network services to verify correct behavior, and currently have those tests call However, the primary motivation for that is not that the tests are "volatile" but rather than they can only work when the person running the test has a suitable network connection to access the relevant services. They are volatile as defined by this proposal, but that's not the main motivation for skipping them by default, so this example might not be relevant. |
Ultimately, beliefs about what is correct here depend on why you want to run the test: is it to test that the code works, or is it to test that the external, volatile dependencies still work? Most of the time, you run tests to check the source code in the repo where you are working. In that context, if you've run Sometimes you are running tests to check a full end-to-end behavior, including that external, volatile dependencies are still working as expected. In that case, using |
I think perhaps the main point of contention here may be whether "volatile tests" are common enough and useful enough to deserve different treatment than unit tests? For what it's worth, I agree that the caching mechanism as currently implemented is a fine answer for unit tests, and that unit tests are likely the most common situation and therefore it makes sense for the default behavior to prioritize those. However, I read this proposal as extending Go's testing facilities to better support integration-type tests (aka "end-to-end tests") so that those who wish to write them and use them don't need to fight the test harness to use them effectively. Thinking that you've got a passing integration test suite when really all you've done is recalled an older positive result from the cache is a real hazard that I've encountered myself and have seen others on my team encounter. I do find your argument convincing @rsc -- particularly the part of only wanting to run these relatively-expensive tests once you've got fully-passing unit tests. To me, that seems to favor the compromise of making uncacheable tests not run by default, but for (I could also perhaps accept the argument that EDIT: I came back to this some days later and found myself more receptive to the idea that However, the Perhaps a different way to look at this, then, is to expose that test-program-building behavior callable from outside of the I would imagine the test-program-building helper allowing its caller to customize the filename suffix to search for and the function name prefixes to search for, so that e.g. an integration test suite could use functions named with I realize this is a totally separate proposal, and so am sharing this only to say that my thinking evolved since I originally wrote this comment. I would suggest against discussing this alternative proposal here (whether in favor or against) to avoid derailing the current discussion, but if anyone is feeling a certain way about what I wrote here then perhaps they'd like to use the 👍 or 👎 reactions to signal that, and if it seems like it's an interesting direction I will write up a separate proposal for it. |
I think we understand the relevant issues. We could implement -volatile but it doesn't seem like the right answer here. For now it seems like -count=1 is as good as anything else. |
(There is the separate issue of the Mastodon report that test caching was horribly broken and not noticing source file edits. That's a separate discussion if they can reproduce it.) |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
Proposal Details
While generally, a test function should be self-contained and isolated to prevent flakes, there are cases where a test needs to interact with state not reflected in the build artifact. For example an integration test, that tests interaction with a CLI tool or relies on a separate database server. For such tests, the current behavior of the Go test cache is counterproductive: It might conclude that since the code itself has not changed and re-use a cached test run, even if the external resource has changed and thus the test needs to be re-run.
It is possible to pass
-count=1
to force a re-run, but this is flawed as well, as it applies globally. If you want to run all tests in a large project and rungo test -count=1 ./...
, that will re-run all tests, even though most of them might be perfectly cacheable. There is a reason, after all, that the test cache was introduced.So it might be useful to have a way to indicate that one specific test function depends on external state, that makes it non-cacheable.
Thus, I propose to add a method to
*testing.T
to exempt a function from result caching:The call would just be recorded in the
*T
and after the test function is finished, its result would not be stored in the cache ifVolatile
was called. Thus no other tests are affected by use ofVolatile
.One drawback of this mechanism is that it again runs all volatile tests on every invocation of
go test
, even if the external resources did not change. Especially ifVolatile
is overused, that would again increase test running times. Theoretically, it would be possible to prevent that by allowing the test function to include a token that encapsulates the external state (e.g. by hashing the version of the database server or the contents of the called binary), though this might be too finicky, ultimately:I'm not terribly sure this is a good idea. It came up in a discussion on Mastodon and it doesn't seem like a completely unreasonable compromise. So I wanted to propose it formally, to gather some feedback.
The text was updated successfully, but these errors were encountered: