Selenium WebDriver wrapper Framework in Java, which supports Automation of most of the web browsers.

Open Source Love Gitter CircleCI Test Coverage Quality Gate Maintainability Reliability Security Vulnerability Duplicate Code Maven Central Github Releases License

Detailed documentation on main project site is under development.

:question: What is this Framework about?

This is a Selenium WebDriver wrapper Framework which enables robust, maintainable and easy to write test scripts. It supports latest stable Selenium WebDriver 3.141.59.

:bulb: What features does this framework offer?

Some of the key features which this framework offers are as follows:

:point_right: Latest stable Selenium WebDriver 3.141.59.

:point_right: Minimal learning curve.

:point_right: Supports Chrome, Safari, Firefox, IE and Edge

:point_right: Supports execution on BrowserStack, SauceLabs and Selenium Grid.

:point_right: On-demand highlighting of Elements.

:point_right: On-demand video recording and screenshots.

:point_right: On-demand delay of test execution by allowing predefined delays.

:point_right: On-demand headless mode execution for Chrome and Firefox.

:point_right: Inline verification of elements.

:point_right: Supports logging of events to Log file.

:point_right: Supports all major test frameworks like TestNG, JUnit, Cucumber, etc.

:point_right: Parallel execution of tests on different browsers.

:pushpin: Usage?

You can use the following dependency into your pom.xml to use this library.


Or you can add the following into your build.gradle file.

 compile "com.github.wasiqb.coteafs:selenium:3.2.0"

:smile: How it is easy to write Tests with this Framework?

Getting hands-on with this framework requires minimal time. You can start writing tests in following 4 simple steps.

