Karl
Karl

Reputation: 619

Python Selenium Test Suite Single Webdriver Instance?

I'm having some real issues trying to work out how to get this to work, and I'm sure there are some experts on here who can work it out for me, please :)

So I have a number of test cases in python that all follow on from each other, but are individual scripts, I want to combine these and run them in order, in a single webdriver instance, as they all follow on, but I can't seem to work out how to do it..

I have created a test suite -

import unittest

from Searchfieldreturnscorrectvalue import SearchFieldReturnsCorrectValue

from Navigatetostreetlightprecontentpage import Navigatetostreetlightprecontentpage


class TestSuite(unittest.TestSuite):

  def suite():
    suite = unittest.TestSuite()
suite.addTest(Searchfieldreturnscorrectvalue('test_searchfieldreturnscorrectvalue'))
suite.addTest(Navigatetostreetlightprecontentpage('test_navigatetostreetlightprecontentpage'))
return suite

if __name__ == "__main__":
  unittest.main()

This runs the tests, but the second one fails as it tried to run it in a second firefox instance..

Searchfieldreturnscorrectvalue.py

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class SearchFieldReturnsCorrectValue(unittest.TestCase):
def setUp(self):
    self.driver = webdriver.Firefox()
    self.driver.implicitly_wait(30)
    self.base_url = "https://www.XXXXX.com/"
    self.verificationErrors = []
    self.accept_next_alert = True

def test_search_field_returns_correct_value(self):
    driver = self.driver
    driver.get(self.base_url + "/")
    driver.find_element_by_id("edit-search-block-form--2").click()
    driver.find_element_by_id("edit-query").clear()
    driver.find_element_by_id("edit-query").send_keys("street light")
    driver.find_element_by_id("edit-query").send_keys(Keys.ENTER)
    for i in range(60):
        try:
            if self.is_element_present(By.LINK_TEXT, "Street lighting"): break
        except: pass
        time.sleep(1)
    else: self.fail("time out")
    try: self.assertEqual("Street lighting", driver.find_element_by_link_text("Street lighting").text)
    except AssertionError as e: self.verificationErrors.append(str(e))

def is_element_present(self, how, what):
    try: self.driver.find_element(by=how, value=what)
    except NoSuchElementException as e: return False
    return True

def is_alert_present(self):
    try: self.driver.switch_to_alert()
    except NoAlertPresentException as e: return False
    return True

def close_alert_and_get_its_text(self):
    try:
        alert = self.driver.switch_to_alert()
        alert_text = alert.text
        if self.accept_next_alert:
            alert.accept()
        else:
            alert.dismiss()
        return alert_text
    finally: self.accept_next_alert = True

def tearDown(self):
    self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
unittest.main()

Navigatetostreetlightprecontentpage.py

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class Navigatetostreetlightprecontentpage(unittest.TestCase):
def setUp(self):
    self.driver = webdriver.Firefox()
    self.verificationErrors = []
    self.accept_next_alert = True

def test_navigatetostreetlightprecontentpage(self):
    driver = self.driver
    driver.find_element_by_link_text("Street lighting").click()
    try: self.assertEqual("Street lighting", driver.find_element_by_css_selector("h1.page-title__main__title").text)
    except AssertionError as e: self.verificationErrors.append(str(e))
    try: self.assertEqual("Report a faulty street light | Cheshire East", driver.title)
    except AssertionError as e: self.verificationErrors.append(str(e))

def is_element_present(self, how, what):
    try: self.driver.find_element(by=how, value=what)
    except NoSuchElementException as e: return False
    return True

def is_alert_present(self):
    try: self.driver.switch_to_alert()
    except NoAlertPresentException as e: return False
    return True

def close_alert_and_get_its_text(self):
    try:
        alert = self.driver.switch_to_alert()
        alert_text = alert.text
        if self.accept_next_alert:
            alert.accept()
        else:
            alert.dismiss()
        return alert_text
    finally: self.accept_next_alert = True

def tearDown(self):
    self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
unittest.main()

I don't know if a test suite is the correct way to do it, or to just get all the tests into one file, but I still would want the "Classes/Tests" to individually report pass/fail, at the moment I can't get that to work, I think it is something to do with the setUp(self) needing to be moved to a setUpModule and shared? But I can't work it out, if someone could please point me in the right direction, I would be very grateful.

Thanks

Update

Example of what I have tired as per comment bellow, still not working..

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class SeleniumTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
    cls.driver = webdriver.Firefox()
    cls.driver.maximize_window()

