├── .gitignore ├── LICENSE ├── README.md ├── requirements.txt └── tests ├── __init__.py ├── data ├── __init__.py ├── config.py └── settings.json ├── features ├── __init__.py └── dashboard.feature ├── framework ├── __init__.py └── webapp.py ├── pages ├── __init__.py └── dashboard.py └── steps ├── __init__.py ├── common.py └── dashboard.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # PyCharm 104 | .idea/ 105 | 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rhoynar Software Consulting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-selenium-bdd 2 | A Python based Test framework including BDD, Selenium Webdriver and Page Object Model. 3 | 4 | Read more about how to use this repository in the medium article: [BDD, Cucumber and Selenium WebDriver based Test Automation Framework in Python](https://medium.com/@hmurari/bdd-cucumber-and-selenium-webdriver-based-test-automation-framework-in-python-ae092a7581d3) 5 | 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://pypi.org/simple 2 | behave==1.2.6 3 | selenium==3.13.0 4 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/__init__.py -------------------------------------------------------------------------------- /tests/data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/data/__init__.py -------------------------------------------------------------------------------- /tests/data/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | settings = None 5 | 6 | 7 | def load_settings(): 8 | global settings 9 | with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.json')) as f: 10 | settings = json.load(f) 11 | 12 | 13 | load_settings() 14 | -------------------------------------------------------------------------------- /tests/data/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://www.google.com", 3 | "browser": "chrome" 4 | } 5 | -------------------------------------------------------------------------------- /tests/features/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/features/__init__.py -------------------------------------------------------------------------------- /tests/features/dashboard.feature: -------------------------------------------------------------------------------- 1 | Feature: Dashboard 2 | 3 | Scenario Outline: Components 4 | Given I load the website 5 | When I go to "Dashboard" page 6 | Then I see this component "" 7 | Examples: 8 | | rows | 9 | | Status | 10 | | Detector Settings | 11 | | Battery | 12 | | GPS | 13 | 14 | Scenario Outline: Status 15 | Given I load the website 16 | When I go to "Dashboard" page 17 | Then Dashboard Status shows correct values for row "" 18 | Examples: 19 | | rows | 20 | | Status | 21 | | White Reference Count | 22 | | Collect Reference Count | 23 | | Dark Reference Count | 24 | | Last White Reference | 25 | | Last Optimize | 26 | | Last Dark Reference | 27 | | Last Wavelength Check | 28 | 29 | Scenario: Status Refresh 30 | Given I load the website 31 | When I go to "Dashboard" page 32 | Then Clicking on Status Refresh should refresh status component 33 | 34 | Scenario: Battery 35 | Given I load the website 36 | When I go to "Dashboard" page 37 | Then Dashboard Battery shows Battery or AC Power with correct icon. 38 | 39 | Scenario: Battery Refresh 40 | Given I load the website 41 | When I go to "Dashboard" page 42 | Then Clicking on Battery Refresh should refresh battery component 43 | 44 | Scenario Outline: Detector Settings 45 | Given I load the website 46 | When I go to "Dashboard" page 47 | Then Dashboard Detector Settings shows correct values for row "" 48 | Examples: 49 | | rows | 50 | | VNIR | 51 | | SWIR1 | 52 | | SWIR2 | 53 | 54 | Scenario Outline: GPS 55 | Given I load the website 56 | When I go to "Dashboard" page 57 | Then Dashboard GPS shows correct values for row "" 58 | Examples: 59 | | rows | 60 | | Fix | 61 | | Location | 62 | | Altitude | 63 | | Format | 64 | 65 | -------------------------------------------------------------------------------- /tests/framework/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/framework/__init__.py -------------------------------------------------------------------------------- /tests/framework/webapp.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from data.config import settings 3 | from urllib.parse import urljoin 4 | 5 | 6 | class WebApp: 7 | instance = None 8 | 9 | @classmethod 10 | def get_instance(cls): 11 | if cls.instance is None: 12 | cls.instance = WebApp() 13 | return cls.instance 14 | 15 | def __init__(self): 16 | if str(settings['browser']).lower() is "firefox": 17 | self.driver = webdriver.Firefox() 18 | elif str(settings['browser']).lower() is "chrome": 19 | self.driver = webdriver.Chrome() 20 | else: 21 | self.driver = webdriver.Firefox() 22 | 23 | def get_driver(self): 24 | return self.driver 25 | 26 | def load_website(self): 27 | self.driver.get(settings['url']) 28 | 29 | def goto_page(self, page): 30 | self.driver.get(urljoin(settings['url'], page.lower())) 31 | 32 | def verify_component_exists(self, component): 33 | # Simple implementation 34 | assert component in self.driver.find_element_by_tag_name('body').text, \ 35 | "Component {} not found on page".format(component) 36 | 37 | 38 | webapp = WebApp.get_instance() 39 | -------------------------------------------------------------------------------- /tests/pages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/pages/__init__.py -------------------------------------------------------------------------------- /tests/pages/dashboard.py: -------------------------------------------------------------------------------- 1 | from framework.webapp import webapp 2 | 3 | 4 | class Dashboard(): 5 | instance = None 6 | 7 | @classmethod 8 | def get_instance(cls): 9 | if cls.instance is None: 10 | cls.instance = Dashboard() 11 | return cls.instance 12 | 13 | def __init__(self): 14 | self.driver = webapp.get_driver() 15 | 16 | def verify_status(self, row): 17 | # Ex: 18 | # status = self.driver.find_element_by_id('dashboard-status-component').text 19 | # assert row in status, "{} not present in status component".format(row) 20 | print('Verifying dashboard status..') 21 | 22 | def verify_refresh(self): 23 | # Ex: 24 | # refresh = self.driver.find_element_by_id('dashboard-status-refresh-btn') 25 | # refresh.click() 26 | print('Verifying dashboard refresh component..') 27 | 28 | def verify_battery_status(self): 29 | # Ex: 30 | # battery = self.driver.find_element_by_id('dashboard-battery-status-component').text 31 | # assert battery is not None 32 | print('Verifying Battery status..') 33 | 34 | def verify_battery_refresh(self): 35 | # Ex: 36 | # refresh = self.driver.find_element_by_id('dashboard-battery-refresh-btn') 37 | # refresh.click() 38 | print('Verifying battery refresh..') 39 | 40 | def verify_gps_setting(self, row): 41 | # Ex: 42 | # status = self.driver.find_element_by_id('gps-setting-component').text 43 | # assert row in status, "{} not present in GPS component".format(row) 44 | print('Verifying GPS setting..') 45 | 46 | 47 | dashboard = Dashboard.get_instance() 48 | -------------------------------------------------------------------------------- /tests/steps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoynar/python-selenium-bdd/41eb54dd8c197a67a5f34f0c1d27115abceb5b7d/tests/steps/__init__.py -------------------------------------------------------------------------------- /tests/steps/common.py: -------------------------------------------------------------------------------- 1 | from behave import given, when, then 2 | from framework.webapp import webapp 3 | 4 | 5 | @given(u'I load the website') 6 | def step_impl_load_website(context): 7 | webapp.load_website() 8 | 9 | 10 | @when(u'I go to "{page}" page') 11 | def step_impl_goto_page(context, page): 12 | webapp.goto_page(page) 13 | 14 | 15 | @then(u'I see this component "{component}"') 16 | def step_impl_verify_component(context, component): 17 | webapp.verify_component_exists(component) 18 | -------------------------------------------------------------------------------- /tests/steps/dashboard.py: -------------------------------------------------------------------------------- 1 | from behave import given, when, then 2 | from pages.dashboard import dashboard 3 | 4 | 5 | @then(u'Dashboard Status shows correct values for row "{row}"') 6 | def step_impl_dashboard_status(context, row): 7 | dashboard.verify_status(row) 8 | 9 | 10 | @then(u'Clicking on Status Refresh should refresh status component') 11 | def step_impl_status_refresh(context): 12 | dashboard.verify_refresh() 13 | 14 | 15 | @then(u'Dashboard Battery shows Battery or AC Power with correct icon.') 16 | def step_impl_battery_status(context): 17 | dashboard.verify_battery_status() 18 | 19 | 20 | @then(u'Clicking on Battery Refresh should refresh battery component') 21 | def step_impl_battery_refresh(context): 22 | dashboard.verify_battery_refresh() 23 | 24 | 25 | @then(u'Dashboard Detector Settings shows correct values for row "{row}"') 26 | def step_impl_detector_settings(context, row): 27 | dashboard.veify_detector_setting(row) 28 | 29 | 30 | @then(u'Dashboard GPS shows correct values for row "{row}"') 31 | def step_impl_gps_settings(context, row): 32 | dashboard.verify_gps_setting(row) 33 | --------------------------------------------------------------------------------