11from glob import glob
2+ from io import TextIOWrapper
23from pathlib import Path
4+ from typing import List
5+ import os
6+ from uuid import uuid4
7+
8+ from _pytest .terminal import TerminalReporter
9+ from _pytest .config import ExitCode , Config
10+ from _pytest .reports import BaseReport
11+ from pytest import CollectReport , TestReport
312
413pytest_plugins = []
514for f in glob ("**/fixtures/**/*.py" , recursive = True ):
@@ -11,3 +20,63 @@ def pytest_collection_modifyitems(session, config, items):
1120 # Only considers functions inside /tests directory as unit tests
1221 # otherwise test functions in the main part of the repo are also detected
1322 items [:] = [i for i in items if i .location [0 ].startswith ("tests" )]
23+
24+
25+ def _write_details (writer : TextIOWrapper , title : str , content : str ):
26+ if content :
27+ writer .write ("<details>\n " )
28+ writer .write (f"<summary>{ title } </summary>\n \n " )
29+ writer .write (f"```\n { content } \n ```\n " )
30+ writer .write ("\n </details>\n " )
31+
32+ def _write_report (writer : TextIOWrapper , report : BaseReport ):
33+ writer .write (f"\n \n <h4 id=user-content-{ report .html_id } >{ report .nodeid } </h4>\n \n " )
34+ writer .write (f"```python\n { report .longreprtext } \n ```\n " )
35+ _write_details (writer , "Log" , report .caplog )
36+ _write_details (writer , "Stdout" , report .capstdout )
37+ _write_details (writer , "Stderr" , report .capstderr )
38+
39+
40+ def pytest_terminal_summary (
41+ terminalreporter : TerminalReporter , exitstatus : ExitCode , config : Config
42+ ):
43+ file = Path (os .getenv ("GITHUB_STEP_SUMMARY" , "local_report.md" ))
44+
45+ with file .open ("w" , encoding = "utf-8" ) as writer :
46+ writer .write ("### Pytest report\n " )
47+ writer .write (f"Test results: { ExitCode (exitstatus ).name } { '✅' if exitstatus == ExitCode .OK else '❌' } \n \n " )
48+
49+ writer .write ("\n | Status |Count |\n " )
50+ writer .write ("| :---: | :---: |\n " )
51+
52+ total = 0
53+ for k , v in terminalreporter .stats .items ():
54+ if not k or k == "warnings" :
55+ continue
56+ total += len (v )
57+ writer .write (f"| { k .capitalize ()} | { len (v )} |\n " )
58+ writer .write (f"| Total | { total } |\n \n " )
59+
60+ failures : List [TestReport ] = [
61+ report for report in terminalreporter .stats .get ("failed" , [])
62+ ]
63+ errors : List [CollectReport ] = [
64+ report for report in terminalreporter .stats .get ("error" , [])
65+ ]
66+
67+ writer .write ("### Table of contents\n \n " )
68+ for error in errors :
69+ error .html_id = str (uuid4 ())
70+ writer .write (f"- [Error : { error .nodeid .split ('::' )[- 1 ]} ](#user-content-{ error .html_id } )\n " )
71+ for failure in failures :
72+ failure .html_id = str (uuid4 ())
73+ writer .write (f"- [Failure : { failure .nodeid .split ('::' )[- 1 ]} ](#user-content-{ failure .html_id } )\n " )
74+
75+
76+ writer .write ("\n ### Errors\n \n " )
77+ for error in errors :
78+ _write_report (writer , error )
79+
80+ writer .write ("\n ### Failures\n \n " )
81+ for failure in failures :
82+ _write_report (writer , failure )
0 commit comments