{"id":16356942,"url":"https://github.com/previousdeveloper/selenium-best-practices","last_synced_at":"2025-03-16T15:32:08.022Z","repository":{"id":28315138,"uuid":"31828005","full_name":"previousdeveloper/Selenium-best-practices","owner":"previousdeveloper","description":"For writing maintainable and scalable E2E Test.","archived":false,"fork":false,"pushed_at":"2017-06-19T19:24:46.000Z","size":7,"stargazers_count":105,"open_issues_count":0,"forks_count":19,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-10-12T01:44:39.817Z","etag":null,"topics":["java","selenium","selenium-best-practices"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"alwx/react-native-http-bridge","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/previousdeveloper.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-07T21:24:05.000Z","updated_at":"2024-05-11T20:45:50.000Z","dependencies_parsed_at":"2022-08-01T13:37:44.395Z","dependency_job_id":null,"html_url":"https://github.com/previousdeveloper/Selenium-best-practices","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/previousdeveloper%2FSelenium-best-practices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/previousdeveloper%2FSelenium-best-practices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/previousdeveloper%2FSelenium-best-practices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/previousdeveloper%2FSelenium-best-practices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/previousdeveloper","download_url":"https://codeload.github.com/previousdeveloper/Selenium-best-practices/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221665513,"owners_count":16860271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","selenium","selenium-best-practices"],"created_at":"2024-10-11T01:44:36.210Z","updated_at":"2024-10-27T10:50:53.473Z","avatar_url":"https://github.com/previousdeveloper.png","language":null,"readme":"# Goal\nOur goal is to get together Selenium best practices. Feedback is welcome. If you see anything wrong or know better way open an issue or create a pull request, just fork it and change it. We are open to learn and hear new ideas. \n\n# Selenium-best-practices\nSelenium is a portable software testing framework for web applications. It also provides a test domain-specific language to write tests in a number of popular programming languages, including Java, C#, Groovy, Perl, PHP, Python and Ruby.\n\n* [General](#general)\n  * [Use PageObjects Pattern](#use-pageobjects-pattern)\n  * [Prefered Selector Order](#prefered-selector-order)\n  * [Create Ordered Tests](#create-ordered-tests)\n  * [Get Name of the Running Test](#get-name-of-the-running-test)\n  * [Do not Use Magic String](#do-not-use-magic-strings)\n  * [Behavior Driven Design](#behavior-driven-design)\n  * [Use Build Automation System](#use-build-automation-system)\n  * [Learn Continuous Integration Tools](#learn-continuous-integration-tools)\n\n\n\n\n## Use PageObjects Pattern\n\nPage Object is a Design Pattern which has become popular in test automation for enhancing test maintenance and reducing code duplication. An implementation of the page object model can be achieved by separating the abstraction of the test object and the test scripts.\n\n**Advantages of using Page Object Pattern:**\n* Easy to Maintain\n* Easy Readability of scripts\n* Reduce or Eliminate duplicacy\n* Re-usability of code\n* Reliability\n* There is a clean separation between test code and page specific code such as locators  and layout.\n\nUse multi config for each environment. Make it changeable. Read your test case value from config. Don't use a static.\n\n* StageConfig\n * loginUrl=http://stage.com\n * validUsername=testUser@test.com\n * validPassword=123456\n \n* DevConfig\n * loginUrl=http://dev.com\n * validUsername=testUser@test.com\n * validPassword=123456\n\n**Shortcut**\n* Don't use magic strings.\n* Separate to WebPageElement, WebPageObject, WebTest.\n\n\n\n\n## Prefered Selector Order\n\nPreferred selector order : id \u003e name \u003elinks text\u003e css \u003e xpath\n\nCSS and XPath are location based selectors, they are slower than other selectors.\n\n* Id and name are often the easiest and sure way.\n* CSS = Id + name.\n* Last solution should be xpath.\n\n\n## Create Ordered Tests\n\n```java\nimport org.junit.runners.MethodSorters;\n\n//Running tests in order of method names in ascending order\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\n//Running tests in order of method names in ascending order\n@FixMethodOrder(MethodSorters.JVM)\n```\n\n\n## Get Name of the Running Test\n\n```java\nimport org.junit.rules.TestName;\n\n@Rule\npublic TestName name = new TestName();\n\n//example usage; writes every test name before it runs.\n@Before\n    public void logBeforeTestsStart() {\n        log.info(name.getMethodName());\n    }\n\n```\n\n\n## Do not use Magic Strings\n\nIt improves readability of the code and it's easier to maintain.\n\n```java\nWebDriver driver = new HtmlUnitDriver();\n// Don't use, create Constants each element name\nWebElement element = driver.findElement(By.name(\"sample\"));\ndriver.quit();\n```\n\n\n## Behavior Driven Design\n\nBDD is principally an idea about how software development should be managed by both business interests and technical insight, the practice of BDD assumes the use of specialized software tools to support the development process.\nThink all test scenarios.\n\nExample BDD \n\n```\nFeature: Sign up\n\nSign up should be quick.\nWrite all steps.\n1- Open Browser\n2-Navigate to Url\n3-Click Sign Up Button\n4-Write Valid Username and Password\n5-Click Register.\n\nScenario: Successful sign up\nNew users should get a confirmation email and be greeted\npersonally by the site once signed in.\n\nGiven I have chosen to sign up\nWhen I sign up with valid details\nThen I should receive a confirmation email\nAnd I should see a personalized greeting message\n\nScenario: Duplicate email\n\nWhere someone tries to create an account for an email address\nthat already exists.\n\nGiven I have chosen to sign up\nBut I enter an email address that has already registered\nThen I should be told that the email is already registered\nAnd I should be offered the option to recover my password\n\n```\n\n\n###Simple Example\n\n\n##Page Element Class\n```java \n//Write clear class  name.\npublic class WebLoginPageElement {\n\n    private String emailInputId;\n    private String passwordInputId;\n    public WebLoginPageElement() {\n        this.emailInputId = \"Email\";\n        this.passwordInputId = \"Password\";\n        }\n        \n    public String getEmailInputId() {\n        return emailInputId;}\n    \n    public String getPasswordInputId() {\n        return passwordInputId;}\n        \n```\n\n##Page Object Class\n\n```java\npublic class WebLoginPage extends Function {\n\n   //Make own custom WebElement Class.\n   private WebElementFactory elementFactory;\n   private IWebAction elementAction;\n   private WebLoginPageElement loginPageElement;\n\n   public WebLoginPage() {\n     elementFactory = new WebElementFactory(driver);\n     elementAction = new WebAction(driver);\n     loginPageElement = new WebLoginPageElement();\n    }\n\n\n   public WebLoginPage login(String email, String password) {\n    \n    WebElement emailInputElement = \n      elementFactory.createElementById(loginPageElement.getEmailInputId());\n      elementAction.clear(emailInputElement);\n      elementAction.sendKeys(emailInputElement, email);\n\n    WebElement passwordInputElement = \n      elementFactory.createElementById(loginPageElement.getPasswordInputId());\n      elementAction.clear(passwordInputElement);\n      elementAction.sendKeys(passwordInputElement, password);\n\n    WebElement loginSubmitButton =\n      elementFactory.createElementByCssSelector(loginPageElement.getSubmitBtnCss());\n      elementAction.click(loginSubmitButton);\n        return this;}\n```\n\n\n##Test Class\n\n```java\n\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic class WebLoginTest extends Function {\n\n    private static org.apache.log4j.Logger log = Logger.getLogger(WebLoginTest.class);\n    WebElementFactory elementFactory = new WebElementFactory(driver);\n    private static WebLoginPageElement loginPageElement = new WebLoginPageElement();\n    \n    @Rule\n    public TestName name = new TestName();\n\n    @BeforeClass\n    public static void setUpBeforeClass() throws Exception {\n        PropertyConfigurator.configure(IConstants.LOG4j_PROP);\n        openBrowser(RunAllWebTests.getConfigProperties().getLoginUrl());\n    }\n       @AfterClass\n    public static void tearDownAfterClass() throws Exception {\n        driver.close();\n        driver.quit();\n    }\n    \n    //Test all scenarios. \n    @Test\n    public void loginWithEmptyUsername() throws Exception {\n        //Call loginPage \n        new WebLoginPage().login(\n                RunAllWebTests.getConfigProperties().getEmptyUsername(),\n                RunAllWebTests.getConfigProperties().getValidPassword())\n                .assertTruePageContain(loginPageElement.getEmptyUsernameAssert());\n    }\n    \n    @Test\n    public void loginWithWrongFormat(){\n    //...\n    }\n    \n    @Test\n    public void loginWithWrongFormatId(){\n    //...\n    }\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreviousdeveloper%2Fselenium-best-practices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpreviousdeveloper%2Fselenium-best-practices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreviousdeveloper%2Fselenium-best-practices/lists"}