From 314178343633a414bfc275d795efd65e5c1a43fe Mon Sep 17 00:00:00 2001 From: Boris Wrubel Date: Sun, 17 Nov 2019 16:26:38 +0100 Subject: [PATCH 01/11] creation of all file for german copied *.en.md to *.de.md files --- docs_source_files/content/CONTRIBUTING.de.md | 216 ++ docs_source_files/content/_index.de.md | 176 ++ .../driver_idiosyncrasies/_index.de.md | 7 + .../driver_specific_capabilities.de.md | 108 + .../shared_capabilities.de.md | 23 + .../content/findAndReplaceText.sh | 32 + .../content/front_matter/_index.de.md | 7 + .../copyright_and_attributions.de.md | 285 +++ .../typographical_conventions.de.md | 38 + .../content/getting_started/_index.de.md | 16 + .../content/getting_started/quick.de.md | 34 + .../_index.de.md | 29 + .../browsers.de.md | 27 + .../locating_elements.de.md | 199 ++ .../performing_actions_on_the_aut.de.md | 98 + .../third_party_drivers_and_plugins.de.md | 24 + docs_source_files/content/grid/_index.de.md | 27 + .../content/grid/components_of_a_grid.de.md | 34 + .../purposes_and_main_functionalities.de.md | 12 + .../grid/setting_up_your_own_grid.de.md | 251 +++ .../content/grid/when_to_use_grid.de.md | 45 + .../_index.de.md | 28 + .../avoid_sharing_state.de.md | 18 + .../consider_using_a_fluent_api.de.md | 78 + .../domain_specific_language.de.md | 97 + .../fresh_browser_per_test.de.md | 15 + .../generating_application_state.de.md | 16 + .../improved_reporting.de.md | 18 + .../mock_external_services.de.md | 7 + .../page_object_models.de.md | 169 ++ .../test_independency.de.md | 22 + .../content/introduction/_index.de.md | 9 + .../about_this_documentation.de.md | 29 + .../introduction/on_test_automation.de.md | 344 ++++ .../the_selenium_project_and_tools.de.md | 117 ++ .../introduction/types_of_testing.de.md | 115 ++ .../content/legacy_docs/_index.de.md | 11 + .../content/legacy_docs/html-runner.de.md | 94 + .../migrating_from_rc_to_webdriver.de.md | 253 +++ .../content/legacy_docs/selenium_ide.de.md | 1739 +++++++++++++++++ .../content/legacy_docs/selenium_rc.de.md | 1721 ++++++++++++++++ .../content/remote_webdriver/_index.de.md | 15 + .../remote_webdriver_client.de.md | 171 ++ .../remote_webdriver_server.de.md | 101 + .../selenium_installation/_index.de.md | 9 + .../installing_selenium_libraries.de.md | 87 + .../installing_standalone_server.de.md | 22 + .../installing_webdriver_binaries.de.md | 11 + .../content/support_packages/_index.de.md | 8 + .../support_packages/browser_navigation.de.md | 107 + ...mouse_and_keyboard_actions_in_detail.de.md | 155 ++ .../working_with_colours.de.md | 229 +++ .../working_with_select_elements.de.md | 296 +++ .../working_with_web_elements.de.md | 5 + .../content/webdriver/_index.de.md | 25 + .../webdriver/browser_manipulation.de.md | 1008 ++++++++++ .../webdriver/driver_requirements.de.md | 606 ++++++ .../content/webdriver/http_proxies.de.md | 5 + .../js_alerts_prompts_and_confirmations.de.md | 310 +++ .../content/webdriver/keyboard.de.md | 111 ++ .../content/webdriver/mouse.de.md | 5 + .../webdriver/page_loading_strategy.de.md | 5 + .../content/webdriver/support_classes.de.md | 72 + .../understanding_the_components.de.md | 74 + .../content/webdriver/waits.de.md | 472 +++++ .../content/webdriver/web_element.de.md | 78 + .../content/worst_practices/_index.de.md | 7 + .../content/worst_practices/captchas.de.md | 12 + .../worst_practices/file_downloads.de.md | 15 + .../gmail_email_and_facebook_logins.de.md | 32 + .../worst_practices/http_response_codes.de.md | 53 + .../worst_practices/link_spidering.de.md | 21 + .../worst_practices/performance_testing.de.md | 48 + .../worst_practices/test_dependency.de.md | 9 + 74 files changed, 10772 insertions(+) create mode 100644 docs_source_files/content/CONTRIBUTING.de.md create mode 100644 docs_source_files/content/_index.de.md create mode 100644 docs_source_files/content/driver_idiosyncrasies/_index.de.md create mode 100644 docs_source_files/content/driver_idiosyncrasies/driver_specific_capabilities.de.md create mode 100644 docs_source_files/content/driver_idiosyncrasies/shared_capabilities.de.md create mode 100755 docs_source_files/content/findAndReplaceText.sh create mode 100644 docs_source_files/content/front_matter/_index.de.md create mode 100644 docs_source_files/content/front_matter/copyright_and_attributions.de.md create mode 100644 docs_source_files/content/front_matter/typographical_conventions.de.md create mode 100644 docs_source_files/content/getting_started/_index.de.md create mode 100644 docs_source_files/content/getting_started/quick.de.md create mode 100644 docs_source_files/content/getting_started_with_webdriver/_index.de.md create mode 100644 docs_source_files/content/getting_started_with_webdriver/browsers.de.md create mode 100644 docs_source_files/content/getting_started_with_webdriver/locating_elements.de.md create mode 100644 docs_source_files/content/getting_started_with_webdriver/performing_actions_on_the_aut.de.md create mode 100644 docs_source_files/content/getting_started_with_webdriver/third_party_drivers_and_plugins.de.md create mode 100644 docs_source_files/content/grid/_index.de.md create mode 100644 docs_source_files/content/grid/components_of_a_grid.de.md create mode 100644 docs_source_files/content/grid/purposes_and_main_functionalities.de.md create mode 100644 docs_source_files/content/grid/setting_up_your_own_grid.de.md create mode 100644 docs_source_files/content/grid/when_to_use_grid.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/_index.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/avoid_sharing_state.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/consider_using_a_fluent_api.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/domain_specific_language.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/fresh_browser_per_test.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/generating_application_state.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/improved_reporting.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/mock_external_services.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/page_object_models.de.md create mode 100644 docs_source_files/content/guidelines_and_recommendations/test_independency.de.md create mode 100644 docs_source_files/content/introduction/_index.de.md create mode 100644 docs_source_files/content/introduction/about_this_documentation.de.md create mode 100644 docs_source_files/content/introduction/on_test_automation.de.md create mode 100644 docs_source_files/content/introduction/the_selenium_project_and_tools.de.md create mode 100644 docs_source_files/content/introduction/types_of_testing.de.md create mode 100644 docs_source_files/content/legacy_docs/_index.de.md create mode 100644 docs_source_files/content/legacy_docs/html-runner.de.md create mode 100644 docs_source_files/content/legacy_docs/migrating_from_rc_to_webdriver.de.md create mode 100644 docs_source_files/content/legacy_docs/selenium_ide.de.md create mode 100644 docs_source_files/content/legacy_docs/selenium_rc.de.md create mode 100644 docs_source_files/content/remote_webdriver/_index.de.md create mode 100644 docs_source_files/content/remote_webdriver/remote_webdriver_client.de.md create mode 100644 docs_source_files/content/remote_webdriver/remote_webdriver_server.de.md create mode 100644 docs_source_files/content/selenium_installation/_index.de.md create mode 100644 docs_source_files/content/selenium_installation/installing_selenium_libraries.de.md create mode 100644 docs_source_files/content/selenium_installation/installing_standalone_server.de.md create mode 100644 docs_source_files/content/selenium_installation/installing_webdriver_binaries.de.md create mode 100644 docs_source_files/content/support_packages/_index.de.md create mode 100644 docs_source_files/content/support_packages/browser_navigation.de.md create mode 100644 docs_source_files/content/support_packages/mouse_and_keyboard_actions_in_detail.de.md create mode 100644 docs_source_files/content/support_packages/working_with_colours.de.md create mode 100644 docs_source_files/content/support_packages/working_with_select_elements.de.md create mode 100644 docs_source_files/content/support_packages/working_with_web_elements.de.md create mode 100644 docs_source_files/content/webdriver/_index.de.md create mode 100644 docs_source_files/content/webdriver/browser_manipulation.de.md create mode 100644 docs_source_files/content/webdriver/driver_requirements.de.md create mode 100644 docs_source_files/content/webdriver/http_proxies.de.md create mode 100644 docs_source_files/content/webdriver/js_alerts_prompts_and_confirmations.de.md create mode 100644 docs_source_files/content/webdriver/keyboard.de.md create mode 100644 docs_source_files/content/webdriver/mouse.de.md create mode 100644 docs_source_files/content/webdriver/page_loading_strategy.de.md create mode 100644 docs_source_files/content/webdriver/support_classes.de.md create mode 100644 docs_source_files/content/webdriver/understanding_the_components.de.md create mode 100644 docs_source_files/content/webdriver/waits.de.md create mode 100644 docs_source_files/content/webdriver/web_element.de.md create mode 100644 docs_source_files/content/worst_practices/_index.de.md create mode 100644 docs_source_files/content/worst_practices/captchas.de.md create mode 100644 docs_source_files/content/worst_practices/file_downloads.de.md create mode 100644 docs_source_files/content/worst_practices/gmail_email_and_facebook_logins.de.md create mode 100644 docs_source_files/content/worst_practices/http_response_codes.de.md create mode 100644 docs_source_files/content/worst_practices/link_spidering.de.md create mode 100644 docs_source_files/content/worst_practices/performance_testing.de.md create mode 100644 docs_source_files/content/worst_practices/test_dependency.de.md diff --git a/docs_source_files/content/CONTRIBUTING.de.md b/docs_source_files/content/CONTRIBUTING.de.md new file mode 100644 index 000000000000..6fe023d411b8 --- /dev/null +++ b/docs_source_files/content/CONTRIBUTING.de.md @@ -0,0 +1,216 @@ +--- +title: Contributing to the Selenium Site & Documentation +disableToc: true +--- + +Selenium is a big software project, its site and documentation are key +to understanding how things work and learning effective ways to exploit +its potential. + +This project contains both Selenium's site and documentation. This is +an ongoing effort (not targeted at any specific release) to provide +updated information on how to use Selenium effectively, how to get +involved and how to contribute to Selenium. + +Contributions toward the site and docs follow the process described in +the below section about contributions. You should spend some time +familiarising yourself with the documentation by reading +[more about it]({{< ref "/introduction/about_this_documentation.en.md" >}}). + +--- + +The Selenium project welcomes contributions from everyone. There are a +number of ways you can help: + +## Report an issue + +When reporting a new issues or commenting on existing issues please +make sure discussions are related to concrete technical issues with the +Selenium software, its site and/or documentation. + +All of the Selenium components change quite fast over time, so this +might cause the documentation to be out of date. If you find this to +be the case, as mentioned, don't doubt to create an issue for that. +It also might be possible that you know how to bring up to date the +documentation, so please send us a pull request with the related +changes. + +If you are not sure about what you have found is an issue or not, +please ask through the communication channels described at +https://selenium.dev/support. + +## Contributions + +The Selenium project welcomes new contributors. Individuals making +significant and valuable contributions over time are made _Committers_ +and given commit-access to the project. + +This guide will guide you through the contribution process. + +### Step 1: Fork + +Fork the project [on Github](https://github.com/seleniumhq/seleniumhq.github.io) +and check out your copy locally. + +```shell +% git clone git@github.com:username/seleniumhq.github.io.git +% cd seleniumhq.github.io +``` + +#### Dependencies: Hugo + +We use [Hugo](https://gohugo.io/) to build and render the site and docs. +To verify everything locally before even committing any changes, please +[install Hugo](https://gohugo.io/getting-started/installing/), get familiar +with it and [run the local server](https://gohugo.io/getting-started/usage/#livereload) +to render the site locally (detailed instructions can be found in the +next steps). + +### Step 2: Branch + +Create a feature branch and start hacking: + +```shell +% git checkout -b my-feature-branch +``` + +We practice HEAD-based development, which means all changes are applied +directly on top of master. + +### Step 3: Make changes + +The repository contains the site and docs, which are two separate Hugo +projects. If you want to make changes to the site, work on the +`site_source_files` directory. To see a live preview of your changes, +run `hugo server` on the site's root directory. + +```shell +% cd site_source_files +% hugo server +``` + +To make changes to the docs, switch to the `docs_source_files` directory. + +```shell +% cd docs_source_files +% hugo server +``` + +The docs are translated into several languages, and translations are based on +the English content. When you are changing a file, **be sure** to make your +changes in all the other translated files as well. This might differ depending +on the change, for example: + +* If you add a code example to the `browser_manipulation.en.md` file, +also add it to `browser_manipulation.es.md`, `browser_manipulation.ef.md`, +`browser_manipulation.ja.md`, and all other translated files. +* If you find a translation that can be improved, only change the translated +file. +* If you are adding a new language translation, add the new files with the +appropriate suffix. There is no need to have everything translated to submit a +PR, it can be done iteratively. Don't forget to check some needed configuration +values in the `config.toml` file. +* If you make text changes in the English version, replace the same section in +the translated files with your change (yes, in English), and add the following +notice at the top of the file. + + +``` +{{%/* notice info */%}} + Page being translated from +English to {LANGUAGE}. Do you speak {LANGUAGE}? Help us to translate +it by sending us pull requests! +{{%/* /notice */%}} +``` + +### Step 4: Commit + +First make sure git knows your name and email address: + +```shell +% git config --global user.name 'Santa Claus' +% git config --global user.email 'santa@example.com' +``` + +**Writing good commit messages is important.** A commit message +should describe what changed, why, and reference issues fixed (if +any). Follow these guidelines when writing one: + +1. The first line should be around 50 characters or less and contain a + short description of the change. +2. Keep the second line blank. +3. Wrap all other lines at 72 columns. +4. Include `Fixes #N`, where _N_ is the issue number the commit + fixes, if any. + +A good commit message can look like this: + +```text +explain commit normatively in one line + +Body of commit message is a few lines of text, explaining things +in more detail, possibly giving some background about the issue +being fixed, etc. + +The body of the commit message can be several paragraphs, and +please do proper word-wrap and keep columns shorter than about +72 characters or so. That way `git log` will show things +nicely even when it is indented. + +Fixes #141 +``` + +The first line must be meaningful as it's what people see when they +run `git shortlog` or `git log --oneline`. + +### Step 5: Rebase + +Use `git rebase` (not `git merge`) to sync your work from time to time. + +```shell +% git fetch upstream +% git rebase upstream/master +``` + +### Step 6: Test + +Always remember to [run the local server](https://gohugo.io/getting-started/usage/#livereload), +with this you can be safe that your changes have not broken anything. + +### Step 7: Sign the CLA + +Before we can accept, we first ask people to sign a +[Contributor License Agreement](https://spreadsheets.google.com/spreadsheet/viewform?hl=en_US&formkey=dFFjXzBzM1VwekFlOWFWMjFFRjJMRFE6MQ#gid=0) +(or CLA). We ask this so that we know that contributors have the right +to donate the code. + +When you open your pull request we ask that you indicate that you've +signed the CLA. This will reduce the time it takes for us to integrate +it. + +### Step 8: Push + +```shell +% git push origin my-feature-branch +``` + +Go to https://github.com/yourusername/seleniumhq.github.io.git and +press the _Pull Request_ and fill out the form. **Please indicate +that you've signed the CLA** (see Step 7). + +Pull requests are usually reviewed within a few days. If there are +comments to address, apply your changes in new commits (preferably +[fixups](http://git-scm.com/docs/git-commit)) and push to the same +branch. + +### Step 9: Integration + +When code review is complete, a committer will take your PR and +integrate it on the repository's master branch. Because we like to keep a +linear history on the master branch, we will normally squash and rebase +your branch history. + +## Communication + +All details on how to communicate with the project contributors +and the community overall can be found at https://selenium.dev/support diff --git a/docs_source_files/content/_index.de.md b/docs_source_files/content/_index.de.md new file mode 100644 index 000000000000..b7891a1ce42c --- /dev/null +++ b/docs_source_files/content/_index.de.md @@ -0,0 +1,176 @@ +--- +title: "The Selenium Browser Automation Project" +--- + +# The Selenium Browser Automation Project + +Selenium is an umbrella project for a range of tools and libraries +that enable and support the automation of web browsers. + +It provides extensions to emulate user interaction with browsers, +a distribution server for scaling browser allocation, +and the infrastructure for implementations of the +[W3C WebDriver specification](//www.w3.org/TR/webdriver/) +that lets you write interchangeable code for all major web browsers. + +This project is made possible by volunteer contributors +who have put in thousands of hours of their own time, +and made the source code [freely available]({{< ref "/front_matter/copyright_and_attributions.en.md#license" >}}) +for anyone to use, enjoy, and improve. + +Selenium brings together browser vendors, engineers, and enthusiasts +to further an open discussion around automation of the web platform. +The project organises [an annual conference](//seleniumconf.com/) +to teach and nurture the community. + +At the core of Selenium is _[WebDriver]({{< ref "/webdriver/_index.md" >}})_, +an interface to write instruction sets that can be run interchangeably in many +browsers. Here is one of the simplest instructions you can make: + +{{< code-tab >}} + {{< code-panel language="java" >}} +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.support.ui.WebDriverWait; +import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated; + +public class HelloSelenium { + + public static void main(String[] args) { + WebDriver driver = new FirefoxDriver(); + WebDriverWait wait = new WebDriverWait(driver, 10); + try { + driver.get("https://google.com/ncr"); + driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER); + WebElement firstResult = wait.until(presenceOfElementLocated(By.cssSelector("h3>div"))); + System.out.println(firstResult.getAttribute("textContent")); + } finally { + driver.quit(); + } + } +} + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support.expected_conditions import presence_of_element_located + +#This example requires Selenium WebDriver 3.13 or newer +with webdriver.Firefox() as driver: + wait = WebDriverWait(driver, 10) + driver.get("https://google.com/ncr") + driver.find_element_by_name("q").send_keys("cheese" + Keys.RETURN) + first_result = wait.until(presence_of_element_located((By.CSS_SELECTOR, "h3>div"))) + print(first_result.get_attribute("textContent")) + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +using System; +using OpenQA.Selenium; +using OpenQA.Selenium.Firefox; +using OpenQA.Selenium.Support.UI; +using SeleniumExtras.WaitHelpers; + +class HelloSelenium +{ + static void Main() + { + using (IWebDriver driver = new FirefoxDriver()) + { + WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); + driver.Navigate().GoToUrl("https://www.google.com/ncr"); + driver.FindElement(By.Name("q")).SendKeys("cheese" + Keys.Enter); + IWebElement firstResult = wait.Until(ExpectedConditions.ElementExists(By.CssSelector("h3>div"))); + Console.WriteLine(firstResult.GetAttribute("textContent")); + } + } +} + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +require 'selenium-webdriver' + +driver = Selenium::WebDriver.for :firefox +wait = Selenium::WebDriver::Wait.new(timeout: 10) + +begin + driver.get 'https://google.com/ncr' + driver.find_element(name: 'q').send_keys 'cheese', :return + first_result = wait.until { driver.find_element(css: 'h3>div') } + puts first_result.attribute('textContent') +ensure + driver.quit +end + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const {Builder, By, Key, until} = require('selenium-webdriver'); + +(async function example() { + let driver = await new Builder().forBrowser('firefox').build(); + try { + // Navigate to Url + await driver.get('https://www.google.com'); + + // Enter text "cheese" and perform keyboard action "Enter" + await driver.findElement(By.name('q')).sendKeys('cheese', Key.ENTER); + + let firstResult = await driver.wait(until.elementLocated(By.css('h3>div')), 10000); + + console.log(await firstResult.getAttribute('textContent')); + } + finally{ + driver.quit(); + } +})(); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +import org.openqa.selenium.By +import org.openqa.selenium.Keys +import org.openqa.selenium.WebDriver +import org.openqa.selenium.WebElement +import org.openqa.selenium.firefox.FirefoxDriver +import org.openqa.selenium.support.ui.WebDriverWait +import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated + +class HelloSelenium { + + public main(args: Array) { + val driver = new FirefoxDriver() + val wait = new WebDriverWait(driver, 10) + try { + driver.get("https://google.com/ncr") + driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER) + val firstResult = wait.until(presenceOfElementLocated(By.cssSelector("h3>div"))) + System.out.println(firstResult.getAttribute("textContent")) + } finally { + driver.quit() + } + } +} + {{< / code-panel >}} +{{< / code-tab >}} + + +See the _[Quick Tour]({{< ref "/getting_started/quick.en.md" >}})_ for a full explanation +of what goes on behind the scenes when you run this code. +You should continue on to the [narrative documentation]({{< ref "/introduction/_index.md" >}}) +to understand how you can [install]({{< ref "/selenium_installation/_index.md" >}}) and +successfully use Selenium as a test automation tool, +and scaling simple tests like this to run +in large, distributed environments on multiple browsers, +on several different operating systems. + +## Getting started + +If you are new to Selenium, +we have a few resources that can help you +get up to speed right away. + +* [Quick tour]({{< ref "/getting_started/quick.en.md" >}}) + * [WebDriver]({{< ref "/getting_started/quick.en.md#webdriver" >}}) + * [IDE]({{< ref "/getting_started/quick.en.md#ide" >}}) + * [Grid]({{< ref "/getting_started/quick.en.md#grid" >}}) + diff --git a/docs_source_files/content/driver_idiosyncrasies/_index.de.md b/docs_source_files/content/driver_idiosyncrasies/_index.de.md new file mode 100644 index 000000000000..76bc1d9e68f4 --- /dev/null +++ b/docs_source_files/content/driver_idiosyncrasies/_index.de.md @@ -0,0 +1,7 @@ +--- +title: "Driver idiosyncrasies" +chapter: true +weight: 10 +--- + +# Driver idiosyncrasies diff --git a/docs_source_files/content/driver_idiosyncrasies/driver_specific_capabilities.de.md b/docs_source_files/content/driver_idiosyncrasies/driver_specific_capabilities.de.md new file mode 100644 index 000000000000..0330bc1383da --- /dev/null +++ b/docs_source_files/content/driver_idiosyncrasies/driver_specific_capabilities.de.md @@ -0,0 +1,108 @@ +--- +title: "Driver specific capabilities" +weight: 2 +--- + +## Firefox + +### Define Capabilities using `FirefoxOptions` + +`FirefoxOptions` is the new way to define capabilities for the Firefox +browser and should generally be used in preference to DesiredCapabilities. + +{{< code-tab >}} + {{< code-panel language="java" >}} +FirefoxOptions options = new FirefoxOptions(); +options.addPreference("network.proxy.type", 0); +driver = new RemoteWebDriver(options); + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium.webdriver.firefox.options import Options +options = Options() +options.headless = True +driver = webdriver.Firefox(options=options) + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +var options = new FirefoxOptions(); +options.Proxy.Kind = ProxyKind.Direct; +var driver = new FirefoxDriver(options); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val options = new FirefoxOptions() +options.addPreference("network.proxy.type", 0) +driver = RemoteWebDriver(options) + {{< / code-panel >}} +{{< / code-tab >}} + + +### Setting a custom profile + +It is possible to create a custom profile for Firefox as demonstrated below. + +{{< code-tab >}} + {{< code-panel language="java" >}} +FirefoxProfile profile = new FirefoxProfile(); +FirefoxOptions options = new FirefoxOptions(); +options.setProfile(profile); +driver = new RemoteWebDriver(options); + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium.webdriver.firefox.options import Options +from selenium.webdriver.firefox.firefox_profile import FirefoxProfile +options=Options() +firefox_profile = FirefoxProfile() +firefox_profile.set_preference("javascript.enabled", False) +options.profile = firefox_profile + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +var options = new FirefoxOptions(); +var profile = new FirefoxProfile(); +options.Profile = profile; +var driver = new RemoteWebDriver(options); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val options = FirefoxOptions() +options.profile = FirefoxProfile() +driver = RemoteWebDriver(options) + {{< / code-panel >}} +{{< / code-tab >}} + +## Internet Explorer + +### fileUploadDialogTimeout + +In some environments, Internet Explorer may timeout when opening the +File Upload dialog. IEDriver has a default timeout of 1000ms, but you +can increase the timeout using the fileUploadDialogTimeout capability. + +{{< code-tab >}} + {{< code-panel language="java" >}} +// We don't have a Java code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="python" >}} +# We don't have a Python code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +var options = new InternetExplorerOptions(); +options.FileUploadDialogTimeout = TimeSpan.FromMilliseconds(2000); +var driver = new RemoteWebDriver(options); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} +{{< / code-tab >}} diff --git a/docs_source_files/content/driver_idiosyncrasies/shared_capabilities.de.md b/docs_source_files/content/driver_idiosyncrasies/shared_capabilities.de.md new file mode 100644 index 000000000000..e01af9dd4c15 --- /dev/null +++ b/docs_source_files/content/driver_idiosyncrasies/shared_capabilities.de.md @@ -0,0 +1,23 @@ +--- +title: "Shared capabilities" +weight: 1 +--- + +### pageLoadStrategy +When navigating to a new page via URL, by default Selenium will wait +until the page has fully loaded before responding. This works well for +beginners, but can cause long wait times on pages that load a large +number of third party resources. Using a non default strategy can make +test execution faster in cases like this, but can also introduce flakiness +where elements on the page change position as elements load in and change +size. + +The page load strategy queries the +[document.readyState](//developer.mozilla.org/en-US/docs/Web/API/Document/readyState) +as described in the table below: + +| Strategy | Ready State | Notes | +| -------- | ----------- | ----- | +| normal | complete | Used by default, waits for all resources to download | +| eager | interactive | DOM access is ready, but other resources like images may still be loading | +| none | Any | Does not block WebDriver at all | \ No newline at end of file diff --git a/docs_source_files/content/findAndReplaceText.sh b/docs_source_files/content/findAndReplaceText.sh new file mode 100755 index 000000000000..f8ad638f30e0 --- /dev/null +++ b/docs_source_files/content/findAndReplaceText.sh @@ -0,0 +1,32 @@ +# find and copy: +find . -iname "*.en.md" -exec sh -c 'f="{}"; cp "$f" "${f%.en.md}.de.md"' \; + +# find copied files +DE_MD_FILES=$(find . -iname "*.de.md") + +# desired text in _de.md files +DESIRED_TEXT="german not translated yet" + +# see if de_md_files were found +if [ ! -z "$DE_MD_FILES" ] +then + #count files and print info message + FILE_COUNT=$(echo "$DE_MD_FILES" | grep -c '^') + # debugging purposes, can be deleted without harming anything + echo "::: \t $FILE_COUNT files were found. replacing text.." + + for de_file in $DE_MD_FILES + do + # debugging purposes, can be deleted without harming anything + echo "::: \t..in $de_file" + + # empty en_md_file + # echo "$DESIRED_TEXT" > $de_file + + # gewünschter Text UND danach der original Text aus dem copied file + #echo "$DESIRED_TEXT\n$(cat $de_file)" > $de_file + done + +else + echo "no files with extension .de.md found" +fi diff --git a/docs_source_files/content/front_matter/_index.de.md b/docs_source_files/content/front_matter/_index.de.md new file mode 100644 index 000000000000..a0251537ab39 --- /dev/null +++ b/docs_source_files/content/front_matter/_index.de.md @@ -0,0 +1,7 @@ +--- +title: "Front matter" +chapter: true +weight: 13 +--- + +# Front matter diff --git a/docs_source_files/content/front_matter/copyright_and_attributions.de.md b/docs_source_files/content/front_matter/copyright_and_attributions.de.md new file mode 100644 index 000000000000..38e553bd453c --- /dev/null +++ b/docs_source_files/content/front_matter/copyright_and_attributions.de.md @@ -0,0 +1,285 @@ +--- +title: "Copyright and attributions" +weight: 1 +--- + +## **The Documentation of Selenium** + +Copyright {{< copyright >}}, Software Freedom Conservancy. + +Every effort has been made to make this documentation +as complete and as accurate as possible, +but no warranty or fitness is implied. +The information provided is on an “as-is” basis. +The authors and the publisher shall have +neither liability nor responsibility to any person or entity +with respect to any loss or damages arising +from the information contained in this book. +No patent liability is assumed with respect +to the use of the information contained herein. + + +## Attributions + +### Thanks to: + +#### [Selenium Main Repository](//github.com/SeleniumHQ/selenium/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/selenium/contributors?per_page=100" %}} + +#### [Selenium IDE](//github.com/SeleniumHQ/selenium-ide/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/selenium-ide/contributors?per_page=100" %}} + +#### [Docker Selenium](//github.com/SeleniumHQ/docker-selenium/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/docker-selenium/contributors?per_page=100" %}} + +#### [Selenium Website & Docs](//github.com/SeleniumHQ/seleniumhq.github.io/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/seleniumhq.github.io/contributors?per_page=100" %}} + +#### [Previous Selenium Website](//github.com/SeleniumHQ/www.seleniumhq.org/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/www.seleniumhq.org/contributors?per_page=100" %}} + +#### [Previous Documentation Rewrite Project](//github.com/SeleniumHQ/docs/) + +{{% ghcontributors "https://api.github.com/repos/seleniumhq/docs/contributors?per_page=100" %}} + + +## Third-Party software used by Selenium documentation project: + +| Software | Version | License | +| -------- | ------- | ------- | +| [Hugo](//gohugo.io/) | v0.55.6 | [Apache 2.0](//gohugo.io/about/license/) | +| [Hugo Learn Theme](//themes.gohugo.io/hugo-theme-learn/) | v2.3.0 | [MIT](//github.com/matcornic/hugo-theme-learn/blob/master/LICENSE.md) | +| [Code Tabs Style](//codepen.io/markcaron/pen/MvGRYV) | --- | [MIT](//blog.codepen.io/legal/licensing/) | + + +## HTML version and source code + +An HTML version of this documentation is freely available from +[https://seleniumhq.github.io/docs](//seleniumhq.github.io/docs). + +The source code for the examples included, +and for the book itself is available from the Selenium documentation repository +at [https://seleniumhq.github.io/docs](//seleniumhq.github.io/docs). +See instructions on how to check out the code via git at +[https://help.github.com/articles/fetching-a-remote/](//help.github.com/articles/fetching-a-remote/). + + +## License + +All code and documentation originating from the Selenium project +is licensed under the Apache 2.0 license, +with the [Software Freedom Conservancy](//sfconservancy.org/) +as the copyright holder. + +The license is included here for convenience, +but you can also find it on the +[Apache Foundation's websites](//apache.org/licenses/LICENSE-2.0.html): + +```markdown + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +``` diff --git a/docs_source_files/content/front_matter/typographical_conventions.de.md b/docs_source_files/content/front_matter/typographical_conventions.de.md new file mode 100644 index 000000000000..071d9fe712fb --- /dev/null +++ b/docs_source_files/content/front_matter/typographical_conventions.de.md @@ -0,0 +1,38 @@ +--- +title: "Typographical conventions" +weight: 2 +--- + +## Capitalisation of titles + +One should avoid title capitalisation, +such as _A Very Fine Heading_, +and instead go for _A very fine heading_. +Gratutious capitalisation, or title case, +often show a misunderstanding of – or a disregard for – +orthographic conventions. +We prefer what is known as _sentence case_, +with a single initial capital to start headers. + +## Line length + +When editing the documentation’s source, +which is written in plain HTML, +limit your line lengths to around 72 characters. + +Some of us take this one step further +and use what is called +[_semantic linefeeds_](//rhodesmill.org/brandon/2012/one-sentence-per-line), +which is a technique whereby the HTML source lines, +which are not read by the public, +are split at ‘natural breaks’ in the prose. +In other words, sentences are split +at natural breaks between clauses. +Instead of fussing with the lines of each paragraph +so that they all end near the right margin, +linefeeds can be added anywhere +that there is a break between ideas. + +This can make diffs very easy to read +when collaborating through git, +but it is not something we enforce contributors to use. diff --git a/docs_source_files/content/getting_started/_index.de.md b/docs_source_files/content/getting_started/_index.de.md new file mode 100644 index 000000000000..f47202f553cf --- /dev/null +++ b/docs_source_files/content/getting_started/_index.de.md @@ -0,0 +1,16 @@ +--- +title: "Getting started" +chapter: true +weight: 1 +--- + +# Getting started + +If you are new to Selenium, +we have a few resources that can help you +get up to speed right away. + +* [Quick tour]({{< ref "/getting_started/quick.en.md" >}}) + * [WebDriver]({{< ref "/getting_started/quick.en.md#webdriver" >}}) + * [IDE]({{< ref "/getting_started/quick.en.md#ide" >}}) + * [Grid]({{< ref "/getting_started/quick.en.md#grid" >}}) diff --git a/docs_source_files/content/getting_started/quick.de.md b/docs_source_files/content/getting_started/quick.de.md new file mode 100644 index 000000000000..19eb64bf05b0 --- /dev/null +++ b/docs_source_files/content/getting_started/quick.de.md @@ -0,0 +1,34 @@ +--- +title: "Quick tour" +weight: 1 +--- + +Selenium is not just one tool or API +but it composes many tools. + +## WebDriver + +If you are beginning with desktop website test automation then you +are going to be using WebDriver APIs. _[WebDriver]({{< ref "/webdriver/_index.md" >}})_ +uses browser automation APIs provided by browser vendors to control browser and +run tests. This is as if a real user is operating the browser. Since +WebDriver does not require its API to be compiled with application +code, it is not intrusive in nature. Hence, you are testing the +same application which you push live. + + +## IDE + +_[IDE](https://selenium.dev/selenium-ide)_ (Integrated Development Environment) +is the tool you use to develop your Selenium test cases. It’s an easy-to-use Chrome +and Firefox extension and is generally the most efficient way to develop +test cases. It records the users actions in the browser for you, using +existing Selenium commands, with parameters defined by the context of +that element. This is not only a time-saver, but also an excellent way +of learning Selenium script syntax. + +## Grid + +Soon after development of WebDriver tests, you may face a need of +running your tests on multiple browser and operating system combinations. +This is where _[Grid]({{< ref "/grid/_index.md" >}})_ comes to the rescue. diff --git a/docs_source_files/content/getting_started_with_webdriver/_index.de.md b/docs_source_files/content/getting_started_with_webdriver/_index.de.md new file mode 100644 index 000000000000..3079037b9cc7 --- /dev/null +++ b/docs_source_files/content/getting_started_with_webdriver/_index.de.md @@ -0,0 +1,29 @@ +--- +title: "Getting started with WebDriver" +chapter: true +weight: 4 +--- + +# Getting started with WebDriver + +Selenium supports automation of all the major browsers in the market +through the use of _WebDriver_. +WebDriver is an API and protocol that defines a language-neutral interface +for controlling the behaviour of web browsers. +Each browser is backed by a specific WebDriver implementation, called a *driver*. +The driver is the component responsible for delegating down to the browser, +and handles communication to and from Selenium and the browser. + +This separation is part of a conscious effort to have browser vendors +take responsibility for the implementation for their browsers. +Selenium makes use of these third party drivers where possible, +but also provides its own drivers maintained by the project +for the cases when this is not a reality. + +The Selenium framework ties all of these pieces together +through a user-facing interface that enables the different browser backends +to be used transparently, +enabling cross-browser and cross-platform automation. + +More details about drivers can be found in +[Driver Idiosyncrasies]({{< ref "/driver_idiosyncrasies/_index.md" >}}). \ No newline at end of file diff --git a/docs_source_files/content/getting_started_with_webdriver/browsers.de.md b/docs_source_files/content/getting_started_with_webdriver/browsers.de.md new file mode 100644 index 000000000000..fd0c1da29d88 --- /dev/null +++ b/docs_source_files/content/getting_started_with_webdriver/browsers.de.md @@ -0,0 +1,27 @@ +--- +title: "Browsers" +weight: 1 +--- + +## Consumer browsers + +The Selenium framework officially supports the following browsers: + +| Browser | Maintainer | Versions Supported | +| -------- | ---------- | ------------------ | +| Chromium | [Chromium](//sites.google.com/a/chromium.org/chromedriver/) | All versions | +| Firefox | [Mozilla](//github.com/mozilla/geckodriver/) | 54 and newer | +| Internet Explorer | Selenium | 6 and newer | +| Opera | Opera [Chromium](//github.com/operasoftware/operachromiumdriver/) / [Presto](//github.com/operasoftware/operaprestodriver) | 10.5 and newer | +| Safari | [Apple](//webkit.org/blog/6900/webdriver-support-in-safari-10/) | 10 and newer | + +## Specialized browsers + +There is also a set of specialized browsers out there +typically used in development environments. +We can make use of some of these browsers for automation purposes also, +and Selenium ties in support for the following specialized drivers: + +| Driver Name | Purpose | Maintainer | +| -------- | ---------- | ------------------ | +| HtmlUnitDriver | Headless browser emulator backed by Rhino | Selenium project | diff --git a/docs_source_files/content/getting_started_with_webdriver/locating_elements.de.md b/docs_source_files/content/getting_started_with_webdriver/locating_elements.de.md new file mode 100644 index 000000000000..c089e8ac2f6b --- /dev/null +++ b/docs_source_files/content/getting_started_with_webdriver/locating_elements.de.md @@ -0,0 +1,199 @@ +--- +title: "Locating elements" +weight: 3 +--- + +### Locating one element + +One of the most fundamental techniques to learn when using WebDriver is +how to find elements on the page. WebDriver offers a number of built-in selector +types, amongst them finding an element by its ID attribute: + +{{< code-tab >}} + {{< code-panel language="java" >}} +WebElement cheese = driver.findElement(By.id("cheese")); + {{< / code-panel >}} + {{< code-panel language="python" >}} +driver.find_element_by_id("cheese") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +IWebElement element = driver.FindElement(By.Id("cheese")); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +driver.find_element(id: "cheese") + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const cheese = await driver.findElement(By.id('cheese')); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val cheese: WebElement = driver.findElement(By.id("cheese")) + {{< / code-panel >}} +{{< / code-tab >}} + +As seen in the example, locating elements in WebDriver is done on the +`WebDriver` instance object. The `findElement(By)` method returns +another fundamental object type, the `WebElement`. + +* `WebDriver` represents the browser +* `WebElement` represents a particular DOM node + (a control, e.g. a link or input field, etc.) + +Once you have a reference to a web element that's been “found”, +you can narrow the scope of your search +by using the same call on that object instance: + +{{< code-tab >}} + {{< code-panel language="java" >}} +WebElement cheese = driver.findElement(By.id("cheese")); +WebElement cheddar = cheese.findElement(By.id("cheddar")); + {{< / code-panel >}} + {{< code-panel language="python" >}} +cheese = driver.find_element_by_id("cheese") +cheddar = cheese.find_elements_by_id("cheddar") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +IWebElement cheese = driver.FindElement(By.Id("cheese")); +IWebElement cheddar = cheese.FindElement(By.Id("cheddar")); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +cheese = driver.find_element(id: "cheese") +cheddar = cheese.find_elements(id: "cheddar") + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const cheese = await driver.findElement(By.id('cheese')); +const cheddar = await cheese.findElement(By.id('cheddar')); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val cheese = driver.findElement(By.id("cheese")) +val cheddar = cheese.findElement(By.id("cheddar")) + {{< / code-panel >}} +{{< / code-tab >}} + +You can do this because both the _WebDriver_ and _WebElement_ types +implement the [_SearchContext_](//seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/SearchContext.html>SearchContext) +interface. In WebDriver, this is known as a _role-based interface_. +Role-based interfaces allow you to determine whether a particular +driver implementation supports a given feature. These interfaces are +clearly defined and try to adhere to having only a single role of +responsibility. You can read more about WebDriver's design and what +roles are supported in which drivers in the [Some Other Section Which +Must Be Named](#). + + +Consequently, the _By_ interface used above also supports a +number of additional locator strategies. A nested lookup might not be +the most effective cheese location strategy since it requires two +separate commands to be issued to the browser; first searching the DOM +for an element with ID “cheese”, then a search for “cheddar” in a +narrowed context. + +To improve the performance slightly, we should try to use a more +specific locator: WebDriver supports looking up elements +by CSS locators, allowing us to combine the two previous locators into +one search: + +{{< code-tab >}} + {{< code-panel language="java" >}} +driver.findElement(By.cssSelector("#cheese #cheddar")); + {{< / code-panel >}} + {{< code-panel language="python" >}} +cheddar = driver.find_element_by_css_selector("#cheese #cheddar") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +driver.FindElement(By.CssSelector("#cheese #cheddar")); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +mucho_cheese = driver.find_elements(css: "#cheese #cheddar") + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const cheddar = await driver.findElement(By.css('#cheese #cheddar')); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +driver.findElement(By.cssSelector("#cheese #cheddar")) + {{< / code-panel >}} +{{< / code-tab >}} + +### Locating multiple elements + +It is possible that the document we are working with may turn out to have an +ordered list of the cheese we like the best: + +```html +
    +
  1. … +
  2. … +
  3. … +
  4. … + +``` + +Since more cheese is undisputably better, and it would be cumbersome +to have to retrieve each of the items individually, a superior +technique for retrieving cheese is to make use of the pluralized +version `findElements(By)`. This method returns a collection of web +elements. If only one element is found, it will still return a +collection (of one element). If no element matches the locator, an +empty list will be returned. + +{{< code-tab >}} + {{< code-panel language="java" >}} +List muchoCheese = driver.findElements(By.cssSelector("#cheese li")); + {{< / code-panel >}} + {{< code-panel language="python" >}} +mucho_cheese = driver.find_elements_by_css_selector("#cheese li") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +IReadOnlyList muchoCheese = driver.FindElements(By.CssSelector(“#cheese li”)); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +mucho_cheese = driver.find_elements(css: "#cheese li") + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const muchoCheese = await driver.findElements(By.css('#cheese li')); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val muchoCheese: List = driver.findElements(By.cssSelector("#cheese li")) + {{< / code-panel >}} +{{< / code-tab >}} + +### Element selection strategies + +There are eight different built-in element location strategies in WebDriver: + +| Locator | Description | +| -------- | ---------- | +| class name | Locates elements whose class name contains the search value (compound class names are not permitted) | +| css selector | Locates elements matching a CSS selector | +| id | Locates elements whose ID attribute matches the search value | +| name | Locates elements whose NAME attribute matches the search value | +| link text | Locates anchor elements whose visible text matches the search value | +| partial link text | Locates anchor elements whose visible text matches the search value | +| tag name | Locates elements whose tag name matches the search value | +| xpath | Locates elements matching an XPath expression | + +### Tips on using selectors + +In general, if HTML IDs are available, unique, and consistently +predictable, they are the preferred method for locating an element on +a page. They tend to work very quickly, and forego much processing +that comes with complicated DOM traversals. + +If unique IDs are unavailable, a well-written CSS selector is the +preferred method of locating an element. XPath works as well as CSS +selectors, but the syntax is complicated and frequently difficult to +debug. Though XPath selectors are very flexible, they are typically +not performance tested by browser vendors and tend to be quite slow. + +Selection strategies based on link text and partial link text have +drawbacks in that they only work on link elements. Additionally, they +call down to XPath selectors internally in WebDriver. + +Tag name can be a dangerous way to locate elements. There are +frequently multiple elements of the same tag present on the page. +This is mostly useful when calling the _findElements(By)_ method which +returns a collection of elements. + +The recommendation is to keep your locators as compact and +readable as possible. Asking WebDriver to traverse the DOM structure +is an expensive operation, and the more you can narrow the scope of +your search, the better. diff --git a/docs_source_files/content/getting_started_with_webdriver/performing_actions_on_the_aut.de.md b/docs_source_files/content/getting_started_with_webdriver/performing_actions_on_the_aut.de.md new file mode 100644 index 000000000000..c3b6baf214d8 --- /dev/null +++ b/docs_source_files/content/getting_started_with_webdriver/performing_actions_on_the_aut.de.md @@ -0,0 +1,98 @@ +--- +title: "Performing actions on the AUT*" +weight: 4 +--- + +You can set an element's text using the sendKeys method as follows: + +{{< code-tab >}} + {{< code-panel language="java" >}} +String name = "Charles"; +driver.findElement(By.name("name")).sendKeys(name); + {{< / code-panel >}} + {{< code-panel language="python" >}} +name = "Charles" +driver.find_element_by_name("name").send_keys(name) + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +string name = "Charles"; +driver.FindElement(By.Name("name")).SendKeys(name); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +name = "Charles" +driver.find_element(name: "name").send_keys(name) + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const name = "Charles"; +await driver.findElement(By.name('name')).sendKeys(name); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val name = "Charles" +driver.findElement(By.name("name")).sendKeys(name) + {{< / code-panel >}} +{{< / code-tab >}} + +Some web applications use JavaScript libraries to add drag-and-drop +functionality. The following is a basic example of dragging one +element onto another element: + +{{< code-tab >}} + {{< code-panel language="java" >}} +WebElement source = driver.findElement(By.id("source")); +WebElement target = driver.findElement(By.id("target")); +new Actions(driver).dragAndDrop(source, target).build().perform(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +source = driver.find_element_by_id("source") +target = driver.find_element_by_id("target") +ActionChains(driver).drag_and_drop(source, target).perform() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +IWebElement source = driver.FindElement(By.Id("source")); +IWebElement target = driver.FindElement(By.Id("target")); +new Actions(driver).DragAndDrop(source, target).Build().Perform(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +source = driver.find_element(id: "source") +target = driver.find_element(id: "target") +driver.action.drag_and_drop(source, target).perform + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +const actions = driver.actions({bridge: true}); +const source = await driver.findElement(By.id('source')); +const target = await driver.findElement(By.id('target')); +await actions.dragAndDrop(source, target).perform(); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val source = driver.findElement(By.id("source")) +val target = driver.findElement(By.id("target")) +Actions(driver).dragAndDrop(source, target).build().perform() + {{< / code-panel >}} +{{< / code-tab >}} + +### Clicking on an element + +You can click on an element using the click method: + +{{< code-tab >}} + {{< code-panel language="java" >}} +driver.findElement(By.cssSelector("input[type='submit']")).click(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +driver.find_element_by_css_selector("input[type='submit']").click() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +driver.FindElement(By.CssSelector("input[type='submit']")).Click(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +driver.find_element(css: "input[type='submit']").click + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +await driver.findElement(By.css("input[type='submit']")).click(); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +driver.findElement(By.cssSelector("input[type='submit']")).click() + {{< / code-panel >}} +{{< / code-tab >}} + +***AUT**: Application under test diff --git a/docs_source_files/content/getting_started_with_webdriver/third_party_drivers_and_plugins.de.md b/docs_source_files/content/getting_started_with_webdriver/third_party_drivers_and_plugins.de.md new file mode 100644 index 000000000000..69b410e775e8 --- /dev/null +++ b/docs_source_files/content/getting_started_with_webdriver/third_party_drivers_and_plugins.de.md @@ -0,0 +1,24 @@ +--- +title: "Third party drivers and plugins" +weight: 2 +--- + +Selenium can be extended through the use of plugins. Here are a number of +plugins created and maintained by third parties. For more information on how +to create your own plugin or have it listed, consult the docs. + +Please note that these plugins are not supported, maintained, hosted, or +endorsed by the Selenium project. In addition, be advised that the plugins +listed below are not necessarily licensed under the Apache License v.2.0. +Some of the plugins are available under another free and open source software +license; others are only available under a proprietary license. Any questions +about plugins and their license of distribution need to be raised with their +respective developer(s). + +|Browser|Latest|Change log|Issue Tracker| +|--- |--- |--- |--- | +|[Mozilla GeckoDriver](https://github.com/mozilla/geckodriver/)|[latest](https://github.com/mozilla/geckodriver/releases)|[change log](https://github.com/mozilla/geckodriver/blob/release/CHANGES.md)|[issue tracker](https://github.com/mozilla/geckodriver/issues)| +|[Google Chrome Driver](https://sites.google.com/a/chromium.org/chromedriver/)|[latest](https://sites.google.com/a/chromium.org/chromedriver/downloads)|[change log](https://sites.google.com/a/chromium.org/chromedriver/downloads)|[issue tracker](https://bugs.chromium.org/p/chromedriver/issues/list)| +|[Opera](http://choice.opera.com/developer/tools/operadriver/)|[latest](https://github.com/operasoftware/operachromiumdriver/releases)|-|[issue tracker](https://github.com/operasoftware/operachromiumdriver/issues)| +|[Microsoft Edge Driver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)|[latest](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads)|-|[issue tracker](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/)| +|[SafariDriver](https://webkit.org/blog/6900/webdriver-support-in-safari-10/)|Built in|-|[issue tracker](https://bugreport.apple.com/)| diff --git a/docs_source_files/content/grid/_index.de.md b/docs_source_files/content/grid/_index.de.md new file mode 100644 index 000000000000..dc2e63095e89 --- /dev/null +++ b/docs_source_files/content/grid/_index.de.md @@ -0,0 +1,27 @@ +--- +title: "Grid" +chapter: true +weight: 9 +--- + +# Grid + +_Selenium Grid_ is a smart proxy server +that allows Selenium tests to route commands to remote web browser instances. +Its aim is to provide an easy way to run tests in parallel on multiple machines. + +With Selenium Grid, +one server acts as the hub that routes JSON formatted test commands +to one or more registered Grid nodes. +Tests contact the hub to obtain access to remote browser instances. +The hub has a list of registered servers that it provides access to, +and allows control of these instances. + +Selenium Grid allows us to run tests in parallel on multiple machines, +and to manage different browser versions and browser configurations centrally +(instead of in each individual test). + +Selenium Grid is not a silver bullet. +It solves a subset of common delegation and distribution problems, +but will for example not manage your infrastructure, +and might not suit your specific needs. diff --git a/docs_source_files/content/grid/components_of_a_grid.de.md b/docs_source_files/content/grid/components_of_a_grid.de.md new file mode 100644 index 000000000000..14295e1ad18b --- /dev/null +++ b/docs_source_files/content/grid/components_of_a_grid.de.md @@ -0,0 +1,34 @@ +--- +title: "Components of a Grid" +weight: 2 +--- + +![Grid](/images/grid.png) + +## Hub +* Intermediary and manager +* Accepts requests to run tests +* Takes instructions from client and executes them remotely on the nodes +* Manages threads + +A _Hub_ is a central point where all your tests are sent. +Each Selenium Grid consists of exactly one hub. The hub needs to be reachable +from the respective clients (i.e. CI server, Developer machine etc.) +The hub will connect one or more nodes +that tests will be delegated to. + +## Nodes + +* Where the browsers live +* Registers itself to the hub and communicates its capabilities +* Receives requests from the hub and executes them + +_Nodes_ are different Selenium instances +that will execute tests on individual computer systems. +There can be many nodes in a grid. +The machines which are nodes do not need to be the same platform +or have the same browser selection as that of the hub or the other nodes. +A node on Windows might have the capability of +offering Internet Explorer as a browser option, +whereas this wouldn't be possible on Linux or Mac. + diff --git a/docs_source_files/content/grid/purposes_and_main_functionalities.de.md b/docs_source_files/content/grid/purposes_and_main_functionalities.de.md new file mode 100644 index 000000000000..248ad2029f73 --- /dev/null +++ b/docs_source_files/content/grid/purposes_and_main_functionalities.de.md @@ -0,0 +1,12 @@ +--- +title: "Purposes and main functionalities" +menuTitle: "Purposes and functionalities" +weight: 1 +--- + +* Central entry point for all tests +* Management and control of the nodes / environment where the browsers run +* Scaling +* Running tests in parallel +* Cross platform testing +* Load balancing diff --git a/docs_source_files/content/grid/setting_up_your_own_grid.de.md b/docs_source_files/content/grid/setting_up_your_own_grid.de.md new file mode 100644 index 000000000000..e9235f49e147 --- /dev/null +++ b/docs_source_files/content/grid/setting_up_your_own_grid.de.md @@ -0,0 +1,251 @@ +--- +title: "Setting up your own Grid" +weight: 3 +--- + +To use Selenium Grid, +you need to maintain your own infrastructure for the nodes. +As this can be a cumbersome and time intense effort, +many organizations use IaaS providers +such as Amazon EC2 and Google Compute +to provide this infrastructure. + +Other options include using providers such as Sauce Labs or Testing Bot +who provide a Selenium Grid as a service in the cloud. +It is certainly possible to also run nodes on your own hardware. +This chapter will go into detail about the option of running your own grid, +complete with its own node infrastructure. + + +## Quick start + +This example will show you how to start the Selenium 2 Grid Hub, +and register both a WebDriver node and a Selenium 1 RC legacy node. +We will also show you how to call the grid from Java. +The hub and nodes are shown here running on the same machine, +but of course you can copy the selenium-server-standalone to multiple machines. + +The `selenium-server-standalone` package includes the hub, +WebDriver, and legacy RC needed to run the Grid, +_ant_ is not required anymore. +You can download the `selenium-server-standalone-.jar` from +[https://selenium.dev/downloads/](https://selenium.dev/downloads/). + + +### Step 1: Start the Hub + +The Hub is the central point that will receive test requests +and distribute them to the right nodes. +The distribution is done on a capabilities basis, +meaning a test requiring a set of capabilities +will only be distributed to nodes offering that set or subset of capabilities. + +Because a test's desired capabilities are just what the name implies, _desired_, +the hub cannot guarantee that it will locate a node +fully matching the requested desired capabilities set. + +Open a command prompt +and navigate to the directory where you copied +the `selenium-server-standalone.jar` file. +You start the hub by passing the `-role hub` flag +to the standalone server: + +```shell +java -jar selenium-server-standalone.jar -role hub +``` + +The Hub will listen to port 4444 by default. +You can view the status of the hub by opening a browser window and navigating to +[http://localhost:4444/grid/console](http://localhost:4444/grid/console). + +To change the default port, +you can add the optional `-port` flag +with an integer representing the port to listen to when you run the command. +Also, all of the other options you see in the JSON config file (seen below) +are possible command-line flags. + +You certainly can get by with only the simple command shown above, +but if you need more advanced configuration, +you can also specify a JSON format config file, for convenience, +to configure the hub when you start it. +You can do it like so: + +```shell +java -jar selenium-server-standalone.jar -role hub -hubConfig hubConfig.json -debug +``` + +Below you will see an example of a `hubConfig.json` file. +We will go into more detail on how to provide node configuration files in step 2. + +```json +{ + "_comment" : "Configuration for Hub - hubConfig.json", + "host": ip, + "maxSession": 5, + "port": 4444, + "cleanupCycle": 5000, + "timeout": 300000, + "newSessionWaitTimeout": -1, + "servlets": [], + "prioritizer": null, + "capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher", + "throwOnCapabilityNotPresent": true, + "nodePolling": 180000, + "platform": "WINDOWS"} +``` + + +### Step 2: Start the Nodes + +Regardless of whether you want to run a grid with new WebDriver functionality, +or a grid with Selenium 1 RC functionality, +or both at the same time, +you use the same `selenium-server-standalone.jar` file to start the nodes: + +```shell +java -jar selenium-server-standalone.jar -role node -hub http://localhost:4444 +``` + +If a port is not specified through the `-port` flag, +a free port will be chosen. You can run multiple nodes on one machine +but if you do so, you need to be aware of your systems memory resources +and problems with screenshots if your tests take them. + + +#### Configuration of Node with options + +As mentioned, for backwards compatibility +“wd” and “rc” roles are still a valid subset of the “node” role. +But those roles limit the types of remote connections to their corresponding API, +while “node” allows both RC and WebDriver remote connections. + +Passing JVM properties (using the `-D` flag +_before the -jar argument_) +on the command line as well, +and these will be picked up and propagated to the nodes: + +`-Dwebdriver.chrome.driver=chromedriver.exe` + + +#### Configuration of Node with JSON + +You can also start grid nodes that are configured +with a JSON configuration file + +```shell +java -Dwebdriver.chrome.driver=chromedriver.exe -jar selenium-server-standalone.jar -role node -nodeConfig node1Config.json +``` + +And here is an example of a `nodeConfig.json` file: + +```json +{ + "capabilities": [ + { + "browserName": "firefox", + "acceptSslCerts": true, + "javascriptEnabled": true, + "takesScreenshot": false, + "firefox_profile": "", + "browser-version": "27", + "platform": "WINDOWS", + "maxInstances": 5, + "firefox_binary": "", + "cleanSession": true + }, + { + "browserName": "chrome", + "maxInstances": 5, + "platform": "WINDOWS", + "webdriver.chrome.driver": "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" + }, + { + "browserName": "internet explorer", + "maxInstances": 1, + "platform": "WINDOWS", + "webdriver.ie.driver": "C:/Program Files (x86)/Internet Explorer/iexplore.exe" + } + ], + "configuration": { + "_comment" : "Configuration for Node", + "cleanUpCycle": 2000, + "timeout": 30000, + "proxy": "org.openqa.grid.selenium.proxy.WebDriverRemoteProxy", + "port": 5555, + "host": ip, + "register": true, + "hubPort": 4444, + "maxSession": 5 + } +} +``` + +A note about the `-host` flag + +For both hub and node, if the `-host` flag is not specified, +`0.0.0.0` will be used by default. This will bind to all the +public (non-loopback) IPv4 interfaces of the machine. If you have a special +network configuration or any component that creates extra network interfaces, +it is advised to set the `-host` flag with a value that allows the +hub/node to be reachable from a different machine. + +#### Specifying the port + +The default TCP/IP port used by the hub is 4444. If you need to change the port +please use above mentioned configurations. + +## Troubleshooting + +### Using Log file +For advanced troubleshooting you can specify a log file to log system messages. +Start Selenium GRID hub or node with -log argument. Please see the below example: + +```shell +java -jar selenium-server-standalone.jar -role hub -log log.txt +``` + +Use your favorite text editor to open log file (log.txt in the example above) to find +"ERROR" logs if you get issues. + +### Using `-debug` argument + +Also you can use `-debug` argument to print debug logs to console. +Start Selenium Grid Hub or Node with `-debug` argument. Please see +the below example: + +```shell +java -jar selenium-server-standalone.jar -role hub -debug +``` + +## Warning + +The Selenium Grid must be protected from external access using appropriate +firewall permissions. + +Failure to protect your Grid could result in one or more of the following occurring: + +* You provide open access to your Grid infrastructure +* You allow third parties to access internal web applications and files +* You allow third parties to run custom binaries + +See this blog post on [Detectify](//labs.detectify.com), which gives a good +overview of how a publicly exposed Grid could be misused: +[Don't Leave your Grid Wide Open](//labs.detectify.com/2017/10/06/guest-blog-dont-leave-your-grid-wide-open/). + + +## Docker Selenium +[Docker](//www.docker.com/) provides a convenient way to +provision and scale Selenium Grid infrastructure in a unit known as a container. +Containers are standardised units of software that contain everything required +to run the desired application, including all dependencies, in a reliable and repeatable +way on different machines. + +The Selenium project maintains a set of Docker images which you can download +and run to get a working grid up and running quickly. Nodes are available for +both Firefox and Chrome. Full details of how to provision a grid can be found +within the [Docker Selenium](//github.com/SeleniumHQ/docker-selenium) +repository. + +### Prerequisite +The only requirement to run a Grid is to have Docker installed and working. +[Install Docker](//www.docker.com/products/docker-desktop). diff --git a/docs_source_files/content/grid/when_to_use_grid.de.md b/docs_source_files/content/grid/when_to_use_grid.de.md new file mode 100644 index 000000000000..151fae769f3a --- /dev/null +++ b/docs_source_files/content/grid/when_to_use_grid.de.md @@ -0,0 +1,45 @@ +--- +title: "When to use Grid" +weight: 4 +--- + +Generally speaking, there’s two reasons why you might want to use Grid. + +* To run your tests against multiple browsers, multiple versions of browser, +and browsers running on different operating systems. +* To reduce the time it takes for the test suite to complete a test pass. + +Grid is used to speed up the execution of a test pass by using +multiple machines to run tests in parallel. For example, if you have a suite of +100 tests, but you set up Grid to support 4 different machines (VMs or +separate physical machines) to run those tests, your test suite will complete +in (roughly) one-fourth the time as it would if you ran your tests sequentially +on a single machine. For large test suites, and long-running test suite such as +those performing large amounts of data-validation, this can be a significant +time-saver. Some test suites can take hours to run. Another reason to boost the +time spent running the suite is to shorten the turnaround time for test results +after developers check-in code for the AUT. Increasingly software teams +practicing Agile software development want test feedback as immediately as +possible as opposed to wait overnight for an overnight test pass. + +Grid is also used to support running tests against multiple runtime +environments, specifically, against different browsers at the same time. For +example, a ‘grid’ of virtual machines can be setup with each supporting a +different browser that the application to be tested must support. So, machine 1 +has Internet Explorer 8, machine 2, Internet Explorer 9, machine 3 the latest +Chrome, and machine 4 the latest Firefox. When the test suite is run, +Selenium-Grid receives each test-browser combination and assigns each test to +run against its required browser. + +In addition, one can have a grid of all the same browser, type and version. For +instance, one could have a grid of 4 machines each running 3 instances of +Firefox 70, allowing for a ‘server-farm’ (in a sense) of available Firefox +instances. When the suite runs, each test is passed to Grid which +assigns the test to the next available Firefox instance. In this manner one +gets test pass where conceivably 12 tests are all running at the same time in +parallel, significantly reducing the time required to complete a test pass. + +Grid is very flexible. These two examples can be combined to allow +multiple instances of each browser type and version. A configuration such as +this would provide both, parallel execution for fast test pass completion and +support for multiple browser types and versions simultaneously. diff --git a/docs_source_files/content/guidelines_and_recommendations/_index.de.md b/docs_source_files/content/guidelines_and_recommendations/_index.de.md new file mode 100644 index 000000000000..b53f75b3550e --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/_index.de.md @@ -0,0 +1,28 @@ +--- +title: "Guidelines and recommendations" +menuTitle: "Guidelines" +chapter: true +weight: 7 +--- + +# Guidelines and recommendations + +A note on "Best Practices": We've intentionally avoided the phrase "Best +Practices" in this documentation. No one approach works for all situations. +We prefer the idea of "Guidelines and Recommendations". We encourage +you to read through these and thoughtfully decide what approaches +will work for you in your particular environment. + +Functional testing is difficult to get right for many reasons. +As if application state, complexity, and dependencies do not make testing difficult enough, +dealing with browsers (especially with cross-browser incompatibilities) +makes writing good tests a challenge. + +Selenium provides tools to make functional user interaction easier, +but does not help you write well-architected test suites. +In this chapter we offer advice, guidelines, and recommendations. +on how to approach functional web page automation. + +This chapter records software design patterns popular +amongst many of the users of Selenium +that have proven successful over the years. diff --git a/docs_source_files/content/guidelines_and_recommendations/avoid_sharing_state.de.md b/docs_source_files/content/guidelines_and_recommendations/avoid_sharing_state.de.md new file mode 100644 index 000000000000..1f751a11ec64 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/avoid_sharing_state.de.md @@ -0,0 +1,18 @@ +--- +title: "Avoid sharing state" +weight: 6 +--- + + +Although mentioned in several places it is worth mentioning again. Ensure +tests are isolated from one another. + +* Do not share test data. Imagine several tests that each query the database +for valid orders before picking one to perform an action on. Should two tests +pick up the same order you are likely to get unexpected behaviour. + +* Clean up stale data in the application that might be picked up by another +test e.g. invalid order records. + +* Create a new WebDriver instance per test. This helps ensure test isolation +and makes parallelisation simpler. diff --git a/docs_source_files/content/guidelines_and_recommendations/consider_using_a_fluent_api.de.md b/docs_source_files/content/guidelines_and_recommendations/consider_using_a_fluent_api.de.md new file mode 100644 index 000000000000..3eca47059305 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/consider_using_a_fluent_api.de.md @@ -0,0 +1,78 @@ +--- +title: "Consider using a fluent API" +weight: 8 +--- + + +Martin Fowler coined the term ["Fluent API"](//www.martinfowler.com/bliki/FluentInterface.html). Selenium already +implements something like this in their `FluentWait` class, which is +meant as an alternative to the standard Wait class. +You could enable the Fluent API design pattern in your page object +and then query the Google search page with a code snippet like this one: + +```java +driver.get( "http://www.google.com/webhp?hl=en&tab=ww" ); +GoogleSearchPage gsp = new GoogleSearchPage(); +gsp.withFluent().setSearchString().clickSearchButton(); +``` + +The Google page object class with this fluent behavior +might look like this: + +```java +public class GoogleSearchPage extends LoadableComponent { + private final WebDriver driver; + private GSPFluentInterface gspfi; + + public class GSPFluentInterface { + private GoogleSearchPage gsp; + + public GSPFluentInterface(GoogleSearchPage googleSearchPage) { + gsp = googleSearchPage; + } + + public GSPFluentInterface clickSearchButton() { + gsp.searchButton.click(); + return this; + } + + public GSPFluentInterface setSearchString( String sstr ) { + clearAndType( gsp.searchField, sstr ); + return this; + } + } + + @FindBy(id = "gbqfq") private WebElement searchField; + @FindBy(id = "gbqfb") private WebElement searchButton; + public GoogleSearchPage(WebDriver driver) { + gspfi = new GSPFluentInterface( this ); + this.get(); // If load() fails, calls isLoaded() until page is finished loading + PageFactory.initElements(driver, this); // Initialize WebElements on page + } + + public GSPFluentInterface withFluent() { + return gspfi; + } + + public void clickSearchButton() { + searchButton.click(); + } + + public void setSearchString( String sstr ) { + clearAndType( searchField, sstr ); + } + + @Override + protected void isLoaded() throws Error { + Assert.assertTrue("Google search page is not yet loaded.", isSearchFieldVisible() ); + } + + @Override + protected void load() { + if ( isSFieldPresent ) { + Wait wait = new WebDriverWait( driver, 3 ); + wait.until( visibilityOfElementLocated( By.id("gbqfq") ) ).click(); + } + } +} +``` diff --git a/docs_source_files/content/guidelines_and_recommendations/domain_specific_language.de.md b/docs_source_files/content/guidelines_and_recommendations/domain_specific_language.de.md new file mode 100644 index 000000000000..d119ff37879b --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/domain_specific_language.de.md @@ -0,0 +1,97 @@ +--- +title: "Domain specific language" +weight: 2 +--- + +A domain specific language (DSL) is a system which provides the user with +an expressive means of solving a problem. It allows a user to +interact with the system on their terms – not just programmer-speak. + +Your users, in general, do not care how your site looks. They do not +care about the decoration, animations, or graphics. They +want to use your system to push their new employees through the +process with minimal difficulty; they want to book travel to Alaska; +they want to configure and buy unicorns at a discount. Your job as +tester is to come as close as you can to “capturing” this mind-set. +With that in mind, we set about “modeling” the application you are +working on, such that the test scripts (the user's only pre-release +proxy) “speak” for, and represent the user. + +With Selenium, DSL is usually represented by methods, written to make +the API simple and readable – they enable a report between the +developers and the stakeholders (users, product owners, business +intelligence specialists, etc.). + +## Benefits + +* **Readable:** Business stakeholders can understand it. +* **Writable:** Easy to write, avoids unnecessary duplication. +* **Extensible:** Functionality can (reasonably) be added + without breaking contracts and existing functionality. +* **Maintainable:** By leaving the implementation details out of test + cases, you are well-insulated against changes to the AUT*. + + +## Java + +Here is an example of a reasonable DSL method in Java. +For brevity's sake, it assumes the `driver` object is pre-defined +and available to the method. + +```java +/** + * Takes a username and password, fills out the fields, and clicks "login". + * @return An instance of the AccountPage + */ +public AccountPage loginAsUser(String username, String password) { + WebElement loginField = driver.findElement(By.id("loginField")); + loginField.clear(); + loginField.sendKeys(username); + + // Fill out the password field. The locator we're using is "By.id", and we should + // have it defined elsewhere in the class. + WebElement passwordField = driver.findElement(By.id("password")); + passwordField.clear(); + passwordField.sendKeys(password); + + // Click the login button, which happens to have the id "submit". + driver.findElement(By.id("submit")).click(); + + // Create and return a new instance of the AccountPage (via the built-in Selenium + // PageFactory). + return PageFactory.newInstance(AccountPage.class); +} +``` + +This method completely abstracts the concepts of input fields, +buttons, clicking, and even pages from your test code. Using this +approach, all a tester has to do is call this method. This gives +you a maintenance advantage: if the login fields ever changed, you +would only ever have to change this method - not your tests. + +```java +public void loginTest() { + loginAsUser("cbrown", "cl0wn3"); + + // Now that we're logged in, do some other stuff--since we used a DSL to support + // our testers, it's as easy as choosing from available methods. + do.something(); + do.somethingElse(); + Assert.assertTrue("Something should have been done!", something.wasDone()); + + // Note that we still haven't referred to a button or web control anywhere in this + // script... +} +``` + +It bears repeating: one of your primary goals should be writing an +API that allows your tests to address **the problem at hand, and NOT +the problem of the UI**. The UI is a secondary concern for your +users – they do not care about the UI, they just want to get their job +done. Your test scripts should read like a laundry list of things +the user wants to DO, and the things they want to KNOW. The tests +should not concern themselves with HOW the UI requires you to go +about it. + +***AUT**: Application under test + diff --git a/docs_source_files/content/guidelines_and_recommendations/fresh_browser_per_test.de.md b/docs_source_files/content/guidelines_and_recommendations/fresh_browser_per_test.de.md new file mode 100644 index 000000000000..8ddbb3ecf9ba --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/fresh_browser_per_test.de.md @@ -0,0 +1,15 @@ +--- +title: "Fresh browser per test" +weight: 9 +--- + +Start each test from a clean known state. +Ideally, spin up a new virtual machine for each test. +If spinning up a new virtual machine is not practical, +at least start a new WebDriver for each test. +For Firefox, start a WebDriver with your known profile. + +```java +FirefoxProfile profile = new FirefoxProfile(new File("pathToFirefoxProfile")); +WebDriver driver = new FirefoxDriver(profile); +``` diff --git a/docs_source_files/content/guidelines_and_recommendations/generating_application_state.de.md b/docs_source_files/content/guidelines_and_recommendations/generating_application_state.de.md new file mode 100644 index 000000000000..e04909a40636 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/generating_application_state.de.md @@ -0,0 +1,16 @@ +--- +title: "Generating application state" +weight: 3 +--- + +Selenium should not be used to prepare a test case. All repetitive +actions and preparations for a test case, should be done through other +methods. For example, most web UIs have authentication (e.g. a login +form). Eliminating logging in via web browser before every test will +improve both the speed and stability of the test. A method should be +created to gain access to the AUT* (e.g. using an API to login and set a +cookie). Also, creating methods to pre-load data for +testing should not be done using Selenium. As mentioned previously, +existing APIs should be leveraged to create data for the AUT*. + +***AUT**: Application under test diff --git a/docs_source_files/content/guidelines_and_recommendations/improved_reporting.de.md b/docs_source_files/content/guidelines_and_recommendations/improved_reporting.de.md new file mode 100644 index 000000000000..7571b66b8f79 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/improved_reporting.de.md @@ -0,0 +1,18 @@ +--- +title: "Improved reporting" +weight: 5 +--- + +Selenium is not designed to report on the status of test cases +run. Taking advantage of the built-in reporting capabilities of unit +test frameworks is a good start. Most unit test frameworks have +reports that can generate xUnit or HTML formatted reports. xUnit +reports are popular for importing results to a Continuous Integration +(CI) server like Jenkins, Travis, Bamboo, etc. Here are some links +for more information regarding report outputs for several languages. + +[NUnit 3 Console Runner](//github.com/nunit/docs/wiki/Console-Runner) +[NUnit 3 Console Command Line](//github.com/nunit/docs/wiki/Console-Command-Line) +[xUnit getting test results in TeamCity](//xunit.net/docs/getting-test-results-in-teamcity) +[xUnit getting test results in CruiseControl.NET](//xunit.net/docs/getting-test-results-in-ccnet) +[xUnit getting test results in Azure DevOps](//xunit.net/docs/getting-test-results-in-azure-devops) diff --git a/docs_source_files/content/guidelines_and_recommendations/mock_external_services.de.md b/docs_source_files/content/guidelines_and_recommendations/mock_external_services.de.md new file mode 100644 index 000000000000..0e993beeb3e4 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/mock_external_services.de.md @@ -0,0 +1,7 @@ +--- +title: "Mock external services" +weight: 4 +--- + +Eliminating the dependencies on external services will greatly improve +the speed and stability of your tests. \ No newline at end of file diff --git a/docs_source_files/content/guidelines_and_recommendations/page_object_models.de.md b/docs_source_files/content/guidelines_and_recommendations/page_object_models.de.md new file mode 100644 index 000000000000..8a526adfcd32 --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/page_object_models.de.md @@ -0,0 +1,169 @@ +--- +title: "Page object models" +weight: 1 +--- + +Page Object is a Design Pattern which has become popular in test automation for +enhancing test maintenance and reducing code duplication. A page object is an +object-oriented class that serves as an interface to a page of your AUT. The +tests then use the methods of this page object class whenever they need to +interact with the UI of that page. The benefit is that if the UI changes for +the page, the tests themselves don’t need to change, only the code within the +page object needs to change. Subsequently all changes to support that new UI +are located in one place. + +The Page Object Design Pattern provides the following advantages: + +* There is a clean separation between test code and page specific code such as + locators (or their use if you’re using a UI Map) and layout. +* There is a single repository for the services or operations offered by the page + rather than having these services scattered throughout the tests. + +In both cases this allows any modifications required due to UI changes to all +be made in one place. Useful information on this technique can be found on +numerous blogs as this ‘test design pattern’ is becoming widely used. We +encourage the reader who wishes to know more to search the internet for blogs +on this subject. Many have written on this design pattern and can provide +useful tips beyond the scope of this user guide. To get you started, though, +we’ll illustrate page objects with a simple example. + +First, consider an example, typical of test automation, that does not use a +page object: + +```java +/*** + * Tests login feature + */ +public class Login { + + public void testLogin() { + selenium.type("inputBox", "testUser"); + selenium.type("password", "my supersecret password"); + selenium.click("sign-in"); + selenium.waitForPageToLoad("PageWaitPeriod"); + Assert.assertTrue(selenium.isElementPresent("compose button"), + "Login was unsuccessful"); + } +} +``` + +There are two problems with this approach. + +* There is no separation between the test method and the AUT’s locators (IDs in +this example); both are intertwined in a single method. If the AUT’s UI changes +its identifiers, layout, or how a login is input and processed, the test itself +must change. +* The ID-locators would be spread in multiple tests, in all tests that had to +use this login page. + +Applying the page object techniques, this example could be rewritten like this +in the following example of a page object for a Sign-in page. + +```java +/** + * Page Object encapsulates the Sign-in page. + */ +public class SignInPage { + + private Selenium selenium; + + public SignInPage(Selenium selenium) { + this.selenium = selenium; + if(!selenium.getTitle().equals("Sign in page")) { + throw new IllegalStateException("This is not sign in page, current page is: " + +selenium.getLocation()); + } + } + + /** + * Login as valid user + * + * @param userName + * @param password + * @return HomePage object + */ + public HomePage loginValidUser(String userName, String password) { + selenium.type("usernamefield", userName); + selenium.type("passwordfield", password); + selenium.click("sign-in"); + selenium.waitForPageToLoad("waitPeriod"); + + return new HomePage(selenium); + } +} +``` + +and page object for a Home page could look like this. + +```java +/** + * Page Object encapsulates the Home Page + */ +public class HomePage { + + private Selenium selenium; + + public HomePage(Selenium selenium) { + if (!selenium.getTitle().equals("Home Page of logged in user")) { + throw new IllegalStateException("This is not Home Page of logged in user, current page" + + "is: " +selenium.getLocation()); + } + } + + public HomePage manageProfile() { + // Page encapsulation to manage profile functionality + return new HomePage(selenium); + } + + /*More methods offering the services represented by Home Page + of Logged User. These methods in turn might return more Page Objects + for example click on Compose mail button could return ComposeMail class object*/ + +} +``` + +So now, the login test would use these two page objects as follows. + +```java +/*** + * Tests login feature + */ +public class TestLogin { + + public void testLogin() { + SignInPage signInPage = new SignInPage(selenium); + HomePage homePage = signInPage.loginValidUser("userName", "password"); + Assert.assertTrue(selenium.isElementPresent("compose button"), + "Login was unsuccessful"); + } +} +``` + +There is a lot of flexibility in how the page objects may be designed, but +there are a few basic rules for getting the desired maintainability of your +test code. + +Page objects themselves should never make verifications or assertions. This is +part of your test and should always be within the test’s code, never in an page +object. The page object will contain the representation of the page, and the +services the page provides via methods but no code related to what is being +tested should be within the page object. + +There is one, single, verification which can, and should, be within the page +object and that is to verify that the page, and possibly critical elements on +the page, were loaded correctly. This verification should be done while +instantiating the page object. In the examples above, both the SignInPage and +HomePage constructors check that the expected page is available and ready for +requests from the test. + +A page object does not necessarily need to represent an entire page. The Page +Object design pattern could be used to represent components on a page. If a +page in the AUT has multiple components, it may improve maintainability if +there is a separate page object for each component. + +There are other design patterns that also may be used in testing. Some use a +Page Factory for instantiating their page objects. Discussing all of these is +beyond the scope of this user guide. Here, we merely want to introduce the +concepts to make the reader aware of some of the things that can be done. As +was mentioned earlier, many have blogged on this topic and we encourage the +reader to search for blogs on these topics. diff --git a/docs_source_files/content/guidelines_and_recommendations/test_independency.de.md b/docs_source_files/content/guidelines_and_recommendations/test_independency.de.md new file mode 100644 index 000000000000..6dd8baaa942b --- /dev/null +++ b/docs_source_files/content/guidelines_and_recommendations/test_independency.de.md @@ -0,0 +1,22 @@ +--- +title: "Test independency" +weight: 7 +--- + + +Write each test as its own unit. Write the tests in a way that will not be +reliant on other tests to complete: + +Let us say there is a content management system with which you can create +some custom content which then appears on your website as a module after +publishing, and it may take some time to sync between the CMS and the +application. + +A wrong way of testing your module is that the content is created and +published in one test, and then checking the module in another test. This +is not feasible as the content may not be available immediately for the +other test after publishing. + +Instead, you can create a stub content which can be turned on and off +within the affected test, and use that for validating the module. However, +for content creation, you can still have a separate test. diff --git a/docs_source_files/content/introduction/_index.de.md b/docs_source_files/content/introduction/_index.de.md new file mode 100644 index 000000000000..359e7f09c909 --- /dev/null +++ b/docs_source_files/content/introduction/_index.de.md @@ -0,0 +1,9 @@ +--- +title: "Introduction" +chapter: true +weight: 2 +--- + +# Introduction + +Selenium is an umbrella project for a range of tools and libraries that enable and support the automation of web browsers. \ No newline at end of file diff --git a/docs_source_files/content/introduction/about_this_documentation.de.md b/docs_source_files/content/introduction/about_this_documentation.de.md new file mode 100644 index 000000000000..0f19f70826f9 --- /dev/null +++ b/docs_source_files/content/introduction/about_this_documentation.de.md @@ -0,0 +1,29 @@ +--- +title: "About this documentation" +weight: 4 +--- + +These docs, like the code itself, are maintained 100% by volunteers +within the Selenium community. +Many have been using it since its inception, +but many more have only been using it for a short while, +and have given their time to help improve the on-boarding experience +for new users. + +If there is an issue with the documentation, we want to know! +The best way to communicate an issue is to visit +[https://github.com/seleniumhq/seleniumhq.github.io/issues](//github.com/seleniumhq/seleniumhq.github.io/issues) +and search to see whether or not the issue has been filed already. +If not, feel free to open one! + +Many members of the community frequent +the _#selenium_ IRC channel at [irc.freenode.net](//freenode.net/). +Feel free to drop in and ask questions +and if you get help which you think could be of use within these documents, +be sure to add your contribution! +We can update these documents, +but it is much easier for everyone when we get contributions +from outside the normal committers. + + + diff --git a/docs_source_files/content/introduction/on_test_automation.de.md b/docs_source_files/content/introduction/on_test_automation.de.md new file mode 100644 index 000000000000..eb7496a9a551 --- /dev/null +++ b/docs_source_files/content/introduction/on_test_automation.de.md @@ -0,0 +1,344 @@ +--- +title: "On test automation" +weight: 2 +--- + +First, start by asking yourself whether or not you really need to use a browser. +Odds are that, at some point, if you are working on a complex web application, +you will need to open a browser and actually test it. + +Functional end-user tests such as Selenium tests are expensive to run, however. +Furthermore, they typically require substantial infrastructure +to be in place to be run effectively. +It is a good rule to always ask yourself if what you want to test +can be done using more lightweight test approaches such as unit tests +or with a lower-level approach. + +Once you have made the determination that you are in the web browser testing business, +and you have your Selenium environment ready to begin writing tests, +you will generally perform some combination of three steps: + +* Set up the data +* Perform a discrete set of actions +* Evaluate the results + +You will want to keep these steps as short as possible; +one or two operations should be enough most of the time. +Browser automation has the reputation of being “flaky”, +but in reality that is because users frequently demand too much of it. +In later chapters, we will return to techniques you can use +to mitigate apparent intermittent problems in tests, +in particular on how to [overcome race conditions]({{< ref "/webdriver/waits.en.md" >}}) +between the browser and WebDriver. + +By keeping your tests short +and using the web browser only when you have absolutely no alternative, +you can have many tests with minimal flake. + +A distinct advantage of Selenium tests +are their inherent ability to test all components of the application, +from backend to frontend, from a user's perspective. +So in other words, whilst functional tests may be expensive to run, +they also encompass large business-critical portions at one time. + + +### Testing requirements + +As mentioned before, Selenium tests can be expensive to run. +To what extent depends on the browser you are running the tests against, +but historically browsers' behaviour has varied so much that it has often +been a stated goal to cross-test against multiple browsers. + +Selenium allows you to run the same instructions against multiple browsers +on multiple operating systems, +but the enumeration of all the possible browsers, +their different versions, and the many operating systems they run on +will quickly become a non-trivial undertaking. + + +### Let’s start with an example + +Larry has written a web site which allow users to order their own +custom unicorns. + +The general workflow (what we will call the “happy path”) is something +like this: + +* Create an account +* Configure the unicorn +* Add it to the shopping cart +* Check out and pay +* Give feedback about the unicorn + + +It would be tempting to write one grand Selenium script +to perform all these operations–many will try. +**Resist the temptation!** +Doing so will result in a test that +a) takes a long time, +b) will be subject to some common issues around page rendering timing issues, and +c) is such that if it fails, +it will not give you a concise, “glanceable” method for diagnosing what went wrong. + +The preferred strategy for testing this scenario would be +to break it down to a series of independent, speedy tests, +each of which has one “reason” to exist. + +Let us pretend you want to test the second step: +Configuring your unicorn. +It will perform the following actions: + +* Create an account +* Configure a unicorn + +Note that we are skipping the rest of these steps, +we will test the rest of the workflow in other small, discrete test cases, +after we are done with this one. + +To start off, you need to create an account. +Here you have some choices to make: + +* Do you want to use an existing account? +* Do you want to create a new account? +* Are there any special properties of such a user that need to be + taken into account before configuration begins? + +Regardless of how you answer this question, +the solution is to make it part of the "set up the data" portion of the test. +If Larry has exposed an API which enables you (or anyone) +to create and update user accounts, +be sure to use that to answer this question. +If possible, you want to launch the browser only after you have a user "in hand", +whose credentials you can just log in with. + +If each test for each workflow begins with the creation of a user account, +many seconds will be added to the execution of each test. +Calling an API and talking to a database are quick, +“headless” operations that don't require the expensive process of +opening a browser, navigating to the right pages, +clicking and waiting for the forms to be submitted, etc. + +Ideally, you can address this set-up phase in one line of code, +which will execute before any browser is launched: + +{{< code-tab >}} + {{< code-panel language="java" >}} +// Create a user who has read-only permissions--they can configure a unicorn, +// but they do not have payment information set up, nor do they have +// administrative privileges. At the time the user is created, its email +// address and password are randomly generated--you don't even need to +// know them. +User user = UserFactory.createCommonUser(); //This method is defined elsewhere. + +// Log in as this user. +// Logging in on this site takes you to your personal "My Account" page, so the +// AccountPage object is returned by the loginAs method, allowing you to then +// perform actions from the AccountPage. +AccountPage accountPage = loginAs(user.getEmail(), user.getPassword()); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# Create a user who has read-only permissions--they can configure a unicorn, +# but they do not have payment information set up, nor do they have +# administrative privileges. At the time the user is created, its email +# address and password are randomly generated--you don't even need to +# know them. +user = user_factory.create_common_user() #This method is defined elsewhere. + +# Log in as this user. +# Logging in on this site takes you to your personal "My Account" page, so the +# AccountPage object is returned by the loginAs method, allowing you to then +# perform actions from the AccountPage. +account_page = login_as(user.get_email(), user.get_password()) + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +// Create a user who has read-only permissions--they can configure a unicorn, +// but they do not have payment information set up, nor do they have +// administrative privileges. At the time the user is created, its email +// address and password are randomly generated--you don't even need to +// know them. +val user = UserFactory.createCommonUser() //This method is defined elsewhere. + +// Log in as this user. +// Logging in on this site takes you to your personal "My Account" page, so the +// AccountPage object is returned by the loginAs method, allowing you to then +// perform actions from the AccountPage. +val accountPage = loginAs(user.getEmail(), user.getPassword()) + {{< / code-panel >}} +{{< / code-tab >}} + +As you can imagine, the `UserFactory` can be extended +to provide methods such as `createAdminUser()`, and `createUserWithPayment()`. +The point is, these two lines of code do not distract you from the ultimate purpose of this test: +configuring a unicorn. + +The intricacies of the [Page Object model]({{< ref "/guidelines_and_recommendations/page_object_models.en.md" >}}) +will be discussed in later chapters, but we will introduce the concept here: + +Your tests should be composed of actions, +performed from the user's point of view, +within the context of pages in the site. +These pages are stored as objects, +which will contain specific information about how the web page is composed +and how actions are performed– +very little of which should concern you as a tester. + +What kind of unicorn do you want? +You might want pink, but not necessarily. +Purple has been quite popular lately. +Does she need sunglasses? Star tattoos? +These choices, while difficult, are your primary concern as a tester– +you need to ensure that your order fulfillment center +sends out the right unicorn to the right person, +and that starts with these choices. + +Notice that nowhere in that paragraph do we talk about buttons, +fields, drop-downs, radio buttons, or web forms. +**Neither should your tests!** +You want to write your code like the user trying to solve their problem. +Here is one way of doing this (continuing from the previous example): + +{{< code-tab >}} + {{< code-panel language="java" >}} +// The Unicorn is a top-level Object--it has attributes, which are set here. +// This only stores the values; it does not fill out any web forms or interact +// with the browser in any way. +Unicorn sparkles = new Unicorn("Sparkles", UnicornColors.PURPLE, UnicornAccessories.SUNGLASSES, UnicornAdornments.STAR_TATTOOS); + +// Since we are already "on" the account page, we have to use it to get to the +// actual place where you configure unicorns. Calling the "Add Unicorn" method +// takes us there. +AddUnicornPage addUnicornPage = accountPage.addUnicorn(); + +// Now that we're on the AddUnicornPage, we will pass the "sparkles" object to +// its createUnicorn() method. This method will take Sparkles' attributes, +// fill out the form, and click submit. +UnicornConfirmationPage unicornConfirmationPage = addUnicornPage.createUnicorn(sparkles); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# The Unicorn is a top-level Object--it has attributes, which are set here. +# This only stores the values; it does not fill out any web forms or interact +# with the browser in any way. +sparkles = Unicorn("Sparkles", UnicornColors.PURPLE, UnicornAccessories.SUNGLASSES, UnicornAdornments.STAR_TATTOOS) + +# Since we're already "on" the account page, we have to use it to get to the +# actual place where you configure unicorns. Calling the "Add Unicorn" method +# takes us there. +add_unicorn_page = account_page.add_unicorn() + +# Now that we're on the AddUnicornPage, we will pass the "sparkles" object to +# its createUnicorn() method. This method will take Sparkles' attributes, +# fill out the form, and click submit. +unicorn_confirmation_page = add_unicorn_page.create_unicorn(sparkles) + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +// The Unicorn is a top-level Object--it has attributes, which are set here. +// This only stores the values; it does not fill out any web forms or interact +// with the browser in any way. +val sparkles = Unicorn("Sparkles", UnicornColors.PURPLE, UnicornAccessories.SUNGLASSES, UnicornAdornments.STAR_TATTOOS) + +// Since we are already "on" the account page, we have to use it to get to the +// actual place where you configure unicorns. Calling the "Add Unicorn" method +// takes us there. +val addUnicornPage = accountPage.addUnicorn() + +// Now that we're on the AddUnicornPage, we will pass the "sparkles" object to +// its createUnicorn() method. This method will take Sparkles' attributes, +// fill out the form, and click submit. +unicornConfirmationPage = addUnicornPage.createUnicorn(sparkles) + + {{< / code-panel >}} +{{< / code-tab >}} + +Now that you have configured your unicorn, +you need to move on to step 3: making sure it actually worked. + +{{< code-tab >}} + {{< code-panel language="java" >}} +// The exists() method from UnicornConfirmationPage will take the Sparkles +// object--a specification of the attributes you want to see, and compare +// them with the fields on the page. +Assert.assertTrue("Sparkles should have been created, with all attributes intact", unicornConfirmationPage.exists(sparkles)); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# The exists() method from UnicornConfirmationPage will take the Sparkles +# object--a specification of the attributes you want to see, and compare +# them with the fields on the page. +assert unicorn_confirmation_page.exists(sparkles), "Sparkles should have been created, with all attributes intact" + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +// The exists() method from UnicornConfirmationPage will take the Sparkles +// object--a specification of the attributes you want to see, and compare +// them with the fields on the page. +assertTrue("Sparkles should have been created, with all attributes intact", unicornConfirmationPage.exists(sparkles)) + {{< / code-panel >}} +{{< / code-tab >}} + +Note that the tester still has not done anything but talk about unicorns in this code– +no buttons, no locators, no browser controls. +This method of _modelling_ the application +allows you to keep these test-level commands in place and unchanging, +even if Larry decides next week that he no longer likes Ruby-on-Rails +and decides to re-implement the entire site +in the latest Haskell bindings with a Fortran front-end. + +Your page objects will require some small maintenance +in order to conform to the site redesign, +but these tests will remain the same. +Taking this basic design, +you will want to keep going through your workflows with the fewest browser-facing steps possible. +Your next workflow will involve adding a unicorn to the shopping cart. +You will probably want many iterations of this test in order to make sure the cart is keeping its state properly: +Is there more than one unicorn in the cart before you start? +How many can fit in the shopping cart? +If you create more than one with the same name and/or features, will it break? +Will it only keep the existing one or will it add another? + +Each time you move through the workflow, +you want to try to avoid having to create an account, +login as the user, and configure the unicorn. +Ideally, you will be able to create an account +and pre-configure a unicorn via the API or database. +Then all you have to do is log in as the user, locate Sparkles, +and add her to the cart. + + +### To automate or not to automate? + +Is automation always advantageous? When should one decide to automate test +cases? + +It is not always advantageous to automate test cases. There are times when +manual testing may be more appropriate. For instance, if the application’s user +interface will change considerably in the near future, then any automation +might need to be rewritten anyway. Also, sometimes there simply is not enough +time to build test automation. For the short term, manual testing may be more +effective. If an application has a very tight deadline, there is currently no +test automation available, and it’s imperative that the testing get done within +that time frame, then manual testing is the best solution. diff --git a/docs_source_files/content/introduction/the_selenium_project_and_tools.de.md b/docs_source_files/content/introduction/the_selenium_project_and_tools.de.md new file mode 100644 index 000000000000..e12e35a6ef45 --- /dev/null +++ b/docs_source_files/content/introduction/the_selenium_project_and_tools.de.md @@ -0,0 +1,117 @@ +--- +title: "The Selenium project and tools" +weight: 1 +--- + +### Selenium controls web browsers + +_Selenium_ is many things, +but at its core it is a toolset for web browser automation +that uses the best techniques available +to remotely control browser instances +and emulate a user's interaction with the browser. + +It allows users to simulate common activities performed by end-users; +entering text into fields, +selecting drop-down values and checking boxes, +and clicking links in documents. +It also provides many other controls such as mouse movement, +arbitrary JavaScript execution, and much more. + +Although used primarily for front-end testing of websites, +Selenium is at its core a browser user agent _library_. +The interfaces are ubiquitous to their application, +which encourages composition with other libraries to suit your purpose. + + +### One interface to rule them all + +One of the project's guiding principles +is to support a common interface for all (major) browser technologies. +Web browsers are incredibly complex, highly engineered applications, +performing their operations in completely different ways +but which frequently look the same while doing so. +Even though the text is rendered in the same fonts, +the images are displayed in the same place +and the links take you to the same destination. +What is happening underneath is as different as night and day. +Selenium “abstracts” these differences, +hiding their details and intricacies from the person writing the code. +This allows you to write several lines of code to perform a complicated workflow, +but these same lines will execute on Firefox, +Internet Explorer, Chrome, and all other supported browsers. + + +### Tools and support + +Selenium's minimalist design approach gives it +versatility to be included as a component in bigger applications. +The surrounding infrastructure provided under the Selenium umbrella +gives you the tools to put together +your own [grid of browsers]({{< ref "/grid/_index.md" >}}) +so tests can be run on different browsers and multiple operating systems +across a range of machines. + +Imagine a bank of computers in your server room or data centre +all firing up browsers at the same time +hitting your site's links, forms, +and tables—testing your application 24 hours a day. +Through the simple programming interface +provided for the most common languages, +these tests will run tirelessly in parallel, +reporting back to you when errors occur. + +It is an aim to help make this a reality for you, +by providing users with tools and documentation to not only control browsers, +but to make it easy to scale and deploy such grids. + + +### Who uses Selenium + +Many of the most important companies in the world +have adopted Selenium for their browser-based testing, +often replacing years-long efforts involving other proprietary tools. +As it has grown in popularity, so have its requirements and challenges multiplied. + +As the web becomes more complicated +and new technologies are added to websites, +it's the mission of this project to keep up with them where possible. +Being an open source project, +this support is provided through the generous donation of time from many volunteers, +every one of which has a “day job”. + +Another mission of the project is to encourage +more volunteers to partake in this effort, +and build a strong community +so that the project can continue to keep up with emerging technologies +and remain a dominant platform for functional test automation. + + +### History + +When Selenium 1 was released in 2004, +it was out of the necessity to reduce time spent +manually verifying consistent behaviour in the front-end of a web application. +It made use of what tools were available at the time, +and relied heavily on the injection of JavaScript to the web page under test +to emulate a user's interaction. + +Whilst JavaScript is a good tool to let you introspect the properties of the DOM +and to do certain client-side observations that you would otherwise not be able to do, +it falls short on the ability to naturally replicate a user's interactions +as if the mouse and keyboard are being used. + +Since then, Selenium has grown and matured a lot, +into a tool widely used by many—if not most—of +the largest organisations around the world. +Selenium has gone from a homebrewed test automation toolkit developed at Thoughtworks +for a niché audience and a specific use case, +to the world's _de facto_ browser automation library. + +Just as Selenium RC made use of the tools of the trade available at the time, +[Selenium WebDriver]({{< ref "/webdriver/_index.md" >}}) drives that tradition on by taking +the browser interaction part to the browser vendor's home turf, +and asking them to take responsibility of the backend, browser-facing implementations. +Recently this work has evolved into a W3C standardisation process +where the goal is to turn the WebDriver component in Selenium +into the _du jour_ remote control library for user agents. diff --git a/docs_source_files/content/introduction/types_of_testing.de.md b/docs_source_files/content/introduction/types_of_testing.de.md new file mode 100644 index 000000000000..476234423eb4 --- /dev/null +++ b/docs_source_files/content/introduction/types_of_testing.de.md @@ -0,0 +1,115 @@ +--- +title: "Types of testing" +weight: 3 +--- +## Acceptance testing +This type of test is done in order to determine if a product's +feature matches its requirements. +This generally involves the customer's feedback or specification. + +For web applications, the automation of this testing can be done +directly with Selenium by simulating user expected behaviour. +This simulation could be done by record/playback or through the +different supported languages as explained in this documentation. +Note: Acceptance testing is a subtype of **_functional testing_**, +which some people might also refer to. + +### Functional testing +This type of test is done in order to determine if a product's +feature functions properly, without issues. + +This generally includes: the tests work without errors +(404, exceptions...), in a usable way (correct redirections), +in an accessible way and matching its specifications +(see **_acceptance testing_** above). + +For web applications, the automation of this testing can be +done directly with Selenium by simulating expected returns. +This simulation could be done by record/playback or through +the different supported languages as explained in this documentation. + +### Performance testing +As its name indicates, performance tests are done in order +to measure how well an application is performing. + +There are two main sub-types for performance testing: + +#### Load testing +Load testing is done in order to verify how well the +application works under different defined loads +(usually a particular number of users connected at once). + +#### Stress testing +Stress testing is done in order to verify how well the +application works under stress (or above the maximum supported load). + +Generally, performance tests are done by executing a +number of Selenium written tests simulating different users +hitting a particular function on the web app and +retrieving some meaningful measurements. + +This is generally done by other tools that retrieve the metrics. +One such tools is **_JMeter_**. + +For a web application, details to measure include: +throughput, latency, data loss, individual component loading times... + +Note: All browsers have a performance tab in their +developers' tools section (accessible by pressing F12) + +Note 2: is a subtype of **_non-functional testing_** +as this is generally measured per system and not per function/feature. + +### Regression testing +This testing is generally done after a change, fix or feature addition. + +In order to ensure that the change has not broken any of the existing +functionality, some already executed tests are executed again. + +The set of re-executed test can be full or partial +and can include several different types, depending +on the application and development team. + +### Test driven development (TDD) +Rather than a test type _per se_, TDD is an iterative +development methodology in which tests drive the design of a feature. + +Each cycle starts by creating a set of unit tests that +the feature should eventually pass (they should fail their first time executed). + +After this, development takes place in order to make the tests pass. +The tests are executed again, starting another cycle +and this process continues until all tests are passing. + +This aims to speed up the development of an application +based on the fact that defects are less costly the earlier they are found. + +### Behavior-driven development (BDD) +BDD is also an iterative development methodology +based on the above TDD, in which the goal is to involve +all the parties in the development of an application. + +Each cycle starts by creating some specification +(which should fail). Then create the failing unit +tests (which should also fail) and then do the development. + +This cycle is repeated until all types of tests are passing. + +In order to do so, a specification language is +used. It should be understandable by all parties and +simple, standard and explicit. +Most tools use **_Gherkin_** as this language. + +The goal is to be able to detect even more errors +than TDD, by targeting potential acceptance errors +too and make communication between parties smoother. + +A set of tools are currently available in order +to write the specifications and match them with code functions, +such as **_Cucumber_** or **_SpecFlow._** + +A set of tools are built on top of Selenium to make this process +even faster by directly transforming the BDD specifications into +executable code. +Some of these are: **_JBehave, Capybara and Robot Framework_**. + diff --git a/docs_source_files/content/legacy_docs/_index.de.md b/docs_source_files/content/legacy_docs/_index.de.md new file mode 100644 index 000000000000..e83168914435 --- /dev/null +++ b/docs_source_files/content/legacy_docs/_index.de.md @@ -0,0 +1,11 @@ +--- +title: "Legacy" +chapter: true +weight: 12 +--- + +# Legacy + +Under this section you can find all the documentation related to the legacy components of Selenium. +This is meant to be kept purely for historical reasons and not as a incentive to use deprecated +components. diff --git a/docs_source_files/content/legacy_docs/html-runner.de.md b/docs_source_files/content/legacy_docs/html-runner.de.md new file mode 100644 index 000000000000..83307f758cde --- /dev/null +++ b/docs_source_files/content/legacy_docs/html-runner.de.md @@ -0,0 +1,94 @@ +--- +title: "HTML runner" +weight: 3 +--- + +_Selenium HTML-runner_ allows you to run Test Suites from a +command line. Test Suites are HTML exports from Selenium IDE or +campatible tools. + + +## Common information + +* Combination of releases of geckodriver / firefox / +selenium-html-runner matters. There might be a software +compatibility matrix somewhere. +* selenium-html-runner runs only Test Suite (not Test Case - +for example an export from Monitis Transaction Monitor). Be +sure you comply with this. +* For Linux users with no DISPLAY - you need to start html-runner +with Virtual display (search for xvfb) + +## Example Linux environment +Install / download following software packages: + +```shell +[user@localhost ~]$ cat /etc/redhat-release +CentOS Linux release 7.4.1708 (Core) + +[user@localhost ~]$ rpm -qa | egrep -i "xvfb|java-1.8|firefox" +xorg-x11-server-Xvfb-1.19.3-11.el7.x86_64 +firefox-52.4.0-1.el7.centos.x86_64 +java-1.8.0-openjdk-1.8.0.151-1.b12.el7_4.x86_64 +java-1.8.0-openjdk-headless-1.8.0.151-1.b12.el7_4.x86_64 +``` + +Test Suite example: + +```html +[user@localhost ~]$ cat testsuite.html + + + + + + Test Suite + + + + + +
    Test Suite
    YOUR-TEST-SCENARIO
    + + +``` + + +## How to run selenium-html-runner headless + +Now, the most important part, an example of how to run the +selenium-html-runner! Your experience might vary depending on software +combinations - geckodriver/FF/html-runner releases. + +```shell +xvfb-run java -Dwebdriver.gecko.driver=/home/mmasek/geckodriver.0.18.0 -jar selenium-html-runner-3.7.1.jar -htmlSuite "firefox" "https://YOUR-BASE-URL" "$(pwd)/testsuite.html" "results.html" ; grep result: -A1 results.html/firefox.results.html +``` + +```shell +[user@localhost ~]$ xvfb-run java -Dwebdriver.gecko.driver=/home/mmasek/geckodriver.0.18.0 -jar selenium-html-runner-3.7.1.jar -htmlSuite "*firefox" "https://YOUR-BASE-URL" "$(pwd)/testsuite.html" "results.html" ; grep result: -A1 results.html/firefox.results.html +Multi-window mode is longer used as an option and will be ignored. +1510061109691 geckodriver INFO geckodriver 0.18.0 +1510061109708 geckodriver INFO Listening on 127.0.0.1:2885 +1510061110162 geckodriver::marionette INFO Starting browser /usr/bin/firefox with args ["-marionette"] +1510061111084 Marionette INFO Listening on port 43229 +1510061111187 Marionette WARN TLS certificate errors will be ignored for this session +Nov 07, 2017 1:25:12 PM org.openqa.selenium.remote.ProtocolHandshake createSession +INFO: Detected dialect: W3C +2017-11-07 13:25:12.714:INFO::main: Logging initialized @3915ms to org.seleniumhq.jetty9.util.log.StdErrLog +2017-11-07 13:25:12.804:INFO:osjs.Server:main: jetty-9.4.z-SNAPSHOT +2017-11-07 13:25:12.822:INFO:osjsh.ContextHandler:main: Started o.s.j.s.h.ContextHandler@87a85e1{/tests,null,AVAILABLE} +2017-11-07 13:25:12.843:INFO:osjs.AbstractConnector:main: Started ServerConnector@52102734{HTTP/1.1,[http/1.1]}{0.0.0.0:31892} +2017-11-07 13:25:12.843:INFO:osjs.Server:main: Started @4045ms +Nov 07, 2017 1:25:13 PM org.openqa.selenium.server.htmlrunner.CoreTestCase run +INFO: |open | /auth_mellon.php | | +Nov 07, 2017 1:25:14 PM org.openqa.selenium.server.htmlrunner.CoreTestCase run +INFO: |waitForPageToLoad | 3000 | | +. +. +.etc + +result: +PASS + + +``` diff --git a/docs_source_files/content/legacy_docs/migrating_from_rc_to_webdriver.de.md b/docs_source_files/content/legacy_docs/migrating_from_rc_to_webdriver.de.md new file mode 100644 index 000000000000..f159dd1e2cb0 --- /dev/null +++ b/docs_source_files/content/legacy_docs/migrating_from_rc_to_webdriver.de.md @@ -0,0 +1,253 @@ +--- +title: "Migrating from RC to WebDriver" +weight: 2 +--- + + +## How to Migrate to Selenium WebDriver + + +A common question when adopting Selenium 2 is what's the correct thing to do +when adding new tests to an existing set of tests? Users who are new to the +framework can begin by using the new WebDriver APIs for writing their tests. +But what of users who already have suites of existing tests? This guide is +designed to demonstrate how to migrate your existing tests to the new APIs, +allowing all new tests to be written using the new features offered by WebDriver. + +The method presented here describes a piecemeal migration to the WebDriver +APIs without needing to rework everything in one massive push. This means +that you can allow more time for migrating your existing tests, which +may make it easier for you to decide where to spend your effort. + +This guide is written using Java, because this has the best support for +making the migration. As we provide better tools for other languages, +this guide shall be expanded to include those languages. + + +## Why Migrate to WebDriver + + +Moving a suite of tests from one API to another API requires an enormous +amount of effort. Why would you and your team consider making this move? +Here are some reasons why you should consider migrating your Selenium Tests +to use WebDriver. + +* Smaller, compact API. WebDriver's API is more Object Oriented than the +original Selenium RC API. This can make it easier to work with. +* Better emulation of user interactions. Where possible, WebDriver makes +use of native events in order to interact with a web page. This more closely +mimics the way that your users work with your site and apps. In addition, +WebDriver offers the advanced user interactions APIs which allow you to +model complex interactions with your site. +* Support by browser vendors. Opera, Mozilla and Google are all active +participants in WebDriver's development, and each have engineers working +to improve the framework. Often, this means that support for WebDriver +is baked into the browser itself: your tests run as fast and as stably as +possible. + + +## Before Starting + + +In order to make the process of migrating as painless as possible, make +sure that all your tests run properly with the latest Selenium release. +This may sound obvious, but it's best to have it said! + + +## Getting Started + + +The first step when starting the migration is to change how you obtain +your instance of Selenium. When using Selenium RC, this is done like so: + +```java +Selenium selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.yoursite.com"); +selenium.start(); +``` + +This should be replaced like so: + +```java +WebDriver driver = new FirefoxDriver(); +Selenium selenium = new WebDriverBackedSelenium(driver, "http://www.yoursite.com"); +``` + +## Next Steps + + +Once your tests execute without errors, the next stage is to migrate +the actual test code to use the WebDriver APIs. Depending on how well +abstracted your code is, this might be a short process or a long one. +In either case, the approach is the same and can be summed up simply: +modify code to use the new API when you come to edit it. + +If you need to extract the underlying WebDriver implementation from +the Selenium instance, you can simply cast it to WrapsDriver: + +```java +WebDriver driver = ((WrapsDriver) selenium).getWrappedDriver(); +``` + +This allows you to continue passing the Selenium instance around as +normal, but to unwrap the WebDriver instance as required. + +At some point, you're codebase will mostly be using the newer APIs. +At this point, you can flip the relationship, using WebDriver throughout +and instantiating a Selenium instance on demand: + +```java +Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl); +``` + +## Common Problems + + +Fortunately, you're not the first person to go through this migration, +so here are some common problems that others have seen, and how to solve them. + + +### Clicking and Typing is More Complete + + +A common pattern in a Selenium RC test is to see something like: + +```java +selenium.type("name", "exciting tex"); +selenium.keyDown("name", "t"); +selenium.keyPress("name", "t"); +selenium.keyUp("name", "t"); +``` + +This relies on the fact that "type" simply replaces the content of the +identified element without also firing all the events that would normally +be fired if a user interacts with the page. The final direct invocations +of "key*" cause the JS handlers to fire as expected. + +When using the WebDriverBackedSelenium, the result of filling in the form +field would be "exciting texttt": not what you'd expect! The reason for this +is that WebDriver more accurately emulates user behavior, and so will have +been firing events all along. + +This same fact may sometimes cause a page load to fire earlier than it would +do in a Selenium 1 test. You can tell that this has happened if a +"StaleElementException" is thrown by WebDriver. + + +### WaitForPageToLoad Returns Too Soon + +Discovering when a page load is complete is a tricky business. Do we mean +"when the load event fires", "when all AJAX requests are complete", "when +there's no network traffic", "when document.readyState has changed" or something +else entirely? + +WebDriver attempts to simulate the original Selenium behavior, but this doesn't +always work perfectly for various reasons. The most common reason is that it's +hard to tell the difference between a page load not having started yet, and a +page load having completed between method calls. This sometimes means that +control is returned to your test before the page has finished (or even started!) +loading. + +The solution to this is to wait on something specific. Commonly, this might be +for the element you want to interact with next, or for some Javascript variable +to be set to a specific value. An example would be: + +```java +Wait wait = new WebDriverWait(driver, 30); +WebElement element= wait.until(visibilityOfElementLocated(By.id("some_id"))); +``` + +Where "visibilityOfElementLocated" is implemented as: + +```java +public ExpectedCondition visibilityOfElementLocated(final By locator) { + return new ExpectedCondition() { + public WebElement apply(WebDriver driver) { + WebElement toReturn = driver.findElement(locator); + if (toReturn.isDisplayed()) { + return toReturn; + } + return null; + } + }; +} +``` + +This may look complex, but it's almost all boiler-plate code. The only +interesting bit is that the "ExpectedCondition" will be evaluated repeatedly +until the "apply" method returns something that is neither "null" +nor Boolean.FALSE. + +Of course, adding all these "wait" calls may clutter up your code. If +that's the case, and your needs are simple, consider using the implicit waits: + +```java +driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); +``` + +By doing this, every time an element is located, if the element is not present, +the location is retried until either it is present, or until 30 seconds have +passed. + +### Finding By XPath or CSS Selectors Doesn't Always Work, But It Does In Selenium 1 + +In Selenium 1, it was common for xpath to use a bundled library rather than +the capabilities of the browser itself. WebDriver will always use the native +browser methods unless there's no alternative. That means that complex xpath +expressions may break on some browsers. + +CSS Selectors in Selenium 1 were implemented using the Sizzle library. This +implements a superset of the CSS Selector spec, and it's not always clear where +you've crossed the line. If you're using the WebDriverBackedSelenium and use a +Sizzle locator instead of a CSS Selector for finding elements, a warning will +be logged to the console. It's worth taking the time to look for these, +particularly if tests are failing because of not being able to find elements. + +### There is No Browserbot + +Selenium RC was based on Selenium Core, and therefore when you executed +Javascript, you could access bits of Selenium Core to make things easier. +As WebDriver is not based on Selenium Core, this is no longer possible. +How can you tell if you're using Selenium Core? Simple! Just look to see +if your "getEval" or similar calls are using "selenium" or "browserbot" +in the evaluated Javascript. + +You might be using the browserbot to obtain a handle to the current window +or document of the test. Fortunately, WebDriver always evaluates JS in the +context of the current window, so you can use "window" or "document" directly. + +Alternatively, you might be using the browserbot to locate elements. +In WebDriver, the idiom for doing this is to first locate the element, +and then pass that as an argument to the Javascript. Thus: + +```java +String name = selenium.getEval( + "selenium.browserbot.findElement('id=foo', browserbot.getCurrentWindow()).tagName"); +``` + +becomes: + +```java +WebElement element = driver.findElement(By.id("foo")); +String name = (String) ((JavascriptExecutor) driver).executeScript( + "return arguments[0].tagName", element); +``` + +Notice how the passed in "element" variable appears as the first item +in the JS standard "arguments" array. + + +### Executing Javascript Doesn't Return Anything + + +WebDriver's JavascriptExecutor will wrap all JS and evaluate it as an anonymous expression. This means that you need to use the "return" keyword: + +```java +String title = selenium.getEval("browserbot.getCurrentWindow().document.title"); +``` + +becomes: + +```java +((JavascriptExecutor) driver).executeScript("return document.title;"); +``` + diff --git a/docs_source_files/content/legacy_docs/selenium_ide.de.md b/docs_source_files/content/legacy_docs/selenium_ide.de.md new file mode 100644 index 000000000000..bf75064ed877 --- /dev/null +++ b/docs_source_files/content/legacy_docs/selenium_ide.de.md @@ -0,0 +1,1739 @@ +--- +title: "Legacy Selenium IDE" +weight: 4 +--- + + +## Introduction + +The Selenium-IDE (Integrated Development Environment) is the tool you use to +develop your Selenium test cases. It’s an easy-to-use Firefox plug-in and is +generally the most efficient way to develop test cases. It also contains a +context menu that allows you to first select a UI element from the browser’s +currently displayed page and then select from a list of Selenium commands with +parameters pre-defined according to the context of the selected UI element. +This is not only a time-saver, but also an excellent way of learning Selenium +script syntax. + +This chapter is all about the Selenium IDE and how to use it effectively. + +## Installing the IDE + +Using Firefox, first, download the IDE from the SeleniumHQ [downloads page](https://selenium.dev/downloads) + +Firefox will protect you from installing addons from unfamiliar locations, so +you will need to click ‘Allow’ to proceed with the installation, as shown in +the following screenshot. + +![Selenium IDE Installation 1](/images/legacy_docs/selenium_ide_installation_1.png) + +When downloading from Firefox, you’ll be presented with the following window. + +![Selenium IDE Installation 2](/images/legacy_docs/selenium_ide_installation_2.png) + +Select Install Now. The Firefox Add-ons window pops up, first showing a progress bar, +and when the download is complete, displays the following. + +![Selenium IDE Installation 3](/images/legacy_docs/selenium_ide_installation_3.png) + +Restart Firefox. After Firefox reboots you will find the Selenium-IDE listed under +the Firefox Tools menu. + +![Selenium IDE Installation 4](/images/legacy_docs/selenium_ide_installation_4.png) + +## Opening the IDE + +To run the Selenium-IDE, simply select it from the Firefox Tools menu. It opens +as follows with an empty script-editing window and a menu for loading, or +creating new test cases. + +![Selenium IDE Open](/images/legacy_docs/selenium_ide_open.png) + +## IDE Features + +### Menu Bar + +The File menu has options for Test Case and Test Suite (suite of Test Cases). +Using these you can add a new Test Case, open a Test Case, save a Test Case, +export Test Case in a language of your choice. You can also open the recent +Test Case. All these options are also available for Test Suite. + +The Edit menu allows copy, paste, delete, undo, and select all operations for +editing the commands in your test case. The Options menu allows the changing of +settings. You can set the timeout value for certain commands, add user-defined +user extensions to the base set of Selenium commands, and specify the format +(language) used when saving your test cases. The Help menu is the standard +Firefox Help menu; only one item on this menu–UI-Element Documentation–pertains +to Selenium-IDE. + +### Toolbar + +The toolbar contains buttons for controlling the execution of your test cases, +including a step feature for debugging your test cases. The right-most button, +the one with the red-dot, is the record button. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_1.png) +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_2.png) + +Speed Control: controls how fast your test case runs. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_3.png) + +Run All: Runs the entire test suite when a test suite with multiple test cases is loaded. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_4.png) + +Run: Runs the currently selected test. When only a single test is loaded +this button and the Run All button have the same effect. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_5.png) +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_6.png) + +Pause/Resume: Allows stopping and re-starting of a running test case. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_7.png) + +Step: Allows you to “step” through a test case by running it one command at a time. +Use for debugging test cases. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_8.png) + +TestRunner Mode: Allows you to run the test case in a browser loaded with the +Selenium-Core TestRunner. The TestRunner is not commonly used now and is likely +to be deprecated. This button is for evaluating test cases for backwards +compatibility with the TestRunner. Most users will probably not need this +button. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_9.png) + +Apply Rollup Rules: This advanced feature allows repetitive sequences of +Selenium commands to be grouped into a single action. Detailed documentation on +rollup rules can be found in the UI-Element Documentation on the Help menu. + +![Selenium IDE Features](/images/legacy_docs/selenium_ide_features_10.png) + + +### Test Case Pane + +Your script is displayed in the test case pane. It has two tabs, one for +displaying the command and their parameters in a readable “table” format. + +![Selenium IDE Image Pane](/images/legacy_docs/selenium_ide_image_pane.png) + +The other tab - Source displays the test case in the native format in which the +file will be stored. By default, this is HTML although it can be changed to a +programming language such as Java or C#, or a scripting language like Python. +See the Options menu for details. The Source view also allows one to edit the +test case in its raw form, including copy, cut and paste operations. + +The Command, Target, and Value entry fields display the currently selected +command along with its parameters. These are entry fields where you can modify +the currently selected command. The first parameter specified for a command in +the Reference tab of the bottom pane always goes in the Target field. If a +second parameter is specified by the Reference tab, it always goes in the Value +field. + +![Selenium IDE Entry Fields](/images/legacy_docs/selenium_ide_entry_fields.png) + +If you start typing in the Command field, a drop-down list will be populated +based on the first characters you type; you can then select your desired +command from the drop-down. + +### Log/Reference/UI-Element/Rollup Pane + +The bottom pane is used for four different functions–Log, Reference, +UI-Element, and Rollup–depending on which tab is selected. + +#### Log + +When you run your test case, error messages and information messages showing +the progress are displayed in this pane automatically, even if you do not first +select the Log tab. These messages are often useful for test case debugging. +Notice the Clear button for clearing the Log. Also notice the Info button is a +drop-down allowing selection of different levels of information to log. + +![Selenium IDE Bottom Box](/images/legacy_docs/selenium_ide_bottom_box.png) + + +#### Reference + +The Reference tab is the default selection whenever you are entering or +modifying Selenese commands and parameters in Table mode. In Table mode, the +Reference pane will display documentation on the current command. When entering +or modifying commands, whether from Table or Source mode, it is critically +important to ensure that the parameters specified in the Target and Value +fields match those specified in the parameter list in the Reference pane. The +number of parameters provided must match the number specified, the order of +parameters provided must match the order specified, and the type of parameters +provided must match the type specified. If there is a mismatch in any of these +three areas, the command will not run correctly. + +![Selenium IDE Bottom Box](/images/legacy_docs/selenium_ide_bottom_box_ref.png) + +While the Reference tab is invaluable as a quick reference, it is still often +necessary to consult the Selenium Reference document. + +#### UI-Element and Rollup + +Detailed information on these two panes (which cover advanced features) can be +found in the UI-Element Documentation on the Help menu of Selenium-IDE. + +## Building Test Cases + +There are three primary methods for developing test cases. Frequently, a test +developer will require all three techniques. + +### Recording + +Many first-time users begin by recording a test case from their interactions +with a website. When Selenium-IDE is first opened, the record button is ON by +default. If you do not want Selenium-IDE to begin recording automatically you +can turn this off by going under Options > Options… and deselecting “Start +recording immediately on open.” + +During recording, Selenium-IDE will automatically insert commands into your +test case based on your actions. Typically, this will include: + +* clicking a link - click or clickAndWait commands +* entering values - type command +* selecting options from a drop-down listbox - select command +* clicking checkboxes or radio buttons - click command + +Here are some “gotchas” to be aware of: + +* The type command may require clicking on some other area of the web page for it +to record. +* Following a link usually records a click command. You will often need to change +this to clickAndWait to ensure your test case pauses until the new page is +completely loaded. Otherwise, your test case will continue running commands +before the page has loaded all its UI elements. This will cause unexpected test +case failures. + +### Adding Verifications and Asserts With the Context Menu + +Your test cases will also need to check the properties of a web-page. This +requires assert and verify commands. We won’t describe the specifics of these +commands here; that is in the chapter on Selenium Commands – “Selenese”. Here +we’ll simply describe how to add them to your test case. + +With Selenium-IDE recording, go to the browser displaying your test application +and right click anywhere on the page. You will see a context menu showing +verify and/or assert commands. + +The first time you use Selenium, there may only be one Selenium command listed. +As you use the IDE however, you will find additional commands will quickly be +added to this menu. Selenium-IDE will attempt to predict what command, along +with the parameters, you will need for a selected UI element on the current +web-page. + +Let’s see how this works. Open a web-page of your choosing and select a block +of text on the page. A paragraph or a heading will work fine. Now, right-click +the selected text. The context menu should give you a verifyTextPresent command +and the suggested parameter should be the text itself. + +Also, notice the Show All Available Commands menu option. This shows many, many +more commands, again, along with suggested parameters, for testing your +currently selected UI element. + +Try a few more UI elements. Try right-clicking an image, or a user control like +a button or a checkbox. You may need to use Show All Available Commands to see +options other than verifyTextPresent. Once you select these other options, the +more commonly used ones will show up on the primary context menu. For example, +selecting verifyElementPresent for an image should later cause that command to +be available on the primary context menu the next time you select an image and +right-click. + +Again, these commands will be explained in detail in the chapter on Selenium +commands. For now though, feel free to use the IDE to record and select +commands into a test case and then run it. You can learn a lot about the +Selenium commands simply by experimenting with the IDE. + +### Editing + +#### Insert Command + +##### Table View + +Select the point in your test case where you want to insert the command. To do +this, in the Test Case Pane, left-click on the line where you want to insert a +new command. Right-click and select Insert Command; the IDE will add a blank +line just ahead of the line you selected. Now use the command editing text +fields to enter your new command and its parameters. + +##### Source View + +Select the point in your test case where you want to insert the command. To do +this, in the Test Case Pane, left-click between the commands where you want to +insert a new command, and enter the HTML tags needed to create a 3-column row +containing the Command, first parameter (if one is required by the Command), +and second parameter (again, if one is required to locate an element) and third +parameter(again, if one is required to have a value). Example: + +```html + + Command + target (locator) + Value + +``` + +#### Insert Comment + +Comments may be added to make your test case more readable. These comments are +ignored when the test case is run. + +Comments may also be used to add vertical white space (one or more blank lines) +in your tests; just create empty comments. An empty command will cause an error +during execution; an empty comment won’t. + +##### Table View + +Select the line in your test case where you want to insert the comment. +Right-click and select Insert Comment. Now use the Command field to enter the +comment. Your comment will appear in purple text. + +##### Source View + +Select the point in your test case where you want to insert the comment. Add an +HTML-style comment, i.e., ``. + +#### Edit a Command or Comment + +##### Table View + +Simply select the line to be changed and edit it using the Command, Target, +and Value fields. + +##### Source View + +Since Source view provides the equivalent of a WYSIWYG (What You See is What +You Get) editor, simply modify which line you wish–command, parameter, or comment. + +### Opening and Saving a Test Case + +Like most programs, there are Save and Open commands under the File menu. +However, Selenium distinguishes between test cases and test suites. To save +your Selenium-IDE tests for later use you can either save the individual test +cases, or save the test suite. If the test cases of your test suite have not +been saved, you’ll be prompted to save them before saving the test suite. + +When you open an existing test case or suite, Selenium-IDE displays its +Selenium commands in the Test Case Pane. + +## Running Test Cases + +The IDE allows many options for running your test case. You can run a test case +all at once, stop and start it, run it one line at a time, run a single command +you are currently developing, and you can do a batch run of an entire test +suite. Execution of test cases is very flexible in the IDE. + +**Run a Test Case** + +Click the Run button to run the currently displayed test case. + +**Run a Test Suite** + +Click the Run All button to run all the test cases in the currently loaded test +suite. + +**Stop and Start** + +The Pause button can be used to stop the test case while it is running. The +icon of this button then changes to indicate the Resume button. To continue +click Resume. + +**Stop in the Middle** + +You can set a breakpoint in the test case to cause it to stop on a particular +command. This is useful for debugging your test case. To set a breakpoint, +select a command, right-click, and from the context menu select Toggle +Breakpoint. + +**Start from the Middle** + +You can tell the IDE to begin running from a specific command in the middle of +the test case. This also is used for debugging. To set a startpoint, select a +command, right-click, and from the context menu select Set/Clear Start Point. + +**Run Any Single Command** + +Double-click any single command to run it by itself. This is useful when +writing a single command. It lets you immediately test a command you are +constructing, when you are not sure if it is correct. You can double-click it +to see if it runs correctly. This is also available from the context menu. + +## Using Base URL to Run Test Cases in Different Domains + +The Base URL field at the top of the Selenium-IDE window is very useful for +allowing test cases to be run across different domains. Suppose that a site +named http://news.portal.com had an in-house beta site named +http://beta.news.portal.com. Any test cases for these sites that begin with an +open statement should specify a relative URL as the argument to open rather +than an absolute URL (one starting with a protocol such as http: or https:). +Selenium-IDE will then create an absolute URL by appending the open command’s +argument onto the end of the value of Base URL. For example, the test case +below would be run against http://news.portal.com/about.html: + +![Selenium IDE Prod URL](/images/legacy_docs/selenium_ide_base_url_prod.png) + +This same test case with a modified Base URL setting would be run against +http://beta.news.portal.com/about.html: + +![Selenium IDE Beta URL](/images/legacy_docs/selenium_ide_base_url_beta.png) + +## Selenium Commands – “Selenese” + +Selenium commands, often called selenese, are the set of commands that run your +tests. A sequence of these commands is a test script. Here we explain those +commands in detail, and we present the many choices you have in testing your +web application when using Selenium. + +Selenium provides a rich set of commands for fully testing your web-app in +virtually any way you can imagine. The command set is often called selenese. +These commands essentially create a testing language. + +In selenese, one can test the existence of UI elements based on their HTML +tags, test for specific content, test for broken links, input fields, selection +list options, submitting forms, and table data among other things. In addition +Selenium commands support testing of window size, mouse position, alerts, Ajax +functionality, pop up windows, event handling, and many other web-application +features. The Command Reference lists all the available commands. + +A command tells Selenium what to do. Selenium commands come in three “flavors”: +**Actions**, **Accessors**, and **Assertions**. + +* **Actions** are commands that generally manipulate the state of the application. +They do things like “click this link” and “select that option”. If an Action +fails, or has an error, the execution of the current test is stopped. + + Many Actions can be called with the “AndWait” suffix, e.g. “clickAndWait”. This + suffix tells Selenium that the action will cause the browser to make a call to + the server, and that Selenium should wait for a new page to load. + +* **Accessors** examine the state of the application and store the results in +variables, e.g. “storeTitle”. They are also used to automatically generate +Assertions. + +* **Assertions** are like Accessors, but they verify that the state of the +application conforms to what is expected. Examples include “make sure the page +title is X” and “verify that this checkbox is checked”. + +All Selenium Assertions can be used in 3 modes: “assert”, “verify”, and ” +waitFor”. For example, you can “assertText”, “verifyText” and “waitForText”. +When an “assert” fails, the test is aborted. When a “verify” fails, the test +will continue execution, logging the failure. This allows a single “assert” to +ensure that the application is on the correct page, followed by a bunch of +“verify” assertions to test form field values, labels, etc. + +“waitFor” commands wait for some condition to become true (which can be useful +for testing Ajax applications). They will succeed immediately if the condition +is already true. However, they will fail and halt the test if the condition +does not become true within the current timeout setting (see the setTimeout +action below). + +## Script Syntax + +Selenium commands are simple, they consist of the command and two parameters. +For example: + +| | | | +| -------- | ---------------------------- | ----------- | +| verifyText | //div//a[2] | Login | + +The parameters are not always required; it depends on the command. In some +cases both are required, in others one parameter is required, and in still +others the command may take no parameters at all. Here are a couple more +examples: + +| | | | +| -------- | ---------------------------- | ----------------------------- | +| goBackAndWait | | | +| verifyTextPresent | | Welcome to My Home Page | +| type | id=phone | (555) 666-7066 | +| type | id=address1 | ${myVariableAddress} | + +The command reference describes the parameter requirements for each command. + +Parameters vary, however they are typically: + +* a locator for identifying a UI element within a page. +* a text pattern for verifying or asserting expected page content +* a text pattern or a selenium variable for entering text in an input field or +for selecting an option from an option list. + +Locators, text patterns, selenium variables, and the commands themselves are +described in considerable detail in the section on Selenium Commands. + +Selenium scripts that will be run from Selenium-IDE will be stored in an HTML +text file format. This consists of an HTML table with three columns. The first +column identifies the Selenium command, the second is a target, and the final +column contains a value. The second and third columns may not require values +depending on the chosen Selenium command, but they should be present. Each +table row represents a new Selenium command. Here is an example of a test that +opens a page, asserts the page title and then verifies some content on the page: + +```html + + + + +
    open/download/
    assertTitleDownloads
    verifyText//h2Downloads
    +``` + +Rendered as a table in a browser this would look like the following: + +| | | | +| -------- | ---------------------------- | ----------------------------- | +| open | /download/ | | +| assertTitle | | Downloads | +| verifyText | //h2 | Downloads | + +The Selenese HTML syntax can be used to write and run tests without requiring +knowledge of a programming language. With a basic knowledge of selenese and +Selenium-IDE you can quickly produce and run testcases. + +## Test Suites + +A test suite is a collection of tests. Often one will run all the tests in a +test suite as one continuous batch-job. + +When using Selenium-IDE, test suites also can be defined using a simple HTML +file. The syntax again is simple. An HTML table defines a list of tests where +each row defines the filesystem path to each test. An example tells it all. + +```html + + +Test Suite Function Tests - Priority 1 + + + + + + + +
    Suite Of Tests
    Login
    Test Searching for Values
    Test Save
    + + +``` + +A file similar to this would allow running the tests all at once, one after +another, from the Selenium-IDE. + +Test suites can also be maintained when using Selenium-RC. This is done via +programming and can be done a number of ways. Commonly Junit is used to +maintain a test suite if one is using Selenium-RC with Java. Additionally, if +C# is the chosen language, Nunit could be employed. If using an interpreted +language like Python with Selenium-RC then some simple programming would be +involved in setting up a test suite. Since the whole reason for using +Selenium-RC is to make use of programming logic for your testing this usually +isn’t a problem. + +## Commonly Used Selenium Commands + +To conclude our introduction of Selenium, we’ll show you a few typical Selenium +commands. These are probably the most commonly used commands for building +tests. + +**open** + +opens a page using a URL. + +**click/clickAndWait** + +performs a click operation, and optionally waits for a new page to load. + +**verifyTitle/assertTitle** + +verifies an expected page title. + +**verifyTextPresent** + +verifies expected text is somewhere on the page. + +**verifyElementPresent** + +verifies an expected UI element, as defined by its HTML tag, is present on the +page. + +**verifyText** + +verifies expected text and its corresponding HTML tag are present on the page. + +**verifyTable** + +verifies a table’s expected contents. + +**waitForPageToLoad** + +pauses execution until an expected new page loads. Called automatically when +clickAndWait is used. + +**waitForElementPresent** + +pauses execution until an expected UI element, as defined by its HTML tag, is +present on the page. + +## Verifying Page Elements + +Verifying UI elements on a web page is probably the most common feature of your +automated tests. Selenese allows multiple ways of checking for UI elements. It +is important that you understand these different methods because these methods +define what you are actually testing. + +For example, will you test that… + +1. an element is present somewhere on the page? +1. specific text is somewhere on the page? +1. specific text is at a specific location on the page? + +For example, if you are testing a text heading, the text and its position at +the top of the page are probably relevant for your test. If, however, you are +testing for the existence of an image on the home page, and the web designers +frequently change the specific image file along with its position on the page, +then you only want to test that an image (as opposed to the specific image +file) exists somewhere on the page. + +## Assertion or Verification? + +Choosing between “assert” and “verify” comes down to convenience and management +of failures. There’s very little point checking that the first paragraph on the +page is the correct one if your test has already failed when checking that the +browser is displaying the expected page. If you’re not on the correct page, +you’ll probably want to abort your test case so that you can investigate the +cause and fix the issue(s) promptly. On the other hand, you may want to check +many attributes of a page without aborting the test case on the first failure +as this will allow you to review all failures on the page and take the +appropriate action. Effectively an “assert” will fail the test and abort the +current test case, whereas a “verify” will fail the test and continue to run +the test case. + +The best use of this feature is to logically group your test commands, and +start each group with an “assert” followed by one or more “verify” test +commands. An example follows: + +| Command | Target | Value | +| -------- | ---------------------------- | ----------------------------- | +| open | /download/ | | +| assertTitle | | Downloads | +| verifyText | //h2 | Downloads | +| assertTable | 1.2.1 | Selenium IDE | +| verifyTable | 1.2.2 | June 3, 2008 | +| verifyTable | 1.2.3 | 1.0 beta 2 | + +The above example first opens a page and then “asserts” that the correct page +is loaded by comparing the title with the expected value. Only if this passes +will the following command run and “verify” that the text is present in the +expected location. The test case then “asserts” the first column in the second +row of the first table contains the expected value, and only if this passed +will the remaining cells in that row be “verified”. + +### **verifyTextPresent** + +The command `verifyTextPresent` is used to verify specific text exists somewhere +on the page. It takes a single argument–the text pattern to be verified. For +example: + +| Command | Target | Value | +| -------- | ---------------------------- | ----------------------------- | +| verifyTextPresent | Marketing Analysis | | + +This would cause Selenium to search for, and verify, that the text string +“Marketing Analysis” appears somewhere on the page currently being tested. Use +verifyTextPresent when you are interested in only the text itself being present +on the page. Do not use this when you also need to test where the text occurs +on the page. + +### **verifyElementPresent** + +Use this command when you must test for the presence of a specific UI element, +rather than its content. This verification does not check the text, only the +HTML tag. One common use is to check for the presence of an image. + +| Command | Target | Value | +| -------- | ---------------------------- | ----------------------------- | +| verifyElementPresent | //div/p/img | | + +This command verifies that an image, specified by the existence of an +HTML tag, is present on the page, and that it follows a
    tag and a

    +tag. The first (and only) parameter is a locator for telling the Selenese +command how to find the element. Locators are explained in the next section. + +`verifyElementPresent` can be used to check the existence of any HTML tag within +the page. You can check the existence of links, paragraphs, divisions

    , +etc. Here are a few more examples. + +| Command | Target | Value | +| -------- | ---------------------------- | ----------------------------- | +| verifyElementPresent | //div/p | | +| verifyElementPresent | //div/a | | +| verifyElementPresent | id=Login | | +| verifyElementPresent | link=Go to Marketing Research | | +| verifyElementPresent | //a[2] | | +| verifyElementPresent | //head/title | | + +These examples illustrate the variety of ways a UI element may be tested. Again, +locators are explained in the next section. + +### **verifyText** + +Use `verifyText` when both the text and its UI element must be tested. verifyText +must use a locator. If you choose an _XPath_ or _DOM_ locator, you can verify that +specific text appears at a specific location on the page relative to other UI +components on the page. + +| Command | Target | Value | +| -------- | ---------------------------- | ------------------------------------------------------------------- | +| verifyText | //table/tr/td/div/p | This is my text and it occurs right after the div inside the table. | + + +## Locating Elements + +For many Selenium commands, a target is required. This target identifies an +element in the content of the web application, and consists of the location +strategy followed by the location in the format `locatorType=location`. The +locator type can be omitted in many cases. The various locator types are +explained below with examples for each. + +### Locating by Identifier + +This is probably the most common method of locating elements and is the +catch-all default when no recognized locator type is used. With this strategy, +the first element with the id attribute value matching the location will be used. If +no element has a matching id attribute, then the first element with a name +attribute matching the location will be used. + +For instance, your page source could have id and name attributes +as follows: + +```html + + +
    + + + +
    + + +``` + +The following locator strategies would return the elements from the HTML +snippet above indicated by line number: + +- ``identifier=loginForm`` (3) +- ``identifier=password`` (5) +- ``identifier=continue`` (6) +- ``continue`` (6) + +Since the ``identifier`` type of locator is the default, the ``identifier=`` +in the first three examples above is not necessary. + +### Locating by Id + +This type of locator is more limited than the identifier locator type, but +also more explicit. Use this when you know an element's id attribute. + +```html + + +
    + + + + +
    + + +``` + +- ``id=loginForm`` (3) + +### Locating by Name + +The name locator type will locate the first element with a matching name +attribute. If multiple elements have the same value for a name attribute, then +you can use filters to further refine your location strategy. The default +filter type is value (matching the value attribute). + +```html + + +
    + + + + +
    + + +``` + +- ``name=username`` (4) +- ``name=continue value=Clear`` (7) +- ``name=continue Clear`` (7) +- ``name=continue type=button`` (7) + +Note: Unlike some types of XPath and DOM locators, the three + types of locators above allow Selenium to test a UI element independent + of its location on + the page. So if the page structure and organization is altered, the test + will still pass. You may or may not want to also test whether the page + structure changes. In the case where web designers frequently alter the + page, but its functionality must be regression tested, testing via id and + name attributes, or really via any HTML property, becomes very important. + +### Locating by XPath + +XPath is the language used for locating nodes in an XML document. As HTML can +be an implementation of XML (XHTML), Selenium users can leverage this powerful +language to target elements in their web applications. XPath extends beyond (as +well as supporting) the simple methods of locating by id or name +attributes, and opens up all sorts of new possibilities such as locating the +third checkbox on the page. + +One of the main reasons for using XPath is when you don't have a suitable id +or name attribute for the element you wish to locate. You can use XPath to +either locate the element in absolute terms (not advised), or relative to an +element that does have an id or name attribute. XPath locators can also be +used to specify elements via attributes other than id and name. + +Absolute XPaths contain the location of all elements from the root (html) and +as a result are likely to fail with only the slightest adjustment to the +application. By finding a nearby element with an id or name attribute (ideally +a parent element) you can locate your target element based on the relationship. +This is much less likely to change and can make your tests more robust. + +Since only ``xpath`` locators start with "//", it is not necessary to include +the ``xpath=`` label when specifying an XPath locator. + +```html + + +
    + + + + +
    + + +``` + +- ``xpath=/html/body/form[1]`` (3) - *Absolute path (would break if the HTML was + changed only slightly)* +- ``//form[1]`` (3) - *First form element in the HTML* +- ``xpath=//form[@id='loginForm']`` (3) - *The form element with attribute named 'id' and the value 'loginForm'* +- ``xpath=//form[input/@name='username']`` (3) - *First form element with an input child + element with attribute named 'name' and the value 'username'* +- ``//input[@name='username']`` (4) - *First input element with attribute named 'name' and the value + 'username'* +- ``//form[@id='loginForm']/input[1]`` (4) - *First input child element of the + form element with attribute named 'id' and the value 'loginForm'* +- ``//input[@name='continue'][@type='button']`` (7) - *Input with attribute named 'name' and the value 'continue' + and attribute named 'type' and the value 'button'* +- ``//form[@id='loginForm']/input[4]`` (7) - *Fourth input child element of the + form element with attribute named 'id' and value 'loginForm'* + +These examples cover some basics, but in order to learn more, the +following references are recommended: + +* [W3Schools XPath Tutorial](http://www.w3schools.com/xml/xpath_intro.asp>) +* [W3C XPath Recommendation](http://www.w3.org/TR/xpath) + +There are also a couple of very useful Firefox Add-ons that can assist in +discovering the XPath of an element: + +* [XPath Checker](https://addons.mozilla.org/en-US/firefox/addon/1095?id=1095) + XPath and can be used to test XPath results. +* [Firebug](https://addons.mozilla.org/en-US/firefox/addon/1843 - XPath + suggestions are just one of the many powerful features of this very useful add-on. + +### Locating Hyperlinks by Link Text + +This is a simple method of locating a hyperlink in your web page by using the +text of the link. If two links with the same text are present, then the first +match will be used. + +```html + + +

    Are you sure you want to do this?

    + Continue + Cancel + + +``` + +- ``link=Continue`` (4) +- ``link=Cancel`` (5) + + +### Locating by DOM + +The Document Object Model represents an HTML document and can be accessed +using JavaScript. This location strategy takes JavaScript that evaluates to +an element on the page, which can be simply the element's location using the +hierarchical dotted notation. + +Since only ``dom`` locators start with "document", it is not necessary to include +the ``dom=`` label when specifying a DOM locator. + +```html + + +
    + + + + +
    + + +``` + +- ``dom=document.getElementById('loginForm')`` (3) +- ``dom=document.forms['loginForm']`` (3) +- ``dom=document.forms[0]`` (3) +- ``document.forms[0].username`` (4) +- ``document.forms[0].elements['username']`` (4) +- ``document.forms[0].elements[0]`` (4) +- ``document.forms[0].elements[3]`` (7) + +You can use Selenium itself as well as other sites and extensions to explore +the DOM of your web application. A good reference exists on [W3Schools](http://www.w3schools.com/js/js_htmldom.asp). + +### Locating by CSS + +CSS (Cascading Style Sheets) is a language for describing the rendering of HTML +and XML documents. CSS uses Selectors for binding style properties to elements +in the document. These Selectors can be used by Selenium as another locating +strategy. + +```html + + +
    + + + + +
    + + +``` + +- ``css=form#loginForm`` (3) +- ``css=input[name="username"]`` (4) +- ``css=input.required[type="text"]`` (4) +- ``css=input.passfield`` (5) +- ``css=#loginForm input[type="button"]`` (7) +- ``css=#loginForm input:nth-child(2)`` (5) + +For more information about CSS Selectors, the best place to go is [the W3C +publication](http://www.w3.org/TR/css3-selectors/). You'll find additional +references there. + +### Implicit Locators + +You can choose to omit the locator type in the following situations: + + - Locators without an explicitly defined locator strategy will default + to using the identifier locator strategy. See `Locating by Identifier`_. + + - Locators starting with "//" will use the XPath locator strategy. + See `Locating by XPath`_. + + - Locators starting with "document" will use the DOM locator strategy. + See `Locating by DOM`_ + + +## Matching Text Patterns + +Like locators, *patterns* are a type of parameter frequently required by Selenese +commands. Examples of commands which require patterns are **verifyTextPresent**, +**verifyTitle**, **verifyAlert**, **assertConfirmation**, **verifyText**, and +**verifyPrompt**. And as has been mentioned above, link locators can utilize +a pattern. Patterns allow you to *describe*, via the use of special characters, +what text is expected rather than having to specify that text exactly. + +There are three types of patterns: *globbing*, *regular expressions*, and *exact*. + +### Globbing Patterns + +Most people are familiar with globbing as it is utilized in +filename expansion at a DOS or Unix/Linux command line such as ``ls *.c``. +In this case, globbing is used to display all the files ending with a ``.c`` +extension that exist in the current directory. Globbing is fairly limited. +Only two special characters are supported in the Selenium implementation: + +`*` which translates to "match anything," i.e., nothing, a single character, or many characters. + +`[ ]` (*character class*) which translates to "match any single character +found inside the square brackets." A dash (hyphen) can be used as a shorthand +to specify a range of characters (which are contiguous in the ASCII character +set). A few examples will make the functionality of a character class clear: + +``[aeiou]`` matches any lowercase vowel + +``[0-9]`` matches any digit + +``[a-zA-Z0-9]`` matches any alphanumeric character + +In most other contexts, globbing includes a third special character, the **?**. +However, Selenium globbing patterns only support the asterisk and character +class. + +To specify a globbing pattern parameter for a Selenese command, you can +prefix the pattern with a **glob:** label. However, because globbing +patterns are the default, you can also omit the label and specify just the +pattern itself. + +Below is an example of two commands that use globbing patterns. The +actual link text on the page being tested +was "Film/Television Department"; by using a pattern +rather than the exact text, the **click** command will work even if the +link text is changed to "Film & Television Department" or "Film and Television +Department". The glob pattern's asterisk will match "anything or nothing" +between the word "Film" and the word "Television". + +| Command | Target | Value | +| -------- | -------------------------------------- | ------------------------------------------------------------------ | +| click | link=glob:Film*Television Department | | +| verifyTitle | glob:\*Film\*Television\* | | + + +The actual title of the page reached by clicking on the link was "De Anza Film And +Television Department - Menu". By using a pattern rather than the exact +text, the ``verifyTitle`` will pass as long as the two words "Film" and "Television" appear +(in that order) anywhere in the page's title. For example, if +the page's owner should shorten +the title to just "Film & Television Department," the test would still pass. +Using a pattern for both a link and a simple test that the link worked (such as +the ``verifyTitle`` above does) can greatly reduce the maintenance for such +test cases. + +#### Regular Expression Patterns + +*Regular expression* patterns are the most powerful of the three types +of patterns that Selenese supports. Regular expressions +are also supported by most high-level programming languages, many text +editors, and a host of tools, including the Linux/Unix command-line +utilities **grep**, **sed**, and **awk**. In Selenese, regular +expression patterns allow a user to perform many tasks that would +be very difficult otherwise. For example, suppose your test needed +to ensure that a particular table cell contained nothing but a number. +``regexp: [0-9]+`` is a simple pattern that will match a decimal number of any length. + +Whereas Selenese globbing patterns support only the **\*** +and **[ ]** (character +class) features, Selenese regular expression patterns offer the same +wide array of special characters that exist in JavaScript. Below +are a subset of those special characters: + +| PATTERN | MATCH | +| ------------- | --------------------------------------------------------------------------------- | +| . | any single character | +| [ ] | character class: any single character that appears inside the brackets | +| \* | quantifier: 0 or more of the preceding character (or group) | +| \+ | quantifier: 1 or more of the preceding character (or group) | +| ? | quantifier: 0 or 1 of the preceding character (or group) | +| {1,5} | quantifier: 1 through 5 of the preceding character (or group) | +| \| | alternation: the character/group on the left or the character/group on the right | +| ( ) | grouping: often used with alternation and/or quantifier | + +Regular expression patterns in Selenese need to be prefixed with +either ``regexp:`` or ``regexpi:``. The former is case-sensitive; the +latter is case-insensitive. + +A few examples will help clarify how regular expression patterns can +be used with Selenese commands. The first one uses what is probably +the most commonly used regular expression pattern--**.\*** ("dot star"). This +two-character sequence can be translated as "0 or more occurrences of +any character" or more simply, "anything or nothing." It is the +equivalent of the one-character globbing pattern **\*** (a single asterisk). + +| Command | Target | Value | +| -------- | -------------------------------------- | ------------------------------------------------------------------ | +| click | link=glob:Film*Television Department | | +| verifyTitle | regexp:.\*Film.\*Television.\* | | + + +The example above is functionally equivalent to the earlier example +that used globbing patterns for this same test. The only differences +are the prefix (**regexp:** instead of **glob:**) and the "anything +or nothing" pattern (**.\*** instead of just **\***). + +The more complex example below tests that the Yahoo! +Weather page for Anchorage, Alaska contains info on the sunrise time: + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ------------------------------------------------- | +| open | http://weather.yahoo.com/forecast/USAK0012.html | | +| verifyTextPresent | regexp:Sunrise: \*[0-9]{1,2}:[0-9]{2} [ap]m | | + + +Let's examine the regular expression above one part at a time: + +| | | +| -------------------------- | --------------------------------------------------------------------------------- | +| ``Sunrise: *`` | The string **Sunrise:** followed by 0 or more spaces | +| ``[0-9]{1,2}`` | 1 or 2 digits (for the hour of the day) | +| ``:`` | The character **:** (no special characters involved) | +| ``[0-9]{2}`` | 2 digits (for the minutes) followed by a space | +| ``[ap]m`` | "a" or "p" followed by "m" (am or pm) | + + +#### Exact Patterns + +The **exact** type of Selenium pattern is of marginal usefulness. +It uses no special characters at all. So, if you needed to look for +an actual asterisk character (which is special for both globbing and +regular expression patterns), the **exact** pattern would be one way +to do that. For example, if you wanted to select an item labeled +"Real \*" from a dropdown, the following code might work or it might not. +The asterisk in the ``glob:Real *`` pattern will match anything or nothing. +So, if there was an earlier select option labeled "Real Numbers," it would +be the option selected rather than the "Real \*" option. + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ------------------------------------------------- | +| select | //select | glob:Real \* | + +In order to ensure that the "Real \*" item would be selected, the ``exact:`` +prefix could be used to create an **exact** pattern as shown below: + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ------------------------------------------------- | +| select | //select | exact:Real \* | + +But the same effect could be achieved via escaping the asterisk in a +regular expression pattern: + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ------------------------------------------------- | +| select | //select | regexp:Real \\\* | + +It's rather unlikely that most testers will ever need to look for +an asterisk or a set of square brackets with characters inside them (the +character class for globbing patterns). Thus, globbing patterns and +regular expression patterns are sufficient for the vast majority of us. + + +## The "AndWait" Commands + +The difference between a command and its *AndWait* +alternative is that the regular command (e.g. *click*) will do the action and +continue with the following command as fast as it can, while the *AndWait* +alternative (e.g. *clickAndWait*) tells Selenium to **wait** for the page to +load after the action has been done. + +The *AndWait* alternative is always used when the action causes the browser to +navigate to another page or reload the present one. + +Be aware, if you use an *AndWait* command for an action that +does not trigger a navigation/refresh, your test will fail. This happens +because Selenium will reach the *AndWait*'s timeout without seeing any +navigation or refresh being made, causing Selenium to raise a timeout +exception. + +## The waitFor Commands in AJAX applications + +In AJAX driven web applications, data is retrieved from server without +refreshing the page. Using *andWait* commands will not work as the page is not +actually refreshed. Pausing the test execution for a certain period of time is +also not a good approach as web element might appear later or earlier than the +stipulated period depending on the system's responsiveness, load or other +uncontrolled factors of the moment, leading to test failures. The best approach +would be to wait for the needed element in a dynamic period and then continue +the execution as soon as the element is found. + +This is done using *waitFor* commands, as *waitForElementPresent* or +*waitForVisible*, which wait dynamically, checking for the desired condition +every second and continuing to the next command in the script as soon as the +condition is met. + +## Sequence of Evaluation and Flow Control + +When a script runs, it simply runs in sequence, one command after another. + +Selenese, by itself, does not support condition statements (if-else, etc.) or +iteration (for, while, etc.). Many useful tests can be conducted without flow +control. However, for a functional test of dynamic content, possibly involving +multiple pages, programming logic is often needed. + +When flow control is needed, there are three options: + +a) Run the script using Selenium-RC and a client library such as Java or + PHP to utilize the programming language's flow control features. +b) Run a small JavaScript snippet from within the script using the storeEval command. +c) Install the `goto_sel_ide.js extension`. + +Most testers will export the test script into a programming language file that uses the +Selenium-RC API (see the Selenium-IDE chapter). However, some organizations prefer +to run their scripts from Selenium-IDE whenever possible (for instance, when they have +many junior-level people running tests for them, or when programming skills are +lacking). If this is your case, consider a JavaScript snippet or the goto_sel_ide.js extension. + + +## Store Commands and Selenium Variables + +You can use Selenium variables to store constants at the +beginning of a script. Also, when combined with a data-driven test design +(discussed in a later section), Selenium variables can be used to store values +passed to your test program from the command-line, from another program, or from +a file. + +The plain *store* command is the most basic of the many store commands and can be used +to simply store a constant value in a selenium variable. It takes two +parameters, the text value to be stored and a selenium variable. Use the +standard variable naming conventions of only alphanumeric characters when +choosing a name for your variable. + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------- | +| store | paul@mysite.org | | + + +Later in your script, you'll want to use the stored value of your +variable. To access the value of a variable, enclose the variable in +curly brackets ({}) and precede it with a dollar sign like this. + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------- | +| verifyText | //div/p | \\${userName} | + +A common use of variables is for storing input for an input field. + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------- | +| type | id=login | \\${userName} | + + +Selenium variables can be used in either the first or second parameter and +are interpreted by Selenium prior to any other operations performed by the +command. A Selenium variable may also be used within a locator expression. + +An equivalent store command exists for each verify and assert command. Here +are a couple more commonly used store commands. + +### storeElementPresent + +This corresponds to verifyElementPresent. It simply stores a boolean value--"true" +or "false"--depending on whether the UI element is found. + +### storeText + +StoreText corresponds to verifyText. It uses a locator to identify specific +page text. The text, if found, is stored in the variable. StoreText can be +used to extract text from the page being tested. + +### storeEval + +This command takes a script as its +first parameter. Embedding JavaScript within Selenese is covered in the next section. +StoreEval allows the test to store the result of running the script in a variable. + + +## JavaScript and Selenese Parameters + +JavaScript can be used with two types of Selenese parameters: script +and non-script (usually expressions). In most cases, you'll want to access +and/or manipulate a test case variable inside the JavaScript snippet used as +a Selenese parameter. All variables created in your test case are stored in +a JavaScript *associative array*. An associative array has string indexes +rather than sequential numeric indexes. The associative array containing +your test case's variables is named **storedVars**. Whenever you wish to +access or manipulate a variable within a JavaScript snippet, you must refer +to it as **storedVars['yourVariableName']**. + +### JavaScript Usage with Script Parameters + +Several Selenese commands specify a **script** parameter including +**assertEval**, **verifyEval**, **storeEval**, and **waitForEval**. +These parameters require no special syntax. A Selenium-IDE +user would simply place a snippet of JavaScript code into +the appropriate field, normally the **Target** field (because +a **script** parameter is normally the first or only parameter). + +The example below illustrates how a JavaScript snippet +can be used to perform a simple numerical calculation: + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------- | +| store | 10 | hits | +| storeXpathCount | //blockquote | blockquotes | +| storeEval | storedVars['hits'].storedVars['blockquotes'] | paragraphs | + +This next example illustrates how a JavaScript snippet can include calls to +methods, in this case the JavaScript String object's ``toUpperCase`` method +and ``toLowerCase`` method. + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------- | +| store | Edith Wharton | name | +| storeEval | storedVars['name'].toUpperCase() | uc | +| storeEval | storedVars['name'].toUpperCase() | lc | + + +#### JavaScript Usage with Non-Script Parameters + +JavaScript can also be used to help generate values for parameters, even +when the parameter is not specified to be of type **script**. +However, in this case, special syntax is required--the *entire* parameter +value must be prefixed by ``javascript{`` with a trailing ``}``, which encloses the JavaScript +snippet, as in ``javascript{*yourCodeHere*}``. +Below is an example in which the ``type`` command's second parameter +``value`` is generated via JavaScript code using this special syntax: + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------------------------- | +| store | league of nations | searchString | +| type | q | javascript{storedVars['searchString'].toUpperCase()} | + + +## *echo* - The Selenese Print Command + +Selenese has a simple command that allows you to print text to your test's +output. This is useful for providing informational progress notes in your +test which display on the console as your test is running. These notes also can be +used to provide context within your test result reports, which can be useful +for finding where a defect exists on a page in the event your test finds a +problem. Finally, echo statements can be used to print the contents of +Selenium variables. + + +| Command | Target | Value | +| -------- | ------------------------------------------------- | ---------------------------------------------------- | +| echo | Testing page footer now. | | +| echo | Username is \\${userName} | | + + +## Alerts, Popups, and Multiple Windows + +Suppose that you are testing a page that looks like this. + +```html + + + + + + + + + + + New Window Link + + + +
    + + + + +``` + +The user must respond to alert/confirm boxes, as well as moving focus to newly +opened popup windows. Fortunately, Selenium can cover JavaScript pop-ups. + +But before we begin covering alerts/confirms/prompts in individual detail, it is +helpful to understand the commonality between them. Alerts, confirmation boxes +and prompts all have variations of the following + +|Command|Description| +|--- |--- | +|assertFoo(pattern)|throws error if pattern doesn’t match the text of the pop-up| +|assertFooPresent|throws error if pop-up is not available| +|assertFooNotPresent|throws error if any pop-up is present| +|storeFoo(variable)|stores the text of the pop-up in a variable| +|storeFooPresent(variable)|stores the text of the pop-up in a variable and returns true or false| + + +When running under Selenium, JavaScript pop-ups will not appear. This is because +the function calls are actually being overridden at runtime by Selenium's own +JavaScript. However, just because you cannot see the pop-up doesn't mean you don't +have to deal with it. To handle a pop-up, you must call its ``assertFoo(pattern)`` +function. If you fail to assert the presence of a pop-up your next command will be +blocked and you will get an error similar to the following ``[error] Error: There +was an unexpected Confirmation! [Chose an option.]`` + +### Alerts + +Let's start with alerts because they are the simplest pop-up to handle. To begin, +open the HTML sample above in a browser and click on the "Show alert" button. You'll +notice that after you close the alert the text "Alert is gone." is displayed on the +page. Now run through the same steps with Selenium IDE recording, and verify +the text is added after you close the alert. Your test will look something like +this: + +|Command|Target|Value| +|--- |--- |--- | +|open|/|| +|click|btnAlert|| +|assertAlert|I’m blocking!|| +|verifyTextPresent|Alert is gone.|| + +You may be thinking "That's odd, I never tried to assert that alert." But this is +Selenium-IDE handling and closing the alert for you. If you remove that step and replay +the test you will get the following error ``[error] Error: There was an unexpected +Alert! [I'm blocking!]``. You must include an assertion of the alert to acknowledge +its presence. + +If you just want to assert that an alert is present but either don't know or don't care +what text it contains, you can use ``assertAlertPresent``. This will return true or false, +with false halting the test. + +### Confirmations + +Confirmations behave in much the same way as alerts, with ``assertConfirmation`` and +``assertConfirmationPresent`` offering the same characteristics as their alert counterparts. +However, by default Selenium will select OK when a confirmation pops up. Try recording +clicking on the "Show confirm box" button in the sample page, but click on the "Cancel" button +in the popup, then assert the output text. Your test may look something like this: + +|Command|Target|Value| +|--- |--- |--- | +|open|/|| +|click|btnConfirm|| +|chooseCancelOnNextConfirmation||| +|assertConfirmation|Choose an option.|| +|verifyTextPresent|Rejected|| + +The ``chooseCancelOnNextConfirmation`` function tells Selenium that all following +confirmation should return false. It can be reset by calling chooseOkOnNextConfirmation. + +You may notice that you cannot replay this test, because Selenium complains that there +is an unhandled confirmation. This is because the order of events Selenium-IDE records +causes the click and chooseCancelOnNextConfirmation to be put in the wrong order (it makes sense +if you think about it, Selenium can't know that you're cancelling before you open a confirmation) +Simply switch these two commands and your test will run fine. + +### Prompts + +Prompts behave in much the same way as alerts, with ``assertPrompt`` and ``assertPromptPresent`` +offering the same characteristics as their alert counterparts. By default, Selenium will wait for +you to input data when the prompt pops up. Try recording clicking on the "Show prompt" button in +the sample page and enter "Selenium" into the prompt. Your test may look something like this: + +|Command|Target|Value| +|--- |--- |--- | +|open|/|| +|answerOnNextPrompt|Selenium!|| +|click|id=btnPrompt|| +|assertPrompt|What’s the best web QA tool?|| +|verifyTextPresent|Selenium!|| + +If you choose cancel on the prompt, you may notice that answerOnNextPrompt will simply show a +target of blank. Selenium treats cancel and a blank entry on the prompt basically as the same thing. + +## Debugging + +Debugging means finding and fixing errors in your test case. This is a normal +part of test case development. + +We won't teach debugging here as most new users to Selenium will already have +some basic experience with debugging. If this is new to you, we recommend +you ask one of the developers in your organization. + +### Breakpoints and Startpoints + +The Sel-IDE supports the setting of breakpoints and the ability to start and +stop the running of a test case, from any point within the test case. That is, one +can run up to a specific command in the middle of the test case and inspect how +the test case behaves at that point. To do this, set a breakpoint on the +command just before the one to be examined. + +To set a breakpoint, select a command, right-click, and from the context menu +select *Toggle Breakpoint*. Then click the Run button to run your test case from +the beginning up to the breakpoint. + +It is also sometimes useful to run a test case from somewhere in the middle to +the end of the test case or up to a breakpoint that follows the starting point. +For example, suppose your test case first logs into the website and then +performs a series of tests and you are trying to debug one of those tests. +However, you only need to login once, but you need to keep rerunning your +tests as you are developing them. You can login once, then run your test case +from a startpoint placed after the login portion of your test case. That will +prevent you from having to manually logout each time you rerun your test case. + +To set a startpoint, select a command, right-click, and from the context +menu select *Set/Clear Start Point*. Then click the Run button to execute the +test case beginning at that startpoint. + +### Stepping Through a Testcase + +To execute a test case one command at a time ("step through" it), follow these +steps: + +1. Start the test case running with the Run button from the toolbar. + +2. Immediately pause the executing test case with the Pause button. + +3. Repeatedly select the Step button. + +### Find Button + +The Find button is used to see which UI element on the currently displayed +webpage (in the browser) is used in the currently selected Selenium command. +This is useful when building a locator for a command's first parameter (see the +section on :ref:`locators ` in the Selenium Commands chapter). +It can be used with any command that identifies a UI element on a webpage, +i.e. *click*, *clickAndWait*, *type*, and certain *assert* and *verify* commands, +among others. + +From Table view, select any command that has a locator parameter. +Click the Find button. +Now look on the webpage: There should be a bright green rectangle +enclosing the element specified by the locator parameter. + +### Page Source for Debugging + +Often, when debugging a test case, you simply must look at the page source (the +HTML for the webpage you're trying to test) to determine a problem. Firefox +makes this easy. Simply right-click the webpage and select 'View->Page Source. +The HTML opens in a separate window. Use its Search feature (Edit=>Find) +to search for a keyword to find the HTML for the UI element you're trying +to test. + +Alternatively, select just that portion of the webpage for which you want to +see the source. Then right-click the webpage and select View Selection +Source. In this case, the separate HTML window will contain just a small +amount of source, with highlighting on the portion representing your +selection. + +### Locator Assistance + +Whenever Selenium-IDE records a locator-type argument, it stores +additional information which allows the user to view other possible +locator-type arguments that could be used instead. This feature can be +very useful for learning more about locators, and is often needed to help +one build a different type of locator than the type that was recorded. + +This locator assistance is presented on the Selenium-IDE window as a drop-down +list accessible at the right end of the Target field +(only when the Target field contains a recorded locator-type argument). +Below is a snapshot showing the +contents of this drop-down for one command. Note that the first column of +the drop-down provides alternative locators, whereas the second column +indicates the type of each alternative. + +![Selenium Locator Assistance](/images/legacy_docs/selenium_ide_locator_assistance.png) + + +## Writing a Test Suite + +A test suite is a collection of test cases which is displayed in the leftmost +pane in the IDE. +The test suite pane can be manually opened or closed via selecting a small dot +halfway down the right edge of the pane (which is the left edge of the +entire Selenium-IDE window if the pane is closed). + +The test suite pane will be automatically opened when an existing test suite +is opened *or* when the user selects the New Test Case item from the +File menu. In the latter case, the new test case will appear immediately +below the previous test case. + +Selenium-IDE also supports loading pre-existing test cases by using the File +-> Add Test Case menu option. This allows you to add existing test cases to +a new test suite. + +A test suite file is an HTML file containing a one-column table. Each +cell of each row in the section contains a link to a test case. +The example below is of a test suite containing four test cases: + +```html + + + + Sample Selenium Test Suite + + + + + + + + + + + + +
    Test Cases for De Anza A-Z Directory Links
    A Links
    B Links
    C Links
    D Links
    + + +``` + +Note: Test case files should not have to be co-located with the test suite file + that invokes them. And on Mac OS and Linux systems, that is indeed the + case. However, at the time of this writing, a bug prevents Windows users + from being able to place the test cases elsewhere than with the test suite + that invokes them. + +## User Extensions + +User extensions are JavaScript files that allow one to create his or her own +customizations and features to add additional functionality. Often this is in +the form of customized commands although this extensibility is not limited to +additional commands. + +There are a number of useful extensions_ created by users. + +*IMPORTANT: THIS SECTION IS OUT OF DATE--WE WILL BE REVISING THIS SOON.* + +* _extensions: http://wiki.openqa.org/display/SEL/Contributed+User-Extensions + +.. _[`goto_sel_ide.js extension`](http://wiki.openqa.org/download/attachments/379/goto_sel_ide.js): + +Perhaps the most popular of all Selenium-IDE extensions +is one which provides flow control in the form of while loops and primitive +conditionals. This extension is the goto_sel_ide.js_. For an example +of how to use the functionality provided by this extension, look at the +page_ created by its author. + +To install this extension, put the pathname to its location on your +computer in the **Selenium Core extensions** field of Selenium-IDE's +Options=>Options=>General tab. + +![Selenium IDE Extensions Install](/images/legacy_docs/selenium_ide_extensions_install.png) + +After selecting the **OK** button, you must close and reopen Selenium-IDE +in order for the extensions file to be read. Any change you make to an +extension will also require you to close and reopen Selenium-IDE. + +Information on writing your own extensions can be found near the +bottom of the Selenium Reference_ document. + +Sometimes it can prove very useful to debug step by step Selenium IDE and your +User Extension. The only debugger that appears able to debug +XUL/Chrome based extensions is Venkman which is supported in Firefox until version 32 included. +The step by step debug has been verified to work with Firefox 32 and Selenium IDE 2.9.0. + +## Format + +Format, under the Options menu, allows you to select a language for saving +and displaying the test case. The default is HTML. + +If you will be using Selenium-RC to run your test cases, this feature is used +to translate your test case into a programming language. Select the +language, e.g. Java, PHP, you will be using with Selenium-RC for developing +your test programs. Then simply save the test case using File=>Export Test Case As. +Your test case will be translated into a series of functions in the language you +choose. Essentially, program code supporting your test is generated for you +by Selenium-IDE. + +Also, note that if the generated code does not suit your needs, you can alter +it by editing a configuration file which defines the generation process. +Each supported language has configuration settings which are editable. This +is under the Options=>Options=>Formats tab. + +## Executing Selenium-IDE Tests on Different Browsers + +While Selenium-IDE can only run tests against Firefox, tests +developed with Selenium-IDE can be run against other browsers, using a +simple command-line interface that invokes the Selenium-RC server. This topic +is covered in the :ref:`Run Selenese tests ` section on Selenium-RC +chapter. The *-htmlSuite* command-line option is the particular feature of interest. + +## Troubleshooting + +Below is a list of image/explanation pairs which describe frequent +sources of problems with Selenium-IDE: + +*Table view is not available with this format.* + +This message can be occasionally displayed in the Table tab when Selenium IDE is +launched. The workaround is to close and reopen Selenium IDE. See +[issue 1008](http://code.google.com/p/selenium/issues/detail?id=1008). +for more information. If you are able to reproduce this reliably then please +provide details so that we can work on a fix. + +------------------ + +*error loading test case: no command found* + +You've used **File=>Open** to try to open a test suite file. Use **File=>Open +Test Suite** instead. + +An enhancement request has been raised to improve this error message. See +[issue 1010](http://code.google.com/p/selenium/issues/detail?id=1010). + +------------------ + +![Selenium IDE Trouble Timing](/images/legacy_docs/selenium_ide_trouble_timing.png) + +This type of **error** may indicate a timing problem, i.e., the element +specified by a locator in your command wasn't fully loaded when the command +was executed. Try putting a **pause 5000** before the command to determine +whether the problem is indeed related to timing. If so, investigate using an +appropriate **waitFor\*** or **\*AndWait** command before the failing command. + +------------------ + +![Selenium IDE Trouble Param](/images/legacy_docs/selenium_ide_trouble_param.png) + +Whenever your attempt to use variable substitution fails as is the +case for the **open** command above, it indicates +that you haven't actually created the variable whose value you're +trying to access. This is +sometimes due to putting the variable in the **Value** field when it +should be in the **Target** field or vice versa. In the example above, +the two parameters for the **store** command have been erroneously +placed in the reverse order of what is required. +For any Selenese command, the first required parameter must go +in the **Target** field, and the second required parameter (if one exists) +must go in the **Value** field. + +---------- + +*error loading test case: [Exception... "Component returned failure code: +0x80520012 (NS_ERROR_FILE_NOT_FOUND) [nsIFileInputStream.init]" nresult: +"0x80520012 (NS_ERROR_FILE_NOT_FOUND)" location: "JS frame :: +chrome://selenium-ide/content/file-utils.js :: anonymous :: line 48" data: no]* + +One of the test cases in your test suite cannot be found. Make sure that the +test case is indeed located where the test suite indicates it is located. Also, +make sure that your actual test case files have the .html extension both in +their filenames, and in the test suite file where they are referenced. + +An enhancement request has been raised to improve this error message. See +[issue 1011](http://code.google.com/p/selenium/issues/detail?id=1011). + +---------- + +![Selenium IDE Trouble Extension](/images/legacy_docs/selenium_ide_trouble_extension.png) + +Your extension file's contents have not been read by Selenium-IDE. Be +sure you have specified the proper pathname to the extensions file via +**Options=>Options=>General** in the **Selenium Core extensions** field. +Also, Selenium-IDE must be restarted after any change to either an +extensions file *or* to the contents of the **Selenium Core extensions** +field. + diff --git a/docs_source_files/content/legacy_docs/selenium_rc.de.md b/docs_source_files/content/legacy_docs/selenium_rc.de.md new file mode 100644 index 000000000000..ee4c9074dedd --- /dev/null +++ b/docs_source_files/content/legacy_docs/selenium_rc.de.md @@ -0,0 +1,1721 @@ +--- +title: "Selenium 1 (Selenium RC)" +weight: 1 +--- + + +## Introduction +Selenium RC was the main Selenium project for a long time, before the +WebDriver/Selenium merge brought up Selenium 2, a more powerful tool. +It is worth to highlight that Selenium 1 is not supported anymore. + +## How Selenium RC Works +First, we will describe how the components of Selenium RC operate and the role each plays in running +your test scripts. + +### RC Components + +Selenium RC components are: + +* The Selenium Server which launches and kills browsers, interprets and runs the Selenese commands passed from the test program, and acts as an *HTTP proxy*, intercepting and verifying HTTP messages passed between the browser and the AUT. +* Client libraries which provide the interface between each programming language and the Selenium RC Server. + +Here is a simplified architecture diagram: + +![Architecture Diagram Simple](/images/legacy_docs/selenium_rc_architecture_diagram_simple.png) + +The diagram shows the client libraries communicate with the +Server passing each Selenium command for execution. Then the server passes the +Selenium command to the browser using Selenium-Core JavaScript commands. The +browser, using its JavaScript interpreter, executes the Selenium command. This +runs the Selenese action or verification you specified in your test script. + +### Selenium Server + +Selenium Server receives Selenium commands from your test program, +interprets them, and reports back to your program the results of +running those tests. + +The RC server bundles Selenium Core and automatically injects +it into the browser. This occurs when your test program opens the +browser (using a client library API function). +Selenium-Core is a JavaScript program, actually a set of JavaScript +functions which interprets and executes Selenese commands using the +browser's built-in JavaScript interpreter. + +The Server receives the Selenese commands from your test program +using simple HTTP GET/POST requests. This means you can use any +programming language that can send HTTP requests to automate +Selenium tests on the browser. + +### Client Libraries + +The client libraries provide the programming support that allows you to +run Selenium commands from a program of your own design. There is a +different client library for each supported language. A Selenium client +library provides a programming interface (API), i.e., a set of functions, +which run Selenium commands from your own program. Within each interface, +there is a programming function that supports each Selenese command. + +The client library takes a Selenese command and passes it to the Selenium Server +for processing a specific action or test against the application under test +(AUT). The client library +also receives the result of that command and passes it back to your program. +Your program can receive the result and store it into a program variable and +report it as a success or failure, +or possibly take corrective action if it was an unexpected error. + +So to create a test program, you simply write a program that runs +a set of Selenium commands using a client library API. And, optionally, if +you already have a Selenese test script created in the Selenium-IDE, you can +*generate the Selenium RC code*. The Selenium-IDE can translate (using its +Export menu item) its Selenium commands into a client-driver's API function +calls. See the Selenium-IDE chapter for specifics on exporting RC code from +Selenium-IDE. + +## Installation + +Installation is rather a misnomer for Selenium. Selenium has a set of libraries available +in the programming language of your choice. You could download them from the [downloads page](https://selenium.dev/downloads/). + +Once you've chosen a language to work with, you simply need to: + +* Install the Selenium RC Server. +* Set up a programming project using a language specific client driver. + +### Installing Selenium Server + +The Selenium RC server is simply a Java *jar* file (*selenium-server-standalone-.jar*), which doesn't +require any special installation. Just downloading the zip file and extracting the +server in the desired directory is sufficient. + +### Running Selenium Server + +Before starting any tests you must start the server. Go to the directory +where Selenium RC's server is located and run the following from a command-line +console. + +```shell + java -jar selenium-server-standalone-.jar +``` + +This can be simplified by creating +a batch or shell executable file (.bat on Windows and .sh on Linux) containing the command +above. Then make a shortcut to that executable on your +desktop and simply double-click the icon to start the server. + +For the server to run you'll need Java installed +and the PATH environment variable correctly configured to run it from the console. +You can check that you have Java correctly installed by running the following +on a console. + +```shell + java -version +``` + +If you get a version number (which needs to be 1.5 or later), you're ready to start using Selenium RC. + +### Using the Java Client Driver + +* Download Selenium java client driver zip from the SeleniumHQ [downloads page](https://selenium.dev/downloads/). +* Extract selenium-java-.jar file +* Open your desired Java IDE (Eclipse, NetBeans, IntelliJ, Netweaver, etc.) +* Create a java project. +* Add the selenium-java-.jar files to your project as references. +* Add to your project classpath the file selenium-java-.jar. +* From Selenium-IDE, export a script to a Java file and include it in your Java + project, or write your Selenium test in Java using the selenium-java-client API. + The API is presented later in this chapter. You can either use JUnit, or TestNg + to run your test, or you can write your own simple main() program. These concepts are + explained later in this section. +* Run Selenium server from the console. +* Execute your test from the Java IDE or from the command-line. + +For details on Java test project configuration, see the Appendix sections +Configuring Selenium RC With Eclipse and Configuring Selenium RC With Intellij. + +### Using the Python Client Driver + +* Install Selenium via PIP, instructions linked at SeleniumHQ [downloads page](https://selenium.dev/downloads/) +* Either write your Selenium test in Python or export + a script from Selenium-IDE to a python file. +* Run Selenium server from the console +* Execute your test from a console or your Python IDE + +For details on Python client driver configuration, see the appendix Python Client Driver Configuration. + +### Using the .NET Client Driver + +* Download Selenium RC from the SeleniumHQ [downloads page](https://selenium.dev/downloads/) +* Extract the folder +* Download and install [NUnit](https://nunit.org/download/) ( + Note: You can use NUnit as your test engine. If you're not familiar yet with + NUnit, you can also write a simple main() function to run your tests; + however NUnit is very useful as a test engine.) +* Open your desired .Net IDE (Visual Studio, SharpDevelop, MonoDevelop) +* Create a class library (.dll) +* Add references to the following DLLs: nmock.dll, nunit.core.dll, nunit. + framework.dll, ThoughtWorks.Selenium.Core.dll, ThoughtWorks.Selenium.IntegrationTests.dll + and ThoughtWorks.Selenium.UnitTests.dll +* Write your Selenium test in a .Net language (C#, VB.Net), or export + a script from Selenium-IDE to a C# file and copy this code into the class file + you just created. +* Write your own simple main() program or you can include NUnit in your project + for running your test. These concepts are explained later in this chapter. +* Run Selenium server from console +* Run your test either from the IDE, from the NUnit GUI or from the command line + +For specific details on .NET client driver configuration with Visual Studio, see the appendix +.NET client driver configuration. + +### Using the Ruby Client Driver + +* If you do not already have RubyGems, install it from RubyForge. +* Run ``gem install selenium-client`` +* At the top of your test script, add ``require "selenium/client"`` +* Write your test script using any Ruby test harness (eg Test::Unit, + Mini::Test or RSpec). +* Run Selenium RC server from the console. +* Execute your test in the same way you would run any other Ruby + script. + + +For details on Ruby client driver configuration, see the `Selenium-Client documentation`_ + +## From Selenese to a Program + +The primary task for using Selenium RC is to convert your Selenese into a programming +language. In this section, we provide several different language-specific examples. + +### Sample Test Script + +Let's start with an example Selenese test script. Imagine recording +the following test with Selenium-IDE. + +| | | | +| -------- | ---------------------------- | ----------- | +| open | / | | +| type | q | selenium rc | +| clickAndWait | btnG | | +| assertTextPresent | Results * for selenium rc | | + + +Note: This example would work with the Google search page http://www.google.com + +### Selenese as Programming Code + +Here is the test script exported (via Selenium-IDE) to each of the supported +programming languages. If you have at least basic knowledge of an object- +oriented programming language, you will understand how Selenium +runs Selenese commands by reading one of these +examples. To see an example in a specific language, select one of these buttons. + +#### CSharp +``` csharp + + using System; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + using NUnit.Framework; + using Selenium; + + namespace SeleniumTests + { + [TestFixture] + public class NewTest + { + private ISelenium selenium; + private StringBuilder verificationErrors; + + [SetUp] + public void SetupTest() + { + selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com/"); + selenium.Start(); + verificationErrors = new StringBuilder(); + } + + [TearDown] + public void TeardownTest() + { + try + { + selenium.Stop(); + } + catch (Exception) + { + // Ignore errors if unable to close the browser + } + Assert.AreEqual("", verificationErrors.ToString()); + } + + [Test] + public void TheNewTest() + { + selenium.Open("/"); + selenium.Type("q", "selenium rc"); + selenium.Click("btnG"); + selenium.WaitForPageToLoad("30000"); + Assert.AreEqual("selenium rc - Google Search", selenium.GetTitle()); + } + } + } + +``` + +#### Java + +```java + + /** Add JUnit framework to your classpath if not already there + * for this example to work + */ + package com.example.tests; + + import com.thoughtworks.selenium.*; + import java.util.regex.Pattern; + + public class NewTest extends SeleneseTestCase { + public void setUp() throws Exception { + setUp("http://www.google.com/", "*firefox"); + } + public void testNew() throws Exception { + selenium.open("/"); + selenium.type("q", "selenium rc"); + selenium.click("btnG"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Results * for selenium rc")); + } + } + +``` + +#### Php + +```php + setBrowser("*firefox"); + $this->setBrowserUrl("http://www.google.com/"); + } + + function testMyTestCase() + { + $this->open("/"); + $this->type("q", "selenium rc"); + $this->click("btnG"); + $this->waitForPageToLoad("30000"); + $this->assertTrue($this->isTextPresent("Results * for selenium rc")); + } + } + ?> + +``` + +#### Python + +```python + + from selenium import selenium + import unittest, time, re + + class NewTest(unittest.TestCase): + def setUp(self): + self.verificationErrors = [] + self.selenium = selenium("localhost", 4444, "*firefox", + "http://www.google.com/") + self.selenium.start() + + def test_new(self): + sel = self.selenium + sel.open("/") + sel.type("q", "selenium rc") + sel.click("btnG") + sel.wait_for_page_to_load("30000") + self.failUnless(sel.is_text_present("Results * for selenium rc")) + + def tearDown(self): + self.selenium.stop() + self.assertEqual([], self.verificationErrors) + +``` + +#### Ruby + +```ruby + + require "selenium/client" + require "test/unit" + + class NewTest < Test::Unit::TestCase + def setup + @verification_errors = [] + if $selenium + @selenium = $selenium + else + @selenium = Selenium::Client::Driver.new("localhost", 4444, "*firefox", "http://www.google.com/", 60); + @selenium.start + end + @selenium.set_context("test_new") + end + + def teardown + @selenium.stop unless $selenium + assert_equal [], @verification_errors + end + + def test_new + @selenium.open "/" + @selenium.type "q", "selenium rc" + @selenium.click "btnG" + @selenium.wait_for_page_to_load "30000" + assert @selenium.is_text_present("Results * for selenium rc") + end + end + +``` + +In the next section we'll explain how to build a test program using the generated code. + +## Programming Your Test + +Now we'll illustrate how to program your own tests using examples in each of the +supported programming languages. +There are essentially two tasks: + +* Generate your script into a programming + language from Selenium-IDE, optionally modifying the result. +* Write a very simple main program that executes the generated code. + +Optionally, you can adopt a test engine platform like JUnit or TestNG for Java, +or NUnit for .NET if you are using one of those languages. + +Here, we show language-specific examples. The language-specific APIs tend to +differ from one to another, so you'll find a separate explanation for each. + +* Java +* C# +* Python +* Ruby +* Perl, PHP + + +### Java + +For Java, people use either JUnit or TestNG as the test engine. +Some development environments like Eclipse have direct support for these via +plug-ins. This makes it even easier. Teaching JUnit or TestNG is beyond the scope of +this document however materials may be found online and there are publications +available. If you are already a "java-shop" chances are your developers will +already have some experience with one of these test frameworks. + +You will probably want to rename the test class from "NewTest" to something +of your own choosing. Also, you will need to change the browser-open +parameters in the statement: + +```java + selenium = new DefaultSelenium("localhost", 4444, "*iehta", "http://www.google.com/"); +``` + +The Selenium-IDE generated code will look like this. This example +has comments added manually for additional clarity. + +```java + package com.example.tests; + // We specify the package of our tests + + import com.thoughtworks.selenium.*; + // This is the driver's import. You'll use this for instantiating a + // browser and making it do what you need. + + import java.util.regex.Pattern; + // Selenium-IDE add the Pattern module because it's sometimes used for + // regex validations. You can remove the module if it's not used in your + // script. + + public class NewTest extends SeleneseTestCase { + // We create our Selenium test case + + public void setUp() throws Exception { + setUp("http://www.google.com/", "*firefox"); + // We instantiate and start the browser + } + + public void testNew() throws Exception { + selenium.open("/"); + selenium.type("q", "selenium rc"); + selenium.click("btnG"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Results * for selenium rc")); + // These are the real test steps + } + } +``` + + +### `C#` + +The .NET Client Driver works with Microsoft.NET. +It can be used with any .NET testing framework +like NUnit or the Visual Studio 2005 Team System. + +Selenium-IDE assumes you will use NUnit as your testing framework. +You can see this in the generated code below. It includes the *using* statement +for NUnit along with corresponding NUnit attributes identifying +the role for each member function of the test class. + +You will probably have to rename the test class from "NewTest" to +something of your own choosing. Also, you will need to change the browser-open +parameters in the statement: + +```csharp + selenium = new DefaultSelenium("localhost", 4444, "*iehta", "http://www.google.com/"); +``` + +The generated code will look similar to this. + +```csharp + + using System; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + using NUnit.Framework; + using Selenium; + + namespace SeleniumTests + + { + [TestFixture] + + public class NewTest + + { + private ISelenium selenium; + + private StringBuilder verificationErrors; + + [SetUp] + + public void SetupTest() + + { + selenium = new DefaultSelenium("localhost", 4444, "*iehta", + "http://www.google.com/"); + + selenium.Start(); + + verificationErrors = new StringBuilder(); + } + + [TearDown] + + public void TeardownTest() + { + try + { + selenium.Stop(); + } + + catch (Exception) + { + // Ignore errors if unable to close the browser + } + + Assert.AreEqual("", verificationErrors.ToString()); + } + [Test] + + public void TheNewTest() + { + // Open Google search engine. + selenium.Open("http://www.google.com/"); + + // Assert Title of page. + Assert.AreEqual("Google", selenium.GetTitle()); + + // Provide search term as "Selenium OpenQA" + selenium.Type("q", "Selenium OpenQA"); + + // Read the keyed search term and assert it. + Assert.AreEqual("Selenium OpenQA", selenium.GetValue("q")); + + // Click on Search button. + selenium.Click("btnG"); + + // Wait for page to load. + selenium.WaitForPageToLoad("5000"); + + // Assert that "www.openqa.org" is available in search results. + Assert.IsTrue(selenium.IsTextPresent("www.openqa.org")); + + // Assert that page title is - "Selenium OpenQA - Google Search" + Assert.AreEqual("Selenium OpenQA - Google Search", + selenium.GetTitle()); + } + } + } +``` + +You can allow NUnit to manage the execution +of your tests. Or alternatively, you can write a simple `main()` program that +instantiates the test object and runs each of the three methods, `SetupTest()`, +`TheNewTest()`, and `TeardownTest()` in turn. + + +### Python + +Pyunit is the test framework to use for Python. + +The basic test structure is: + +```python + + from selenium import selenium + # This is the driver's import. You'll use this class for instantiating a + # browser and making it do what you need. + + import unittest, time, re + # This are the basic imports added by Selenium-IDE by default. + # You can remove the modules if they are not used in your script. + + class NewTest(unittest.TestCase): + # We create our unittest test case + + def setUp(self): + self.verificationErrors = [] + # This is an empty array where we will store any verification errors + # we find in our tests + + self.selenium = selenium("localhost", 4444, "*firefox", + "http://www.google.com/") + self.selenium.start() + # We instantiate and start the browser + + def test_new(self): + # This is the test code. Here you should put the actions you need + # the browser to do during your test. + + sel = self.selenium + # We assign the browser to the variable "sel" (just to save us from + # typing "self.selenium" each time we want to call the browser). + + sel.open("/") + sel.type("q", "selenium rc") + sel.click("btnG") + sel.wait_for_page_to_load("30000") + self.failUnless(sel.is_text_present("Results * for selenium rc")) + # These are the real test steps + + def tearDown(self): + self.selenium.stop() + # we close the browser (I'd recommend you to comment this line while + # you are creating and debugging your tests) + + self.assertEqual([], self.verificationErrors) + # And make the test fail if we found that any verification errors + # were found +``` + +### Ruby + + +Old (pre 2.0) versions of Selenium-IDE generate Ruby code that requires the old Selenium +gem. Therefore, it is advisable to update any Ruby scripts generated by the +IDE as follows: + +1. On line 1, change ``require "selenium"`` to ``require +"selenium/client"`` + +2. On line 11, change ``Selenium::SeleniumDriver.new`` to +``Selenium::Client::Driver.new`` + +You probably also want to change the class name to something more +informative than "Untitled," and change the test method's name to +something other than "test_untitled." + +Here is a simple example created by modifying the Ruby code generated +by Selenium IDE, as described above. + +```ruby + + # load the Selenium-Client gem + require "selenium/client" + + # Load Test::Unit, Ruby's default test framework. + # If you prefer RSpec, see the examples in the Selenium-Client + # documentation. + require "test/unit" + + class Untitled < Test::Unit::TestCase + + # The setup method is called before each test. + def setup + + # This array is used to capture errors and display them at the + # end of the test run. + @verification_errors = [] + + # Create a new instance of the Selenium-Client driver. + @selenium = Selenium::Client::Driver.new \ + :host => "localhost", + :port => 4444, + :browser => "*chrome", + :url => "http://www.google.com/", + :timeout_in_second => 60 + + # Start the browser session + @selenium.start + + # Print a message in the browser-side log and status bar + # (optional). + @selenium.set_context("test_untitled") + + end + + # The teardown method is called after each test. + def teardown + + # Stop the browser session. + @selenium.stop + + # Print the array of error messages, if any. + assert_equal [], @verification_errors + end + + # This is the main body of your test. + def test_untitled + + # Open the root of the site we specified when we created the + # new driver instance, above. + @selenium.open "/" + + # Type 'selenium rc' into the field named 'q' + @selenium.type "q", "selenium rc" + + # Click the button named "btnG" + @selenium.click "btnG" + + # Wait for the search results page to load. + # Note that we don't need to set a timeout here, because that + # was specified when we created the new driver instance, above. + @selenium.wait_for_page_to_load + + begin + + # Test whether the search results contain the expected text. + # Notice that the star (*) is a wildcard that matches any + # number of characters. + assert @selenium.is_text_present("Results * for selenium rc") + + rescue Test::Unit::AssertionFailedError + + # If the assertion fails, push it onto the array of errors. + @verification_errors << $! + + end + end + end + +``` + +### Perl, PHP + +The members of the documentation team +have not used Selenium RC with Perl or PHP. If you are using Selenium RC with either of +these two languages please contact the Documentation Team (see the chapter on contributing). +We would love to include some examples from you and your experiences, to support Perl and PHP users. + + +## Learning the API + +The Selenium RC API uses naming conventions +that, assuming you understand Selenese, much of the interface +will be self-explanatory. Here, however, we explain the most critical and +possibly less obvious aspects. + +### Starting the Browser + +#### CSharp +```csharp + selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com/"); + selenium.Start(); +``` + +#### Java +```java + + setUp("http://www.google.com/", "*firefox"); +``` + +#### Perl +```perl + my $sel = Test::WWW::Selenium->new( host => "localhost", + port => 4444, + browser => "*firefox", + browser_url => "http://www.google.com/" ); +``` + +#### Php +```php + $this->setBrowser("*firefox"); + $this->setBrowserUrl("http://www.google.com/"); +``` + +#### Python +```python + self.selenium = selenium("localhost", 4444, "*firefox", + "http://www.google.com/") + self.selenium.start() +``` + +#### Ruby +```ruby + @selenium = Selenium::ClientDriver.new("localhost", 4444, "*firefox", "http://www.google.com/", 10000); + @selenium.start +``` + +Each of these examples opens the browser and represents that browser +by assigning a "browser instance" to a program variable. This +program variable is then used to call methods from the browser. +These methods execute the Selenium commands, i.e. like *open* or *type* or the *verify* +commands. + +The parameters required when creating the browser instance +are: + +* **host** + Specifies the IP address of the computer where the server is located. Usually, this is + the same machine as where the client is running, so in this case *localhost* is passed. In some clients this is an optional parameter. + +* **port** + Specifies the TCP/IP socket where the server is listening waiting + for the client to establish a connection. This also is optional in some + client drivers. + +* **browser** + The browser in which you want to run the tests. This is a required + parameter. + +* **url** + The base url of the application under test. This is required by all the + client libs and is integral information for starting up the browser-proxy-AUT communication. + +Note that some of the client libraries require the browser to be started explicitly by calling +its `start()` method. + +### Running Commands + +Once you have the browser initialized and assigned to a variable (generally +named "selenium") you can make it run Selenese commands by calling the respective +methods from the browser variable. For example, to call the *type* method +of the selenium object: + +``` + selenium.type("field-id","string to type") +``` + +In the background the browser will actually perform a *type* operation, +essentially identical to a user typing input into the browser, by +using the locator and the string you specified during the method call. + +## Reporting Results + +Selenium RC does not have its own mechanism for reporting results. Rather, it allows +you to build your reporting customized to your needs using features of your +chosen programming language. That's great, but what if you simply want something +quick that's already done for you? Often an existing library or test framework can +meet your needs faster than developing your own test reporting code. + +### Test Framework Reporting Tools + +Test frameworks are available for many programming languages. These, along with +their primary function of providing a flexible test engine for executing your tests, +include library code for reporting results. For example, Java has two +commonly used test frameworks, JUnit and TestNG. .NET also has its own, NUnit. + +We won't teach the frameworks themselves here; that's beyond the scope of this +user guide. We will simply introduce the framework features that relate to Selenium +along with some techniques you can apply. There are good books available on these +test frameworks however along with information on the internet. + +### Test Report Libraries + +Also available are third-party libraries specifically created for reporting +test results in your chosen programming language. These often support a +variety of formats such as HTML or PDF. + +### What's The Best Approach? + +Most people new to the testing frameworks will begin with the framework's +built-in reporting features. From there most will examine any available libraries +as that's less time consuming than developing your own. As you begin to use +Selenium no doubt you will start putting in your own "print statements" for +reporting progress. That may gradually lead to you developing your own +reporting, possibly in parallel to using a library or test framework. Regardless, +after the initial, but short, learning curve you will naturally develop what works +best for your own situation. + +### Test Reporting Examples + +To illustrate, we'll direct you to some specific tools in some of the other languages +supported by Selenium. The ones listed here are commonly used and have been used +extensively (and therefore recommended) by the authors of this guide. + +#### Test Reports in Java + +* If Selenium Test cases are developed using JUnit then JUnit Report can be used + to generate test reports. + +* If Selenium Test cases are developed using TestNG then no external task + is required to generate test reports. The TestNG framework generates an + HTML report which list details of tests. + +* ReportNG is a HTML reporting plug-in for the TestNG framework. + It is intended as a replacement for the default TestNG HTML report. + ReportNG provides a simple, colour-coded view of the test results. + +##### Logging the Selenese Commands + +* Logging Selenium can be used to generate a report of all the Selenese commands + in your test along with the success or failure of each. Logging Selenium extends + the Java client driver to add this Selenese logging ability. + +#### Test Reports for Python + +* When using Python Client Driver then HTMLTestRunner can be used to + generate a Test Report. + +#### Test Reports for Ruby + +* If RSpec framework is used for writing Selenium Test Cases in Ruby + then its HTML report can be used to generate a test report. + + +## Adding Some Spice to Your Tests + +Now we'll get to the whole reason for using Selenium RC, adding programming logic to your tests. +It's the same as for any program. Program flow is controlled using condition statements +and iteration. In addition you can report progress information using I/O. In this section +we'll show some examples of how programming language constructs can be combined with +Selenium to solve common testing problems. + +You will find as you transition from the simple tests of the existence of +page elements to tests of dynamic functionality involving multiple web-pages and +varying data that you will require programming logic for verifying expected +results. Basically, the Selenium-IDE does not support iteration and +standard condition statements. You can do some conditions by embedding javascript +in Selenese parameters, however +iteration is impossible, and most conditions will be much easier in a +programming language. In addition, you may need exception handling for +error recovery. For these reasons and others, we have written this section +to illustrate the use of common programming techniques to +give you greater 'verification power' in your automated testing. + +The examples in this section are written +in C# and Java, although the code is simple and can be easily adapted to the other supported +languages. If you have some basic knowledge +of an object-oriented programming language you shouldn't have difficulty understanding this section. + +### Iteration + +Iteration is one of the most common things people need to do in their tests. +For example, you may want to to execute a search multiple times. Or, perhaps for +verifying your test results you need to process a "result set" returned from a database. + +Using the same Google search example we used earlier, let's +check the Selenium search results. This test could use the Selenese: + +| | | | +| -------- | ---------------------------- | ------------- | +| open | / | | +| type | q | selenium rc | +| clickAndWait | btnG | | +| assertTextPresent | Results * for selenium rc | | +| type | q | selenium ide | +| clickAndWait | btnG | | +| assertTextPresent | Results * for selenium ide | | +| type | q | selenium grid | +| clickAndWait | btnG | | +| assertTextPresent | Results * for selenium grid | | + + +The code has been repeated to run the same steps 3 times. But multiple +copies of the same code is not good program practice because it's more +work to maintain. By using a programming language, we can iterate +over the search results for a more flexible and maintainable solution. + +#### In `C#` + +```csharp + // Collection of String values. + String[] arr = {"ide", "rc", "grid"}; + + // Execute loop for each String in array 'arr'. + foreach (String s in arr) { + sel.open("/"); + sel.type("q", "selenium " +s); + sel.click("btnG"); + sel.waitForPageToLoad("30000"); + assertTrue("Expected text: " +s+ " is missing on page." + , sel.isTextPresent("Results * for selenium " + s)); + } +``` + +### Condition Statements + +To illustrate using conditions in tests we'll start with an example. +A common problem encountered while running Selenium tests occurs when an +expected element is not available on page. For example, when running the +following line: + +``` + selenium.type("q", "selenium " +s); +``` + +If element 'q' is not on the page then an exception is +thrown: + +```java + com.thoughtworks.selenium.SeleniumException: ERROR: Element q not found +``` + +This can cause your test to abort. For some tests that's what you want. But +often that is not desirable as your test script has many other subsequent tests +to perform. + +A better approach is to first validate whether the element is really present +and then take alternatives when it it is not. Let's look at this using Java. + +```java + // If element is available on page then perform type operation. + if(selenium.isElementPresent("q")) { + selenium.type("q", "Selenium rc"); + } else { + System.out.printf("Element: " +q+ " is not available on page.") + } +``` + +The advantage of this approach is to continue with test execution even if some UI +elements are not available on page. + + +### Executing JavaScript from Your Test + +JavaScript comes very handy in exercising an application which is not directly supported +by selenium. The **getEval** method of selenium API can be used to execute JavaScript from +selenium RC. + +Consider an application having check boxes with no static identifiers. +In this case one could evaluate JavaScript from selenium RC to get ids of all +check boxes and then exercise them. + +```java + public static String[] getAllCheckboxIds () { + String script = "var inputId = new Array();";// Create array in java script. + script += "var cnt = 0;"; // Counter for check box ids. + script += "var inputFields = new Array();"; // Create array in java script. + script += "inputFields = window.document.getElementsByTagName('input');"; // Collect input elements. + script += "for(var i=0; i.jar +``` + +To see the list of options, run the server with the ``-h`` option. + +```bash + $ java -jar selenium-server-standalone-.jar -h +``` + +You'll see a list of all the options you can use with the server and a brief +description of each. The provided descriptions will not always be enough, so we've +provided explanations for some of the more important options. + + +### Proxy Configuration + +If your AUT is behind an HTTP proxy which requires authentication then you should +configure http.proxyHost, http.proxyPort, http.proxyUser and http.proxyPassword +using the following command. + +```bash + $ java -jar selenium-server-standalone-.jar -Dhttp.proxyHost=proxy.com -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password +``` + +### Multi-Window Mode + +If you are using Selenium 1.0 you can probably skip this section, since multiwindow mode is +the default behavior. However, prior to version 1.0, Selenium by default ran the +application under test in a sub frame as shown here. + +![Single window mode](/images/legacy_docs/selenium_rc_single_window_mode.png) + +Some applications didn't run correctly in a sub frame, and needed to be +loaded into the top frame of the window. The multi-window mode option allowed +the AUT to run in a separate window rather than in the default +frame where it could then have the top frame it required. + +![Multiwindow Mode](/images/legacy_docs/selenium_rc_multi_window_mode.png) + +For older versions of Selenium you must specify multiwindow mode explicitly +with the following option: + +```bash + -multiwindow +``` + +As of Selenium RC 1.0, if you want to run your test within a +single frame (i.e. using the standard for earlier Selenium versions) +you can state this to the Selenium Server using the option + +```bash + -singlewindow +``` + +### Specifying the Firefox Profile + +Firefox will not run two instances simultaneously unless you specify a +separate profile for each instance. Selenium RC 1.0 and later runs in a +separate profile automatically, so if you are using Selenium 1.0, you can +probably skip this section. However, if you're using an older version of +Selenium or if you need to use a specific profile for your tests +(such as adding an https certificate or having some addons installed), you will +need to explicitly specify the profile. + +First, to create a separate Firefox profile, follow this procedure. +Open the Windows Start menu, select "Run", then type and enter one of the +following: + +```bash + firefox.exe -profilemanager +``` + +```bash + firefox.exe -P +``` + +Create the new profile using the dialog. Then when you run Selenium Server, +tell it to use this new Firefox profile with the server command-line option +*\-firefoxProfileTemplate* and specify the path to the profile using its filename +and directory path. + +```bash + -firefoxProfileTemplate "path to the profile" +``` + +**Warning**: Be sure to put your profile in a new folder separate from the default!!! + The Firefox profile manager tool will delete all files in a folder if you + delete a profile, regardless of whether they are profile files or not. + +More information about Firefox profiles can be found in [Mozilla's Knowledge Base](http://support.mozilla.com/en/kb/Managing+profiles) + +### Run Selenese Directly Within the Server Using -htmlSuite + +You can run Selenese html files directly within the Selenium Server +by passing the html file to the server's command line. For instance: + +```bash + java -jar selenium-server-standalone-.jar -htmlSuite "*firefox" + "http://www.google.com" "c:\absolute\path\to\my\HTMLSuite.html" + "c:\absolute\path\to\my\results.html" +``` + +This will automatically launch your HTML suite, run all the tests and save a +nice HTML report with the results. + +*Note:* When using this option, the server will start the tests and wait for a + specified number of seconds for the test to complete; if the test doesn't + complete within that amount of time, the command will exit with a non-zero + exit code and no results file will be generated. + +This command line is very long so be careful when +you type it. Note this requires you to pass in an HTML +Selenese suite, not a single test. Also be aware the -htmlSuite option is incompatible with ``-interactive`` +You cannot run both at the same time. + +### Selenium Server Logging + +#### Server-Side Logs + +When launching selenium server the **-log** option can be used to record +valuable debugging information reported by the Selenium Server to a text file. + +```bash + java -jar selenium-server-standalone-.jar -log selenium.log +``` + +This log file is more verbose than the standard console logs (it includes DEBUG +level logging messages). The log file also includes the logger name, and the ID +number of the thread that logged the message. For example: + +```bash + 20:44:25 DEBUG [12] org.openqa.selenium.server.SeleniumDriverResourceHandler - + Browser 465828/:top frame1 posted START NEW +``` + +The message format is + +```bash + TIMESTAMP(HH:mm:ss) LEVEL [THREAD] LOGGER - MESSAGE +``` + +This message may be multiline. + +#### Browser-Side Logs + +JavaScript on the browser side (Selenium Core) also logs important messages; +in many cases, these can be more useful to the end-user than the regular Selenium +Server logs. To access browser-side logs, pass the **-browserSideLog** +argument to the Selenium Server. + + +```bash + java -jar selenium-server-standalone-.jar -browserSideLog +``` + +**-browserSideLog** must be combined with the **-log** argument, to log +browserSideLogs (as well as all other DEBUG level logging messages) to a file. + + +## Specifying the Path to a Specific Browser + +You can specify to Selenium RC a path to a specific browser. This is useful if +you have different versions of the same browser and you wish to use a specific +one. Also, this is used to allow your tests to run against a browser not +directly supported by Selenium RC. When specifying the run mode, use the +\*custom specifier followed by the full path to the browser's executable: + +```bash + *custom +``` + + +## Selenium RC Architecture + +*Note:* This topic tries to explain the technical implementation behind + Selenium RC. It's not fundamental for a Selenium user to know this, but + could be useful for understanding some of the problems you might find in the + future. + +To understand in detail how Selenium RC Server works and why it uses proxy injection +and heightened privilege modes you must first understand `the same origin policy`_. + +### The Same Origin Policy + +The main restriction that Selenium faces is the +Same Origin Policy. This security restriction is applied by every browser +in the market and its objective is to ensure that a site's content will never +be accessible by a script from another site. The Same Origin Policy dictates that +any code loaded within the browser can only operate within that website's domain. +It cannot perform functions on another website. So for example, if the browser +loads JavaScript code when it loads www.mysite.com, it cannot run that loaded code +against www.mysite2.com--even if that's another of your sites. If this were possible, +a script placed on any website you open would be able to read information on +your bank account if you had the account page +opened on other tab. This is called XSS (Cross-site Scripting). + +To work within this policy, Selenium-Core (and its JavaScript commands that +make all the magic happen) must be placed in the same origin as the Application +Under Test (same URL). + +Historically, Selenium-Core was limited by this problem since it was implemented in +JavaScript. Selenium RC is not, however, restricted by the Same Origin Policy. Its +use of the Selenium Server as a proxy avoids this problem. It, essentially, tells the +browser that the browser is working on a single "spoofed" website that the Server +provides. + +*Note:* You can find additional information about this topic on Wikipedia + pages about Same Origin Policy and XSS. + + +### Proxy Injection + +The first method Selenium used to avoid the The Same Origin Policy was Proxy Injection. +In Proxy Injection Mode, the Selenium Server acts as a client-configured **HTTP +proxy**[^1], that sits between the browser and the Application Under Test[^2]. +It then masks the AUT under a fictional URL (embedding +Selenium-Core and the set of tests and delivering them as if they were coming +from the same origin). + +[^1]: The proxy is a third person in the middle that passes the ball between the two parts. It acts as a "web server" that delivers the AUT to the browser. Being a proxy gives Selenium Server the capability of "lying" about the AUT's real URL. + +[^2]: The browser is launched with a configuration profile that has set localhost:4444 as the HTTP proxy, this is why any HTTP request that the browser does will pass through Selenium server and the response will pass through it and not from the real server. + +Here is an architectural diagram. + +![Architectural Diagram 1](/images/legacy_docs/selenium_rc_architecture_diagram_1.png) + +As a test suite starts in your favorite language, the following happens: + +1. The client/driver establishes a connection with the selenium-RC server. +2. Selenium RC server launches a browser (or reuses an old one) with a URL + that injects Selenium-Core's JavaScript into the browser-loaded web page. +3. The client-driver passes a Selenese command to the server. +4. The Server interprets the command and then triggers the corresponding + JavaScript execution to execute that command within the browser. + Selenium-Core instructs the browser to act on that first instruction, typically opening a page of the + AUT. +5. The browser receives the open request and asks for the website's content from + the Selenium RC server (set as the HTTP proxy for the browser to use). +6. Selenium RC server communicates with the Web server asking for the page and once + it receives it, it sends the page to the browser masking the origin to look + like the page comes from the same server as Selenium-Core (this allows + Selenium-Core to comply with the Same Origin Policy). +7. The browser receives the web page and renders it in the frame/window reserved + for it. + +### Heightened Privileges Browsers + +This workflow in this method is very similar to Proxy Injection but the main +difference is that the browsers are launched in a special mode called *Heightened +Privileges*, which allows websites to do things that are not commonly permitted +(as doing XSS_, or filling file upload inputs and pretty useful stuff for +Selenium). By using these browser modes, Selenium Core is able to directly open +the AUT and read/interact with its content without having to pass the whole AUT +through the Selenium RC server. + +Here is the architectural diagram. + +![Architectural Diagram 1](/images/legacy_docs/selenium_rc_architecture_diagram_2.png) + +As a test suite starts in your favorite language, the following happens: + +1. The client/driver establishes a connection with the selenium-RC server. +2. Selenium RC server launches a browser (or reuses an old one) with a URL + that will load Selenium-Core in the web page. +3. Selenium-Core gets the first instruction from the client/driver (via another + HTTP request made to the Selenium RC Server). +4. Selenium-Core acts on that first instruction, typically opening a page of the + AUT. +5. The browser receives the open request and asks the Web Server for the page. + Once the browser receives the web page, renders it in the frame/window reserved + for it. + +## Handling HTTPS and Security Popups + +Many applications switch from using HTTP to HTTPS when they need to send +encrypted information such as passwords or credit card information. This is +common with many of today's web applications. Selenium RC supports this. + +To ensure the HTTPS site is genuine, the browser will need a security +certificate. Otherwise, when the browser accesses the AUT using HTTPS, it will +assume that application is not 'trusted'. When this occurs the browser +displays security popups, and these popups cannot be closed using Selenium RC. + +When dealing with HTTPS in a Selenium RC test, you must use a run mode that supports this and handles +the security certificate for you. You specify the run mode when your test program +initializes Selenium. + +In Selenium RC 1.0 beta 2 and later use \*firefox or \*iexplore for the run +mode. In earlier versions, including Selenium RC 1.0 beta 1, use \*chrome or +\*iehta, for the run mode. Using these run modes, you will not need to install +any special security certificates; Selenium RC will handle it for you. + +In version 1.0 the run modes \*firefox or \*iexplore are +recommended. However, there are additional run modes of \*iexploreproxy and +\*firefoxproxy. These are provided for backwards compatibility only, and +should not be used unless required by legacy test programs. Their use will +present limitations with security certificate handling and with the running +of multiple windows if your application opens additional browser windows. + +In earlier versions of Selenium RC, \*chrome or \*iehta were the run modes that +supported HTTPS and the handling of security popups. These were considered ‘experimental +modes although they became quite stable and many people used them. If you are using +Selenium 1.0 you do not need, and should not use, these older run modes. + +### Security Certificates Explained + +Normally, your browser will trust the application you are testing +by installing a security certificate which you already own. You can +check this in your browser's options or Internet properties (if you don't +know your AUT's security certificate ask your system administrator). +When Selenium loads your browser it injects code to intercept +messages between the browser and the server. The browser now thinks +untrusted software is trying to look like your application. It responds by alerting you with popup messages. + +To get around this, Selenium RC, (again when using a run mode that support +this) will install its own security certificate, temporarily, to your +client machine in a place where the browser can access it. This tricks the +browser into thinking it's accessing a site different from your AUT and effectively suppresses the popups. + +Another method used with earlier versions of Selenium was to +install the Cybervillians security certificate provided with your Selenium +installation. Most users should no longer need to do this however; if you are +running Selenium RC in proxy injection mode, you may need to explicitly install this +security certificate. + + +## Supporting Additional Browsers and Browser Configurations + +The Selenium API supports running against multiple browsers in addition to +Internet Explorer and Mozilla Firefox. See the https://selenium.dev website for +supported browsers. In addition, when a browser is not directly supported, +you may still run your Selenium tests against a browser of your choosing by +using the "\*custom" run-mode (i.e. in place of \*firefox or \*iexplore) when +your test application starts the browser. With this, you pass in the path to +the browsers executable within the API call. This can also be done from the +Server in interactive mode. + +```bash + cmd=getNewBrowserSession&1=*custom c:\Program Files\Mozilla Firefox\MyBrowser.exe&2=http://www.google.com +``` + + +### Running Tests with Different Browser Configurations + +Normally Selenium RC automatically configures the browser, but if you launch +the browser using the "\*custom" run mode, you can force Selenium RC +to launch the browser as-is, without using an automatic configuration. + +For example, you can launch Firefox with a custom configuration like this: + +```bash + cmd=getNewBrowserSession&1=*custom c:\Program Files\Mozilla Firefox\firefox.exe&2=http://www.google.com +``` + +Note that when launching the browser this way, you must manually +configure the browser to use the Selenium Server as a proxy. Normally this just +means opening your browser preferences and specifying "localhost:4444" as +an HTTP proxy, but instructions for this can differ radically from browser to +browser. Consult your browser's documentation for details. + +Be aware that Mozilla browsers can vary in how they start and stop. +One may need to set the MOZ_NO_REMOTE environment variable to make Mozilla browsers +behave a little more predictably. Unix users should avoid launching the browser using +a shell script; it's generally better to use the binary executable (e.g. firefox-bin) directly. + + +## Troubleshooting Common Problems + +When getting started with Selenium RC there's a few potential problems +that are commonly encountered. We present them along with their solutions here. + +### Unable to Connect to Server + +When your test program cannot connect to the Selenium Server, Selenium throws an exception in your test program. +It should display this message or a similar one: + +```bash + "Unable to connect to remote server (Inner Exception Message: + No connection could be made because the target machine actively + refused it )" + + (using .NET and XP Service Pack 2) +``` + +If you see a message like this, be sure you started the Selenium Server. If +so, then there is a problem with the connectivity between the Selenium Client +Library and the Selenium Server. + +When starting with Selenium RC, most people begin by running their test program +(with a Selenium Client Library) and the Selenium Server on the same machine. To +do this use "localhost" as your connection parameter. +We recommend beginning this way since it reduces the influence of potential networking problems +which you're getting started. Assuming your operating system has typical networking +and TCP/IP settings you should have little difficulty. In truth, many people +choose to run the tests this way. + +If, however, you do want to run Selenium Server +on a remote machine, the connectivity should be fine assuming you have valid TCP/IP +connectivity between the two machines. + +If you have difficulty connecting, you can use common networking tools like *ping*, +*telnet*, *ifconfig(Unix)/ipconfig* (Windows), etc to ensure you have a valid +network connection. If unfamilar with these, your system administrator can assist you. + +### Unable to Load the Browser + +Ok, not a friendly error message, sorry, but if the Selenium Server cannot load the browser +you will likely see this error. + +```bash + (500) Internal Server Error +``` + +This could be caused by + +* Firefox (prior to Selenium 1.0) cannot start because the browser is already open and you did + not specify a separate profile. See the section on Firefox profiles under Server Options. +* The run mode you're using doesn't match any browser on your machine. Check the parameters you + passed to Selenium when you program opens the browser. +* You specified the path to the browser explicitly (using "\*custom"--see above) but the path is + incorrect. Check to be sure the path is correct. Also check the user group to be sure there are + no known issues with your browser and the "\*custom" parameters. + +### Selenium Cannot Find the AUT + +If your test program starts the browser successfully, but the browser doesn't +display the website you're testing, the most likely cause is your test +program is not using the correct URL. + +This can easily happen. When you use Selenium-IDE to export your script, +it inserts a dummy URL. You must manually change the URL to the correct one +for your application to be tested. + +### Firefox Refused Shutdown While Preparing a Profile + +This most often occurs when you run your Selenium RC test program against Firefox, +but you already have a Firefox browser session running and, you didn't specify +a separate profile when you started the Selenium Server. The error from the +test program looks like this: + +```bash + Error: java.lang.RuntimeException: Firefox refused shutdown while + preparing a profile +``` + +Here's the complete error message from the server: + +```bash + 16:20:03.919 INFO - Preparing Firefox profile... + 16:20:27.822 WARN - GET /selenium-server/driver/?cmd=getNewBrowserSession&1=*fir + efox&2=http%3a%2f%2fsage-webapp1.qa.idc.com HTTP/1.1 + java.lang.RuntimeException: Firefox refused shutdown while preparing a profile + at org.openqa.selenium.server.browserlaunchers.FirefoxCustomProfileLaunc + her.waitForFullProfileToBeCreated(FirefoxCustomProfileLauncher.java:277) + ... + Caused by: org.openqa.selenium.server.browserlaunchers.FirefoxCustomProfileLaunc + her$FileLockRemainedException: Lock file still present! C:\DOCUME~1\jsvec\LOCALS + ~1\Temp\customProfileDir203138\parent.lock +``` + +To resolve this, see the section on Specifying a Separate Firefox Profile + +### Versioning Problems + +Make sure your version of Selenium supports the version of your browser. For +example, Selenium RC 0.92 does not support Firefox 3. At times you may be lucky +(I was). But don't forget to check which +browser versions are supported by the version of Selenium you are using. When in +doubt, use the latest release version of Selenium with the most widely used version +of your browser. + +### Error message: "(Unsupported major.minor version 49.0)" while starting server + +This error says you're not using a correct version of Java. +The Selenium Server requires Java 1.5 or higher. + +To check double-check your java version, run this from the command line. + +```bash + java -version +``` + +You should see a message showing the Java version. + +```bash + java version "1.5.0_07" + Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03) + Java HotSpot(TM) Client VM (build 1.5.0_07-b03, mixed mode) +``` + +If you see a lower version number, you may need to update the JRE, +or you may simply need to add it to your PATH environment variable. + + +### 404 error when running the getNewBrowserSession command + +If you're getting a 404 error while attempting to open a page on +"http://www.google.com/selenium-server/", then it must be because the Selenium +Server was not correctly configured as a proxy. The "selenium-server" directory +doesn't exist on google.com; it only appears to exist when the proxy is +properly configured. Proxy Configuration highly depends on how the browser is +launched with firefox, iexplore, opera, or custom. + +* iexplore: If the browser is launched using \*iexplore, you could be + having a problem with Internet Explorer's proxy settings. Selenium + Server attempts To configure the global proxy settings in the Internet + Options Control Panel. You must make sure that those are correctly + configured when Selenium Server launches the browser. Try looking at + your Internet Options control panel. Click on the "Connections" tab + and click on "LAN Settings". + * If you need to use a proxy to access the application you want to test, + you'll need to start Selenium Server with "-Dhttp.proxyHost"; + see the `Proxy Configuration`_ for more details. + * You may also try configuring your proxy manually and then launching + the browser with \*custom, or with \*iehta browser launcher. + +* custom: When using \*custom you must configure the proxy correctly(manually), + otherwise you'll get a 404 error. Double-check that you've configured your proxy + settings correctly. To check whether you've configured the proxy correctly is to + attempt to intentionally configure the browser incorrectly. Try configuring the + browser to use the wrong proxy server hostname, or the wrong port. If you had + successfully configured the browser's proxy settings incorrectly, then the + browser will be unable to connect to the Internet, which is one way to make + sure that one is adjusting the relevant settings. + +* For other browsers (\*firefox, \*opera) we automatically hard-code + the proxy for you, and so there are no known issues with this functionality. + If you're encountering 404 errors and have followed this user guide carefully + post your results to user group for some help from the user community. + +### Permission Denied Error + +The most common reason for this error is that your session is attempting to violate +the same-origin policy by crossing domain boundaries (e.g., accesses a page from +http://domain1 and then accesses a page from http://domain2) or switching protocols +(moving from http://domainX to https://domainX). + +This error can also occur when JavaScript attempts to find UI objects +which are not yet available (before the page has completely loaded), or +are no longer available (after the page has started +to be unloaded). This is most typically encountered with AJAX pages +which are working with sections of a page or subframes that load and/or reload +independently of the larger page. + +This error can be intermittent. Often it is impossible to reproduce the problem +with a debugger because the trouble stems from race conditions which +are not reproducible when the debugger's overhead is added to the system. +Permission issues are covered in some detail in the tutorial. Read the section +about the `The Same Origin Policy`_, `Proxy Injection`_ carefully. + + +### Handling Browser Popup Windows + +There are several kinds of "Popups" that you can get during a Selenium test. +You may not be able to close these popups by running selenium commands if +they are initiated by the browser and not your AUT. You may +need to know how to manage these. Each type of popup needs to be addressed differently. + +* HTTP basic authentication dialogs: These dialogs prompt for a + username/password to login to the site. To login to a site that requires + HTTP basic authentication, use a username and password in the URL, as + described in `RFC 1738`_, like this: open("http://myusername:myuserpassword@myexample.com/blah/blah/blah"). + +* SSL certificate warnings: Selenium RC automatically attempts to spoof SSL + certificates when it is enabled as a proxy; see more on this + in the section on HTTPS. If your browser is configured correctly, + you should never see SSL certificate warnings, but you may need to + configure your browser to trust our dangerous "CyberVillains" SSL certificate + authority. Again, refer to the HTTPS section for how to do this. + +* modal JavaScript alert/confirmation/prompt dialogs: Selenium tries to conceal + those dialogs from you (by replacing window.alert, window.confirm and + window.prompt) so they won't stop the execution of your page. If you're + seeing an alert pop-up, it's probably because it fired during the page load process, + which is usually too early for us to protect the page. Selenese contains commands + for asserting or verifying alert and confirmation popups. See the sections on these + topics in Chapter 4. + + +### On Linux, why isn't my Firefox browser session closing? + +On Unix/Linux you must invoke "firefox-bin" directly, so make sure that +executable is on the path. If executing Firefox through a +shell script, when it comes time to kill the browser Selenium RC will kill +the shell script, leaving the browser running. You can specify the path +to firefox-bin directly, like this. + +```bash + cmd=getNewBrowserSession&1=*firefox /usr/local/firefox/firefox-bin&2=http://www.google.com +``` + +### Firefox \*chrome doesn't work with custom profile + +Check Firefox profile folder -> prefs.js -> user_pref("browser.startup.page", 0); +Comment this line like this: "//user_pref("browser.startup.page", 0);" and try again. + + +### Is it ok to load a custom pop-up as the parent page is loading (i.e., before the parent page's javascript window.onload() function runs)? + +No. Selenium relies on interceptors to determine window names as they are being loaded. +These interceptors work best in catching new windows if the windows are loaded AFTER +the onload() function. Selenium may not recognize windows loaded before the onload function. + +### Firefox on Linux + +On Unix/Linux, versions of Selenium before 1.0 needed to invoke "firefox-bin" +directly, so if you are using a previous version, make sure that the real +executable is on the path. + +On most Linux distributions, the real *firefox-bin* is located on: + +```bash + /usr/lib/firefox-x.x.x/ +``` + +Where the x.x.x is the version number you currently have. So, to add that path +to the user's path. you will have to add the following to your .bashrc file: + +```bash + export PATH="$PATH:/usr/lib/firefox-x.x.x/" +``` + +If necessary, you can specify the path to firefox-bin directly in your test, +like this: + +```bash + "*firefox /usr/lib/firefox-x.x.x/firefox-bin" +``` + +### IE and Style Attributes + +If you are running your tests on Internet Explorer and you cannot locate +elements using their `style` attribute. +For example: + +```bash + //td[@style="background-color:yellow"] +``` + +This would work perfectly in Firefox, Opera or Safari but not with IE. +IE interprets the keys in `@style` as uppercase. So, even if the +source code is in lowercase, you should use: + +```bash + //td[@style="BACKGROUND-COLOR:yellow"] +``` + +This is a problem if your test is intended to work on multiple browsers, but +you can easily code your test to detect the situation and try the alternative +locator that only works in IE. + +### Error encountered - "Cannot convert object to primitive value" with shut down of \*googlechrome browser + +To avoid this error you have to start browser with an option that disables same origin policy checks: + +```bash + selenium.start("commandLineFlags=--disable-web-security"); +``` + + +### Error encountered in IE - "Couldn't open app window; is the pop-up blocker enabled?" + +To avoid this error you have to configure the browser: disable the popup blocker +AND uncheck 'Enable Protected Mode' option in Tools >> Options >> Security. diff --git a/docs_source_files/content/remote_webdriver/_index.de.md b/docs_source_files/content/remote_webdriver/_index.de.md new file mode 100644 index 000000000000..3ef9603cd39d --- /dev/null +++ b/docs_source_files/content/remote_webdriver/_index.de.md @@ -0,0 +1,15 @@ +--- +title: "Remote WebDriver" +chapter: true +weight: 6 +--- + +# Remote WebDriver + +You can use WebDriver remotely the same way you would use it +locally. The primary difference is that a remote WebDriver needs to be +configured so that it can run your tests on a separate machine. + +A remote WebDriver is composed of two pieces: a client and a +server. The client is your WebDriver test and the server is simply a +Java servlet, which can be hosted in any modern JEE app server. \ No newline at end of file diff --git a/docs_source_files/content/remote_webdriver/remote_webdriver_client.de.md b/docs_source_files/content/remote_webdriver/remote_webdriver_client.de.md new file mode 100644 index 000000000000..b632b7ad7fc1 --- /dev/null +++ b/docs_source_files/content/remote_webdriver/remote_webdriver_client.de.md @@ -0,0 +1,171 @@ +--- +title: "Remote WebDriver client" +weight: 2 +--- + +To run a remote WebDriver client, we first need to connect to the RemoteWebDriver. +We do this by pointing the URL to the address of the server running our tests. +In order to customize our configuration, we set desired capabilities. +Below is an example of instantiating a remote WebDriver object +pointing to our remote web server, _www.example.com_, +running our tests on Firefox. + +{{< code-tab >}} + {{< code-panel language="java" >}} +FirefoxOptions firefoxOptions = new FirefoxOptions(); +WebDriver driver = new RemoteWebDriver(new URL("http://www.example.com"), firefoxOptions); +driver.get("http://www.google.com"); +driver.quit(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# We don't have a Python code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="csharp" >}} + FirefoxOptions firefoxOptions = new FirefoxOptions(); + IWebDriver driver = new RemoteWebDriver(new Uri("http://www.example.com"), firefoxOptions); + driver.Navigate().GoToUrl("http://www.google.com"); + driver.Quit(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +require 'selenium-webdriver' + +driver = Selenium::WebDriver.for :remote, url: "http://www.example.com", desired_capabilities: :firefox +driver.get "http://www.google.com" +driver.close + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +firefoxOptions = FirefoxOptions() +driver: WebDriver = new RemoteWebDriver(new URL("http://www.example.com"), firefoxOptions) +driver.get("http://www.google.com") +driver.quit() + {{< / code-panel >}} +{{< / code-tab >}} + + +To further customize our test configuration, we can add other desired capabilities. + + +## Desired capabilities + +Desired capabilities can be expanded further. +All remote Webdriver capabilities are sent through JsonWireProtocol. +For a list of configurable capabilities, and more information on JsonWireProtocol, +please visit the documentation +[here](//github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities). + +For example, suppose you wanted to run Chrome on Windows XP, +using Chrome version 67: + +{{< code-tab >}} + {{< code-panel language="java" >}} +ChromeOptions chromeOptions = new ChromeOptions(); +chromeOptions.setCapability("browserVersion", "67"); +chromeOptions.setCapability("platformName", "Windows XP"); +WebDriver driver = new RemoteWebDriver(new URL("http://www.example.com"), chromeOptions); +driver.get("http://www.google.com"); +driver.quit(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# We don't have a Python code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +var chromeOptions = new ChromeOptions(); +chromeOptions.BrowserVersion = "67"; +chromeOptions.PlatformName = "Windows XP"; +IWebDriver driver = new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub"), chromeOptions); +driver.Navigate().GoToUrl("http://www.google.com"); +driver.Quit(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +caps = Selenium::WebDriver::Remote::Capabilities.chrome +caps.platform = Windows XP +caps.version = 67 + +driver = Selenium::WebDriver.for :remote, :url => "http://www.example.com", :desired_capabilities => caps + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val chromeOptions = ChromeOptions() +chromeOptions.setCapability("browserVersion", "67"); +chromeOptions.setCapability("platformName", "Windows XP"); +val driver: WebDriver = new RemoteWebDriver(new URL("http://www.example.com"), chromeOptions) +driver.get("http://www.google.com") +driver.quit(); + {{< / code-panel >}} +{{< / code-tab >}} + + +## Local file detector + +The Local File Detector allows the transfer of files from the client +machine to the remote server. For example, if a test needs to upload a +file to a web application, a remote WebDriver can automatically transfer +the file from the local machine to the remote web server during +runtime. This allows the file to be uploaded from the remote machine +running the test. It is not enabled by default and can be enabled in +the following way: + +{{< code-tab >}} + {{< code-panel language="java" >}} +driver.setFileDetector(new LocalFileDetector()); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# We don't have a Python code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +var allowsDetection = this.driver as IAllowsFileDetection; +if (allowsDetection != null) +{ + allowsDetection.FileDetector = new LocalFileDetector(); +} + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +@driver.file_detector = lambda do |args| + # args => ["/path/to/file"] + str = args.first.to_s + str if File.exist?(str) +end + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +driver.setFileDetector(new LocalFileDetector()) + {{< / code-panel >}} +{{< / code-tab >}} + +Once the above code is defined, you can upload a file in your test in the following way: + +{{< code-tab >}} + {{< code-panel language="java" >}} +driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload"); +WebElement upload = driver.findElement(By.id("myfile")); +upload.sendKeys("/Users/sso/the/local/path/to/darkbulb.jpg"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# We don't have a Python code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +driver.Navigate().GoToUrl("http://sso.dev.saucelabs.com/test/guinea-file-upload"); +IWebElement upload = driver.FindElement(By.Id("myfile")); +upload.SendKeys(@"/Users/sso/the/local/path/to/darkbulb.jpg"); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +@driver.navigate.to "http://sso.dev.saucelabs.com/test/guinea-file-upload" + element = @driver.find_element(:id, 'myfile') + element.send_keys "/Users/sso/SauceLabs/sauce/hostess/maitred/maitred/public/images/darkbulb.jpg" + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +driver.get("http://sso.dev.saucelabs.com/test/guinea-file-upload") +val upload: WebElement = driver.findElement(By.id("myfile")) +upload.sendKeys("/Users/sso/the/local/path/to/darkbulb.jpg") + {{< / code-panel >}} +{{< / code-tab >}} diff --git a/docs_source_files/content/remote_webdriver/remote_webdriver_server.de.md b/docs_source_files/content/remote_webdriver/remote_webdriver_server.de.md new file mode 100644 index 000000000000..2d3570c76003 --- /dev/null +++ b/docs_source_files/content/remote_webdriver/remote_webdriver_server.de.md @@ -0,0 +1,101 @@ +--- +title: "Remote WebDriver server" +weight: 1 +--- + +The server will always run on the machine with the browser you want to +test. The server can be used either from the command line or through code +configuration. + + +## Starting the server from the command line + +Once you have downloaded `selenium-server-standalone-{VERSION}.jar`, +place it on the computer with the browser you want to test. Then, from +the directory with the jar, run the following: + +```shell +java -jar selenium-server-standalone-{VERSION}.jar +``` + +## Considerations for running the server + +The caller is expected to terminate each session properly, calling +either `Selenium#stop()` or `WebDriver#quit`. + +The selenium-server keeps in-memory logs for each ongoing session, +which are cleared when `Selenium#stop()` or `WebDriver#quit` is called. If +you forget to terminate these sessions, your server may leak memory. If +you keep extremely long-running sessions, you will probably need to +stop/quit every now and then (or increase memory with -Xmx jvm option). + + +## Timeouts (from version 2.21) + +The server has two different timeouts, which can be set as follows: + +```shell +java -jar selenium-server-standalone-{VERSION}.jar -timeout=20 -browserTimeout=60 +``` + +* browserTimeout + * Controls how long the browser is allowed to hang (value in seconds). +* timeout + * Controls how long the client is allowed to be gone + before the session is reclaimed (value in seconds). + +The system property `selenium.server.session.timeout` +is no longer supported as of 2.21. + +Please note that the `browserTimeout` +is intended as a backup timeout mechanism +when the ordinary timeout mechanism fails, +which should be used mostly in grid/server environments +to ensure that crashed/lost processes do not stay around for too long, +polluting the runtime environment. + + +## Configuring the server programmatically + +In theory, the process is as simple as mapping the `DriverServlet` to +a URL, but it is also possible to host the page in a lightweight +container, such as Jetty, configured entirely in code. + +* Download the `selenium-server.zip` and unpack. +* Put the JARs on the CLASSPATH. +* Create a new class called `AppServer`. +Here, we are using Jetty, so you will need to [download](//www.eclipse.org/jetty/download.html) +that as well: + +```java +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.nio.SelectChannelConnector; +import org.mortbay.jetty.security.SslSocketConnector; +import org.mortbay.jetty.webapp.WebAppContext; + +import javax.servlet.Servlet; +import java.io.File; + +import org.openqa.selenium.remote.server.DriverServlet; + +public class AppServer { + private Server server = new Server(); + + public AppServer() throws Exception { + WebAppContext context = new WebAppContext(); + context.setContextPath(""); + context.setWar(new File(".")); + server.addHandler(context); + + context.addServlet(DriverServlet.class, "/wd/*"); + + SelectChannelConnector connector = new SelectChannelConnector(); + connector.setPort(3001); + server.addConnector(connector); + + server.start(); + } +} +``` + diff --git a/docs_source_files/content/selenium_installation/_index.de.md b/docs_source_files/content/selenium_installation/_index.de.md new file mode 100644 index 000000000000..fd920c0aec6f --- /dev/null +++ b/docs_source_files/content/selenium_installation/_index.de.md @@ -0,0 +1,9 @@ +--- +title: "Selenium installation" +chapter: true +weight: 3 +--- + +# Selenium Installation + +Selenium setup is quite different from the setup of other commercial tools. To use Selenium in your automation project you need to install the language bindings libraries for your language of choice. In addition you will need WebDriver binaries for the browsers you want to automate and run test on. \ No newline at end of file diff --git a/docs_source_files/content/selenium_installation/installing_selenium_libraries.de.md b/docs_source_files/content/selenium_installation/installing_selenium_libraries.de.md new file mode 100644 index 000000000000..a1b0c53a6a7c --- /dev/null +++ b/docs_source_files/content/selenium_installation/installing_selenium_libraries.de.md @@ -0,0 +1,87 @@ +--- +title: "Installing Selenium libraries" +weight: 1 +--- + +First you need to install the Selenium bindings for your automation project. +The installation process for libraries depends on the language you choose to use. + +## _Java_ +Installation of Selenium libraries for Java can be done using Maven. +Add the _selenium-java_ dependency in your project pom.xml: + +```xml + + org.seleniumhq.selenium + selenium-java + 3.X + +``` + +The _selenium-java_ dependency supports running your automation +project with all Selenium supported browsers. If you want to run tests +only in a specific browser, you can add the dependency for that browser +in your _pom.xml_ file. +For example, you should add following dependency in your _pom.xml_ +file to run your tests only in Firefox: + +```xml + + org.seleniumhq.selenium + selenium-firefox-driver + 3.X + +``` + +In a similar manner, if you want to run tests only in Chrome, +you should add the following dependency: + +```xml + + org.seleniumhq.selenium + selenium-chrome-driver + 3.X + +``` + +## _Python_ +Installation of Selenium libraries for Python can be done using pip: + +```shell +pip install selenium +``` + +Alternatively you can download the [PyPI source archive](https://pypi.org/project/selenium/#files) +(selenium-x.x.x.tar.gz) and install it using _setup.py_: + +```shell +python setup.py install +``` + +## _C#_ +Installation of Selenium libraries for C# can be done using NuGet: + +```shell +# Using package manager +Install-Package Selenium.WebDriver +# or using .Net CLI +dotnet add package Selenium.WebDriver +``` + +## _Ruby_ +Installation of Selenium libraries for Ruby can be done using gem: + +```shell +gem install selenium-webdriver +``` + +## _JavaScript_ +Installation of Selenium libraries for JavaScript can be done using npm: + +```shell +npm install selenium-webdriver +``` + +## _Kotlin_ +Due to missing native language bindings for Kotlin, you have to use the Java Bindings, e.g. with maven [Java](#java) + diff --git a/docs_source_files/content/selenium_installation/installing_standalone_server.de.md b/docs_source_files/content/selenium_installation/installing_standalone_server.de.md new file mode 100644 index 000000000000..9858dba98afa --- /dev/null +++ b/docs_source_files/content/selenium_installation/installing_standalone_server.de.md @@ -0,0 +1,22 @@ +--- +title: "Installing Standalone server" +weight: 3 +--- + +If you plan to use [Grid]({{< ref "/grid/_index.md" >}}) then you should download the +[selenium-server-standalone JAR](//selenium.dev/downloads/) file. + The _selenium-server-standalone_ jar is never uploaded, but all the components are available via + [selenium-server](//repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-server/). + The standalone JAR contains everything, including the remote Selenium server + and the client-side bindings. + This means that if you use the selenium-server-standalone jar + in your project, you do not have to add selenium-java + or a browser specific jar. + + ```xml + + org.seleniumhq.selenium + selenium-server + 3.X + +``` diff --git a/docs_source_files/content/selenium_installation/installing_webdriver_binaries.de.md b/docs_source_files/content/selenium_installation/installing_webdriver_binaries.de.md new file mode 100644 index 000000000000..baeca92ecc8b --- /dev/null +++ b/docs_source_files/content/selenium_installation/installing_webdriver_binaries.de.md @@ -0,0 +1,11 @@ +--- +title: "Installing WebDriver binaries" +weight: 2 +--- + +To execute your project and control the browser you need to have +browser-specific WebDriver binaries installed. + +Download the [WebDriver binary]({{< ref "/webdriver/driver_requirements.en.md#quick-reference" >}}) +supported by your browser and place it in the +[System PATH]({{< ref "/webdriver/driver_requirements.en.md#adding-executables-to-your-path" >}}). diff --git a/docs_source_files/content/support_packages/_index.de.md b/docs_source_files/content/support_packages/_index.de.md new file mode 100644 index 000000000000..fc0f09a61d44 --- /dev/null +++ b/docs_source_files/content/support_packages/_index.de.md @@ -0,0 +1,8 @@ +--- +title: "Support packages" +chapter: true +weight: 11 +--- + +# Support packages + diff --git a/docs_source_files/content/support_packages/browser_navigation.de.md b/docs_source_files/content/support_packages/browser_navigation.de.md new file mode 100644 index 000000000000..92fb0a02c42a --- /dev/null +++ b/docs_source_files/content/support_packages/browser_navigation.de.md @@ -0,0 +1,107 @@ +--- +title: "Browser navigation" +weight: 1 +--- + +There are commands for various webpage loading actions: + +{{< code-tab >}} + {{< code-panel language="java" >}} +// Navigate to a URL (both of the statements below are +// functionally equivalent). +driver.get("https://www.google.com"); +driver.navigate().to("https://www.google.com"); + +// Go forward one page in the browser (if you're not on the +// last page that was viewed). +driver.navigate().forward(); + +// Go back one page in the browser (if you're not on the +// first page that was viewed). +driver.navigate().back(); + +// Refresh the current page. +driver.navigate().refresh(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +# Navigate to a URL. +driver.get('https://www.google.com') + +# Go forward one page in the browser (if you're not on the +# last page that was viewed). +driver.forward() + +# Go back one page in the browser (if you're not on the +# first page that was viewed). +driver.back() + +# Refresh the current page. +driver.refresh() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// Navigate to a URL +driver.Navigate().GoToUrl("http://www.google.com"); + +// Go forward one page in the browser (if you're not on the +// last page that was viewed). +driver.Navigate().Forward(); + +// Go back one page in the browser (if you're not on the +// first page that was viewed). +driver.Navigate().Back(); + +// Refresh the current page. +driver.Navigate().Refresh(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# Navigate to a URL (both of the statements below are +# functionally equivalent). +driver.get('https://www.google.com') +driver.navigate.to('https://www.google.com') + +# Go forward one page in the browser (if you're not on the +# last page that was viewed). +driver.navigate.forward + +# Go back one page in the browser (if you're not on the +# first page that was viewed). +driver.navigate.back + +# Refresh the current page. +driver.navigate.refresh + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +# Navigate to a URL (both of the statements below are +# functionally equivalent). +driver.get("https://www.google.com"); +driver.navigate().to("https://www.google.com"); + +# Go forward one page in the browser (if you're not on the +# last page that was viewed). +driver.navigate().forward(); + +# Go back one page in the browser (if you're not on the +# first page that was viewed). +driver.navigate().back(); + +# Refresh the current page. +driver.navigate().refresh(); + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +// Navigate to a URL (both of the statements below are +// functionally equivalent). +driver.get("https://www.google.com") +driver.navigate().to("https://www.google.com") + +// Go forward one page in the browser (if you're not on the +// last page that was viewed). +driver.navigate().forward() + +// Go back one page in the browser (if you're not on the +// first page that was viewed). +driver.navigate().back() + +// Refresh the current page. +driver.navigate().refresh() + {{< / code-panel >}} +{{< / code-tab >}} diff --git a/docs_source_files/content/support_packages/mouse_and_keyboard_actions_in_detail.de.md b/docs_source_files/content/support_packages/mouse_and_keyboard_actions_in_detail.de.md new file mode 100644 index 000000000000..960737a1a224 --- /dev/null +++ b/docs_source_files/content/support_packages/mouse_and_keyboard_actions_in_detail.de.md @@ -0,0 +1,155 @@ +--- +title: "Mouse and keyboard actions in detail" +weight: 4 +--- + +Suppose you have an arbitrary web element **e:** + +{{< code-tab >}} + {{< code-panel language="java" >}} +WebElement e = driver.findElement(By.id("testElement")); + {{< / code-panel >}} + {{< code-panel language="python" >}} +e = driver.find_element_by_id("testElement") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +IWebElement e = driver.FindElement(By.Id("testElement")); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val element = driver.findElement(By.id("testElement")) + {{< / code-panel >}} +{{< / code-tab >}} + +You can simulate mouse clicking on e if it is visible and has a height and width +that are greater than 0: + +{{< code-tab >}} + {{< code-panel language="java" >}} +e.click(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +e.click() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +e.Click(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +e.click() + {{< / code-panel >}} +{{< / code-tab >}} + +Moreover, it is possible to mimic hovering of the cursor over **e**. In order +to do so, you will need the following import statement: + +{{< code-tab >}} + {{< code-panel language="java" >}} +import org.openqa.selenium.interactions.Actions; + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium.webdriver import ActionChains + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +using OpenQA.Selenium.Interactions; + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +import org.openqa.selenium.interactions.Actions + {{< / code-panel >}} +{{< / code-tab >}} + +With this statement in place, you can now move over the element in question: + +{{< code-tab >}} + {{< code-panel language="java" >}} +Actions actions = new Actions(driver); +actions.moveToElement(e); +actions.perform(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +actions = ActionChains(driver) +actions.move_to_element(e) +actions.perform() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} + Actions actions = new Actions(driver); + actions.MoveToElement(e); + actions.Perform(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val actions = Actions(driver) +actions.moveToElement(e); +actions.perform(); + {{< / code-panel >}} +{{< / code-tab >}} + +If **e** is an **input** or **textarea** element, the following keyboard +actions can be carried out: + +* Enter a sequence of characters in e: + +{{< code-tab >}} + {{< code-panel language="java" >}} +e.sendKeys("Test"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +e.send_keys("Test") + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +e.SendKeys("Test"); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +e.sendKeys("Test") + {{< / code-panel >}} +{{< / code-tab >}} + +* Delete the text that is in e (if there is any): + +{{< code-tab >}} + {{< code-panel language="java" >}} +e.clear(); + {{< / code-panel >}} + {{< code-panel language="python" >}} +e.clear() + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +e.Clear(); + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +# We don't have a Ruby code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +e.clear() + {{< / code-panel >}} +{{< / code-tab >}} diff --git a/docs_source_files/content/support_packages/working_with_colours.de.md b/docs_source_files/content/support_packages/working_with_colours.de.md new file mode 100644 index 000000000000..cf097990bd8e --- /dev/null +++ b/docs_source_files/content/support_packages/working_with_colours.de.md @@ -0,0 +1,229 @@ +--- +title: "Working with colours" +weight: 2 +--- + +You will occasionally want to validate the colour of something as part of your tests; +the problem is that colour definitions on the web are not constant. +Would it not be nice if there was an easy way to compare +a HEX representation of a colour with a RGB representation of a colour, +or a RGBA representation of a colour with a HSLA representation of a colour? + +Worry not. There is a solution: the _Color_ class! + +First of all, you will need to import the class: + +{{< code-tab >}} + {{< code-panel language="java" >}} +import org.openqa.selenium.support.Color; + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium.webdriver.support.color import Color + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +include Selenium::WebDriver::Support + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}}import org.openqa.selenium.support.Color{{< / code-panel >}} +{{< / code-tab >}} + +You can now start creating colour objects. +Every colour object will need to be created from a string representation of +your colour. +Supported colour representations are: + +{{< code-tab >}} + {{< code-panel language="java" >}} +private final Color HEX_COLOUR = Color.fromString("#2F7ED8"); +private final Color RGB_COLOUR = Color.fromString("rgb(255, 255, 255)"); +private final Color RGB_COLOUR = Color.fromString("rgb(40%, 20%, 40%)"); +private final Color RGBA_COLOUR = Color.fromString("rgba(255, 255, 255, 0.5)"); +private final Color RGBA_COLOUR = Color.fromString("rgba(40%, 20%, 40%, 0.5)"); +private final Color HSL_COLOUR = Color.fromString("hsl(100, 0%, 50%)"); +private final Color HSLA_COLOUR = Color.fromString("hsla(100, 0%, 50%, 0.5)"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +HEX_COLOUR = Color.from_string('#2F7ED8') +RGB_COLOUR = Color.from_string('rgb(255, 255, 255)') +RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)') +RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)') +RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)') +HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)') +HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)') + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +HEX_COLOUR = Color.from_string('#2F7ED8') +RGB_COLOUR = Color.from_string('rgb(255, 255, 255)') +RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)') +RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)') +RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)') +HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)') +HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)') + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +private val HEX_COLOUR = Color.fromString("#2F7ED8") +private val RGB_COLOUR = Color.fromString("rgb(255, 255, 255)") +private val RGB_COLOUR_PERCENT = Color.fromString("rgb(40%, 20%, 40%)") +private val RGBA_COLOUR = Color.fromString("rgba(255, 255, 255, 0.5)") +private val RGBA_COLOUR_PERCENT = Color.fromString("rgba(40%, 20%, 40%, 0.5)") +private val HSL_COLOUR = Color.fromString("hsl(100, 0%, 50%)") +private val HSLA_COLOUR = Color.fromString("hsla(100, 0%, 50%, 0.5)") + {{< / code-panel >}} +{{< / code-tab >}} + +The Color class also supports all of the base colour definitions +specified in +[http://www.w3.org/TR/css3-color/#html4](//www.w3.org/TR/css3-color/#html4). + +{{< code-tab >}} + {{< code-panel language="java" >}} +private final Color BLACK = Color.fromString("black"); +private final Color CHOCOLATE = Color.fromString("chocolate"); +private final Color HOTPINK = Color.fromString("hotpink"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +BLACK = Color.from_string('black') +CHOCOLATE = Color.from_string('chocolate') +HOTPINK = Color.from_string('hotpink') + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +BLACK = Color.from_string('black') +CHOCOLATE = Color.from_string('chocolate') +HOTPINK = Color.from_string('hotpink') + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +private val BLACK = Color.fromString("black") +private val CHOCOLATE = Color.fromString("chocolate") +private val HOTPINK = Color.fromString("hotpink") + {{< / code-panel >}} +{{< / code-tab >}} + +Sometimes browsers will return a colour value of "transparent" +if no colour has been set on an element. +The Color class also supports this: + +{{< code-tab >}} + {{< code-panel language="java" >}} +private final Color TRANSPARENT = Color.fromString("transparent"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +TRANSPARENT = Color.from_string('transparent') + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +TRANSPARENT = Color.from_string('transparent') + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +private val TRANSPARENT = Color.fromString("transparent") + {{< / code-panel >}} +{{< / code-tab >}} + +You can now safely query an element +to get its colour/background colour knowing that +any response will be correctly parsed +and converted into a valid Color object: + +{{< code-tab >}} + {{< code-panel language="java" >}} +Color loginButtonColour = driver.findElement(By.id("login")).getCssValue("color"); +Color loginButtonBackgroundColour = driver.findElement(By.id("login")).getCssValue("background-color"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +login_button_colour = driver.find_element_by_id('login').value_of_css_property('color') +login_button_background_colour = driver.find_element_by_id('login').value_of_css_property('background-color'); + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +login_button_colour = driver.find_element(id: 'login').css_value('color') +login_button_background_colour = driver.find_element(id: 'login').css_value('background-color'); + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +val loginButtonColour = driver.findElement(By.id("login")).getCssValue("color") +val loginButtonBackgroundColour = driver.findElement(By.id("login")).getCssValue("background-color") + {{< / code-panel >}} +{{< / code-tab >}} + +You can then directly compare colour objects: + + +{{< code-tab >}} + {{< code-panel language="java" >}} +assert loginButtonBackgroundColour.equals(HOTPINK); + {{< / code-panel >}} + {{< code-panel language="python" >}} +assert login_button_background_colour == HOTPINK + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +assert(login_button_background_colour == HOTPINK) + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +assert(loginButtonBackgroundColour.equals(HOTPINK)) + {{< / code-panel >}} +{{< / code-tab >}} + +Or you can convert the colour into one of the following formats +and perform a static validation: + +{{< code-tab >}} + {{< code-panel language="java" >}} +assert loginButtonBackgroundColour.asHex().equals("#ff69b4"); +assert loginButtonBackgroundColour.asRgba().equals("rgba(255, 105, 180, 1)"); +assert loginButtonBackgroundColour.asRgb().equals("rgb(255, 105, 180)"); + {{< / code-panel >}} + {{< code-panel language="python" >}} +assert login_button_background_colour.hex == '#ff69b4' +assert login_button_background_colour.rgba == 'rgba(255, 105, 180, 1)' +assert login_button_background_colour.rgb == 'rgb(255, 105, 180)' + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +// We don't have a C# code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +assert(login_button_background_colour.hex == '#ff69b4') +assert(login_button_background_colour.rgba == 'rgba(255, 105, 180, 1)') +assert(login_button_background_colour.rgb == 'rgb(255, 105, 180)') + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +assert(loginButtonBackgroundColour.asHex().equals("#ff69b4")) +assert(loginButtonBackgroundColour.asRgba().equals("rgba(255, 105, 180, 1)")) +assert(loginButtonBackgroundColour.asRgb().equals("rgb(255, 105, 180)")) + {{< / code-panel >}} +{{< / code-tab >}} + +Colours are no longer a problem. diff --git a/docs_source_files/content/support_packages/working_with_select_elements.de.md b/docs_source_files/content/support_packages/working_with_select_elements.de.md new file mode 100644 index 000000000000..0193fa04e1e0 --- /dev/null +++ b/docs_source_files/content/support_packages/working_with_select_elements.de.md @@ -0,0 +1,296 @@ +--- +title: "Working with select elements" +weight: 3 +--- + +Select elements can require quite a bit of boiler plate code to automate. +To reduce this, and make your tests cleaner, there is a +`Select` class in the Selenium support package. +To use it, you will need the following import statement: + +{{< code-tab >}} + {{< code-panel language="java" >}} +import org.openqa.selenium.support.ui.Select; + {{< / code-panel >}} + {{< code-panel language="python" >}} +from selenium.webdriver.support.select import Select + {{< / code-panel >}} + {{< code-panel language="csharp" >}} +using OpenQA.Selenium.Support.UI + {{< / code-panel >}} + {{< code-panel language="ruby" >}} +include Selenium::WebDriver::Support + {{< / code-panel >}} + {{< code-panel language="javascript" >}} +// We don't have a JavaScript code sample yet - Help us out and raise a PR + {{< / code-panel >}} + {{< code-panel language="kotlin" >}} +import org.openqa.selenium.support.ui.Select + {{< / code-panel >}} +{{< / code-tab >}} + +You are then able to create a Select object using a WebElement that +references a `` element. +First of all, there are different ways of selecting an option +from the ` + + + + +``` + +There are three ways to select the first option from the above element: + +{{< code-tab >}} + {{< code-panel language="java" >}} +// Select an