summaryrefslogtreecommitdiffstats
path: root/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py')
-rw-r--r--contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py172
1 files changed, 90 insertions, 82 deletions
diff --git a/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py b/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
index f7a89268452..340bf90ebfa 100644
--- a/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
+++ b/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
@@ -49,20 +49,6 @@ _ALL_OPTIONS = [
SEED_OPTION,
EXPLAIN_OPTION,
]
-_FIXTURE_MSG = """Function-scoped fixture {0!r} used by {1!r}
-
-Function-scoped fixtures are not reset between examples generated by
-`@given(...)`, which is often surprising and can cause subtle test bugs.
-
-If you were expecting the fixture to run separately for each generated example,
-then unfortunately you will need to find a different way to achieve your goal
-(e.g. using a similar context manager instead of a fixture).
-
-If you are confident that your test will work correctly even though the
-fixture is not reset between generated examples, you can suppress this health
-check to assure Hypothesis that you understand what you are doing.
-"""
-
STATS_KEY = "_hypothesis_stats"
FAILING_EXAMPLES_KEY = "_hypothesis_failing_examples"
@@ -160,7 +146,9 @@ else:
settings_str = settings.default.show_changed()
if settings_str != "":
settings_str = f" -> {settings_str}"
- return f"hypothesis profile {settings._current_profile!r}{settings_str}"
+ return (
+ f"hypothesis profile {settings.get_current_profile_name()!r}{settings_str}"
+ )
def pytest_configure(config):
config.addinivalue_line("markers", "hypothesis: Tests which use hypothesis.")
@@ -174,7 +162,9 @@ else:
verbosity_name = config.getoption(VERBOSITY_OPTION)
if verbosity_name and verbosity_name != settings.default.verbosity.name:
verbosity_value = Verbosity[verbosity_name]
- name = f"{settings._current_profile}-with-{verbosity_name}-verbosity"
+ name = (
+ f"{settings.get_current_profile_name()}-with-{verbosity_name}-verbosity"
+ )
# register_profile creates a new profile, exactly like the current one,
# with the extra values given (in this case 'verbosity')
settings.register_profile(name, verbosity=verbosity_value)
@@ -183,7 +173,7 @@ else:
config.getoption(EXPLAIN_OPTION)
and Phase.explain not in settings.default.phases
):
- name = f"{settings._current_profile}-with-explain-phase"
+ name = f"{settings.get_current_profile_name()}-with-explain-phase"
phases = (*settings.default.phases, Phase.explain)
settings.register_profile(name, phases=phases)
settings.load_profile(name)
@@ -240,79 +230,97 @@ else:
raise_hypothesis_usage_error(message % (name,))
yield
- else:
- from hypothesis import HealthCheck, settings as Settings
- from hypothesis.internal.escalation import current_pytest_item
- from hypothesis.internal.healthcheck import fail_health_check
- from hypothesis.reporting import with_reporter
- from hypothesis.statistics import collector, describe_statistics
+ return
- # Retrieve the settings for this test from the test object, which
- # is normally a Hypothesis wrapped_test wrapper. If this doesn't
- # work, the test object is probably something weird
- # (e.g a stateful test wrapper), so we skip the function-scoped
- # fixture check.
- settings = getattr(
- item.obj, "_hypothesis_internal_use_settings", Settings.default
- )
+ from hypothesis import HealthCheck, settings as Settings
+ from hypothesis.internal.escalation import current_pytest_item
+ from hypothesis.internal.healthcheck import fail_health_check
+ from hypothesis.reporting import with_reporter
+ from hypothesis.statistics import collector, describe_statistics
- # Check for suspicious use of function-scoped fixtures, but only
- # if the corresponding health check is not suppressed.
- fixture_params = False
- if not set(settings.suppress_health_check).issuperset(
- {HealthCheck.function_scoped_fixture, HealthCheck.differing_executors}
- ):
- # Warn about function-scoped fixtures, excluding autouse fixtures because
- # the advice is probably not actionable and the status quo seems OK...
- # See https://github.com/HypothesisWorks/hypothesis/issues/377 for detail.
- argnames = None
- for fx_defs in item._request._fixturemanager.getfixtureinfo(
- node=item, func=item.function, cls=None
- ).name2fixturedefs.values():
- if argnames is None:
- argnames = frozenset(signature(item.function).parameters)
- for fx in fx_defs:
- fixture_params |= bool(fx.params)
- if fx.argname in argnames:
- active_fx = item._request._get_active_fixturedef(fx.argname)
- if active_fx.scope == "function":
- fail_health_check(
- settings,
- _FIXTURE_MSG.format(fx.argname, item.nodeid),
- HealthCheck.function_scoped_fixture,
- )
+ # Retrieve the settings for this test from the test object, which
+ # is normally a Hypothesis wrapped_test wrapper. If this doesn't
+ # work, the test object is probably something weird
+ # (e.g a stateful test wrapper), so we skip the function-scoped
+ # fixture check.
+ settings = getattr(
+ item.obj, "_hypothesis_internal_use_settings", Settings.default
+ )
- if fixture_params or (item.get_closest_marker("parametrize") is not None):
- # Disable the differing_executors health check due to false alarms:
- # see https://github.com/HypothesisWorks/hypothesis/issues/3733
- from hypothesis import settings as Settings
+ # Check for suspicious use of function-scoped fixtures, but only
+ # if the corresponding health check is not suppressed.
+ fixture_params = False
+ if not set(settings.suppress_health_check).issuperset(
+ {HealthCheck.function_scoped_fixture, HealthCheck.differing_executors}
+ ):
+ # Warn about function-scoped fixtures, excluding autouse fixtures because
+ # the advice is probably not actionable and the status quo seems OK...
+ # See https://github.com/HypothesisWorks/hypothesis/issues/377 for detail.
+ argnames = None
+ for fx_defs in item._request._fixturemanager.getfixtureinfo(
+ node=item, func=item.function, cls=None
+ ).name2fixturedefs.values():
+ if argnames is None:
+ argnames = frozenset(signature(item.function).parameters)
+ for fx in fx_defs:
+ fixture_params |= bool(fx.params)
+ if fx.argname not in argnames:
+ continue
+ active_fx = item._request._get_active_fixturedef(fx.argname)
+ if active_fx.scope == "function":
+ fail_health_check(
+ settings,
+ f"{item.nodeid!r} uses a function-scoped fixture {fx.argname!r}."
+ "\n\n"
+ "Function-scoped fixtures are not reset between inputs "
+ "generated by `@given(...)`, which is often surprising and "
+ "can cause subtle test bugs."
+ "\n\n"
+ "If you were expecting the fixture to run separately "
+ "for each generated input, then unfortunately you "
+ "will need to find a different way to achieve your "
+ "goal (for example, replacing the fixture with a similar "
+ "context manager inside of the test)."
+ "\n\n"
+ "If you are confident that your test will work correctly "
+ "even though the fixture is not reset between generated "
+ "inputs, you can suppress this health check with "
+ "@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]). "
+ "See "
+ "https://hypothesis.readthedocs.io/en/latest/reference/api.html#hypothesis.HealthCheck "
+ "for details.",
+ HealthCheck.function_scoped_fixture,
+ )
- fn = getattr(item.obj, "__func__", item.obj)
- fn._hypothesis_internal_use_settings = Settings(
- parent=settings,
- suppress_health_check={HealthCheck.differing_executors}
- | set(settings.suppress_health_check),
- )
+ if fixture_params or (item.get_closest_marker("parametrize") is not None):
+ # Disable the differing_executors health check due to false alarms:
+ # see https://github.com/HypothesisWorks/hypothesis/issues/3733
+ fn = getattr(item.obj, "__func__", item.obj)
+ fn._hypothesis_internal_use_settings = Settings(
+ parent=settings,
+ suppress_health_check={HealthCheck.differing_executors}
+ | set(settings.suppress_health_check),
+ )
+
+ # Give every parametrized test invocation a unique database key
+ key = item.nodeid.encode()
+ item.obj.hypothesis.inner_test._hypothesis_internal_add_digest = key
- # Give every parametrized test invocation a unique database key
- key = item.nodeid.encode()
- item.obj.hypothesis.inner_test._hypothesis_internal_add_digest = key
+ store = StoringReporter(item.config)
- store = StoringReporter(item.config)
+ def note_statistics(stats):
+ stats["nodeid"] = item.nodeid
+ item.hypothesis_statistics = describe_statistics(stats)
- def note_statistics(stats):
- stats["nodeid"] = item.nodeid
- item.hypothesis_statistics = describe_statistics(stats)
+ with (
+ collector.with_value(note_statistics),
+ with_reporter(store),
+ current_pytest_item.with_value(item),
+ ):
+ yield
- with collector.with_value(note_statistics):
- # NOTE: For compatibility with Python 3.9's LL(1)
- # parser, this is written as a nested with-statement,
- # instead of a compound one.
- with with_reporter(store):
- with current_pytest_item.with_value(item):
- yield
- if store.results:
- item.hypothesis_report_information = "\n".join(store.results)
+ if store.results:
+ item.hypothesis_report_information = "\n".join(store.results)
def _stash_get(config, key, default):
if hasattr(config, "stash"):