{"id":4550,"date":"2016-08-11T12:20:38","date_gmt":"2016-08-11T16:20:38","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=4550"},"modified":"2018-04-03T10:24:40","modified_gmt":"2018-04-03T14:24:40","slug":"pytest-and-browserstack","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/pytest-and-browserstack\/","title":{"rendered":"pytest and Browserstack"},"content":{"rendered":"<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/BrowserStack\">BrowserStack<\/a> is a cloud-based testing tool that enables developers\/testers to test their application across various browsers on different operating systems and mobile devices. We use Browserstack a lot at <a href=\"https:\/\/www.qxf2.com\/?utm_source=pytest_browserstack&#038;utm_medium=click&#038;utm_campaign=From%2520blog\">Qxf2<\/a> and recommend it to all our clients. We recently started using <a href=\"http:\/\/docs.pytest.org\/en\/latest\/\">pytest<\/a> to run our tests. We were surprised how quick and easy it was to configure pytest to run our tests on Browserstack. We have decided to share how we were able to do it.<\/p>\n<hr>\n<h3>Overview<\/h3>\n<p>BrowserStack needs four pieces of information to start a test:<br \/>\na) the browser<br \/>\nb) the browser version<br \/>\nc) the operating system<br \/>\nd) the operating system version<\/p>\n<p>In this post, we&#8217;ll show you how to add these four pieces of information as command line parameters to pytest. While the task at hand is direct, we thought this topic would make a good backdrop for you to learn more about pytest. So throughout this blog post, we have sprinkled in some useful tips that will help you get comfortable with pytest. If you do not understand some of the terms we use &#8211; it&#8217;s ok! You can still integrate your tests to use pytest and BrowserStack by following the step by step guide and the detailed code samples.<\/p>\n<hr>\n<h3>How to configure pytest to work with BrowserStack<\/h3>\n<p>pytest can be configured to suit our testing needs. It implements all aspects of configuration, collection, running and reporting. For our problem, there is one term in pytest land that you need to become familiar with &#8211; fixtures. A <a href=\"https:\/\/en.wikipedia.org\/wiki\/Test_fixture\">test fixture<\/a> is simply something that a test must (or may) need to know before it can be executed from a known state. We are going to treat each independent piece of information that BrowserStack requires (e.g.: browser, browser version) as <a href=\"http:\/\/doc.pytest.org\/en\/latest\/fixture.html\">pytest fixtures<\/a>. Fixtures can be created for the parameters that are being used in the test function. These fixtures can be held in the test file or be held in a special <code>conftest.py<\/code> file separately. The perk of having fixtures in a <code>conftest.py<\/code> is that it can be used by my multiple tests.<\/p>\n<p><strong>1. Create a conftest.py file<\/strong><br \/>\nTo begin with, create a file called <code>conftest.py<\/code> and place it in the root directory of your repository or code base. Your root directory is going to be the directory from which you kick off the <code>py.test<\/code> command.<\/p>\n<p><strong>2. Add a command line parameter to conftest.py<\/strong><\/p>\n<pre lang='python'>\r\n#Contents of the conftest.py file\r\ndef pytest_addoption(parser):\r\n    parser.addoption(\"-B\",\"--browser\",\r\n                      dest=\"browser\",\r\n                      default=\"firefox\",\r\n                      help=\"Browser. Valid options are firefox, ie and chrome\") \r\n<\/pre>\n<p><strong>3. Add a fixture to conftest.py<\/strong><\/p>\n<pre lang='python'>\r\n@pytest.fixture\r\ndef browser():\r\n    \"pytest fixture for browser\"\r\n    return pytest.config.getoption(\"-B\") #Note how this ties to the newly added command line parameter\r\n<\/pre>\n<p>Everytime pytest sees <code>browser<\/code> as the test function parameter it executes the pytest fixture which looks if any command line parameter has been provided, if no option is given pytest uses the default option that was mentioned when the option was added.<\/p>\n<p>We are almost done! Once you setup your <code>conftest.py<\/code> to take in the browser version, os and os version &#8211; you are done with configuring pytest. You can see the completed conftest file (has fixtures for all four pieces of information that BrowserStack needs) in the &#8216;Putting it all together section&#8217;.<\/p>\n<hr>\n<h3>How to run a test on Browserstack<\/h3>\n<p>In this section we will show you how to modify your test so it works well with BrowserStack and pytest. Let us try running an example test to check the browser title and test the form in the <a href='https:\/\/qxf2.com\/selenium-tutorial-main'>Qxf2-selenium-tutorial-page<\/a> on Browserstack using pytest.<\/p>\n<p>If you are completely new to BrowserStack, you can get started with this <a href=\"https:\/\/qxf2.com\/blog\/browserstack-part1\/\">post<\/a>. For the sake of completeness, we will show you a snippet required to get a webdriver and set useful <a href=\"https:\/\/www.browserstack.com\/automate\/capabilities\">capabilities<\/a>:<\/p>\n<pre lang='python'>\r\n#NOTE: This is highly simplified code to make this post illustrative\r\n#We do not use this code at clients\r\n#We use Driver_Factory to return apporpriate drivers within our framework\r\ndef get_webdriver(browser,browser_version,platform,os_version):\r\n    \"Run the test in browser stack browser stack flag is 'Y'\"\r\n    USERNAME = usename #We fetch values from a conf file in our framework we use on our clients\r\n    PASSWORD = accesskey\r\n    if browser.lower() == 'firefox':\r\n        desired_capabilities = DesiredCapabilities.FIREFOX\r\n    if browser.lower() == 'chrome':\r\n        desired_capabilities = DesiredCapabilities.CHROME\r\n    desired_capabilities['os'] = platform\r\n    desired_capabilities['os_version'] = os_version\r\n    desired_capabilities['browser_version'] = browser_version\r\n\r\n    return webdriver.Remote(command_executor='http:\/\/%s:%s@hub.browserstack.com:80\/wd\/hub'%(USERNAME,PASSWORD),\r\n                            desired_capabilities=desired_capabilities)\r\n<\/pre>\n<p>The <code>get_webdriver<\/code> method gets the browser,browser_version,platform,os_version sets them as the desired capabilities and returns the appropriate webdriver.<\/p>\n<hr>\n<h3>Putting it all together:<\/h3>\n<p>We are including a sample test for you to checkout the pytest and BrowserStack integration. The test script looks like the code below:<\/p>\n<pre lang='python'>\r\n#NOTE: This is highly simplified code to make this post illustrative\r\n#We do not use this code at clients\r\n#Our framework uses the Page Object pattern\r\n\r\n#Contents of test_example_form.py\r\ndef test_example_form(browser,browserstack_flag,browser_version,platform,os_version):\r\n    \"Test example form\"\r\n\r\n    #Create an driver object\r\n    driver = get_webdriver(browser,browser_version,platform,os_version)\r\n    #Create variables to keep count of pass\/fail\r\n    pass_check_counter = 0\r\n    total_checks = 0\r\n    #Visit the tutorial page\r\n    driver.get('http:\/\/qxf2.com\/selenium-tutorial-main') \r\n    print \"The browser for this test it %s\"%browser\r\n    print \"The browser version is %s\"%browser_version\r\n    print \"The platform is %s\"%platform\r\n    print \"The os version is %s\"%os_version\r\n    #Check 1: Is the page title correct?\r\n    if(driver.title==\"Qxf2 Services: Selenium training main\"):\r\n        print \"\\n\"\r\n        print (\"Success: Title of the Qxf2 Tutorial page is correct\")\r\n        pass_check_counter += 1\r\n    else:\r\n        print (\"Failed: Qxf2 Tutorial page Title is incorrect\")\r\n    total_checks += 1 \r\n    #Check 2: Fill name, email and phone in the example form\r\n    total_checks += 1\r\n    name_field = driver.find_element_by_xpath(\"\/\/input[@type='name']\")\r\n    name_field.send_keys('Shivahari')\r\n    email_field = driver.find_element_by_xpath(\"\/\/input[@type='email']\")\r\n    email_field.send_keys('test@qxf2.com')\r\n    phone_field = driver.find_element_by_xpath(\"\/\/input[@type='phone']\")\r\n    phone_field.send_keys('9999999999')\r\n    submit_button = driver.find_element_by_xpath(\"\/\/button[@type='submit']\") #Click on the Click me button\r\n    try:\r\n        submit_button.click()\r\n        pass_check_counter += 1\r\n    except Exception,e:\r\n        print str(e)   \r\n    #Quit the browser window\r\n    driver.quit() \r\n    #Assert if the pass and fail check counters are equal\r\n    assert total_checks == pass_check_counter \r\n<\/pre>\n<p>The completed <code>conftest.py<\/code> looks like this:<\/p>\n<pre lang='python'>\r\n#Contents of conftest.py\r\nimport pytest\r\nimport os\r\n\r\n@pytest.fixture\r\ndef browser():\r\n    \"pytest fixture for browser\"\r\n    return pytest.config.getoption(\"-B\")\r\n\r\n\r\n@pytest.fixture\r\ndef browserstack_flag():\r\n    \"pytest fixture for browserstack flag\"\r\n    return pytest.config.getoption(\"-M\")\r\n\r\n\r\n@pytest.fixture\r\ndef browser_version():\r\n    \"pytest fixture for browser version\"\r\n    return pytest.config.getoption(\"-V\") \r\n\r\n\r\n@pytest.fixture\r\ndef platform():\r\n    \"pytest fixture for platform\"\r\n    return pytest.config.getoption(\"-P\") \r\n\r\n\r\n@pytest.fixture\r\ndef os_version():\r\n    \"pytest fixture for os version\"\r\n    return pytest.config.getoption(\"-O\") \r\n\r\n\r\ndef pytest_addoption(parser):\r\n    parser.addoption(\"-B\",\"--browser\",\r\n                      dest=\"browser\",\r\n                      default=\"firefox\",\r\n                      help=\"Browser. Valid options are firefox, ie and chrome\") \r\n    parser.addoption(\"-M\",\"--browserstack_flag\",\r\n                      dest=\"browserstack_flag\",\r\n                      default=\"N\",\r\n                      help=\"Run the test in Browserstack: Y or N\")\r\n    parser.addoption(\"-V\",\"--ver\",\r\n                      dest=\"browser_version\",\r\n                      help=\"The version of the browser: a whole number\",\r\n                      default=45)\r\n    parser.addoption(\"-P\",\"--platform\",\r\n                      dest=\"platform\",\r\n                      help=\"The operating system: Windows 7, Linux\",\r\n                      default=\"Windows\")\r\n    parser.addoption(\"-O\",\"--os_version\",\r\n                      dest=\"os_version\",\r\n                      help=\"The operating system: xp, 7\",\r\n                      default=\"7\")\r\n<\/pre>\n<hr>\n<h3>Run the test:<\/h3>\n<p>To run the test use the command <code>py.test<\/code><br \/>\n<a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2016\/08\/pytest_test_run2-1.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2016\/08\/pytest_test_run2-1.png\" alt=\"pytest_test_run2\" width=\"788\" height=\"239\" class=\"aligncenter size-full wp-image-4606\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2016\/08\/pytest_test_run2-1.png 788w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2016\/08\/pytest_test_run2-1-300x91.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2016\/08\/pytest_test_run2-1-768x233.png 768w\" sizes=\"auto, (max-width: 788px) 100vw, 788px\" \/><\/a><br \/>\nYou can run this test on a different platform (say OS X Yosemite) using a different browser (say Chrome 50) by using the command:<br \/>\n<code>py.test -B chrome -V 50 -P \"OS X\" -O Yosemite -M y<\/code><\/p>\n<hr>\n<p>There you go,a detailed example to configure pytest and run tests on browserstack. Now try running the tests across different platforms,platform version,browsers and browser versions.<\/p>\n<p><strong>If you liked what you read, know more <a href=\"https:\/\/qxf2.com\/blog\/about-qxf2\/\">about Qxf2<\/a>.<\/strong><\/p>\n<hr>\n<script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.10.1 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-6165 mc4wp-form-theme mc4wp-form-theme-blue\" method=\"post\" data-id=\"6165\" data-name=\"Newsletter\" ><div class=\"mc4wp-form-fields\"><div style=\"border:3px; border-style:dashed;border-color:#56d1e1;padding:1.2em;\">\r\n  <h1 style=\"text-align: center; padding-top: 20px; padding-bottom: 20px; color: #592b1b;\">Subscribe to our weekly Newsletter<\/h1>\r\n  <input style=\"margin: auto;\" type=\"email\" name=\"EMAIL\" placeholder=\"Your email address\" required \/>\r\n  <br>\r\n  <p style=\"text-align: center;\">\r\n    <input style=\"background-color: #890c06 !important; border-color: #890c06;\" type=\"submit\" value=\"Sign up\" \/>\r\n    \r\n  <\/p>\r\n  <p style=\"text-align: center;\">\r\n    <a href=\"http:\/\/mailchi.mp\/c9c7b81ddf13\/the-informed-testers-newsletter-20-oct-2017\"><small>View a sample<\/small><\/a>\r\n  <\/p>\r\n  <br>\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1776764528\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"6165\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin -->\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>BrowserStack is a cloud-based testing tool that enables developers\/testers to test their application across various browsers on different operating systems and mobile devices. We use Browserstack a lot at Qxf2 and recommend it to all our clients. We recently started using pytest to run our tests. We were surprised how quick and easy it was to configure pytest to run [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,107],"tags":[],"class_list":["post-4550","post","type-post","status-publish","format-standard","hentry","category-browserstack","category-pytest"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/4550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=4550"}],"version-history":[{"count":59,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/4550\/revisions"}],"predecessor-version":[{"id":6225,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/4550\/revisions\/6225"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=4550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=4550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=4550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}