- Go to "resources/cert/ZscalerRootCertificate-2048-SHA256.pem" copy this file and pasted in "C:\drive"
- Run the following command on "PowerShell"
mv $env:C:\drive\ZscalerRootCertificate-2048-SHA256.pem $env:APPDATA pip config set global.cert $env:APPDATA\ZscalerRootCertificate-2048-SHA256.pem
- Open Zscaler > More > About > App Policy: Crowley Tunner 2.0 >> Update Policy
- Try to download a Python Package Library: If fail try one more time to download the required library
- Search Inbox on task bar type "Edit environment variables for your account"
- On User variables for {Current User}, on PATH variable click on New
Add:
- C:\Users{Current User}\AppData\Local\Programs\Python\Python312\Scripts
- C:\Users{Current User}\AppData\Local\Programs\Python\Python312
- Check Python Version on Terminal
python --version pip --version
-
Requirements: Have Installed 'Node.js' and 'NPM' Package Management
npm install -g appium npm install -g appium-doctor npm install -g allure-commandline
-
Also is required to install Appium Drivers
appium driver install windows appium driver install gecko appium driver install chromium
-
Check Appium Drivers Installed
appium driver list
-
To execute Desktop Application Automation, user should be start up the Appium Server Before Execute any Test
appium --allow-cors
- Run the 'install.bat' file on project Root
- Check Packages Installed with following command on terminal
pip list
- In order to enable Terminal on Windows Pycharm user enable the following commands
Get-ExecutionPolicy -List Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
- In case that we need to install a individual package from the "requirements.txt" follow the next terminal command
pip install <package> --trusted-host pypi.org --trusted-host files.pythonhosted.org
- For Web Executions: Provide Profile, Application Name, Application Type, Browser and Allure Generate results
--profile=qa --app-name=softship --app-type=web --browser=chrome --alluredir=reports/allure-results
- Initialize Allure Server Report Example:
allure serve C:\Automation\QA%20Automation\applications\web\softship\tests\reports\allure-results
- For API Executions: Provide Profile, Application Name, Application Type and Allure Generate
--profile=qa --app-name=salesforce --app-type=api --alluredir=reports/allure-results
- Example:
pytest --profile=qa --app-name=softship --app-type=web --browser=edge --alluredir=reports/allure-results C:\QA%20Automation\applications\web\softship\tests\test_master_data_customer_suppliers_address.py::TestMasterDataCustomerSuppliersAddress
- Set the commands arguments with the test case specification
- The "BaseTest" class reads the arguments and set the "Driver" session on Top super class "BASE APP", this class share this variable under "BasePage" Child Class.
- All the "Action" Classes use the "Driver" session to Locate every Web Element before apply any action.
- All the "Child Objects" under "BasePage" will have enabled all these actions.
- File class name should be in CamelCase (PascalCase) every word should start with uppercase letter. Not use underscores or spaces.
- Examples:
- LoginPage
- SignUpPage
- WelcomePage
- Methods name should use snake_case format (lowercase letters with the words separated by underscores).
- Avoid method names that are just a verb; Try to be more descriptive if necessary.
- Examples:
- load_page
- set_username
- set_password
- Uses the snake_case format (lowercase letters with words separated by underscores).
- Example:
- user_list
- count_item
- file_name
- Uses a single underscore at the beginning of the name to indicate that a variable or method is "private."
- Example:
- _private_var
- _private_method
- _helper_method
- _driver
-
Locator are tuple objects, can have 2 values or 3 values in case the is necessary to specify the web element name reference. Following the next example the __input_username and __input_password has only the 'By' and 'value' but button_login contains an additional value to specify the reference name Login Button this value will display in the console log.
-
Example Code:
_input_user_name = (By.NAME, "username") _input_password = (By.NAME, "password") _button_login = (By.XPATH, "//button[contains(@class,'login-button')]", "Login Button")
-
Console Log Example:
BasePage - INFO: Event: [LoginPage] | Web Element By: [name] | Locator value: [username] BasePage - INFO: Event: [LoginPage] | Web Element By: [name] | Locator value: [password] BasePage - INFO: Event: [LoginPage] | Web Element By: [xpath] | Locator value: [//button[contains(@class,'login-button')]] | Login Button
In test automation and UI development, using standard prefixes for locators helps keep the code organized and maintainable.
Prefix | Description | Examples |
---|---|---|
_btn_ |
For buttons | _btn_login , _btn_submit , _btn_cancel |
_input_ |
For input fields | _input_username , _input_password , _input_search |
_link_ |
For links | _link_forgot_password , _link_home , _link_terms_of_service |
_chk_ |
For checkboxes | _chk_remember_me , _chk_terms , _chk_subscribe |
_rad_ |
For radio buttons | _rad_male , _rad_female , _rad_yes , _rad_no |
_select_ |
For dropdowns | _select_country , _select_language , _select_category |
_autocomplete_ |
For auto complete | _autocomplete_country , _autocomplete_language |
_txt_ |
For text areas | _txt_description , _txt_comment , _txt_address |
_msg_ |
For messages (error messages, warnings, etc.) | _msg_error , _msg_success , _msg_warning |
_img_ |
For images | _img_logo , _img_banner , _img_profile |
_ico_ |
For icons | _ico_settings , _ico_notification , _ico_search |
_div_ |
For divisions (containers, sections) | _div_header , _div_footer , _div_main_content |
_modal_ |
For modals or pop-ups | _modal_login , _modal_alert , _modal_confirmation |
_tab_ |
For tabs | _tab_profile , _tab_settings , _tab_notifications |
_form_ |
For forms | _form_login , _form_registration , _form_feedback |
_frame_ |
For Frames | _frame_login , _frame_registration , _frame_feedback |
_tbl_ |
For Tables | _tbl_customer , _tbl_suppliers , _tbl_address |
_nav_ |
For navigation elements | _nav_menu , _nav_sidebar , _nav_footer |
_lbl_ |
For Labels elements | _lbl_customer , _lbl_booking , lbl_contract |
Here is an example of how you might use these prefixes in a page class for a test:
from selenium.webdriver.common.by import By
class LoginPage(BasePage):
def __init__(self, driver):
super().__init__(driver)
# Driver
self.driver = driver
# Relative URL
self.relative = "/"
# Name
self._name = self.__class__.__name__
# Locator definitions
self._input_username = (By.ID, "username")
self._input_password = (By.ID, "password")
self._btn_login = (By.ID, "login-button")
self._link_forgot_password = (By.LINK_TEXT, "Forgot Password")
self._msg_error = (By.CSS_SELECTOR, ".error-message")
class HomePage(BasePage):
def __init__(self, driver):
super().__init__(driver)
# Driver
self.driver = driver
# Relative URL
self.relative = "/"
# Name
self._name = self.__class__.__name__
# Locator definitions
self._nav_menu = (By.ID, "main-menu")
self._img_logo = (By.ID, "logo")
self._tab_profile = (By.ID, "profile-tab")
self._btn_logout = (By.ID, "logout-button")
To create a custom template in PyCharm that will be used when creating a new Python class, follow these steps:
- Open Template Settings:
- Go to File > Settings (or PyCharm > Preferences on macOS).
- In the left panel, navigate to Editor > File and Code Templates.
- Create a New Python Template:
- Inside File and Code Templates, select Python Script.
- Click the + button to add a new template.
- Configure the Template:
-
Give your template a name, like Custom Python Class.
-
Ensure that ${NAME} is a variable that PyCharm will automatically replace with the file or class name when creating a new file.
-
In the template editor, paste your code:
from selenium.webdriver.common.by import By from core.asserts.AssertCollector import AssertCollector from core.config.logger_config import setup_logger from core.ui.common.BaseApp import BaseApp from core.ui.common.BasePage import BasePage logger = setup_logger('${NAME}') class ${NAME}(BasePage): def __init__(self, driver): """ Initialize the ${NAME} instance. """ super().__init__(driver) # Driver self.driver = driver # Name self._name = self.__class__.__name__ # Relative URL self.relative = "/web/index.php/auth/login" # Locator definitions self._locator_1 = (By.NAME, "...", "Input Locator_1") self._locator_2 = (By.NAME, "...", "Input Locator_2") @classmethod def get_instance(cls): if not hasattr(cls, '_instance'): cls._instance = ${NAME}(BaseApp.get_driver()) cls._name = __class__.__name__ return cls._instance def load_page(self): base_url = BaseApp.get_base_url() logger.info("LOAD PAGE: " + base_url + self.relative) self.navigation().go(base_url, self.relative) return self def some_method(self): pass
- Save the Template:
- Click OK or Apply to save the new template.
- Use the Template:
- Now, when you create a new file, select New > Python File, and then choose Custom Python Class (or whatever name you gave your template).
- Create an instance of the page object with the static method ".get_instance"
- Withing the test load the page with ".load_page()" method.
from core.config.logger_config import setup_logger
from applications.web.demo.pages.LoginPage import LoginPage
from core.ui.common.BaseTest import BaseTest
from core.utils.decorator import test
logger = setup_logger('TestLogin')
class TestLogin(BaseTest):
LoginPage = LoginPage.get_instance()
@test(test_case_id="HRM-0001", test_description="Verify Login Page headline")
def test_login_headline(self):
# 01. Interact with page elements
self.LoginPage.load_page()
# 02. Validations
self.LoginPage.verify_headline("Login")
WebElement constructor
- set_locator: Waits for the specified element to appear and logs the event.
- is_visible: Returns True if the element is displayed on the page.
- is_enabled: Returns True if the element is enabled and interactive.
- is_selected: Returns True if the element is selected.
- get_tag_name: Retrieves the tag name of the element.
- get_position: Returns the position and size of the element.
- get_css_property: Gets the value of a specified CSS property.
- get_text: Returns the text content of the element.
- get_attribute: Returns the value of a specified attribute.
- wait_for_element: Waits for a single element to be visible within a timeout.
- wait_for_elements: Waits for all matching elements to be visible within a timeout.
- log_console: Formats a log message for better traceability of actions and elements.
One Line
self.click().set_locator(locator="{locator}", page="{page_name}").single_click()
Multi-Line using "" on each line.
self.click()
.set_locator(locator="{locator}", page="{page_name}")
.single_click()
- set_locator: Sets the locator for the target element, waits for it, and logs the process. Returns self to allow method chaining.
- pause: Pauses the execution for a given number of seconds.
- single_click: Clicks the element once, logging whether it was successful.
- double_click: Double-clicks the element if present, logging the action.
- click_and_hold: Clicks and holds on the element, logging if it’s successful.
- context_click: Performs a right-click on the element, logging success or failure.
- drag_and_drop: Drags one element onto another if both are provided.
- mouse_over: Moves the mouse over the element to simulate a hover effect.
- pause: Pauses the execution for a given number of seconds.
- screenshot: Captures a screenshot of the element and attaches it to the Allure report.
One Line
self.send_keys().set_locator(locator="{locator}", page="{page_name}").set_text("")
Multi-Line using "" on each line.
self.send_keys()
.set_locator(locator="{locator}", page="{page_name}")
.set_text("")
- set_locator: Sets the locator for the target element, waits for it, and logs the process. Returns self to allow method chaining.
- set_text: Sets and sends the provided text to the element.
- set_text_by_character: Sends text to the element character by character.
- get_text: Retrieves text from the element's value attribute.
- clear: Clears the text from the element.
- Keyboard actions: press_return, press_enter, press_backspace, press_tab, press_escape
- pause: Pauses the execution for a given number of seconds.
- screenshot: Captures a screenshot of the element and attaches it to the Allure report.
Handle checkboxes form elements.
One Line
self.checkbox().set_locator(locator="{locator}", page="{page_name}").set_value("")
Multi-Line using "" on each line.
self.checkbox()
.set_locator(locator="{locator}", page="{page_name}")
.set_text("")
- set_locator: Sets the locator for the target element, waits for it, and logs the process. Returns self to allow method chaining.
- is_displayed: Checks if the checkbox element is displayed on the page.
- is_selected: Checks if the checkbox element is currently selected.
- set_value: Sets the checkbox value based on the provided boolean.
- pause: Pauses the execution for a given number of seconds.
- screenshot: Captures a screenshot of the element and attaches it to the Allure report.
Manage dropdown options from a standard web element.
One Line
self.dropdown().set_locator(locator="{locator}", page="{page_name}").by_text("")
Multi-Line using "" on each line.
self.dropdown()
.set_locator(locator="{locator}", page="{page_name}")
.by_text("")
- set_locator: Sets the locator for the target element, waits for it, and logs the process. Returns self to allow method chaining.
- by_value: Selects an option by its 'value' attribute.
- by_index: Selects an option by its index.
- by_text: Selects an option by its visible text.
- by_text_contains: Selects an option that contains specific text.
- deselect_all: Deselects all selected options if the dropdown supports multiple selections.
- pause: Pauses the execution for a given number of seconds.
- screenshot: Captures a screenshot of the element and attaches it to the Allure report.
- Integration with CI/CD Tools:
- Support test execution with Jenkins and other CI/CD environments.
- Subtasks: Pipeline configuration, reporting integration. 2Parallelization and Scalability:
- Run multiple test cases in parallel across different browsers, virtual machines, or Docker containers.
- Subtasks: Environment setup, local tests, cloud testing. 3Reporting:
- Right now working with a basic reporting, but research on other possible reporting formats that we can customize.
- Subtasks: Compare tools, implement new formats. 4Documentation
- Update README file with all the support documentation about framework functionality
- Comment Code Properly in order to clarify features functionality 5Research on X-Ray Integration
-
Execution Recording:
- Implement the ability to record videos of test executions, especially useful for analyzing failures in UI and Desktop tests.
-
API: Load Testings:
- Investigate support for load and performance testing with Python
-
Downloads/Uploads Folder Configuration
- Add All Possible API Authorization Endpoints:
- Research on this issue.