@classmethod
def tearDownClass(cls):
    cls.driver.close()
    cls.driver.quit()

class SearchFieldReturnsCorrectValue(SeleniumTest):
def setUp(cls):
    cls.base_url = "https://www.XXXXX.com"
    cls.verificationErrors = []
    cls.accept_next_alert = True

def test_search_field_returns_correct_value(cls):
    driver = cls.driver
    driver.get(cls.base_url + "/")
    driver.find_element_by_id("edit-search-block-form--2").click()
    driver.find_element_by_id("edit-query").clear()
    driver.find_element_by_id("edit-query").send_keys("street light")
    driver.find_element_by_id("edit-query").send_keys(Keys.ENTER)
    for i in range(60):
        try:
            if cls.is_element_present(By.LINK_TEXT, "Street lighting"): break
        except: pass
        time.sleep(1)
    else: cls.fail("time out")
    try: cls.assertEqual("Street lighting", driver.find_element_by_link_text("Street lighting").text)
    except AssertionError as e: cls.verificationErrors.append(str(e))
    driver.find_element_by_link_text("Street lighting").click()

def is_element_present(cls, how, what):
    try: cls.driver.find_element(by=how, value=what)
    except NoSuchElementException as e: return False
    return True

def is_alert_present(cls):
    try: cls.driver.switch_to_alert()
    except NoAlertPresentException as e: return False
    return True

def close_alert_and_get_its_text(cls):
    try:
        alert = cls.driver.switch_to_alert()
        alert_text = alert.text
        if cls.accept_next_alert:
            alert.accept()
        else:
            alert.dismiss()
        return alert_text
    finally: cls.accept_next_alert = True

def tearDown(cls):
    cls.assertEqual([], cls.verificationErrors)            


class Navigatetostreetlightprecontentpage(SeleniumTest):
def setUp(cls):
    cls.verificationErrors = []
    cls.accept_next_alert = True

def test_navigatetostreetlightprecontentpage(cls):
    driver = cls.driver
    try: cls.assertEqual("Street lighting", driver.find_element_by_css_selector("h1.page-title__main__title").text)
    except AssertionError as e: cls.verificationErrors.append(str(e))
    try: cls.assertEqual("Report a faulty street light | Cheshire East", driver.title)
    except AssertionError as e: cls.verificationErrors.append(str(e))

def is_element_present(cls, how, what):
    try: cls.driver.find_element(by=how, value=what)
    except NoSuchElementException as e: return False
    return True

def is_alert_present(cls):
    try: cls.driver.switch_to_alert()
    except NoAlertPresentException as e: return False
    return True

def close_alert_and_get_its_text(cls):
    try:
        alert = cls.driver.switch_to_alert()
        alert_text = alert.text
        if cls.accept_next_alert:
            alert.accept()
        else:
            alert.dismiss()
        return alert_text
    finally: cls.accept_next_alert = True

def tearDown(cls):
    cls.assertEqual([], cls.verificationErrors)

if __name__ == "__main__":
unittest.main()

This seems to be running both classes now, but the second class is never able to locate any elements, but the same line in the first class works perfectly.

Upvotes: 1

Views: 1355

Answers (2)

Sibasish Mohanta
Sibasish Mohanta

Reputation: 1

import unittest

from selenium import webdriver from time import sleep class SeleniumTest(unittest.TestCase):

global driver

@classmethod
def setUpClass(cls):
    #getting a common webdriver instance for all your tests for this module
    cls.driver = webdriver.Chrome("/Users/sibasish/PycharmProjects/CommonDriverInstance/chromedriver")
    cls.driver.get("https://www.google.com")

@classmethod
def tearDownClass(cls):
    cls.driver.close()
    cls.driver.quit()

class MyTestClass(SeleniumTest): def setUp(self): pass

def test_sample1(self):
    print("hello1")
    self.driver.get("https://www.google.com/")
    sleep(4)

def test_sample2(self):
    print("hello2")
    self.driver.get("https://www.facebook.com/")
    sleep(4)

Upvotes: 0

JulienD
JulienD

Reputation: 7293

I am not sure I understood well, but to use a single driver instance, you can use the setupClass class method where you create the driver:

class MyTestClass(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()

    def setUp(self):
         ....

It will still recreate the driver for every new test class, but it does not recreate one for every test (as setUp does).

Personnally I make all my test classes inherit from a SeleniumTest class like this:

class SeleniumTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()

class MyTestClass(SeleniumTest):
    def setUp(self):
         ....

Upvotes: 3

Related Questions