behave API documentation.<\/a><\/p>\n\n\n\nBrowser Initialization with Fixtures<\/h1>\n\n\n\n Ok, let\u2019s start with fixture implementation in the fixtures.py file<\/p>\n\n\n\n
from selenium import webdriver\nfrom web_driver.web import Web\n\n\n\ndef browser_chrome(context, timeout=30, **kwargs):\n browser = webdriver.Chrome(\"C:\/chromedriver.exe\")\n web = Web(browser)\n context.web = web\n yield context.web\n browser.quit()\n<\/pre>\n\n\n\nHere, we have browser_chrome(context, timeout=30, **kwargs) function that will be used as a fixture to start a web browser.<\/p>\n\n\n\n
This function starts a webdriver instance that starts a Chrome browser. Then we create the instance of the Web class to access web elements on webpages. Later, we create a new attribute in context \u2013 web, that can be referenced further in our steps implementations to access the Web instance. By using yield and browser.quit() in the next line, we are making sure that the browser will be closed after all the tests that use browser_chrome are complete.<\/p>\n\n\n\n
Let\u2019s see this in action and provide the implementation for the steps in the scenario we defined earlier in the flight_search.feature file. In the features directory of the project create a new python directory, steps, and add flight_search_steps.py there.<\/p>\n\n\n\n <\/figure>\n\n\n\nfrom behave import given, when, then\nfrom behave.log_capture import capture\n\n\n@given(\"the user is on search page\")\ndef user_on_search_page(context):\n context.web.open(\"http:\/\/blazedemo.com\/\")\n\n\n@when(\"user selects Paris as departure city\")\ndef user_select_departure_city(context):\n context.web.find_by_xpath(\"\/\/select[@name='fromPort']\/option[text()='Paris']\").click()\n\n@when(\"user selects London as destination city\")\ndef user_select_destination_city(context):\n context.web.find_by_xpath(\"\/\/select[@name='toPort']\/option[text()='London']\").click()\n\n@when(\"clicks on Find Flights button\")\ndef user_clicks_on_find_flights(context):\n context.web.find_by_xpath(\"\/\/input[@type='submit']\").click()\n\n@then(\"flights are found\")\ndef flights_are_found(context):\n elements = context.web.finds_by_xpath(\"\/\/table\/tbody\/tr\")\n assert len(elements) > 1\n<\/pre>\n\n\n\nEvery step that is mentioned in the flight_search.feature file has an implementation here. In every step we reference a web instance through the context. This is a convenient way to access a shared resource without taking care of the way it was initialized, isn\u2019t it?<\/p>\n\n\n\n
To apply a fixture, we need to define the behavior for the before_tag option in the features\/environment.py file.<\/p>\n\n\n\n <\/figure>\n\n\n\nfrom behave import use_fixture\n\nfrom fixtures import browser_chrome\n\ndef before_tag(context, tag):\n if tag == \"fixture.browser.chrome\":\n use_fixture(browser_chrome, context)\n<\/pre>\n\n\n\nAs you can see, if a tag equals \u201cfixture.browser.chrome\u201d then we execute the browser_chrome fixture by calling the use_fixture method. To try it out, in your project root directory, execute \u201cbehave\u201d in the command line. The output should look like this:<\/p>\n\n\n\n <\/figure>\n\n\n\nThere are two main disadvantages to loading a webdriver with this fixtures approach:<\/p>\n\n\n\n
1. Fixtures have a scope that is defined by the scope of the tag \u201c@fixture.*\u201d If we are using @fixture in a scenario, then the web browser will be opened and closed for every scenario with the @fixture tag. The same happens if @fixture is applied to a feature. So, if we have multiple features, the browser will start and close for every feature. This is not good if we don\u2019t want our features to be executed in parallel, but a great option otherwise, by the way.<\/p>\n\n\n\n
2. We need to assign a @fixture tag to every scenario or feature that is supposed to have access to a web page. This is not a good option. Moreover, what if we want to switch to another browser? Do we need to go over all the features and modify @fixture.browser every time?! This issue can be solved by applying the fixture in before_all(context) function from environment.py. like this:<\/p>\n\n\n\n
def before_all(context):\n if context.browser == \"chrome\":\n use_fixture(browser_chrome, context)\n<\/pre>\n\n\n\nBut it looks like we are searching for a solution for the issue with instruments that can be used themselves without fixtures. Let\u2019s have a look at how.<\/p>\n\n\n\n
Behave gives us the option to define configurations in configuration files that can be called either \u201c.behaverc\u201d, \u201cbehave.ini\u201d, \u201csetup.cfg\u201d or \u201ctox.ini\u201d (your preference) and are located in one of three places:<\/p>\n\n\n\n
The current working directory (good for per-project settings),<\/li> Your home directory ($HOME), or<\/li> On Windows, in the %APPDATA% directory.<\/li><\/ol>\n\n\n\nThere are a number of configurations that are used by behave to setup your environment. But you can also use this file to identify your own environment variables, such as a browser.<\/p>\n\n\n\n <\/figure>\n\n\n\nBesides the browser, we have stderr_capture and stdout_capture set to False. By default those parameters are set to True, which means that behave will not print any message to the console, or any other output you specified, if the test is not failed. Setting to False will force behave to print any output even if the test passed. This is a great option if you need to see what is going on in your tests.<\/p>\n\n\n\n
Browser Initialization Environment Functions<\/h1>\n\n\n\n Earlier in the blog post, I mentioned there were two ways to start a webdriver. The first one is to use fixtures. We have already defined how to do it. The second option is to use environment functions. Let\u2019s see how to do it.<\/p>\n\n\n\n
We will get access to a Web instance through the before_all environment function in environment.py file. To do that, at first create the web_source\/web_factory.py file.<\/p>\n\n\n\n <\/figure>\n\n\n\nfrom selenium import webdriver\nfrom web.web import Web\n\n\ndef get_web(browser):\n if browser == \"chrome\":\n return Web(webdriver.Chrome(\"C:\/chromedriver.exe\"))\n<\/pre>\n\n\n\nThe code is quite simple and straightforward.<\/p>\n\n\n\n
In the environment.py file for before_all(context):<\/p>\n\n\n\n
from web_source.web_factory import get_web\n\n\ndef before_all(context):\n web = get_web(context.config.userdata['browser'])\n context.web = web\n<\/pre>\n\n\n\nHere, in the code, we are getting the currently set browser from the \u201cbrowser\u201d variable defined in behave.ini in the [behave.userdata] section.<\/p>\n\n\n\n
You can try out this code by executing \u201cbehave\u201d in the command line.<\/p>\n\n\n\n
This approach is more flexible since we don\u2019t need to modify feature files to switch to another browser.<\/p>\n\n\n\n
When to Use Fixtures<\/h1>\n\n\n\n But then you can ask: when should I use fixtures? Fixtures are a good option if your initialization depends on the environment you are currently on. For example, if for the development environment you would like to setup a connection to one database, and for the production environment you would like to setup another connection. This can be achieved in the following way:<\/p>\n\n\n\n
fixture_registry = {\"develop\": develop_database,\n \"production\": production_database}\n\n\ndef before_tag(context, tag):\n if tag.startswith(\"environment\"):\n use_fixture_by_tag(tag, context, fixture_registry)\n<\/pre>\n\n\n\nFor any feature and scenario tagged with @environment.develop or @environment.production, in the before_tag environment function, the appropriate fixture will be loaded and executed as defined in fixture_registry.<\/p>\n\n\n\n
If you don\u2019t know if you should be using fixtures or another approach, just ask yourself: will fixtures create more issues than they solve? If answer is no, that you can use it. Basically, almost everything that is configurable by tags, can be managed by fixtures. If you have tag : slow, you can increase your timeout and then revert it back for fast test cases and so on.<\/p>\n\n\n\n
Implementing Parameterized Steps<\/h1>\n\n\n\n In the feature from the features\/flight_search.feature file we saw how to create a test with static data. But what if we want to search for a flight not only from Paris to London? For such purposes, you can use parameterized steps. Let\u2019s have a look at the implementation:<\/p>\n\n\n\n
The feature file will be modified to a new one:<\/p>\n\n\n\n
Feature: The user can book available flights\n Scenario: The user can find a flight from Paris to London\n Given the user is on the search page\n When the user selects a departure city \"Paris\"\n And the user selects a destination city \"London\"\n And clicks on the Find Flights button\n Then flights are present on the search result page\n<\/pre>\n\n\n\nAnd the steps implementation for choosing cities will be changed: <\/p>\n\n\n\n
@when('the user select departure city \"{city}\"')\ndef user_select_departure_city(context, city):\n context.web.find_by_xpath(\"\/\/select[@name='fromPort']\/option[text()='{}']\".format(city)).click()\n\n@when('the user select destination city \"{city}\"')\ndef user_select_destination_city(context, city):\n context.web.find_by_xpath(\"\/\/select[@name='toPort']\/option[text()='{}']\".format(city)).click()\n \n<\/pre>\n\n\n\nAs you can see now the required city is loaded from parameters.<\/p>\n\n\n\n
Execution Commands<\/h1>\n\n\n\n So far, we have executed our features using the simple command \u201cbehave\u201d. But the behave framework suggests different options for execution. The most useful ones:<\/p>\n\n\n\n
–include, –exclude – to include or exclude features from test run.<\/li> –junit – if you would like to get a junit<\/a> report. You can read more about JUnit on the official site.<\/a><\/li>-logging-level – to specify level of logging. By default INFO is selected, which means that all messages will be captured.<\/li> –logging-format – to define a format messages will be printed within.<\/li> –tags to filter scenarios that you would like to run. Only scenarios with the specified tag will be executed.<\/li><\/ul>\n\n\n\nhttps:\/\/www.blazemeter.com\/blog\/using-the-behave-framework-for-selenium-bdd-testing-a-tutorial\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"Let\u2019s say you have a task to automate the testing of an application. Where should you start? The first step is to choose an approach to test automation, which will be the basis for your test development. When you are searching for possible …. Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"class_list":["post-72","page","type-page","status-publish","hentry"],"yoast_head":"\nUsing the behave Framework for Selenium BDD Testing: A Tutorial • BDD Testing<\/title>\n \n \n \n \n \n \n \n \n \n \n \n \n \n\t \n