Skip to content

Commit

Permalink
Merge pull request #69 from jdi-testing/bumping-dependencies-and-test…
Browse files Browse the repository at this point in the history
…-site

Bumping dependencies and test site
  • Loading branch information
vklonin authored Mar 20, 2024
2 parents ca179df + ecaa6f6 commit 7ba7e6c
Show file tree
Hide file tree
Showing 38 changed files with 223 additions and 231 deletions.
23 changes: 11 additions & 12 deletions .github/workflows/jdi-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,32 @@ on:
jobs:
build:

runs-on: windows-latest
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.x']
python-version: ['3.11']
browser: [chrome, firefox]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Download Chrome driver
run: |
cd utils
python get_driver.py
# TODO: use virtual machine for tests run
- name: Run unit tests
run: |
pytest -v --cov=. --cov-config=.coveragerc --cov-report=html -m unit
shell: cmd
shell: bash
- name: Run tests excluding 'unit' tests on ${{ matrix.browser }}
run: |
pytest -v -m "not unit" --browser=${{ matrix.browser }}
shell: bash
- name: Save debug log file
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: logs
path: debug.log
Expand Down
6 changes: 1 addition & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Getting started

Before you begin:
- Python 3.8 is used for this project.
- Python 3.11 is used for this project.
- For EPAM employees only: have you read the [Best Practices for Managing Secrets](https://elearn.epam.com/courses/course-v1:EPAM+5SCSS+0620/courseware/4b94c749c309409ea878fb7916be316b/ae4553f7cd524229b42f260b0ac692ed/1?activate_block_id=block-v1%3AEPAM%2B5SCSS%2B0620%2Btype%40vertical%2Bblock%40c04f1498c7d04ac4bf87b652741d90bb)?
- Check out the [existing issues](https://github.com/jdi-testing/jdi-python/issues).

Expand All @@ -19,10 +19,6 @@ When you're done making changes, open your PR and get it reviewed.

In order to test the project, run pytest.

Please don't forget to set up the environment variable `TEST_PASSWORD`. For example:

For Windows `set TEST_PASSWORD=<password>`

```bash
pytest <path to the project>/tests --no-header --no-summary -q
```
Expand Down
18 changes: 12 additions & 6 deletions JDI/core/settings/jdi_settings.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import logging
from pathlib import Path

logger = logging.Logger(__name__)

logger = logging.getLogger(__name__)

class PropertyPath:
def __init__(self, filename="jdi.properties"):
self._filename = Path(filename)
project_root = Path(__file__).parents[3]
self._filename = project_root / filename

def get_property_file(self):
logger.info("Directory to search {dir_to_search}".format(dir_to_search=self._filename))
logger.info(f"Directory to search {self._filename.parent}")
if self._filename.exists():
return self._filename
else:
raise FileNotFoundError("There is not property file with name '" + self._filename + "' in your project")
raise FileNotFoundError(f"There is no property file with name '{self._filename}' in your project")


class JDISettings:
Expand Down Expand Up @@ -46,7 +46,13 @@ def get_driver_path():
def get_setting_by_name(setting_name):
if not JDISettings._jdi_settings:
JDISettings._read_jdi_settings()
return JDISettings._jdi_settings.get(setting_name, None)
value = JDISettings._jdi_settings.get(setting_name, None)
if value.lower() in ("true", "yes", "1"):
return True
elif value.lower() in ("false", "no", "0"):
return False
else:
return value

@staticmethod
def get_current_timeout_sec():
Expand Down
53 changes: 25 additions & 28 deletions JDI/web/selenium/driver/selenium_driver_factory.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import os

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.webdriver import WebDriver as ChromeDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.firefox.service import Service as FirefoxService
from selenium.webdriver.firefox.webdriver import WebDriver as FirefoxDriver
from selenium.webdriver.remote.webdriver import WebDriver as RemoteDriver
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager

from JDI.core.settings.jdi_settings import JDISettings
from JDI.web.selenium.driver.driver_types import DriverTypes
from JDI.web.selenium.driver.web_driver_provider import WebDriverProvider


class SeleniumDriverFactory:
Expand All @@ -17,7 +19,6 @@ def __init__(self):
self.options = None
self.current_driver = None
self.browser_size = None
self.drivers_path = JDISettings.get_driver_path()
self.capabilities = {}

def register_driver(self, driver_name, options, capabilities, executor):
Expand All @@ -28,64 +29,60 @@ def register_driver(self, driver_name, options, capabilities, executor):
else:
if driver_name == DriverTypes.chrome.name:
self.current_driver = self.register_chrome_driver()
if driver_name == DriverTypes.firefox.name:
elif driver_name == DriverTypes.firefox.name:
self.current_driver = self.register_firefox_driver()
return driver_name

def set_driver_options_and_capabilities(self, driver_name, options, capabilities, executor):
if driver_name == DriverTypes.chrome.name:
self.options = ChromeOptions()
# TODO: move hardcoded arguments to params
self.options.add_argument("start-maximized")
self.options.add_argument("disable-gpu")
self.add_options(options) if options else True
if not capabilities and executor is not None:
if options:
self.add_options(options)
if not capabilities and executor is None:
self.capabilities = DesiredCapabilities.CHROME
if driver_name == DriverTypes.firefox.name:
elif driver_name == DriverTypes.firefox.name:
self.options = FirefoxOptions()
self.add_options(options) if options else True
if not capabilities and executor is not None:
self.options.add_argument("-start-maximized")
if options:
self.add_options(options)
if not capabilities and executor is None:
self.capabilities = DesiredCapabilities.FIREFOX
if capabilities:
self.capabilities = capabilities

def add_options(self, options):
for arg in options:
for arg in options.arguments:
self.options.add_argument(arg)

def register_chrome_driver(self):
chrome_driver = WebDriverProvider.get_chrome_driver_path()
os.environ["webdriver.chrome.driver"] = chrome_driver
return self.__web_driver_settings(ChromeDriver(executable_path=chrome_driver,
options=self.options,
desired_capabilities=self.capabilities))
service = Service(ChromeDriverManager().install())
return self.__web_driver_settings(ChromeDriver(service=service, options=self.options))

def register_firefox_driver(self):
raise NotImplementedError
service = FirefoxService(GeckoDriverManager().install())
return self.__web_driver_settings(FirefoxDriver(service=service, options=self.options))

def register_remote_driver(self, executor):
chrome_driver = WebDriverProvider.get_chrome_driver_path()
os.environ["webdriver.chrome.driver"] = chrome_driver
driver = self.__web_driver_settings(RemoteDriver(command_executor=executor,
options=self.options,
desired_capabilities=self.capabilities,
options=self.options,
keep_alive=True))
return driver

def __web_driver_settings(self, driver):
if self.browser_size is None:
driver.maximize_window()
if self.browser_size:
driver.set_window_size(*self.browser_size)
else:
driver.set_window_size(self.browser_size)
driver.maximize_window()
driver.implicitly_wait(JDISettings.get_current_timeout_sec())
return driver

def get_driver(self, options=None, capabilities=None, executor=None):
if self.current_driver is not None:
return self.current_driver
else:
if not self.current_driver:
self.register_driver(driver_name=DriverTypes.chrome.name,
options=options,
capabilities=capabilities,
executor=executor)
return self.current_driver
return self.current_driver
10 changes: 4 additions & 6 deletions JDI/web/selenium/driver/web_driver_provider.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import os
from webdriver_manager.chrome import ChromeDriverManager
import sys

from JDI.core.settings.jdi_settings import JDISettings


class WebDriverProvider:
@staticmethod
def get_chrome_driver_path():
chrome = "/chromedriver.exe" if sys.platform.startswith("win") else "chromedriver"
return os.path.join(JDISettings.get_driver_path(), chrome)
chrome = ChromeDriverManager().install()
return chrome

2 changes: 1 addition & 1 deletion JDI/web/selenium/elements/common/text_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, by_locator=None, by_label=None, web_element=None):
def input(self, text):
self.input_action(text)

def input_action(self,text):
def input_action(self, text):
self.get_web_element().send_keys(text)

@scenario(action_name="Send keys to the element")
Expand Down
26 changes: 13 additions & 13 deletions JDI/web/selenium/elements/composite/web_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,27 @@ def open(self):
self.get_driver().get(self.url)

def verify_opened(self):
result = False
url_check_passed = False
if self.check_url_type == CheckPageTypes.EQUAL:
result = self.check_url()
url_check_passed = self.check_url()
elif self.check_url_type == CheckPageTypes.MATCH:
result = self.match_url()
url_check_passed = self.match_url()
elif self.check_url_type == CheckPageTypes.CONTAINS:
result = self.contains_url()
if not result:
url_check_passed = self.contains_url()

if not url_check_passed:
return False

if self.title is None:
return True

if self.check_title_type == CheckPageTypes.EQUAL:
return self.check_title()
if self.check_title_type == CheckPageTypes.MATCH:
return self.match_title()
if self.check_title_type == CheckPageTypes.CONTAINS:
return self.contains_title()

return False
title_check_methods = {
CheckPageTypes.EQUAL: self.check_title,
CheckPageTypes.MATCH: self.match_title,
CheckPageTypes.CONTAINS: self.contains_title
}
title_check_method = title_check_methods.get(self.check_title_type, lambda: False)
return title_check_method()

def should_be_opened(self):
try:
Expand Down
18 changes: 17 additions & 1 deletion JDI/web/selenium/settings/web_settings.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import sys

from selenium.webdriver.remote.command import Command

from JDI.core.logger.jdi_logger import JDILogger
from JDI.core.settings.jdi_settings import JDISettings
from JDI.web.selenium.driver.selenium_driver_factory import \
SeleniumDriverFactory
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions


class WebSettings(JDISettings):
Expand All @@ -21,7 +25,19 @@ def set_driver_factory(driver_factory):

@staticmethod
def use_driver(options=None, capabilities=None, executor=None):
driver_name = JDISettings.get_setting_by_name("driver")
if options is None:
options = ChromeOptions() if JDISettings.get_setting_by_name(
"driver") == "chrome" else FirefoxOptions()

headless = JDISettings.get_setting_by_name("headless")

if headless:
options.add_argument("--headless")

driver_name = next(
(arg.split("=")[1] for arg in sys.argv if arg.startswith("--browser")),
JDISettings.get_setting_by_name("driver"))

JDISettings._driver_factory = SeleniumDriverFactory()
WebSettings.set_driver_factory(JDISettings._driver_factory)
return JDISettings._driver_factory.register_driver(driver_name, options, capabilities, executor)
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,18 @@

# JDI 2.0
Powerful Framework for UI Automation Testing on Python

## Getting started
Before you begin:
- Python 3.11 is used for this project. To install Python on MacOs you can use [Homebrew](https://brew.sh/), on Windows you can use [Chocolatey](https://chocolatey.org/).
- run git clone https://github.com/jdi-testing/jdi-python.git or fork the repository and clone it afterwards.
- create a virtual environment for the project. You can use [virtualenv](https://virtualenv.pypa.io/en/latest/) or [venv](https://docs.python.org/3/library/venv.html) for that.
- set up Python interpreter to use Python 3.11 in your IDE.
- run `pip install -r requirements.txt` to install all required dependencies.

## You can simply run tests to see how it works
1. inside your IDE
2. using pytest
- activate your virtual environment by running `source venv/bin/activate` on MacOs or `venv\Scripts\activate` on Windows
- run `pytest` in the terminal (eg. `pytest ./tests/jdi_uitests_webtests/test/common/` - to run all tests in the specified directory)
- be sure that you are in a project root directory when running the command
7 changes: 5 additions & 2 deletions jdi.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
driver=chrome
; domain=https://www.epam.com/
domain=https://jdi-framework.github.io/tests
domain=https://jdi-testing.github.io/jdi-light
timeout_wait_element=5
timeout_wait_pageLoad=5
drivers_folder=.\
driver_getLatest=true
driver_getLatest=true
headless=True
user=Roman
password=Jdi1234
4 changes: 3 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[pytest]
markers =
unit: marks unit tests
web: marks JDI tests
web: marks JDI tests
log_cli = true
log_cli_level = INFO
2 changes: 2 additions & 0 deletions requirements-dev-win.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-r requirements-dev.txt
pywin32==306
Loading

0 comments on commit 7ba7e6c

Please sign in to comment.