User Input - Filling In Forms,Moving Between Windows and Frames
2012-10-15 18:00
330 查看
User Input - Filling In Forms
We’ve already seen how to enter text into a textarea or text field, but what about the other elements? You can “toggle” the state of checkboxes, and you can use “click” to set something like an OPTION tag selected. Dealing with SELECTtags isn’t too bad:
WebElement select = driver.findElement(By.tagName("select")); List<WebElement> allOptions = select.findElements(By.tagName("option")); for (WebElement option : allOptions) { System.out.println(String.format("Value is: %s", option.getAttribute("value"))); option.click(); }
IWebElement select = driver.FindElement(By.TagName("select")); IList<IWebElement> allOptions = select.FindElements(By.TagName("option")); foreach (IWebElement option in allOptions) { System.Console.WriteLine("Value is: " + option.GetAttribute("value")); option.Click(); }
select = driver.find_element(:tag_name, "select") all_options = select.find_elements(:tag_name, "option") all_options.each do |option| puts "Value is: " + option.attribute("value") option.click end
select = driver.find_element_by_tag_name("select") allOptions = select.find_elements_by_tag_name("option") for option in allOptions: print "Value is: " + option.get_attribute("value") option.click()
This will find the first “SELECT” element on the page, and cycle through each of its OPTIONs in turn, printing out their values, and selecting each in turn. As you will notice, this isn’t the most efficient way of dealing with SELECT
elements. WebDriver’s support classes include one called “Select”, which provides useful methods for interacting with these.
Select select = new Select(driver.findElement(By.tagName("select"))); select.deselectAll(); select.selectByVisibleText("Edam");
SelectElement select = new SelectElement(driver.FindElement(By.TagName("select"))); select.DeselectAll(); select.SelectByText("Edam");
# available since 2.14 select = Selenium::WebDriver::Support::Select.new(driver.find_element(:tag_name, "select")) select.deselect_all() select.select_by(:text, "Edam")
# available since 2.12 from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_tag_name("select")) select.deselect_all() select.select_by_visible_text("Edam")
This will deselect all OPTIONs from the first SELECT on the page, and then select the OPTION with the displayed text of “Edam”.
Once you’ve finished filling out the form, you probably want to submit it. One way to do this would be to find the “submit” button and click it:
driver.findElement(By.id("submit")).click();
driver.find_element(:id, "submit").click
driver.find_element_by_id("submit").click()
Alternatively, WebDriver has the convenience method “submit” on every element. If you call this on an element within a form, WebDriver will walk up the DOM until it finds the enclosing form and then calls submit on that. If the element
isn’t in a form, then theNoSuchElementException will be thrown:
element.submit();
element.submit
element.submit()
Moving Between Windows and Frames
Some web applications have many frames or multiple windows. WebDriver supports moving between named windows using the “switchTo” method:driver.switchTo().window("windowName");
driver.switch_to_window("windowName")
All calls to driver will now be interpreted as being directed to the particular window. But how do you know the window’s name? Take a look at the javascript or link that opened it:
<a href="somewhere.html" target="windowName">Click here to open a new window</a>
Alternatively, you can pass a “window handle” to the “switchTo().window()” method. Knowing this, it’s possible to iterate over every open window like so:
for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); }
driver.window_handles.each do |handle| driver.switch_to.window handle end
for handle in driver.window_handles: driver.switch_to_window(handle)
You can also switch from frame to frame (or into iframes):
driver.switchTo().frame("frameName");
driver.switch_to_frame("frameName")
It’s possible to access subframes by separating the path with a dot, and you can specify the frame by its index too. That is:
driver.switchTo().frame("frameName.0.child");
driver.switch_to_frame("frameName.0.child")
would go to the frame named “child” of the first subframe of the frame called “frameName”.All frames are evaluated as if from *top*.
Popup Dialogs
Starting with Selenium 2.0 beta 1, there is built in support for handling popup dialog boxes. After you’ve triggered an action that opens a popup, you can access the alert with the following:Alert alert = driver.switchTo().alert();
alert = driver.switch_to.alert
alert = driver.switch_to_alert() # usage: alert.dismiss(), etc.
This will return the currently open alert object. With this object you can now accept, dismiss, read its contents or even type into a prompt. This interface works equally well on alerts, confirms, and prompts. Refer to the JavaDocs or RubyDocs for
more information.
Navigation: History and Location
Earlier, we covered navigating to a page using the “get” command (driver.get("http://www.example.com")) As you’ve seen, WebDriver has a number of smaller, task-focused interfaces, and navigation isa useful task. Because loading a page is such a fundamental requirement, the method to do this lives on the main WebDriver interface, but it’s simply a synonym to:
driver.navigate().to("http://www.example.com");
driver.navigate.to "http://www.example.com"
driver.get("http://www.example.com") # python doesn't have driver.navigate
To reiterate: “navigate().to()” and “get()” do exactly the same thing. One’s just a lot easier to type than the other!
The “navigate” interface also exposes the ability to move backwards and forwards in your browser’s history:
driver.navigate().forward(); driver.navigate().back();
driver.navigate.forward driver.navigate.back
driver.forward() driver.back()
Please be aware that this functionality depends entirely on the underlying browser. It’s just possible that something unexpected may happen when you call these methods if you’re used to the behaviour of one browser over another.
Cookies
Before we leave these next steps, you may be interested in understanding how to use cookies. First of all, you need to be on the domain that the cookie will be valid for. If you are trying to preset cookies before you start interactingwith a site and your homepage is large / takes a while to load an alternative is to find a smaller page on the site, typically the 404 page is small (http://example.com/some404page)
// Go to the correct domain driver.get("http://www.example.com"); // Now set the cookie. This one's valid for the entire domain Cookie cookie = new Cookie("key", "value"); driver.manage().addCookie(cookie); // And now output all the available cookies for the current URL Set<Cookie> allCookies = driver.manage().getCookies(); for (Cookie loadedCookie : allCookies) { System.out.println(String.format("%s -> %s", loadedCookie.getName(), loadedCookie.getValue())); } // You can delete cookies in 3 ways // By name driver.manage().deleteCookieNamed("CookieName"); // By Cookie driver.manage().deleteCookie(loadedCookie); // Or all of them driver.manage().deleteAllCookies();
# Go to the correct domain driver.get("http://www.example.com") # Now set the cookie. Here's one for the entire domain # the cookie name here is 'key' and it's value is 'value' driver.add_cookie({'name':'key', 'value':'value', 'path':'/'}) # additional keys that can be passed in are: # 'domain' -> String, # 'secure' -> Boolean, # 'expiry' -> Milliseconds since the Epoch it should expire. # And now output all the available cookies for the current URL for cookie in driver.get_cookies(): print "%s -> %s" % (cookie['name'], cookie['value']) # You can delete cookies in 2 ways # By name driver.delete_cookie("CookieName") # Or all of them driver.delete_all_cookies()
# Go to the correct domain driver.get "http://www.example.com" # Now set the cookie. Here's one for the entire domain # the cookie name here is 'key' and it's value is 'value' driver.manage.add_cookie(:name => 'key', :value => 'value') # additional keys that can be passed in are: # :path => String, :secure -> Boolean, :expires -> Time, DateTime, or seconds since epoch # And now output all the available cookies for the current URL driver.manage.all_cookies.each { |cookie| puts "#{cookie[:name]} => #{cookie[:value]}" } # You can delete cookies in 2 ways # By name driver.manage.delete_cookie("CookieName") # Or all of them driver.manage.delete_all_cookies
Changing the User Agent
This is easy with the Firefox Driver:FirefoxProfile profile = new FirefoxProfile(); profile.addAdditionalPreference("general.useragent.override", "some UA string"); WebDriver driver = new FirefoxDriver(profile);
profile = Selenium::WebDriver::Firefox::Profile.new profile['general.useragent.override'] = "some UA string" driver = Selenium::WebDriver.for :firefox, :profile => profile
Drag And Drop
Here’s an example of using the Actions class to perform a drag and drop. Native events are required to be enabled.WebElement element = driver.findElement(By.name("source")); WebElement target = driver.findElement(By.name("target")); (new Actions(driver)).dragAndDrop(element, target).perform();
element = driver.find_element(:name => 'source') target = driver.find_element(:name => 'target') driver.action.drag_and_drop(element, target).perform
from selenium.webdriver.common.action_chains import ActionChains element = driver.find_element_by_name("source") target = driver.find_element_by_name("target") ActionChains(driver).drag_and_drop(element, target).perform()
Driver Specifics and Tradeoffs
Selenium-WebDriver’s Drivers
WebDriver is the name of the key interface against which tests should be written, but there are several implementations. These include:
HtmlUnit Driver
This is currently the fastest and most lightweight implementation of WebDriver. As the name suggests, this is based on HtmlUnit. HtmlUnit is a java based implementation of a WebBrowser without a GUI. For any language binding (otherthan java) the Selenium Server is required to use this driver.
Usage
WebDriver driver = new HtmlUnitDriver();
IWebDriver driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), DesiredCapabilities.HtmlUnit());
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNIT)
driver = Selenium::WebDriver.for :remote, :url => "http://localhost:4444/wd/hub", :desired_capabilities => :htmlunit
Pros
Fastest implementation of WebDriverA pure Java solution and so it is platform independent.
Supports JavaScript
Cons
Emulates other browsers’ JavaScript behaviour (see below)
JavaScript in the HtmlUnit Driver
None of the popular browsers uses the JavaScript engine used by HtmlUnit (Rhino). If you test JavaScript using HtmlUnit the results may differ significantly from those browsers.When we say “JavaScript” we actually mean “JavaScript and the DOM”. Although the DOM is defined by the W3C each browser has its own quirks and differences in their implementation of the DOM and in how JavaScript interacts with it.
HtmlUnit has an impressively complete implementation of the DOM and has good support for using JavaScript, but it is no different from any other browser: it has its own quirks and differences from both the W3C standard and the DOM implementations of the major
browsers, despite its ability to mimic other browsers.
With WebDriver, we had to make a choice; do we enable HtmlUnit’s JavaScript capabilities and run the risk of teams running into problems that only manifest themselves there, or do we leave JavaScript disabled, knowing that there are
more and more sites that rely on JavaScript? We took the conservative approach, and by default have disabled support when we use HtmlUnit. With each release of both WebDriver and HtmlUnit, we reassess this decision: we hope to enable JavaScript by default
on the HtmlUnit at some point.
Enabling JavaScript
If you can’t wait, enabling JavaScript support is very easy:HtmlUnitDriver driver = new HtmlUnitDriver(true);
WebDriver driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4444/wd/hub"), DesiredCapabilities.HtmlUnitWithJavaScript());
caps = Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true) driver = Selenium::WebDriver.for :remote, :url => "http://localhost:4444/wd/hub", :desired_capabilities => caps
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)
This will cause the HtmlUnit Driver to emulate Firefox 3.6’s JavaScript handling by default.
Firefox Driver
Controls the Firefox browser using a Firefox plugin. The Firefox Profile that is used isstripped down from what is installed on the machine to only include the Selenium WebDriver.xpi (plugin). A few settings are also changed by default (see
the source to see which ones) Firefox Driver is capable of being run and is tested on Windows, Mac, Linux. Currently on versions 3.6, 10, latest - 1, latest
Usage
WebDriver driver = new FirefoxDriver();
IWebDriver driver = new FirefoxDriver();
driver = webdriver.Firefox()
driver = Selenium::WebDriver.for :firefox
Pros
Runs in a real browser and supports JavaScriptFaster than the Internet Explorer Driver
Cons
Slower than the HtmlUnit Driver
Modifying the Firefox Profile
Suppose that you wanted to modify the user agent string (as above), but you’ve got a tricked out Firefox profile that contains dozens of useful extensions. There are two ways to obtain this profile. Assuming that the profile has beencreated using Firefox’s profile manager (firefox -ProfileManager):
ProfileIni allProfiles = new ProfilesIni(); FirefoxProfile profile = allProfiles.getProfile("WebDriver"); profile.setPreferences("foo.bar", 23); WebDriver driver = new FirefoxDriver(profile);
Alternatively, if the profile isn’t already registered with Firefox:
File profileDir = new File("path/to/top/level/of/profile"); FirefoxProfile profile = new FirefoxProfile(profileDir); profile.addAdditionalPreferences(extraPrefs); WebDriver driver = new FirefoxDriver(profile);
As we develop features in the Firefox Driver, we expose
the ability to use them. For example, until we feel native events are stable on Firefox for Linux, they are disabled by default. To enable them:
FirefoxProfile profile = new FirefoxProfile(); profile.setEnableNativeEvents(true); WebDriver driver = new FirefoxDriver(profile);
profile = webdriver.FirefoxProfile() profile.native_events_enabled = True driver = webdriver.Firefox(profile)
profile = Selenium::WebDriver::Firefox::Profile.new profile.native_events = true driver = Selenium::WebDriver.for :firefox, :profile => profile
Info
See the Firefox section in the wiki page for themost up to date info.
Internet Explorer Driver
This driver is controlled by a .dll and is thus only available on Windows OS. Each Selenium release has it’s core functionality tested against versions 6, 7 and 8 on XP, and 9 on Windows7.
Usage
WebDriver driver = new InternetExplorerDriver();
IWebDriver driver = new InternetExlorerDriver();
driver = webdriver.Ie()
driver = Selenium::WebDriver.for :ie
Pros
Runs in a real browser and supports JavaScript with all the quirks your end users see.
Cons
Obviously the Internet Explorer Driver willonly work on Windows!
Comparatively slow (though still pretty snappy :)
XPath is not natively supported in most versions. Sizzle is injected automatically which is significantly slower than other browsers and slower when comparing to CSS selectors in the same browser.
CSS is not natively supported in versions 6 and 7. Sizzle is injected instead.
CSS selectors in IE 8 and 9 are native, but those browsers don’t fully support CSS3
Info
See the Internet Explorer section of thewiki page for the most up to date info. Please take special note of the Required Configuration section.
Chrome Driver
Chrome Driver is maintained / supported by the Chromium project iteslf.WebDriver works with Chrome through the chromedriver binary (found on the chromium project’s download page). You need to have both chromedriver and a version of chrome browser installed. chromedriver needs to be placed somewhere on your system’s path in order
for WebDriver to automatically discover it. The Chrome browser itself is discovered by chromedriver in the default installation path. These both can be overridden by environment variables. Please refer to the
wiki for more information.
Usage
WebDriver driver = new ChromeDriver();
IWebDriver driver = new ChromeDriver();
driver = webdriver.Chrome()
driver = Selenium::WebDriver.for :chrome
Pros
Runs in a real browser and supports JavaScriptBecause Chrome is a Webkit-based browser, the Chrome
Driver may allow you to verify that your site works in Safari. Note that since Chrome uses its own V8 JavaScript engine rather than Safari’s Nitro engine, JavaScript execution may differ.
Cons
Slower than the HtmlUnit Driver
Info
See our wiki for the most up to date info. Moreinfo can also be found on the downloads page
Getting running with Chrome Driver
Download the Chrome Driver executable and followthe other instructions on the wiki page
Opera Driver
See the Opera Driver wiki article in theSelenium Wiki for information on using the Opera Driver.
iPhone Driver
See the iPhone Driver wiki article in the SeleniumWiki for information on using the Mac iOS Driver.
Android Driver
See the Android Driver wiki article in the SeleniumWiki for information on using the Android Driver.
Alternative Back-Ends: Mixing WebDriver and RC Technologies
WebDriver-Backed Selenium-RC
The Java version of WebDriver provides an implementation of the Selenium-RC API. These means that you can use the underlying WebDriver technology using the Selenium-RC API. This is primarily provided for backwards compatibility. Itallows those who have existing test suites using the Selenium-RC API to use WebDriver under the covers. It’s provided to help ease the migration path to Selenium-WebDriver. Also, this allows one to use both APIs, side-by-side, in the same test code.
Selenium-WebDriver is used like this:
// You may use any WebDriver implementation. Firefox is used here as an example
WebDriver driver = new FirefoxDriver();
// A "base url", used by selenium to resolve relative URLs
String baseUrl = "http://www.google.com";
// Create the Selenium implementation
Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);
// Perform actions with selenium
selenium.open("http://www.google.com");
selenium.type("name=q", "cheese");
selenium.click("name=btnG");
// Get the underlying WebDriver implementation back. This will refer to the
// same WebDriver instance as the "driver" variable above.
WebDriver driverInstance = ((WebDriverBackedSelenium) selenium).getWrappedDriver();
//Finally, close the browser. Call stop on the WebDriverBackedSelenium instance
//instead of calling driver.quit(). Otherwise, the JVM will continue running after
//the browser has been closed.
selenium.stop();
Pros
Allows for the WebDriver and Selenium APIs to live side-by-sideProvides a simple mechanism for a managed migration from the Selenium RC API to WebDriver’s
Does not require the standalone Selenium RC server to be run
Cons
Does not implement every methodMore advanced Selenium usage (using “browserbot” or other built-in JavaScript methods from Selenium Core) may not work
Some methods may be slower due to underlying implementation differences
Backing WebDriver with Selenium
WebDriver doesn’t support as many browsers as Selenium RC does, so in order to provide that support while still using the WebDriver API, you can make use of theSeleneseCommandExecutorSafari is supported in this way with the following code (be sure to disable pop-up blocking):
DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setBrowserName("safari"); CommandExecutor executor = new SeleneseCommandExecutor(new URL("http://localhost:4444/"), new URL("http://www.google.com/"), capabilities); WebDriver driver = new RemoteWebDriver(executor, capabilities);
There are currently some major limitations with this approach, notably that findElements doesn’t work as expected. Also, because we’re using Selenium Core for the heavy lifting of driving the browser, you are limited by the JavaScript
sandbox.
Running Standalone Selenium Server for use with RemoteDrivers
From Selenium’s Download page download selenium-server-standalone-<version>.jarand optionally IEDriverServer. If you plan to work with Chrome, download it from Google Code.
Unpack IEDriverServer and/or chromedriver and put them in a directory which is on the $PATH / %PATH% - the Selenium Server should then be able to handle requests for IE / Chrome without additional modifications.
Start the server on the command line with
java -jar <path_to>/selenium-server-standalone-<version>.jar
If you want to use native events functionality, indicate this on the command line with the option
-Dwebdriver.enable.native.events=1
For other command line options, execute
java -jar <path_to>/selenium-server-standalone-<version>.jar -help
In order to function properly, the following ports should be allowed incoming TCP connections: 4444, 7054-5 (or twice as many ports as the number of concurrent instances you plan to run). Under Windows, you may need to unblock the
applications as well.
Additional Resources
You can find further resources for WebDriver in WebDriver’swiki
Of course, don’t hesitate to do an internet search on any Selenium topic, including Selenium-WebDriver’s drivers. There are quite a few blogs on Selenium along with numerous posts on various user forums. Additionally the Selenium User’s
Group is a great resource.http://groups.google.com/group/selenium-users
Next Steps
This chapter has simply been a high level walkthrough of WebDriver and some of its key capabilities. Once getting familiar with the Selenium-WebDriver API you will then want to learn how to build test suites for maintainability, extensibility,and reduced fragility when features of the AUT frequently change. The approach most Selenium experts are now recommending is to design your test code using the Page Object Design Pattern along with possibly a Page Factory. Selenium-WebDriver provides support
for this by supplying a PageFactory class in Java and C#. This is presented,along with other advanced topics, in the next
chapter. Also, for high-level description of this technique, you may want to look at the Test
Design Considerations chapter. Both of these chapters present techniques for writing more maintainable tests by making your test code more modular.
相关文章推荐
- Create Custom Modal Dialog Windows For User Input In Oracle Forms
- Interaction between services and applications at user level in Windows Vista
- Synchronize the folders between Windows and Ubuntu in VirtualBox
- Pro .NET 2.0 Windows Forms and Custom Controls in C#
- Switch between Server Core mode and Server GUI mode in Windows Server 2012 R2
- IUIs and Web-Style Navigation in Windows Forms, Part 2
- Managing Processes and Threads in Windows Forms
- Walking Through Avalon and Windows Forms Interoperability in Code
- DataGridView in Windows Forms – Tips, Tricks and Frequently Asked Questions(FAQ)
- hide the task bar and input panel in Windows Mobile
- DataGridView in Windows Forms – Tips, Tricks and Frequently Asked Questions(FAQ)
- Margin and Padding in Windows Forms Controls
- DataGridView in Windows Forms – Tips, Tricks and Frequently Asked Questions(FAQ)
- Diffrence between Stored Procedure and User Define Function in SQL
- DataGridView in Windows Forms – Tips, Tricks and Frequently Asked Questions(FAQ)
- Security and Versioning Models in the Windows Forms Engine Help You Create and Deploy Smart Clients
- DataGridView in Windows Forms – Tips, Tricks and Frequently Asked Questions(FAQ)
- Pro .NET 2.0 Windows Forms and Custom Controls in VB 2005
- A guide to using Paneled Forms, Multi-Splash Screens, SQL Express, and many more in Windows Application Development
- Mixing Forms and Windows Security in ASP.NET