在为Firefox和Chrome编写selenium测试时避免代码重复

在为Firefox和Chrome编写selenium测试时避免代码重复,selenium,google-chrome,firefox,design-patterns,dry,Selenium,Google Chrome,Firefox,Design Patterns,Dry,如果您为Selenium编写测试来检查Firefox和Chrome,那么测试看起来非常相似,除了设置,请参见例如,它在python中具有相同的功能test\u search\u Chrome和在python中test\u search\u Firefox。selenium中有避免代码重复的模式,例如 有没有办法避免这种巨大的代码重复?您提供的链接中的设置的内容是驱动程序初始化。您可以在另一个类中处理此问题,并从属性文件中删除浏览器类型 def get_driver(self): brow

如果您为Selenium编写测试来检查Firefox和Chrome,那么测试看起来非常相似,除了设置,请参见例如,它在python中具有相同的功能test\u search\u Chrome和在python中test\u search\u Firefox。selenium中有避免代码重复的模式,例如


有没有办法避免这种巨大的代码重复?

您提供的链接中的
设置
的内容是
驱动程序
初始化。您可以在另一个类中处理此问题,并从属性文件中删除浏览器类型

def get_driver(self):
    browser = get_value_from_configurations_file()
    url = get_value_from_configurations_file()

    driver = None
    if browser == 'chrome':
         driver = webdriver.Chrome()
    elif browser == 'firefox':
         driver = webdriver.Firefox()

    driver.maximize_window()
    driver.get(url)

    return driver
我通常在驱动程序工厂和测试之间使用一个“中间人”来处理
驱动程序
操作并获得PO起点

class WebApplication:

    def __init__(self):
        self.__driver = WebDriverFactory().get_driver()

    def get_driver(self):
        return self.__driver

    def get_home_page(self):
        return HomePage(self.__driver)        
并从基本测试类使用它

@pytest.mark.usefixtures("run_for_test")
class AbstractTest(ABC):

    web_application = None

    @pytest.fixture()
    def run_for_test(self, request):
        AbstractTest.web_application = WebApplication()
        # set up for all tests
        yield
        # tear down for all tests
示例测试:

class TestExample(AbstractTest):

    def test_example(self):
        home_page = \
            (self.web_application
             .get_home_page())

这样,只需更改配置文件,即可编写一次测试并在不同浏览器上运行。

您提供的链接中的
设置
内容是
驱动程序
初始化。您可以在另一个类中处理此问题,并从属性文件中删除浏览器类型

def get_driver(self):
    browser = get_value_from_configurations_file()
    url = get_value_from_configurations_file()

    driver = None
    if browser == 'chrome':
         driver = webdriver.Chrome()
    elif browser == 'firefox':
         driver = webdriver.Firefox()

    driver.maximize_window()
    driver.get(url)

    return driver
我通常在驱动程序工厂和测试之间使用一个“中间人”来处理
驱动程序
操作并获得PO起点

class WebApplication:

    def __init__(self):
        self.__driver = WebDriverFactory().get_driver()

    def get_driver(self):
        return self.__driver

    def get_home_page(self):
        return HomePage(self.__driver)        
并从基本测试类使用它

@pytest.mark.usefixtures("run_for_test")
class AbstractTest(ABC):

    web_application = None

    @pytest.fixture()
    def run_for_test(self, request):
        AbstractTest.web_application = WebApplication()
        # set up for all tests
        yield
        # tear down for all tests
示例测试:

class TestExample(AbstractTest):

    def test_example(self):
        home_page = \
            (self.web_application
             .get_home_page())

这样,您只需更改配置文件,就可以编写一次测试并在不同的浏览器上运行。

@Guy的回答指明了方向。使用
MixIns
更简单一些:

class DuckMixin(object):
    def testDuckLoads(self):
        self.browser.get("https://duckduckgo.com")
        self.assertIn("duckduckgo", self.browser.title.lower())

    def testDuckSafe(self):
        self.browser.get("https://duckduckgo.com")
        (self.browser
         .find_element_by_id("search_form_input_homepage")
         .send_keys("porn" + webdriver.common.keys.Keys.RETURN))
        # click to disable temporarily, then wait, then see if available
        self.browser.implicitly_wait(10)
        self.browser.find_element_by_class_name("js-safe-search-temp").click()
        # assert that browser.find_element_by_class_name("js-safe-search-temp") still exists, else throws exception
        self.browser.find_element_by_class_name("js-safe-search-temp")


