You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
3.0KB

  1. from typing import Generator
  2. from typing import Optional
  3. from typing import Union
  4. import pytest
  5. from _pytest._io.saferepr import saferepr
  6. from _pytest.config import Config
  7. from _pytest.config import ExitCode
  8. from _pytest.config.argparsing import Parser
  9. from _pytest.fixtures import FixtureDef
  10. from _pytest.fixtures import SubRequest
  11. def pytest_addoption(parser: Parser) -> None:
  12. group = parser.getgroup("debugconfig")
  13. group.addoption(
  14. "--setuponly",
  15. "--setup-only",
  16. action="store_true",
  17. help="only setup fixtures, do not execute tests.",
  18. )
  19. group.addoption(
  20. "--setupshow",
  21. "--setup-show",
  22. action="store_true",
  23. help="show setup of fixtures while executing tests.",
  24. )
  25. @pytest.hookimpl(hookwrapper=True)
  26. def pytest_fixture_setup(
  27. fixturedef: FixtureDef[object], request: SubRequest
  28. ) -> Generator[None, None, None]:
  29. yield
  30. if request.config.option.setupshow:
  31. if hasattr(request, "param"):
  32. # Save the fixture parameter so ._show_fixture_action() can
  33. # display it now and during the teardown (in .finish()).
  34. if fixturedef.ids:
  35. if callable(fixturedef.ids):
  36. param = fixturedef.ids(request.param)
  37. else:
  38. param = fixturedef.ids[request.param_index]
  39. else:
  40. param = request.param
  41. fixturedef.cached_param = param # type: ignore[attr-defined]
  42. _show_fixture_action(fixturedef, "SETUP")
  43. def pytest_fixture_post_finalizer(fixturedef: FixtureDef[object]) -> None:
  44. if fixturedef.cached_result is not None:
  45. config = fixturedef._fixturemanager.config
  46. if config.option.setupshow:
  47. _show_fixture_action(fixturedef, "TEARDOWN")
  48. if hasattr(fixturedef, "cached_param"):
  49. del fixturedef.cached_param # type: ignore[attr-defined]
  50. def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None:
  51. config = fixturedef._fixturemanager.config
  52. capman = config.pluginmanager.getplugin("capturemanager")
  53. if capman:
  54. capman.suspend_global_capture()
  55. tw = config.get_terminal_writer()
  56. tw.line()
  57. tw.write(" " * 2 * fixturedef.scopenum)
  58. tw.write(
  59. "{step} {scope} {fixture}".format(
  60. step=msg.ljust(8), # align the output to TEARDOWN
  61. scope=fixturedef.scope[0].upper(),
  62. fixture=fixturedef.argname,
  63. )
  64. )
  65. if msg == "SETUP":
  66. deps = sorted(arg for arg in fixturedef.argnames if arg != "request")
  67. if deps:
  68. tw.write(" (fixtures used: {})".format(", ".join(deps)))
  69. if hasattr(fixturedef, "cached_param"):
  70. tw.write("[{}]".format(saferepr(fixturedef.cached_param, maxsize=42))) # type: ignore[attr-defined]
  71. tw.flush()
  72. if capman:
  73. capman.resume_global_capture()
  74. @pytest.hookimpl(tryfirst=True)
  75. def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
  76. if config.option.setuponly:
  77. config.option.setupshow = True
  78. return None