在每次基于Selenium的自动化测试后,我是否应该退出浏览器?

4
我试图让我的Selenium测试尽可能原子化和相互独立,因此我决定在每次测试运行后退出浏览器并创建一个新的Webdriver实例。这种方法对我来说更有意义,并得到了几个讨论此问题的线程的支持。例如:相关问题的这个答案:

您正在关闭webdriver以结束特定测试。 这是一个好方法,但如果您要运行每个新测试,则需要启动新的webdriver。

然而,我也遇到了放弃每个测试后浏览器的看法认为这样做是无必要且低效的。例如:这篇关于Selenium的博客的一部分:

每个测试之前加载浏览器不是好的做法。相反,在所有测试之前加载浏览器,然后在执行所有测试后关闭浏览器是更好的选择,因为这将节省资源和测试执行时间。

作为初学者,我很难选择两者之间的区别。到目前为止,我的测试执行时间不是真正的问题(因为我只有少量测试),但随着开始扩展我的测试套件,我担心这可能成为一个问题。

2
是的,这是个好主意。通常你会想让每个测试都从一个已知状态开始,而不是从之前测试中遗留下来的污染状态开始。 - Corey Goldberg
2个回答

4
直截了当地回答,使用Selenium执行测试时,没有明确的规则来退出或重用同一浏览器客户端。也许决策将基于测试用例的先决条件。如果您的测试是独立的,最好在每次测试运行后quit()当前的Webdriver和浏览器客户端实例,并创建一个新的Webdriver和浏览器客户端实例,这将启动一个新的、干净的WebDriver/浏览器客户端组合,如在测试通过后关闭浏览器中所讨论的那样。
尽管生成新的WebDriver /浏览器客户端组合会产生一些开销,但这可能会提供所需的缓冲,以减少CPU和内存使用,如限制chrome headless CPU和内存使用使用Firefox时Selenium占用过多RAM中所讨论的那样。如果测试不是独立的,并且基于相同的会话、cookie等参数,则重用相同的WebDriver /浏览器客户端是有意义的。

3
我看过的最佳实践文档都指出测试应该是独立的。在每次测试运行时启动一个新的浏览器实例有助于维护每次运行的干净状态。拥有独立的测试并在每个运行中启动新的浏览器可以清除页面以进行并行执行,这是真正节省时间的关键。以下是SauceLabs的其中一个最佳实践文档示例链接:https://wiki.saucelabs.com/display/DOCS/Best+Practices+for+Running+Tests。 - JeffC

3
DebanjanB有一个很棒的答案。我认为没有一个通用的答案。
有一些有趣的平衡点。根据你使用的框架,你可以变得很复杂。我喜欢pytest因为它独特的固定装置用法。
为此,您可以根据需要进行测试或测试集。您可以平衡浏览器加载时间和执行时间,以确定哪种方式更为合理。
例如,在pytest中:
conftest.py:
import pytest
from selenium import webdriver

@pytest.fixture(scope='module')
def module_browser(request):
    """Fixture lasts for an entire file of tests."""
    driver = webdriver.Chrome()
    def fin():
        driver.quit()
    request.addfinalizer(fin())
    return driver

@pytest.fixture(scope='function')
def function_browser(request):
    """Fixture lasts for just a test function."""
    driver = webdriver.Chrome()
    def fin():
        driver.quit()
    request.addfinalizer(fin())
    return driver

现在module_browser()让你可以获取整个测试模块的浏览器。funtion_browser()为每个测试功能提供一个新的浏览器。
让我们变得更加高级...你有一堆需要登录的测试,并且它们正在使用标准账户进行美化检查:
conftest.py 继续...
@pytest.fixture(scope='module')
def logged_in_browser(request):
    """Provide a logged in browser for simple tests."""
    driver = webdriver.Opera()
    # Now go and log this browser in, 
    # so we can use the logged in state for tests.
    log_in_browser(username='RedMage', password='masmune')   
    def fin():
        driver.quit()
    request.addfinalizer(fin())
    return driver

这段内容介绍了一种关于it技术的方法。该方法可以在测试期间保持浏览器开启,并且已经登录。如果登录需要5秒钟,而你又有30个测试需要检查外观方面的事情,那么你可以节省几分钟的时间。
这种灵活性允许您更快地运行某些测试,并以更干净的状态运行其他测试。我们可能需要在整套测试中运行一些测试,同时仍能提高效率。因此,没有一个通用的答案。
使用 pytest 中的 fixture 可以为每个测试选择所需的选项,例如是一个清洁的浏览器还是需要更快的速度。
接下来,在测试中,我们会看到如下代码: test_things.py
def test_logged_out_assets(function_browser):
    driver = function_browser  # just for clarity here.
    driver.get('http://example.com/')
    check_some_stuff(driver)

language_subdomain_list = ['www', 'es', 'de', 'ru', 'cz']
@pytest.parametrize(language_subdomain, language_subdomain_list)
def test_logged_out_assets_multlingual(module_browser, language_subdomain):
    """
    Check the assets come up on each language subdomain.

    This test will run for each of the subdomains as separate tests.
    5 in all.
    """
    driver = module_browser  # for clarity in example.
    url = "http://{}.example.com".format(language_subdomain)
    driver.get(url)
    check_some_stuff(driver)

def test_logged_in_assets(logged_in_browser):
    """
    Check specific assets while logged in.

    Remember, our web browser already is logged in when we get it!
    """
    driver = logged_in_browser  # for clarity in example.
    check_some_assets(driver)

Py.test配件:https://docs.pytest.org/en/latest/fixture.html


谢谢您的回答,将这两种方法结合起来似乎确实很实用。我还没有深入研究pytest fixtures,因为我使用的pytest-selenium插件在幕后完成了大部分工作。不过,我计划回头去尝试理解它们,以便在未来使我的测试更加健壮。 - CrispJam
非常高兴能够帮忙!我还没有尝试过pytest-selenium插件,我会去看一下的。我使用Aerokube/Selenoid运行本地和远程网格实例,所以我只是手动构建了一个连接器并使用它。不过我会去检查一下这个插件的! - NanoMage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接