class DuckDuckGoTestCaseFirefox(unittest.TestCase, DuckMixin):
    def setUp(self):
        profile = webdriver.FirefoxProfile()
        profile.add_extension(extension=os.path.join(DIR, "..", "addon"))
        self.browser = webdriver.Firefox(firefox_profile=profile)

    def tearDown(self):
        self.browser.close()

class DuckDuckGoTestCaseChromium(unittest.TestCase, DuckMixin):
    def setUp(self):
        profile = webdriver.chrome.options.Options()
        profile.add_extension(extension=os.path.join(DIR, "..", "safe.zip"))
        self.browser = webdriver.Chrome(chrome_options=profile)

    def tearDown(self):
        self.browser.close()

@盖伊的回答指明了方向。使用
MixIns
更简单一些:

class DuckMixin(object):
    def testDuckLoads(self):
        self.browser.get("https://duckduckgo.com")
        self.assertIn("duckduckgo", self.browser.title.lower())

    def testDuckSafe(self):
        self.browser.get("https://duckduckgo.com")
        (self.browser
         .find_element_by_id("search_form_input_homepage")
         .send_keys("porn" + webdriver.common.keys.Keys.RETURN))
        # click to disable temporarily, then wait, then see if available
        self.browser.implicitly_wait(10)
        self.browser.find_element_by_class_name("js-safe-search-temp").click()
        # assert that browser.find_element_by_class_name("js-safe-search-temp") still exists, else throws exception
        self.browser.find_element_by_class_name("js-safe-search-temp")


class DuckDuckGoTestCaseFirefox(unittest.TestCase, DuckMixin):
    def setUp(self):
        profile = webdriver.FirefoxProfile()
        profile.add_extension(extension=os.path.join(DIR, "..", "addon"))
        self.browser = webdriver.Firefox(firefox_profile=profile)

    def tearDown(self):
        self.browser.close()

class DuckDuckGoTestCaseChromium(unittest.TestCase, DuckMixin):
    def setUp(self):
        profile = webdriver.chrome.options.Options()
        profile.add_extension(extension=os.path.join(DIR, "..", "safe.zip"))
        self.browser = webdriver.Chrome(chrome_options=profile)

    def tearDown(self):
        self.browser.close()

@close投票者是否愿意解释他的推理?我假设close投票者希望您将代码放入问题本身(您应该这样做)。有一天你可能会删除该回购协议或将其完全更改,那么这个问题就没有背景了。A应该在问题中。第二点可以指出,这个问题是离题的,因为您有工作代码。你真的是在要求对上的代码进行审查。@JeffC:在搜索时,链接的代码出现了,我只有一些丑陋的东西不起作用:我用基类免除了TestCase,但失败了。请@close投票者解释一下他的理由,还是没有?我假设投票人希望你把你的代码放在问题本身(你应该这样做)。有一天你可能会删除该回购协议或将其完全更改,那么这个问题就没有背景了。A应该在问题中。第二点可以指出,这个问题是离题的,因为您有工作代码。你真的是在要求对上的代码进行检查。@JeffC:搜索时出现了链接代码,我只有一些不好的东西没有用:我用基类从TestCase中删除了,但失败了。我要补充的一点是,这两个测试基本相同,所以应该删除一个。驱动程序管理器将负责驱动程序实例,无论是firefox还是chrome。我想你是间接地提到了这一点,但我会明确地说明这一点,因为OP要求得到反馈。另一个次要的评论是关于屏幕截图代码(测试的最后一行)。。。我会删除浏览器名称并添加时间戳,以便以后的sshot不会覆盖以前的sshot。@JeffC我根据您的第一条评论编辑了我的答案。关于第二条评论,我同意,但这不是重点(我个人会从PO上截图),所以我没有提及。我想补充的一点是,这两个测试基本相同,所以应该删除一个。驱动程序管理器将负责驱动程序实例,无论是firefox还是chrome。我想你是间接地提到了这一点,但我会明确地说明这一点,因为OP要求得到反馈。另一个次要的评论是关于屏幕截图代码(测试的最后一行)。。。我会删除浏览器名称并添加时间戳,以便以后的sshot不会覆盖以前的sshot。@JeffC我根据您的第一条评论编辑了我的答案。关于第二条评论,我同意,但这不是重点(我个人会从PO上截图),所以我没有提及。