当 运行 通过 pytest.main() 以编程方式检索 pytest 结果

retrieve pytest results programmatically when run via pytest.main()

我想 运行 pytest 然后存储结果并根据需要将它们呈现给用户(例如将 pytest 结果存储到数据库然后通过 Web 服务公开它们) 我可以从命令行 运行 pytest 选择将结果报告保存到文件中,然后查找并解析文件,但是将结果放在 (pytest) python 应用程序中,然后存储它们感觉很愚蠢到一个文件,然后立即查找该文件,将其解析回 python 代码以供进一步处理。我知道我可以通过 pytest.main(args) 以编程方式 运行 pytest 但是它只有 return 一些退出代码而不是关于测试结果的详细信息 - 我如何在使用 [=20= 时检索结果]()?

我正在寻找像

这样的smt
args =  # arguments 
ret_code = pytest.main(args=args) # pytest.main() as is only returns trivial return code
my_own_method_to_process(pytest.results)   # how to retrieve any kind of pytest.results object that would contain test execution results data (list of executed tests, pass fail info, etc as pytest is displaying into console or saves into file reports)

有几个类似的问题,但总是有一些不适合我的偏差。我只是想从我的代码中 运行 pytest 并且 - 无论输出是什么格式 - 直接获取它并进一步处理。 (请注意,我在公司环境中安装新包(即 pytest 插件)是有限的,所以我想在不安装任何其他 module/pytest 插件到我的环境中的情况下实现这一点)

编写一个小插件来收集和存储每个测试的报告。示例:

import time
import pytest


class ResultsCollector:
    def __init__(self):
        self.reports = []
        self.collected = 0
        self.exitcode = 0
        self.passed = 0
        self.failed = 0
        self.xfailed = 0
        self.skipped = 0
        self.total_duration = 0

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_makereport(self, item, call):
        outcome = yield
        report = outcome.get_result()
        if report.when == 'call':
            self.reports.append(report)

    def pytest_collection_modifyitems(self, items):
        self.collected = len(items)

    def pytest_terminal_summary(self, terminalreporter, exitstatus):
        print(exitstatus, dir(exitstatus))
        self.exitcode = exitstatus.value
        self.passed = len(terminalreporter.stats.get('passed', []))
        self.failed = len(terminalreporter.stats.get('failed', []))
        self.xfailed = len(terminalreporter.stats.get('xfailed', []))
        self.skipped = len(terminalreporter.stats.get('skipped', []))

        self.total_duration = time.time() - terminalreporter._sessionstarttime

def run():
    collector = ResultsCollector()
    pytest.main(plugins=[collector])
    for report in collector.reports:
        print('id:', report.nodeid, 'outcome:', report.outcome)  # etc
    print('exit code:', collector.exitcode)
    print('passed:', collector.passed, 'failed:', collector.failed, 'xfailed:', collector.xfailed, 'skipped:', collector.skipped)
    print('total duration:', collector.total_duration)


if __name__ == '__main__':
    run()