0

Got this error when calling the webdriver object; this has been defined within a fixture. Please refer to the below details:

Code structure:

tests

features

design.feature

step_defs

__init__.py

conftest.py

test1.py

Code in design.feature:

Feature:
 As a user I want to do something...etc

Scenario: Create design
    Given the user log in to "Electric"
    When set the map area 52.21623,0.12519

Code in test1.py:

scenario('../features/design.feature', 'Create design')

def test_create_design():
    pass


@given(parsers.parse('the user log in to "{name}"'), target_fixture='browser')
def login(browser, name: str):
    browser.get(login_url)
    browser.maximize_window()
    username_box = WebDriverWait(browser, 10).until(
        EC.presence_of_element_located((By.ID, "login-user")))
    username_box.send_keys(username)
    password_box = WebDriverWait(browser, 10).until(
        EC.element_to_be_clickable((By.ID, "login-pass")))
    password_box.send_keys(password)
    elm = WebDriverWait(browser, 10).until(
        EC.element_to_be_clickable((By.ID, "login-submission")))
    elm.click()
    time.sleep(5)
    if name == 'Electric':
        elm = WebDriverWait(browser, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@class='ui-layout-center ui-layout-pane ui-layout-pane-center']/"
                                                  "div[@id='app_options' ]/*[@class='box app_options_box'][2]")))
        elm.click()

    elif name == "Configuration":
        elm = WebDriverWait(browser, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, "//*[@class='ui-layout-center ui-layout-pane ui-layout-pane-center']/"
                           "div[@id='app_options' ]/*[@class='box app_options_box']"))
        )
        elm.click()
    time.sleep(5)
    


@when(parsers.parse('set the map area {lat},{long}'))
def set_map_area_and_center(browser, lat: float, long: float):

    print('you are here')
    time.sleep(5)
    browser.execute_script(f"myw.app.map.setView(myw.latLng({lat}, {long}))")
    time.sleep(3)
    browser.quit()

Code in conftest.py:

@pytest.fixture
def browser():
    w = webdriver.Chrome()
    yield w
    w.quit()

Result:

AttributeError: 'NoneType' object has no attribute 'execute_script' when function set_map_area_and_center is run--> at line browser.execute_script. This makes me think somehow the object is not returned from browser fixture? fixture browser is working when called first time in function login.

Expected result:

to be able to call the fixture within conftest.py or test1.py as many times is needed.

Can anybody help me understand why in the first instance(function login) fixture browser worked and second time (function set_map_area_and_center) didn't and how to solve this issue? Cheers.

Notes:

Mardjacku
  • 13
  • 6
  • anybody, any idea is appreciated – Mardjacku Jul 16 '22 at 20:48
  • Where is the `@when` decorator coming from? – Keith Jul 16 '22 at 21:19
  • Hi @Keith, I have updated the details about the code. "when" decorator comes from design.feature file and is inside the Scenario. Please refer to the above code. If you need any other info, please give me a shout. – Mardjacku Jul 16 '22 at 23:20
  • It looks like the pytest fixture is going through a Selenium decorator. Is that correct? – Keith Jul 16 '22 at 23:40
  • Yes, basically decorators "given" and "when" are special pytest-bdd decorators in which steps from Scenario are defined. the weird thing is that in "given", when calling "browser" does not complain but second time, in "when", says basically that browser is of "None" type @Keith – Mardjacku Jul 17 '22 at 07:48
  • yes, I am not sure I can help here, since I haven't used pytest-bdd. I noticed the other one has the `target_fixture` option, but the second doesn't. – Keith Jul 17 '22 at 08:17
  • I'm suspicious that the decorator is altering it, or closing it. – Keith Jul 17 '22 at 08:18
  • the second doesn't because only the given needs to have it-is mandatory, when, does not need to include the target_fixture. The problem here is the webdriver object, I think second time somehow, does not find it; this has nothing to do with the decorator but, I think with how the fixture has been created and called. @Keith – Mardjacku Jul 17 '22 at 09:42

1 Answers1

0

at @given decorator, should not be target_fixture, this will "create" and use another fixture call browser-in my case and, second time when @when decorator wants to use the browser fixture, pytest will raise an error because, basically sees it created 2 times with the same name and does not recognize it, hence the "None" type. To work, instead of:

@given(parsers.parse('the user log in to "{name}"'), target_fixture='browser')
def login(browser, name: str):
    browser.get(login_url)

should be:

@given(parsers.parse('the user log in to "{name}"'))
def login(browser, name: str):
    browser.get(login_url)
Mardjacku
  • 13
  • 6