1. :wrench: Create Config file
Config file is by default searched in `src/test/resources` folder. The name of the config file is by default considered as `selenium-config.yaml`. But the same can be overridden by using System property `coteafs.selenium.config` where you can specify the new config file for the test. #### Sample Config file `src/test/resources/selenium-config.yaml` ```yaml browser: CHROME # CHROME, SAFARI, EDGE, FIREFOX, IE. url: # Application URL. headless_mode: false # true, for headless, else false. driver: # Driver manager specific settings. force_cache: true # true, false (default). Forces to use cached driver. force_download: true # true, false (default). Forces to download driver each time. path: /drivers/ # Local path where drivers will searched for. version: 2.14 # Version of driver. exe_url: https://driver/download/url # Driver download URL. remote: # Remote settings block (required when Browser is Remote). user_id: ${CLOUD_USER} # Cloud User. Not required for Grid. password: ${CLOUD_KEY} # Cloud Key. Not required for Grid. protocol: HTTPS # HTTP, HTTPS. Default HTTP. url: # Remote hub URL source: BROWSERSTACK # BROWSERSTACK, GRID, SAUCELABS capabilities: # Remote capabilities. browser: Chrome browser_version: 75.0 os: Windows os_version: 10 resolution: 1024x768 name: Any Test name cloud_capabilities: # Cloud specific capabilities. seleniumVersion: 3.141.59 name: Sauce-[Java] Sample Test params: # test specific map. user: password: playback: # Playback settings. screen_state: NORMAL # FULL_SCREEN, MAXIMIZED, NORMAL highlight: true # true, to highlight elements, else false. screen_resolution: # Screen resolution settings. width: 1280 # Screen width. height: 768 # Screen height. recording: enable: true # true, to enable recording, else false. path: ./video # Video recording path. prefix: VID # Video file prefix. delays: # On demand delay settings. implicit: 60 # Implicit waits in seconds. explicit: 60 # Explicit waits in seconds. after_frame_switch: 500 # Delay after iFrame switch in milliseconds. after_window_switch: 500 # Delay after Window switch in milliseconds. before_key_press: 0 # delay before key press in milliseconds. after_key_press: 0 # delay after key press in milliseconds. before_mouse_move: 0 # delay before mouse move in milliseconds. after_mouse_move: 0 # delay after mouse move in milliseconds. before_click: 0 # delay before mouse click in milliseconds. after_click: 0 # delay after mouse click in milliseconds. page_load: 60 # page load timeout in seconds. script_load: 60 # script load timeout in seconds. highlight: 500 # highlight delay in milliseconds. screenshot: # Screenshot settings. path: ~/screenshots # default screenshot path. prefix: SCR # screenshot file prefix. extension: jpeg # screenshot file extension. capture_on_error: false # screenshot on error. capture_all: true # always capture screenshot on each event, when true. ``` > **Note:** If you find any config not working, feel free to raise an [issue][].
2. :page_facing_up: Create Page object class
Checkout the following examples which will guide you in writing tests. Lets have a look at the Login page of Guru99 demo site. > Remember, `BrowserPage` class needs to be extended for every page and also a flavour of inheritance can be added as per requirement. #### Sample Page object ```java package com.github.wasiqb.coteafs.selenium.pages; import org.openqa.selenium.By; import com.github.wasiqb.coteafs.selenium.core.BrowserPage; import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; import com.github.wasiqb.coteafs.selenium.core.element.ITextboxActions; public class LoginPage extends BrowserPage { public ITextboxActions password () { return form ().find ( ("password"), "Password"); } public IMouseActions signIn () { return form ().find ( ("btnLogin"), "Login"); } public ITextboxActions userId () { return form ().find ( ("uid"), "User ID"); } private IMouseActions form () { return onClickable ( ("frmLogin"), "Form"); } } ```
3. :runner: Create Page Action class
This is a new concept, here you can define actions specific to each page. This approach abstracts out the page action flows and helps in modularising the classes. So whenever the flow of the page changes, you need to change only at single place. > For every page action you need to extend `AbstractPageAction`. Since it is a generic class, you need to pass the action class name as it's generic type. > Also, `perform` method needs to be implemented for every action class. #### Sample page action ```java package com.github.wasiqb.coteafs.selenium.pages.action; import static java.text.MessageFormat.format; import; import com.github.wasiqb.coteafs.selenium.pages.LoginPage; import com.github.wasiqb.coteafs.selenium.pages.MainPage; public class LoginPageAction extends AbstractPageAction { public static final String PASS = "password"; public static final String USER_ID = "userId"; @Override public void perform () { final LoginPage login = new LoginPage (); login.userId () .enterText (value (USER_ID)); login.password () .enterText (value (PASS)); login.signIn () .click (); login.nextPage (MainPage.class) .managerIdBanner () .verifyText () .endsWith (format ("Manger Id : {0}", value (USER_ID).toString ())); } } ```
4. :white_check_mark: Write Test class
Test which are written using this framework are slightly different than usual. In the tests, Page actions is used instead of page objects. This can be demonstrated as shown below: #### Sample Test > Every test class extends `BrowserTest` class. ```java package com.github.wasiqb.coteafs.selenium; import static com.github.wasiqb.coteafs.selenium.config.ConfigUtil.appSetting; import static com.github.wasiqb.coteafs.selenium.pages.action.LoginPageAction.PASS; import static com.github.wasiqb.coteafs.selenium.pages.action.LoginPageAction.USER_ID; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.github.wasiqb.coteafs.selenium.core.BrowserTest; import com.github.wasiqb.coteafs.selenium.pages.MainPage; import com.github.wasiqb.coteafs.selenium.pages.action.LoginPageAction; public class SeleniumTest extends BrowserTest { @BeforeClass public void setupMethod () { final MainPage main = new MainPage (); main.onDriver () .navigateTo (appSetting ().getUrl ()); } @Test public void testSignIn () { final LoginPageAction login = new LoginPageAction (); login.addInputValue (USER_ID, appSetting ().getParams () .get ("user")) .addInputValue (PASS, appSetting ().getParams () .get ("password")) .perform (); } } ```
5. :microscope: Create TestNG XML file
### Basic syncronous run Following is a simple `testng.xml` file for running the tests on Chrome browser **locally, on grid and on BrowserStack** in sync. ```xml ``` > **Note:** Notice the parameter used in last 2 tests, - `test.browser`: You can override the browser set in config file, it accepts same value as described in confid section. - `test.config`: You can set different config for current test. ### Parallel Run In case you want to run tests for different browsers parallely, you just need to modify the following line in `testng.xml`. ```xml . . . . . . ``` This attributes will tell testng to run all the test blocks in 10 parallel threads.
6. :cyclone: Running TestNG XML file
### Running on local browsers or on Selenium Grid Run the tests using following command, ```bash $ mvn clean install -Dsuite-xml=testng.xml ``` ### Running on BrowserStack or any other cloud solution Run the tests using following command, ```bash $ mvn clean install -Dsuite-xml=testng.xml -DCLOUD_USER= -DCLOUD_KEY= ```

:question: Need Assistance?

:star2: What you do if you like the project?

:gift_heart: Thanks for the support.

For allowing us to run our unit tests on different cloud platforms.

:white_check_mark: Contributors

:ticket: Versioning ideology

:copyright: Wasiq Bhamla