Skip to content

Debug Info

DebugInfo

Bases: Protocol

Protocol for representing required debug info objects interfaces.

Source code in pytest_qaseio/debug_info.py
14
15
16
17
18
19
20
21
22
23
class DebugInfo(typing.Protocol):
    """Protocol for representing required debug info objects interfaces."""

    def generate_debug_comment(
        self,
        file_storage: storage.FileStorage,
        folder: str,
    ) -> str:
        """Generate debug comment with links to debug info files."""
        ...

generate_debug_comment(file_storage, folder)

Generate debug comment with links to debug info files.

Source code in pytest_qaseio/debug_info.py
17
18
19
20
21
22
23
def generate_debug_comment(
    self,
    file_storage: storage.FileStorage,
    folder: str,
) -> str:
    """Generate debug comment with links to debug info files."""
    ...

SeleniumDebugInfo

Representation of selenium debug information.

Source code in pytest_qaseio/debug_info.py
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
class SeleniumDebugInfo:
    """Representation of selenium debug information."""

    def __init__(self, webdriver: "WebDriver") -> None:
        """Set error log and extract data from webdriver."""
        self.webdriver = webdriver
        self.logger = logging.getLogger(__name__)
        self.screenshot = self._extract_screenshot()
        self.html = self._extract_html()
        self.browser_log = self._extract_browser_log()
        self.url = self._extract_url()

    def _extract_screenshot(self) -> bytes | None:
        try:
            return base64.b64decode(
                self.webdriver.get_screenshot_as_base64().encode("utf-8"),
            )
        except Exception:
            self.logger.error(
                msg="Can't extract screenshot from webdriver",
                exc_info=True,
            )
            return None

    def _extract_html(self) -> bytes | None:
        try:
            return self.webdriver.page_source.encode("utf-8")
        except Exception:
            self.logger.error(
                msg="Can't extract html page source from webdriver",
                exc_info=True,
            )
            return None

    def _extract_url(self) -> str:
        try:
            return self.webdriver.current_url
        except Exception:
            self.logger.error(
                msg="Can't extract url from webdriver",
                exc_info=True,
            )
            return ""

    def _extract_browser_log(self) -> str:
        try:
            logs = [
                self._format_log(self.webdriver.get_log(name))  # type: ignore
                for name in self.webdriver.log_types  # type: ignore
            ]
        except Exception:
            # Sometimes there can be problems reading some logs from the
            # browser here (such as `ProtocolError('Connection broken')`).
            # So we skip them if this happens.

            # Also, this method can't work correctly with Geckodriver
            # (raises `WebDriverException` error) because of
            # the following issue
            # https://github.com/mozilla/geckodriver/issues/284
            self.logger.error(msg="Can't extract browser log", exc_info=True)
            logs = []
        return "\n".join(logs)

    @staticmethod
    def _format_log(
        log: collections.abc.Iterable[dict[str, typing.Any]],
    ) -> str:
        """Format logs.

        Copied from pytest-selenium.

        """
        timestamp_format = "%Y-%m-%d %H:%M:%S.%f"
        entries: list[str] = []
        for entry in log:
            timestamp = arrow.get(entry["timestamp"] / 1000.0).strftime(
                timestamp_format,
            )
            entries.append(
                f"{timestamp} {entry['level']} - {entry['message']}",
            )
        return "\n".join(entries)

    def generate_debug_comment(
        self,
        file_storage: storage.FileStorage,
        folder: str,
    ) -> str:
        """Generate debug comment with links to debug info files."""
        screenshot_url = ""
        if self.screenshot:
            try:
                screenshot_url = file_storage.save_file_obj(
                    content=self.screenshot,
                    filename=f"{folder}/screenshot.png",
                )
            except Exception:
                self.logger.error(
                    msg="Can't save screenshot to storage",
                    exc_info=True,
                )

        html_url = ""
        if self.html:
            try:
                html_url = file_storage.save_file_obj(
                    content=self.html,
                    filename=f"{folder}/html.html",
                )
            except Exception:
                self.logger.error(
                    msg="Can't save HTML to storage",
                    exc_info=True,
                )

        try:
            browser_log_url = file_storage.save_file_obj(
                content=self.browser_log.encode("utf-8"),
                filename=f"{folder}/browser_log.txt",
            )
        except Exception:
            self.logger.error(
                msg="Can't save browser log to storage",
                exc_info=True,
            )
            browser_log_url = ""

        return constants.FAILED_TEST_REPORT_TEMPLATE.format(
            url=self.url,
            screenshot_url=screenshot_url,
            html_url=html_url,
            browser_log_url=browser_log_url,
        )

__init__(webdriver)

Set error log and extract data from webdriver.

Source code in pytest_qaseio/debug_info.py
29
30
31
32
33
34
35
36
def __init__(self, webdriver: "WebDriver") -> None:
    """Set error log and extract data from webdriver."""
    self.webdriver = webdriver
    self.logger = logging.getLogger(__name__)
    self.screenshot = self._extract_screenshot()
    self.html = self._extract_html()
    self.browser_log = self._extract_browser_log()
    self.url = self._extract_url()

generate_debug_comment(file_storage, folder)

Generate debug comment with links to debug info files.

Source code in pytest_qaseio/debug_info.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def generate_debug_comment(
    self,
    file_storage: storage.FileStorage,
    folder: str,
) -> str:
    """Generate debug comment with links to debug info files."""
    screenshot_url = ""
    if self.screenshot:
        try:
            screenshot_url = file_storage.save_file_obj(
                content=self.screenshot,
                filename=f"{folder}/screenshot.png",
            )
        except Exception:
            self.logger.error(
                msg="Can't save screenshot to storage",
                exc_info=True,
            )

    html_url = ""
    if self.html:
        try:
            html_url = file_storage.save_file_obj(
                content=self.html,
                filename=f"{folder}/html.html",
            )
        except Exception:
            self.logger.error(
                msg="Can't save HTML to storage",
                exc_info=True,
            )

    try:
        browser_log_url = file_storage.save_file_obj(
            content=self.browser_log.encode("utf-8"),
            filename=f"{folder}/browser_log.txt",
        )
    except Exception:
        self.logger.error(
            msg="Can't save browser log to storage",
            exc_info=True,
        )
        browser_log_url = ""

    return constants.FAILED_TEST_REPORT_TEMPLATE.format(
        url=self.url,
        screenshot_url=screenshot_url,
        html_url=html_url,
        browser_log_url=browser_log_url,
    )