Python Unittest:如何在类中初始化selenium并避免浏览器打开两次?

问题描述 投票:0回答:3

考虑下面的示例,由于我在

setUp
方法中初始化驱动程序并在
test_login
中使用它,浏览器将打开两次,第一次在
setUp
期间,然后它将关闭并开始测试.

如果我从

setUp
中删除逻辑并将其放入
test_login
中,则驱动程序将在
test_profile
tearDown

中未定义

初始化驱动程序并在整个课程中使用它而不导致浏览器打开两次的正确方法是什么?

from selenium import webdriver
import unittest
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager


class Test(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(
            service=Service(ChromeDriverManager().install()))
        self.driver.get('https://example.com/login')
        self.current_url = self.driver.current_url
        self.dashboard_url = 'https://example.com/dashboard'

    def test_login(self):
        self.assertEqual(self.dashboard_url, self.current_url)
    
    def test_profile(self):
        self.driver.get('https://example.com/profile')
    
    def tearDown(self):
        self.driver.close()
python unit-testing selenium-webdriver selenium-chromedriver python-unittest
3个回答
1
投票

您需要使用 setUpClass / tearDownClass:

import unittest


class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print('setUpClass')

    @classmethod
    def tearDownClass(cls) -> None:
        print('tearDownClass')

    def setUp(self):
        print('setUp')

    def test_login(self):
        print('login')

    def test_profile(self):
        print('profile')

    def tearDown(self):
        print('tearDown')

1
投票

你的代码运行得很好。请在setUp和tearDown方法之前添加装饰器

@classmethod
。 另外,问题在于 setUp 方法中的
self.driver.get('https://example.com/login')
行。只需从那里删除它,也许创建一个新函数来保存该代码。


1
投票

这是一个将

unittest.TestCase
与 Selenium 结合使用的示例。它具有
setUp()
tearDown()
步骤,并且它会获得您正在寻找的所需行为,尽管可能比您要求的更多。

您可以使用

python -m unittest
运行它:

import sys
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from unittest import TestCase

class RefinedRawSelenium(TestCase):
    def setUp(self):
        self.driver = None
        options = webdriver.ChromeOptions()
        options.add_argument("--disable-notifications")
        if "linux" in sys.platform:
            options.add_argument("--headless=new")
        options.add_experimental_option(
            "excludeSwitches", ["enable-automation", "enable-logging"],
        )
        prefs = {
            "credentials_enable_service": False,
            "profile.password_manager_enabled": False,
        }
        options.add_experimental_option("prefs", prefs)
        self.driver = webdriver.Chrome(options=options)

    def tearDown(self):
        if self.driver:
            try:
                if self.driver.service.process:
                    self.driver.quit()
            except Exception:
                pass

    def wait_for_element_visible(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was not visible after %s seconds!"
                % (selector, timeout)
            )

    def wait_for_element_clickable(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was not visible/clickable after %s seconds!"
                % (selector, timeout)
            )

    def wait_for_element_not_visible(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.invisibility_of_element((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was still visible after %s seconds!"
                % (selector, timeout)
            )

    def open(self, url):
        self.driver.get(url)

    def click(self, selector, by="css selector", timeout=7):
        el = self.wait_for_element_clickable(selector, by=by, timeout=timeout)
        el.click()

    def type(self, selector, text, by="css selector", timeout=10):
        el = self.wait_for_element_clickable(selector, by=by, timeout=timeout)
        el.clear()
        if not text.endswith("\n"):
            el.send_keys(text)
        else:
            el.send_keys(text[:-1])
            el.submit()

    def assert_element(self, selector, by="css selector", timeout=7):
        self.wait_for_element_visible(selector, by=by, timeout=timeout)

    def assert_text(self, text, selector="html", by="css selector", timeout=7):
        el = self.wait_for_element_visible(selector, by=by, timeout=timeout)
        self.assertIn(text, el.text)

    def assert_exact_text(self, text, selector, by="css selector", timeout=7):
        el = self.wait_for_element_visible(selector, by=by, timeout=timeout)
        self.assertEqual(text, el.text)

    def assert_element_not_visible(
        self, selector, by="css selector", timeout=7
    ):
        self.wait_for_element_not_visible(selector, by=by, timeout=timeout)

    def test_add_item_to_cart(self):
        self.open("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_text("PRODUCTS", "span.title")
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_exact_text("YOUR CART", "span.title")
        self.assert_text("Backpack", "div.cart_item")
        self.click("#remove-sauce-labs-backpack")
        self.assert_element_not_visible("div.cart_item")
        self.click("#react-burger-menu-btn")
        self.click("a#logout_sidebar_link")
        self.assert_element("input#login-button")

# When run with "python" instead of "pytest" or "python -m unittest"
if __name__ == "__main__":
    from unittest import main
    main()

这是取自我在 SeleniumBase/examples/migration/raw_selenium/refined_raw.py

中的示例

这实际上将是我今年在 SeleniumConf 2023 会议上的一部分(https://seleniumconf.com/agenda/#python-selenium-fundamentals-to-frameworks-with-seleniumbase),我将在那里进行演示如何将其简化为这样的内容,在导入中在幕后使用

unittest.TestCase

from seleniumbase import BaseCase

class CleanSeleniumBase(BaseCase):
    def test_add_item_to_cart(self):
        self.open("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_text("PRODUCTS", "span.title")
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_exact_text("YOUR CART", "span.title")
        self.assert_text("Backpack", "div.cart_item")
        self.click("#remove-sauce-labs-backpack")
        self.assert_element_not_visible("div.cart_item")
        self.click("#react-burger-menu-btn")
        self.click("a#logout_sidebar_link")
        self.assert_element("input#login-button")

# When run with "python" instead of "pytest"
if __name__ == "__main__":
    from pytest import main
    main([__file__, "-s"])

(那个使用

seleniumbase.BaseCase
,它继承了
unittest.TestCase
。示例来自SeleniumBase/examples/migration/raw_selenium/simple_sbase.py

© www.soinside.com 2019 - 2024. All rights reserved.