Проблема с Timeout Exception в WebDriverWait + Python

Привет всем,
У меня есть код:

class WebTest(unittest.TestCase):

@classmethod
def setUpClass(cls):
    binary = FirefoxBinary('/home/andrew/Downloads/firefox 45/firefox')
    cls.browser = webdriver.Firefox(firefox_binary=binary)
    cls.wait = WebDriverWait(cls.browser, 10)
    cls.browser.maximize_window()
    cls.browser.get('http://www.test.com/')

def test_login_menu_elements(self):
    self.wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@id='menu_min']"))).click() 
    check_icons(self)
    self.wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@id='menu_min']"))).click() 
    check_fields(self)

def test_add_news(self):
    self.wait.until(EC.element_to_be_clickable((By.XPATH, "//span[contains(.,'News')]"))).click()
    self.wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/manager/news']"))).click()    

@classmethod
def tearDownClass(cls):
    cls.browser.quit()

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

Не могу понять почему у меня появляется ошибка TimeoutException когда все элементы находятся если я не использую wait.until а например использую time.wait(1).

Первое что приходит в голову - time.wait(1) ждет 1 секунду, за которую элементы таки не загружаются, а wait.until будет ждать 10 секунд пока элементы не загрузятся. Потомоу и ексепшн.

Просто не могу понять, что тогда надо изменить

код, который приведен, работает? Я не вижу просто где вы используете time.wait(1).

С time.wait(1) все работает. Но правельно использывать until.wait. У меня until.wait работает на других скриптах, но как я перешол на unittest перестал работать.

Если я запишу все в один метод, например так:
class WebTest(unittest.TestCase):

@classmethod
def setUpClass(cls):
binary = FirefoxBinary(‘/home/andrew/Downloads/firefox 45/firefox’)
cls.browser = webdriver.Firefox(firefox_binary=binary)
cls.wait = WebDriverWait(cls.browser, 10)
cls.browser.maximize_window()
cls.browser.get(‘http://www.test.com/’)

def test_login_menu_elements(self):
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//a[@id=‘menu_min’]”))).click()
check_icons(self)
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//a[@id=‘menu_min’]”))).click()
check_fields(self)
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//span[contains(.,‘News’)]”))).click()
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//a[@href=‘/manager/news’]”))).click()

@classmethod
def tearDownClass(cls):
cls.browser.quit()

if name==‘main’:
unittest.main()

Все будет работать, но когда я разбиваю тест на 2 метода как в моей проблеме у меня выскакивает TimeException. Я немогу разбить свои тесты на методы

Вот так работает

class Testclass(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome('chromedriver.exe')
        self.driver.maximize_window()
        self.driver.get('http://www.google.com/')

    def test_login_menu_elements(self):
        WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "gsfi"))).click()
    
    def test_login_menu_elements_2(self):
        WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.NAME, "btnK"))).click()

        

    def tearDown(self):
        self.driver.quit()

ну или если вам надо вынести отдельно WebDriverWait(self.driver, 10), то можно реализовать вот так

class Testclass(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome('chromedriver.exe')
        self.wait = WebDriverWait(self.driver, 10)
        self.driver.maximize_window()
        self.driver.get('http://www.google.com/')

    def test_login_menu_elements(self):
        self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "gsfi"))).click()
   
    def test_login_menu_elements_2(self):
        self.wait.until(EC.element_to_be_clickable((By.NAME, "btnK"))).click()

Работает, но браузер открывается 2 раза. Я думаю что моя проблема в том что поиск всех алиментов происходит на странице которая задана в def setUp() а когда происходит login то меняется url. Я думаю что нужно в методах указывать на каком url нужно искать элементы.

Ну походу да. Если задача просто проверить элементы - открывайте разные урл.
Если элементы в зависимости от нажатой кнопки - делайте в одном методе.
Я бы так делал, но не факт что это правильный подход )

Вопрос как можно сказать в тесте что, тест перешёл на новый url и надо искать элементы там…

Зависит от организации тестов.
После клика осуществляется переход, ожидаем какойто эелемент на новой странице, и проверяем уже там. Не надо передавать никакой новый url (в случае одного метода).
Или же снимать текущую урлу driver.current_url и передавать куда надо (в случае нескольких методов).

Но в этом случае, зачем делать несколько методов? Как организован тесткейс? Что то нажали на странице, перешли на другую страницу, и там нашли элемент - правильно? Ну это один тесткейс, по сути один метод.

А куда я могу засунуть это в свой код? как бы в методе test_add_news где я могу добавить driver.current_url:

def test_add_news(self):
driver.current_url???<<<<-----
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//span[contains(.,‘News’)]”))).click()
self.wait.until(EC.element_to_be_clickable((By.XPATH, “//a[@href=’/manager/news’]”))).click()

В вашем конкретном случае это делать не совсем корректно. Какой у вас кейс?

Вроде разобрался… Я написал в коде что нужно дождаться одного из элемента который должен, загрузится на следующей странице, и только потом продолжать тест.

Да, все верно

1 лайк

Спасибо за помощь!

1 лайк