user3081458
user3081458

Reputation: 43

Python..Behave..Selenium..Page Objects - Set up browser in environment.py but cannot access in page objects modules

My file structure is as follows

Tests/
├── BehaveTest1
│   ├── BehaveTest1.feature
│       └── environment.py
│   └── steps 
│       └── test_steps.py
├── BehaveTest2
│   ├── BehaveTest2.feature
│       └── environment.py
│   └── steps
│       └── test_steps.py
├── common.py
├── __init__.py

I have set up the Chrome browser in environment.py

from selenium import webdriver

def before_feature(context, feature):
    print("Before feature\n")
    context.browser = webdriver.Chrome()

In a base_model.py I set up the base class for the Page Objects

class BaseModel:
    def __init__(self, browser):
        self.browser = browser

The first Page Object is home_model.py

from selenium.common.exceptions import NoSuchElementException
from .base_model import *

class HomeModel(BaseModel):
    def __init__(self, context):
        BaseModel.__init__(self, context.browser)

    def cookie_notification(self):
        return "all4gn-cookie-policy-notification"

    def click_cookie_notification(self, context):
        context.browser.click_element('class', str(self.cookie_notification()))

When I run the tests, two browsers start up. Why is that?

I want to make all my calls in the Page Objects, NOT in the step definitions. I just want to be able to call the Page Objects to in my step definitions.

This means I need access to the context variable which controls the browser.

Upvotes: 0

Views: 1955

Answers (1)

natn2323
natn2323

Reputation: 2061

First, if you're testing the same system/software, let me suggest that you don't have 2 separate directories to hold your tests.

Why? You can have multiple feature files within a features/ directory and multiple step definitions within the features/steps/ directory. When run in the features/ directory, Behave will search through all the .feature files and use the necessary .py files pertaining to your feature files. The environment.py within your features/ directory applies to all the step definitions in the features/steps/ directory.

If you're testing completely different things (i.e. different feature files needing different environments / environment.py's), then I believe you'd have to control your program at a higher level and possibly reorganize your test suite, since what you've already tried doesn't seem to work.

Even more, if you're using this directory structure for organizational purposes, realize that Behave is strict in regards to its directory structure. Instead, you'll have to use tags and good naming conventions to organize your suite.

Second, for the way you want to use your BaseModel and HomeModel classes within environment.py and within the step definitions, I suggest you follow these steps:

  1. Have all your files within one test suite:

    Tests/
    ├── environment.py
    ├── common.py
    ├── __init__.py
    ├── BehaveTest1.feature
    ├── BehaveTest2.feature
    └── steps 
        └── test_step1.py
        └── test_step2.py 
    
  2. Import your base_model.py and home_model.py files into your environment.py file.
  3. Initialize your class objects in environment.py's before_all(context) function. For example,

    def before_all(context):
        browser = webdriver.Chrome()
        base_model = BaseModel(browser)
        context.home_model = HomeModel(base_model)
    
  4. Make use of your class object within a step:

    def step_impl(context):
        some_string = context.home_model.cookie_notification()
    

From my experience with Behave, this is the normal approach which makes use of Behave and its capabilities.

Upvotes: 1

Related Questions