├── configs ├── SeleniumConfigs.robot ├── EnvDetails.robot ├── BrowserDetails.robot └── ApplicationVariables.robot ├── object-repository ├── locators │ ├── LoginPageLocators.robot │ ├── HomePageLocators.robot │ └── NavBarLocators.robot └── page-objects │ ├── NavBarPo.robot │ ├── LoginPo.robot │ └── CommonPo.robot ├── robot.yaml ├── conda.yaml ├── LICENSE ├── .gitignore ├── test-cases └── LoginTest.robot └── README.md /configs/SeleniumConfigs.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | # Default Timeout 3 | ${SELENIUM_TIMEOUT} 60 -------------------------------------------------------------------------------- /configs/EnvDetails.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | ${ENV} SIT 3 | ${SIT_ENV_URL} https://demoblaze.com/ 4 | ${UAT_ENV_URL} https://uat.demoblaze.com/ 5 | ${TEST_ENV_URL} ${${ENV}_ENV_URL} -------------------------------------------------------------------------------- /object-repository/locators/LoginPageLocators.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | ${usernameTextBox} id=loginusername 3 | ${passwordTextBox} id=loginpassword 4 | ${loginButton} xpath=//button[@onclick='logIn()'] -------------------------------------------------------------------------------- /robot.yaml: -------------------------------------------------------------------------------- 1 | tasks: 2 | Run all tasks: 3 | shell: python -m robot --report NONE --outputdir output --logtitle "Task log" tasks.robot 4 | 5 | condaConfigFile: conda.yaml 6 | artifactsDir: output 7 | PATH: 8 | - . 9 | PYTHONPATH: 10 | - . 11 | ignoreFiles: 12 | - .gitignore 13 | -------------------------------------------------------------------------------- /object-repository/locators/HomePageLocators.robot: -------------------------------------------------------------------------------- 1 | *** Keywords *** 2 | Get Category Locator By Name [Arguments] ${categoryName} 3 | [Documentation] 4 | ... Get category locator by name ... 5 | 6 | ${categoryLocator} Set Variable xpath=//a[@id='itemc' and text()='${categoryName}'] 7 | Return from keyword ${categoryLocator} 8 | -------------------------------------------------------------------------------- /configs/BrowserDetails.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | # Extecution Browser 3 | # ${BROWSER} headlesschrome 4 | # ${BROWSER} headlessfirefox 5 | ${BROWSER} chrome 6 | # ${BROWSER} firefox 7 | # ${BROWSER} safari 8 | 9 | # Browser Dimentions 10 | ${WINDOW_WIDTH} 1900 11 | ${WINDOW_HEIGHT} 1200 -------------------------------------------------------------------------------- /configs/ApplicationVariables.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | # Number of retries 3 | ${SMALL_RETRY_COUNT} 2x 4 | ${MEDIUM_RETRY_COUNT} 3x 5 | ${LARGE_RETRY_COUNT} 5x 6 | 7 | # Delay for a retry 8 | ${RETRY_DELAY} 1 s 9 | 10 | # User credentials 11 | ${USERNAME} osanda 12 | ${PASSWORD} NoShits! 13 | 14 | # Application constants 15 | ${BROWSER_TAB_TITLE} My Store -------------------------------------------------------------------------------- /conda.yaml: -------------------------------------------------------------------------------- 1 | channels: 2 | # Define conda channels here. 3 | - conda-forge 4 | 5 | dependencies: 6 | # Define conda packages here. 7 | # If available, always prefer the conda version of a package. 8 | # Installation will be faster and more efficient. 9 | # https://anaconda.org/search 10 | - python=3.9.13 11 | 12 | - pip=22.1.2 13 | - pip: 14 | # Define pip packages here. 15 | # https://pypi.org/ 16 | - rpaframework==15.6.0 # https://rpaframework.org/releasenotes.html 17 | -------------------------------------------------------------------------------- /object-repository/locators/NavBarLocators.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | ${loginLocator} id=login2 3 | ${logoutLocator} id=logout2 4 | ${loggedInUsernameWithGreetingLocator} id=nameofuser 5 | 6 | 7 | *** Keywords *** 8 | Get Navigation Menu Item Locator By Name [Arguments] ${menuItemName} 9 | [Documentation] 10 | ... Get navigation menu item locator by name ... 11 | 12 | ${menuItemLocator} Set Variable xpath=//a[@class='nav-link' and contains(text(), '${menuItemName}')] 13 | Return from keyword ${menuItemLocator} -------------------------------------------------------------------------------- /object-repository/page-objects/NavBarPo.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Resource ../locators/NavBarLocators.robot 3 | Resource CommonPo.robot 4 | 5 | 6 | *** Variables *** 7 | ${WOMEN_PAGE_TITLE} WOMEN 8 | ${DRESSES_PAGE_TITLE} DRESSES 9 | 10 | 11 | *** Keywords *** 12 | Navigates To Home Page 13 | [Documentation] 14 | ... Navigate to home page ... 15 | 16 | ${homePageLocator} Get Navigation Menu Item Locator By Name [Arguments] Home 17 | Click Element [Arguments] ${homePageLocator} ${SMALL_RETRY_COUNT} 18 | 19 | 20 | Navigates To Contact Page 21 | [Documentation] 22 | ... Navigate to contact page ... 23 | 24 | ${contactPageLocator} Get Navigation Menu Item Locator By Name [Arguments] Contact 25 | Click Element [Arguments] ${contactPageLocator} ${SMALL_RETRY_COUNT} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Osanda Deshan Nimalarathna 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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Image files 5 | *.png 6 | 7 | # HTML files 8 | *.html 9 | *.xml 10 | red.xml 11 | 12 | # Logs and databases # 13 | ###################### 14 | log/ 15 | *.log 16 | *.sql 17 | *.sqlite 18 | 19 | # BlueJ files 20 | *.ctxt 21 | 22 | # Mobile Tools for Java (J2ME) 23 | .mtj.tmp/ 24 | 25 | # Package Files # 26 | *.jar 27 | *.war 28 | *.nar 29 | *.ear 30 | *.zip 31 | *.tar.gz 32 | *.rari 33 | 34 | # IDEA Ignores # 35 | ################ 36 | *.iml 37 | *.ipr 38 | *.iws 39 | .idea/ 40 | out/ 41 | local.properties 42 | .pydevproject 43 | .project 44 | 45 | # eclipse project file 46 | .settings/ 47 | .classpath 48 | .project 49 | 50 | 51 | # VCS # 52 | ####### 53 | .svn 54 | .svn/ 55 | CVS 56 | 57 | # General 58 | .DS_Store 59 | .AppleDouble 60 | .LSOverride 61 | 62 | # Icon must end with two \r 63 | Icon 64 | 65 | 66 | # Thumbnails 67 | ._* 68 | 69 | # Files that might appear in the root of a volume 70 | .DocumentRevisions-V100 71 | .fseventsd 72 | .Spotlight-V100 73 | .TemporaryItems 74 | .Trashes 75 | .VolumeIcon.icns 76 | .com.apple.timemachine.donotpresent 77 | 78 | # Directories potentially created on remote AFP share 79 | .AppleDB 80 | .AppleDesktop 81 | Network Trash Folder 82 | Temporary Items 83 | .apdisk 84 | 85 | /.metadata/ 86 | /libspecs/ 87 | libspecs 88 | 89 | # Test results 90 | /results 91 | -------------------------------------------------------------------------------- /test-cases/LoginTest.robot: -------------------------------------------------------------------------------- 1 | *** Setting *** 2 | Resource ../object-repository/page-objects/LoginPo.robot 3 | 4 | Documentation This suite includes login tests 5 | 6 | Test Teardown Close Browser 7 | 8 | 9 | *** Variables *** 10 | ${invalidUserName} osa 11 | ${invalidPassword} test@12 12 | ${WRONG_PASSWORD_ERROR_MESSAGE} Wrong password. 13 | ${USER_DOES_NOT_EXIST_ERROR_MESSAGE} User does not exist. 14 | 15 | 16 | *** Test Cases *** 17 | Verify That An Unregistered Person Cannot Login To The Application 18 | [Documentation] TVerify that an unregistered person cannot login to the application 19 | [tags] Regression 20 | 21 | Open Browser To Login Page 22 | Submit Login Information [Arguments] ${invalidUserName} ${invalidPassword} 23 | User Should See An Alert With The Error Message [Arguments] ${USER_DOES_NOT_EXIST_ERROR_MESSAGE} 24 | 25 | 26 | Verify That A Registered User Cannot Login To The Application Using An Incorrect Password 27 | [Documentation] Verify that a registered user cannot login to the application using an incorrect password 28 | [tags] Regression 29 | 30 | Open Browser To Login Page 31 | Submit Login Information [Arguments] ${USERNAME} ${invalidPassword} 32 | User Should See An Alert With The Error Message [Arguments] ${WRONG_PASSWORD_ERROR_MESSAGE} 33 | 34 | 35 | Verify That A Registered User Can Login To The Application Using The Correct Password 36 | [Documentation] Verify that a registered user can login to the application using the correct password 37 | [tags] Smoke 38 | 39 | Login To The Application [Arguments] ${USERNAME} ${PASSWORD} 40 | Logout From The Application -------------------------------------------------------------------------------- /object-repository/page-objects/LoginPo.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Resource ../locators/LoginPageLocators.robot 3 | Resource CommonPo.robot 4 | 5 | 6 | *** Keywords *** 7 | Login To The Application [Arguments] ${username} ${password} 8 | [Documentation] 9 | ... Login using valid username and password ... 10 | 11 | Open Browser To Login Page 12 | Submit Login Information [Arguments] ${username} ${password} 13 | Username Should Be Visible On The Navigation Bar [Arguments] ${username} 14 | 15 | 16 | Username Should Be Visible On The Navigation Bar [Arguments] ${username} 17 | [Documentation] 18 | ... User should see the username on the navigation bar ... 19 | 20 | ${loggedInUsernameWithGreeting} Set Variable Welcome ${username} 21 | Element Text Should Be [Arguments] ${loggedInUsernameWithGreetingLocator} ${loggedInUsernameWithGreeting} ${SMALL_RETRY_COUNT} 22 | 23 | 24 | User Should See An Alert With The Error Message [Arguments] ${errorMessage} 25 | [Documentation] 26 | ... User should see an alert with the error message on the browser ... 27 | 28 | Alert Should Be Present ${errorMessage} 29 | 30 | 31 | Submit Login Information [Arguments] ${username} ${password} 32 | [Documentation] 33 | ... Login using the username and password ... 34 | 35 | Set Text [Arguments] ${usernameTextBox} ${username} ${SMALL_RETRY_COUNT} 36 | Set Text [Arguments] ${passwordTextBox} ${password} ${SMALL_RETRY_COUNT} 37 | Click Element [Arguments] ${loginButton} ${SMALL_RETRY_COUNT} 38 | 39 | 40 | Open Browser And Login To The Application 41 | [Documentation] 42 | ... Open browser and login using valid username and password ... 43 | 44 | Open Browser To Login Page 45 | Login To The Application [Arguments] ${USERNAME} ${PASSWORD} -------------------------------------------------------------------------------- /object-repository/page-objects/CommonPo.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Resource ../../configs/EnvDetails.robot 3 | Resource ../../configs/BrowserDetails.robot 4 | Resource ../../configs/SeleniumConfigs.robot 5 | Resource ../../configs/ApplicationVariables.robot 6 | Resource ../locators/NavBarLocators.robot 7 | 8 | Library SeleniumLibrary 9 | Library String 10 | Library OperatingSystem 11 | 12 | 13 | *** Keywords *** 14 | Open Browser To Login Page 15 | [Documentation] 16 | ... Open the browser and navigates to the login page ... 17 | 18 | Open Browser ${TEST_ENV_URL} ${BROWSER} 19 | Set Window Size ${WINDOW_WIDTH} ${WINDOW_HEIGHT} 20 | Set Selenium Timeout ${SELENIUM_TIMEOUT} 21 | Click Element [Arguments] ${loginLocator} ${SMALL_RETRY_COUNT} 22 | Set Log Level DEBUG 23 | 24 | 25 | Logout From The Application 26 | [Documentation] 27 | ... Logout from the application ... 28 | 29 | Click Element [Arguments] ${logoutLocator} ${SMALL_RETRY_COUNT} 30 | Element Should Be Visible [Arguments] ${loginLocator} ${SMALL_RETRY_COUNT} 31 | 32 | 33 | Get Random Text 34 | [Documentation] 35 | ... Return random text value ... 36 | 37 | ${randomText} Generate Random String 8 [LETTERS] 38 | Return From Keyword ${randomText} 39 | 40 | 41 | Get Current Epoch Time 42 | [Documentation] 43 | ... Return current epoch time ... 44 | 45 | ${randomText} Get Time epoch 46 | Return From Keyword ${randomText} 47 | 48 | 49 | Element Should Be Contained In The Page [Arguments] ${locator} ${retryScale} 50 | [Documentation] 51 | ... Verify that the element should be contained in the page ... 52 | 53 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Page Contains Element ${locator} 54 | 55 | 56 | Element Should Not Be Contained In The Page [Arguments] ${locator} ${retryScale} 57 | [Documentation] 58 | ... Verify that the element should not be contained in the page ... 59 | 60 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Page Does Not Contain Element ${locator} 61 | 62 | 63 | Element Should Be Visible [Arguments] ${locator} ${retryScale} 64 | [Documentation] 65 | ... Verify that the element should be visible ... 66 | 67 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Visible ${locator} 68 | 69 | 70 | Element Should Not Be Visible [Arguments] ${locator} ${retryScale} 71 | [Documentation] 72 | ... Verify that the element should not be visible ... 73 | 74 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Not Visible ${locator} 75 | 76 | 77 | Click Element [Arguments] ${locator} ${retryScale} 78 | [Documentation] 79 | ... Click on a given button ... 80 | 81 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Enabled ${locator} 82 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Click Element ${locator} 83 | 84 | 85 | Click Element By JavaScript Executor [Arguments] ${elementXpathLocator} ${retryScale} 86 | [Documentation] 87 | ... Click an element by xpath using javascript executor ... 88 | 89 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Enabled ${elementXpathLocator} 90 | ${elementXpathLocator}= Remove String ${elementXpathLocator} xpath= 91 | Execute JavaScript document.evaluate("${elementXpathLocator}", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0).click(); 92 | 93 | 94 | Element Text Should Be [Arguments] ${locator} ${text} ${retryScale} 95 | [Documentation] 96 | ... Validate the text of an element ... 97 | 98 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Visible ${locator} 99 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Element Text Should Be ${locator} ${text} 100 | 101 | 102 | Set Text [Arguments] ${textBoxLocator} ${text} ${retryScale} 103 | [Documentation] 104 | ... Input text into a text box ... 105 | 106 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Wait Until Element Is Enabled ${textBoxLocator} 107 | Wait Until Keyword Succeeds ${retryScale} ${RETRY_DELAY} Input Text ${textBoxLocator} ${text} 108 | 109 | 110 | Scroll To The Top Of The Page 111 | [Documentation] 112 | ... Scroll to the top of the page 113 | 114 | Execute JavaScript window.scrollTo(0, 0) 115 | 116 | 117 | Scroll To The Bottom Of The Page 118 | [Documentation] 119 | ... Scroll to the bottom of the page 120 | 121 | Execute JavaScript window.scrollTo(0, document.body.scrollHeight) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Robot Framework Page Object Model Demo 2 | 3 | ## Robot Framework Introduction 4 | [Robot Framework](http://robotframework.org) is a generic open source 5 | automation framework for acceptance testing, acceptance test driven 6 | development (ATDD), and robotic process automation (RPA). It has simple plain 7 | text syntax and it can be extended easily with libraries implemented using 8 | Python or Java. 9 | 10 | Robot Framework is operating system and application independent. The core 11 | framework is implemented using [Python](http://python.org), supports both 12 | Python 2 and Python 3, and runs also on [Jython](http://jython.org) (JVM), 13 | [IronPython](http://ironpython.net) (.NET) and [PyPy](http://pypy.org). 14 | The framework has a rich ecosystem around it consisting of various generic 15 | libraries and tools that are developed as separate projects. For more 16 | information about Robot Framework and the ecosystem, see 17 | http://robotframework.org. 18 | 19 | Robot Framework project is hosted on GitHub where you can find source code, 20 | an issue tracker, and some further documentation. Downloads are hosted on PyPI, except 21 | for the standalone JAR distribution that is on Maven central. 22 | 23 | Robot Framework development is sponsored by [Robot Framework Foundation](http://robotframework.org/foundation). 24 | 25 | [GitHub](https://github.com/robotframework/robotframework) 26 | 27 | [PyPI](https://pypi.python.org/pypi/robotframework) 28 | 29 | [Maven central](http://search.maven.org/#search%7Cga%7C1%7Ca%3Arobotframework) 30 | 31 | ## Installation 32 | 1. Download and Install [Python](https://www.python.org/downloads/ "Python"). 33 | 2. Check Python installation 34 | 35 | `python3 -V` 36 | 37 | 3. Install [pip](https://pip.pypa.io/ "pip"). 38 | 39 | `pip3 -V` 40 | 41 | 4. Install Robot Framework. 42 | 43 | `pip3 install robotframework` 44 | 45 | 5. Install Selenium Library. 46 | 47 | `pip3 install robotframework-seleniumlibrary` 48 | 49 | 6. Download and install VSCode [VSCode](https://code.visualstudio.com/docs/?dv=osx "VSCode"). 50 | 7. Install [Robot Code](https://marketplace.visualstudio.com/items?itemName=d-biehl.robotcode "Robot Code") extension from VSCode's Marketplace 51 | 8. Install Browser Drivers 52 | 53 | `pip3 install webdrivermanager` 54 | 55 | ## Example 56 | Here, I have developed sample test cases for a sample web site [Demoblaze](https://demoblaze.com/). 57 | 58 | This project is developed to demontrate Web UI automation using Robot Framework and Selenium Library. 59 | 60 | Here, there are 3 variables `${SMALL_RETRY_SCALE}`, `${MEDIUM_RETRY_SCALE}` and `${LARGE_RETRY_SCALE}` for retrying the keywords when they are failing. Each variable has assigned with the number of retries. Automation engineers are advised to use `${SMALL_RETRY_SCALE}` as the default number of retries for the keywords. If there are big delays in some scenarios, you can use other variables `${MEDIUM_RETRY_SCALE}` and `${LARGE_RETRY_SCALE}`. You can find the examples for this in `object-repository/page-objects` directory. 61 | 62 | Test cases are in `test-cases` directory and covers login functionality. 63 | 64 | ## File organization 65 | ``` 66 | |- robot-framework-page-object-model-demo/ // Home folder for robot selenium UI automation project 67 | |- configs/ApplicationVariables.robot // Application common variables file 68 | |- configs/BrowserDetails.robot // Test execution browser configurations 69 | |- configs/EnvDetails.robot // Test execution environment configurations 70 | |- configs/SeleniumConfigs.robot // Selenium configurations 71 | |- object-repository/locators/*.robot // UI locators of the application 72 | |- object-repository/page-objects/CommonPo.robot // Common keywords for the application 73 | |- object-repository/page-objects/*.robot // Page object keywords of the application 74 | |- test-cases/..../*.robot // Test cases of the application 75 | |- results // Test results will be saving here 76 | |- .gitignore // Excluded the unnecessary files in the repo 77 | |- README.md // This file 78 | ``` 79 | 80 | ## Usage 81 | Starting from Robot Framework 3.0, tests are executed from the command line 82 | using the ``robot`` script or by executing the ``robot`` module directly 83 | like ``python -m robot`` or ``jython -m robot``. 84 | 85 | The basic usage is giving a path to a test (or task) file or directory as an 86 | argument with possible command line options before the path 87 | 88 | python3 -m robot -v ENV:SIT -i Smoke -d results path/to/tests/ 89 | python3 -m robot -v ENV:SIT -i Smoke -d results test-cases/LoginTest.robot 90 | 91 | "***-v***" refers to the variables. To replace a declared value within the code, you can specify a variable name and value. 92 | 93 | "***-i***" refers to the tags. To run only a selected group of tests, you may specify a tag name. 94 | 95 | "***-d***" refers to the test results. The location to save the test results can be specified here. 96 | 97 | Additionally there is ``rebot`` tool for combining results and otherwise 98 | post-processing outputs 99 | 100 | rebot --name Example output1.xml output2.xml 101 | 102 | Run ``robot --help`` and ``rebot --help`` for more information about the command 103 | line usage. For a complete reference manual see [Robot Framework User Guide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html "Robot Framework User Guide"). 104 | 105 | ## License 106 | MIT License [MIT License](https://opensource.org/licenses/MIT) 107 | 108 | ## Copyright 109 | Copyright 2023 [MaxSoft](https://maxsoftlk.github.io/ "MaxSoft") 110 | --------------------------------------------------------------------------------