在复杂测试Sui中捕获测试失败的截图

2024-04-20 02:17:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我想设置一个很好的方式来捕捉截图,当我们的一些机器人框架前端测试失败。当然,我可以补充:

Run Keyword If Test Failed    Capture Page Screenshot

为了测试Teardown,但考虑到我有大量复杂的测试套件,有数百个测试和一个嵌套结构,我需要将其添加到如此多的拆分中,这在我看来很难看。在

我做了一点实验。我认为未来的方法是使用listener。所以我试了一下:

^{pr2}$

它捕获了屏幕截图,但在日志中看不到图片。我可以在测试消息中显示它,在捕获后添加以下步骤:

BuiltIn().set_test_message("*HTML* {} <br/> <img src={}>".format(result.message, screenshot_name))

但这并不是最好的。在

然后我尝试了另一种方法来处理Visitor接口(与--prerunmodifier一起使用):

from robot.api import SuiteVisitor


class CaptureScreenshot(SuiteVisitor):

    def end_test(self, test):
        if test.status == 'FAIL':
            test.keywords.create('Capture Page Screenshot', type='teardown')

但是它用新的测试替换现有的测试Teardown(只有一个关键字“Capture Page Screenshot”)。我以为我可以通过添加Capture关键字来修改现有的Teardowns,但我没有

有什么好的,干净的,Python式的方法吗?我错过什么了吗?在


Tags: 方法runtest框架messageif方式page
2条回答

我把所有的东西都包在一个try/除了测试块中。这样,在任何时候,如果测试失败,屏幕截图在except块中,我会在/…之前/之后得到一个屏幕快照。在

try:
    class UnitTestRunner():
        ...
except:
    driver.save_screenshot('filepath')

最后,它以库侦听器结束,如下所示。我不得不同意Bryan的观点:代码不短也不漂亮,但它实现了预期的目标-在套件中定义了截图捕捉的单点。 作为一个很大的优势,我看到了捕捉失败设置的屏幕截图的可能性-在某些情况下,它可以帮助我们识别可能的基础设施问题。 请注意带有ActionChains的部分-它在浏览器中缩小。我们的前端应用程序使用部分页面滚动,通过这种缩放,我们可以看到更多的内容,这对我们非常有帮助。每个浏览器的操作链的结果不同,所以这是真正的解决方法。在

#!/usr/bin/python
# -*- coding: utf-8 -*-
from Selenium2Library import Selenium2Library
from selenium.common.exceptions import StaleElementReferenceException, WebDriverException
import re


class ExtendedSelenium(Selenium2Library):
    """ Robot Framework library extending Robot Framework Selenium2Library library.
    """
    ROBOT_LISTENER_API_VERSION = 2
    DON_NOT_CAPTURE_KEYWORDS = ["Run Keyword And Ignore Error", "Run Keyword And Expect Error", "Run Keyword And Return Status", "Wait Until.*"]

    def __init__(self, timeout=5.0, implicit_wait=0.0, run_on_failure='', screenshot_root_directory=None):
        super(ExtendedSelenium, self).__init__(timeout, implicit_wait, run_on_failure, screenshot_root_directory)
        self.ROBOT_LIBRARY_LISTENER = self
        self._is_current_keyword_inside_teardown = False
        self._do_not_capture_parent_keywords_count = 0
        self._screenshot_was_captured = False

    def _start_test(self, name, attributes):
        """ Reset flags at the begin of each test.
        """
        self._do_not_capture_parent_keywords_count = 0
        self._is_current_keyword_inside_teardown = False
        self._screenshot_was_captured = False

    def _start_keyword(self, name, attributes):
        """ Set keyword flag at the beginning of teardown.
        If the keyword is one of the 'do not capture keywords' increase _do_not_capture_parent_keywords_count counter.
        """
        if attributes["type"] == "Teardown":
            self._is_current_keyword_inside_teardown = True
        if any(kw for kw in self.DON_NOT_CAPTURE_KEYWORDS if re.match(kw, attributes["kwname"])):
            self._do_not_capture_parent_keywords_count += 1

    def _end_keyword(self, name, attributes):
        """If the keyword is one of the 'do not capture keywords' decrease _do_not_capture_parent_keywords_count counter.
        Capture Screenshot if:
        - keyword failed AND
        - test is not in teardown phase AND
        - the parent keyword isn't one of the 'do not capture keywords'
        RuntimeError exception is thrown when no browser is open (backend test), no screenshot is captured in this case.
        """
        if any(kw for kw in self.DON_NOT_CAPTURE_KEYWORDS if re.match(kw, attributes["kwname"])):
            self._do_not_capture_parent_keywords_count -= 1
        if not attributes["status"] == "PASS" and not self._is_current_keyword_inside_teardown and self._do_not_capture_parent_keywords_count == 0 and not self._screenshot_was_captured:
            self._screenshot_was_captured = True
            try:
                self.capture_page_screenshot()
                # TODO refactor this so it is reusable and nice!
                from selenium.webdriver.common.action_chains import ActionChains
                from selenium.webdriver.common.keys import Keys
                ActionChains(super(ExtendedSelenium, self)._current_browser()).send_keys(Keys.CONTROL, Keys.SUBTRACT, Keys.NULL).perform()
                ActionChains(super(ExtendedSelenium, self)._current_browser()).send_keys(Keys.CONTROL, Keys.SUBTRACT, Keys.NULL).perform()
                self.capture_page_screenshot()
                ActionChains(super(ExtendedSelenium, self)._current_browser()).send_keys(Keys.CONTROL, '0', Keys.NULL).perform()
            except RuntimeError:
                pass

欢迎发表任何意见。在

相关问题 更多 >