Search code examples
pythonselenium-webdriverimportpytest

How to solve the import problem when using pytest?


I can't run my tests through pytest. And I have a strong belief that this is an imports issue. The project structure looks like in the attachment. In the root directory there is a file contest.py with a driver start and close fixture

import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

@pytest.fixture
def browser():
    """Fixture for initializing webdriver"""
    print("\nStarting browser for test...")
    browser = webdriver.Chrome()
    yield browser
    print("\nClosing browser...")
    browser.quit()

Test methods are described in the base_page.py file, which is located in the pages folder

from .locators import BasePageLocators

class BasePage:
   
    def __init__(self, browser, url, timeout=10):
        self.browser = browser
        self.url = url
        browser.implicitly_wait(timeout)

    def open(self):
        self.browser.get(self.url)

    def is_element_present(self, how, what):
        try:
            self.browser.find_element(how, what)
        except:
            return False
        return True
    
    def should_be_sign_up_button(self):
        assert self.is_element_present(*BasePageLocators.SIGN_UP, "No Sign Up button on the page")

    def open_sign_up_modal(self):
        self.browser.find_element(*BasePageLocators.SIGN_UP).click()
        assert self.is_element_present(*BasePageLocators.CREATE_ACCOUNT_H2, "Sign Up modal is not open")

There is a file with locators (locators.py) in a same folder

from selenium.webdriver.common.by import By

class BasePageLocators():
    SIGN_UP = (By.XPATH, "//button[text()='Sign Up']")
    CREATE_ACCOUNT_H2 = (By.XPATH, "//h2[text()='Create Your Account']")

And a file with tests (tase_base_page.py) in the tests folder

from pages.base_page import BasePage

link = "https://somelink.com/"

class TestSignUp():

    def test_see_sign_up(browser):
        page = BasePage(browser, link)
        page.open()
        page.should_be_sign_up_button()

    def test_open_sign_up_modal(browser):
        page = BasePage(browser, link)
        page.open()
        page.open_sign_up_modal()

Every time I run the tests, I get the error "AttributeError: 'TestSignUp' object has no attribute 'implicitly_wait'". But if I remove this method, another error appears, and so it is every time: if I fix one thing, another error appears.

When using the command "pytest --fixtures" from the "tests" folder, the "browser" fixture, which is defined in the conftest.py file, is not output.

I tried creating another project with one test, running it through pytest: the message that no tests were run was displayed, although the browser instance was running.

Asked ChatGPT - useless, implemented all tips - no use

Moved the project directory to the C drive

Added/removed points before imports

Reinstalled pytest, etc.

Help me, please! :)


Solution

  • You are missing the self arg in your test methods

    e.g.

        def test_see_sign_up(self, browser):
            page = BasePage(browser, link)
            page.open()
            page.should_be_sign_up_button()
    

    At the moment you have:

        def test_see_sign_up(browser):
            page = BasePage(browser, link)
            page.open()
            page.should_be_sign_up_button()
    

    This means that instead of receiving the browser fixture value, you have just given your self arg a different name.

    So then when you instantiate the BasePage you are passing the test class instance as browser var.

    Which is why you get AttributeError: 'TestSignUp' object has no attribute 'implicitly_wait' when the BasePage instance calls browser.implicitly_wait(timeout).

    Self arg is required when defining test cases inside a test class. Alternatively you could just define them as module functions without being inside a class, e.g.

    def test_see_sign_up(browser):
        page = BasePage(browser, link)
        page.open()
        page.should_be_sign_up_button()
    
    def test_open_sign_up_modal(browser):
        page = BasePage(browser, link)
        page.open()
        page.open_sign_up_modal()