Skip to content

pytest plugin deepdive #350

@nedtwigg

Description

@nedtwigg
  • When a user makes a pytest call, this hook runs. We create the SnapshotSystem, and find all the tests that are planning to run.
    • @pytest.hookimpl
      def pytest_collection_modifyitems(
      session: pytest.Session, config: pytest.Config, items: List[pytest.Item]
      ) -> None:
      settings = SelfieSettingsAPI(config)
      system = PytestSnapshotSystem(settings)
      session.selfie_system = system # type: ignore
      _initSelfieSystem(system)
      for item in items:
      (file, _, testname) = item.reportinfo()
      system.planning_to_run(TypedPath.of_file(os.path.abspath(file)), testname)
  • For each test that runs, this method gets called.
    • @pytest.hookimpl(hookwrapper=True)
      def pytest_runtest_protocol(item: pytest.Item, nextitem: Optional[pytest.Item]):
      (file, _, testname) = item.reportinfo()
      testfile = TypedPath.of_file(os.path.abspath(file))
      system: PytestSnapshotSystem = item.session.selfie_system # type: ignore
      system.test_start(testfile, testname)
      yield
      system.test_finish(testfile, testname)
    • we notify the system that a test is starting
    • the test runs at the yield
    • we notify the system that a test has finished
  • Within that yield call, this function gets called when a test has something to report
    • @pytest.hookimpl
      def pytest_runtest_makereport(call: pytest.CallInfo[None], item: pytest.Item):
      if call.excinfo is not None and call.when in (
      "call",
      "teardown",
      ):
      system: PytestSnapshotSystem = item.session.selfie_system # type: ignore
      (file, _, testname) = item.reportinfo()
      system.test_failed(TypedPath.of_file(os.path.abspath(file)), testname)
    • if a test fails during the call or teardown phases, we notify the system so that GC won't run
  • And at the very end we call this to mark that everything is done and we can write everything to disk
    • @pytest.hookimpl
      def pytest_sessionfinish(session: pytest.Session, exitstatus):
      system: PytestSnapshotSystem = session.selfie_system # type: ignore
      system.finished_all_tests()
      _clearSelfieSystem(system)
    • An important asterisk is that SnapshotFiles are read / written to disk as we go, they don't wait until the end.

If you look in example-pytest-selfie, you'll see three tests which exercise the subsystems you have built to-date:

If you run them, you'll see that the SnapshotSystem is all wired up to them, but with some NotImplementedError along the way.

If you have something in-progress, go ahead and finish that up. Otherwise, try to get your subsystem to work in this context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions