@pytest.mark.hookwrapper
    def pytest_runtest_makereport(self, item, call):
        """
        Decides when to actually report things.

        pytest runs this (naturally) three times -- with report.when being:
          setup     <--- fixtures are to be initialized in this one
          call      <--- when this finishes the main code has finished
          teardown  <--- tears down fixtures (that still possess important info)

        `setup` and `teardown` are always called, but `call` is called only if `setup` passes.

        See :py:func:`_pytest.runner.runtestprotocol` for proofs / ideas.

        The "other side" (AllureAggregatingListener) expects us to send EXACTLY ONE test report (it wont break, but it will duplicate cases in the report -- which is bad.

        So we work hard to decide exact moment when we call `_stop_case` to do that. This method may benefit from FSM (we keep track of what has already happened via self.test.status)

        Expected behavior is:
          FAILED when call fails and others OK
          BROKEN when either setup OR teardown are broken (and call may be anything)
          PENDING if skipped and xfailed
          SKIPPED if skipped and not xfailed
        """
        report = (yield).get_result()

        status = self.config.hook.pytest_report_teststatus(report=report)
        status = status and status[0]

        if report.when == 'call':
            if report.passed:
                self._fill_case(report, call, status, Status.PASSED)
            elif report.failed:
                self._fill_case(report, call, status, Status.FAILED)
                # FIXME: this is here only to work around xdist's stupid -x thing when in exits BEFORE THE TEARDOWN test log. Meh, i should file an issue to xdist
                if self._magicaldoublereport:
                    # to minimize ze impact
                    self.report_case(item, report)
            elif report.skipped:
                if hasattr(report, 'wasxfail'):
                    self._fill_case(report, call, status, Status.PENDING)
                else:
                    self._fill_case(report, call, status, Status.CANCELED)
        elif report.when == 'setup':  # setup / teardown
            if report.failed:
                self._fill_case(report, call, status, Status.BROKEN)
            elif report.skipped:
                if hasattr(report, 'wasxfail'):
                    self._fill_case(report, call, status, Status.PENDING)
                else:
                    self._fill_case(report, call, status, Status.CANCELED)
        elif report.when == 'teardown':
            # as teardown is always called for testitem -- report our status here
            if not report.passed:
                if self.test.status not in FAILED_STATUSES:
                    # if test was OK but failed at teardown => broken
                    self._fill_case(report, call, status, Status.BROKEN)
                else:
                    # mark it broken so, well, someone has idea of teardown failure
                    # still, that's no big deal -- test has already failed
                    # TODO: think about that once again
                    self.test.status = Status.BROKEN
            self.report_case(item, report)
dataset/ETHPy150Open allure-framework/allure-python/allure/pytest_plugin.py/AllureTestListener.pytest_runtest_makereport/original