diff --git a/docs/userguides/testing.md b/docs/userguides/testing.md index 81e7e9c198..2be9404b5a 100644 --- a/docs/userguides/testing.md +++ b/docs/userguides/testing.md @@ -227,7 +227,7 @@ After each test completes, the chain reverts to that snapshot from the beginning By default, every `pytest` fixture is `function` scoped, meaning it will be replayed each time it is requested (no result-caching). For example, if you deploy a contract in a function-scoped fixture, it will be re-deployed each time the fixture gets used in your tests. -To only deploy once, you can use different scopes, such as `"session"`, `"package"`, `"module"`, or `"class"`, and you **must** use these fixtures right away, either via `autouse=True` or using them in the first collected tests. +To only deploy once, you can use different scopes, such as `"session"`, `"package"`, `"module"`, or `"class"`, and you **should** use these fixtures right away, either via `autouse=True` or using them in the first collected tests. Otherwise, higher-scoped fixtures that arrive late in a Pytest session will cause the snapshotting system to have to rebase itself, which can be costly. For example, if you define a session scoped fixture that deploys a contract and makes transactions, the state changes from those transactions remain in subsequent tests, whether those tests use that fixture or not. However, if a new fixture of a session scope comes into play after module, package, or class scoped snapshots have already been taken, those lower-scoped fixtures are now invalid and have to re-run after the session fixture to ensure the session fixture remains in the session-snapshot. @@ -285,6 +285,18 @@ def token_addresses(request): return tokens[request].address ``` +You can also disable isolation for individual scopes using Ape's config. +For example, the below config will disable isolation across all high-level scopes but maintain isolation for the function-scope. +This is useful if you want your individual tests to be isolated but not any session/module scoped fixtures. + +```toml +[tool.ape.test.isolation] +enable_session = false +enable_package = false +enable_module = false +enable_class = false +``` + ## Ape testing commands ```bash diff --git a/src/ape/pytest/fixtures.py b/src/ape/pytest/fixtures.py index 0f7375bbbc..f1b79ea374 100644 --- a/src/ape/pytest/fixtures.py +++ b/src/ape/pytest/fixtures.py @@ -213,13 +213,13 @@ def _get_rebase(self, scope: Scope) -> Optional[FixtureRebase]: invalids = defaultdict(list) for next_snapshot in self.isolation_manager.next_snapshots(scope): if next_snapshot.identifier is None: - # Thankfully, we haven't reached this scope yet. - # In this case, things are running in a performant order. + # Thankfully, we haven't reached this scope yet (or it is disabled). + # In this case, things are running in a correct/performant order. continue if scope_to_revert is None: # Revert to the closest scope to use. For example, a new - # session comes in but we have already calculated a module + # session comes in, but we have already calculated a module # and a class, revert to pre-module and invalidate the module # and class fixtures. scope_to_revert = next_snapshot.scope