Slide 1

Slide 1 text

WebDriver Web Rebels 2012 Automating 130 browser, platform and language combinations without going insane

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

WebDriver?

Slide 4

Slide 4 text

Selenium?

Slide 5

Slide 5 text

Browser automation Watir Selenium WebDriver 2003 2004 2005 2006 2007 2008 2009 2010 2002 2011

Slide 6

Slide 6 text

Browser automation Watir Selenium WebDriver 2003 2004 2005 2006 2007 2008 2009 2010 2002 2011

Slide 7

Slide 7 text

Browser automation Watir Selenium WebDriver Selenium 2 watir-webdriver 2003 2004 2005 2006 2007 2008 2009 2010 2002 2011

Slide 8

Slide 8 text

Selenium

Slide 9

Slide 9 text

Selenium WTF!?

Slide 10

Slide 10 text

Selenium Selenium Remote Control

Slide 11

Slide 11 text

WebDriver

Slide 12

Slide 12 text

WebDriver • Selenium 2: benefit of hindsight • Language support • Browser support

Slide 13

Slide 13 text

Future • Browser automation standard • Make browser vendors care • Delete implementations from the Selenium tree

Slide 14

Slide 14 text

+ ~ ?

Slide 15

Slide 15 text

Architectural themes • Emulate the user • Prove that the drivers work • You shouldn't need to understand everything • Every API call is an RPC

Slide 16

Slide 16 text

Architectural themes • Designed to accurately emulate user interaction with a web application • Use native events where possible... • ...but make it easy to do cross-browser • API should match user interactions • e.g. no fireEvent() Emulate the user

Slide 17

Slide 17 text

Architectural themes • Extensive automated test suite • Mostly integration tests • Strong culture for adding tests when fixing bugs • Challening CI setup • 6 browsers on 3 OSes with 4 languages • 72 builds per commit Prove the drivers work

Slide 18

Slide 18 text

Architectural themes • Lots of languages / technologies in use • Architecture should allow developers to focus their talents where they'll be most productive You shouldn't need to understand how everything works

Slide 19

Slide 19 text

Architectural themes • Need to communicate with external browser process • Performance at the mercy of network latency • Introduces tension in the API design • Coarseness (== improved performance) • Expressiveness, ease of use Every API call is a RPC

Slide 20

Slide 20 text

WebDriver Internals WebDriver API WebDriver SPI wire protocol browser

Slide 21

Slide 21 text

API user facing

Slide 22

Slide 22 text

API user facing SPI implementor facing

Slide 23

Slide 23 text

API command –> { name: "findElement", parameters: { using: "name", value: "q" } } response <– { status: 0, value : } command –> { name: "sendKeys", parameters: { element: , value: ["webdriver"] } } response <– { status: 0 } SPI driver.find_element(name: 'q').send_keys('webdriver')

Slide 24

Slide 24 text

API command –> { name: "findElement", parameters: { using: "name", value: "q" } } response <– { status: 0, value : } command –> { name: "sendKeys", parameters: { element: , value: ["webdriver"] } } response <– { status: 0 } SPI driver.find_element(name: 'q').send_keys('webdriver')

Slide 25

Slide 25 text

driver.find_element(name: 'q').send_keys('webdriver') API command –> { name: "findElement", parameters: { using: "name", value: "q" } } response <– { status: 0, value : } command –> { name: "sendKeys", parameters: { element: , value: ["webdriver"] } } response <– { status: 0 } SPI

Slide 26

Slide 26 text

API object oriented SPI procedural newSession(browser: 'firefox') findElement(using: 'name', value: 'q') sendKeysToElement(id: '00cbe31e', value: ['webdriver']) getElementAttribute(id: '00cbe31e', name: 'value') driver = Selenium::WebDriver.for :firefox input = driver.find_element(name: 'q') input.send_keys('webdriver') puts input.attribute('value')

Slide 27

Slide 27 text

API object oriented, user facing SPI procedural, implementor facing

Slide 28

Slide 28 text

API SPI wire protocol browser automation atoms, native code

Slide 29

Slide 29 text

API SPI browser automation standard reference implementation wire protocol browser automation atoms, native code

Slide 30

Slide 30 text

Wire protocol • Reference implementation of the Service Provider Interface (SPI) • In spec terms, non-normative (not a requirement for implementors) • Though comes with some benefits • e.g. existing clients in multiple languages

Slide 31

Slide 31 text

Wire protocol Language binding Java Ruby C# Python JS Browser Firefox Opera Chrome IE

Slide 32

Slide 32 text

Wire protocol JSON HTTP Language binding Java Ruby C# Python JS Browser Firefox Opera Chrome IE

Slide 33

Slide 33 text

Wire protocol server client JSON HTTP Language binding Java Ruby C# Python JS Browser Firefox Opera Chrome IE

Slide 34

Slide 34 text

Wire protocol Machine A JSON HTTP Language binding Java Ruby C# Python JS Browser Firefox Opera Chrome IE

Slide 35

Slide 35 text

Wire protocol JSON HTTP Machine B Remote WebDriver Server JSON HTTP Browser Firefox Opera Chrome IE Machine A Language bindings Java Ruby Python C# JS

Slide 36

Slide 36 text

Wire protocol Selenium 2 Grid Hub JSON HTTP Grid Node JSON HTTP Language bindings Java Ruby Python C# JS Grid Node Grid Node CI server

Slide 37

Slide 37 text

Wire protocol Maps SPI commands to RESTish HTTP resources POST /session POST /session/:sessionId/element POST /session/:sessionId/element/:id/value GET /session/:sessionId/element/:id/attribute/:name newSession(browser: 'firefox') findElement(sessionId: 'c688f8e4', using: 'name', value: 'q') sendKeysToElement(id: '00cbe31e', value: ['webdriver']) getElementAttribute(id: '00cbe31e', name: 'value')

Slide 38

Slide 38 text

Wire protocol Maps SPI commands to RESTish HTTP resources POST /session POST /session/c688f8e4/element POST /session/c688f8e4/element/00cbe31e/value GET /session/c688f8e4/element/00cbe31e/attribute/value newSession(browser: 'firefox') findElement(sessionId: 'c688f8e4', using: 'name', value: 'q') sendKeysToElement(id: '00cbe31e', value: ['webdriver']) getElementAttribute(id: '00cbe31e', name: 'value')

Slide 39

Slide 39 text

Wire protocol http://code.google.com/p/selenium/wiki/JsonWireProtocol

Slide 40

Slide 40 text

Automation Atoms • Cross-browser JavaScript library • Google Closure Library + Compiler • Advanced compilation

Slide 41

Slide 41 text

Automation Atoms JavaScript Atoms (built on Google Closure Library) Google Closure Compiler Firefox extension (atoms.js) ChromeDriver (atoms.h) IE driver (atoms.h) Opera driver (OperaAtoms.java)

Slide 42

Slide 42 text

Automation Atoms /** * @param {!Element} elem The element to consider. * @return {string} visible text. */ bot.dom.getVisibleText = function(elem) { var lines = []; bot.dom.appendVisibleTextLinesFromElement_(elem, lines); lines = goog.array.map( lines, bot.dom.trimExcludingNonBreakingSpaceCharacters_); var joined = lines.join('\n'); var trimmed = bot.dom.trimExcludingNonBreakingSpaceCharacters_(joined); // Replace non-breakable spaces with regular ones. return trimmed.replace(/\xa0/g, ' '); };

Slide 43

Slide 43 text

Drivers client httpd.js wire protocol Firefox CommandProcessor JS atoms XPCOM

Slide 44

Slide 44 text

Drivers client wire protocol chromedriver mongoose.c HTTPD JS atoms Chrome Automation Proxy IPC

Slide 45

Slide 45 text

Drivers client wire protocol IEDriver.dll mongoose.c HTTPD JS atoms IE COM APIs COM

Slide 46

Slide 46 text

Drivers client wire protocol OperaDriver Jetty HTTPD JS atoms Opera Scope (protobuf)

Slide 47

Slide 47 text

Drivers client wire protocol Android Jetty HTTPD JS atoms Android APIs

Slide 48

Slide 48 text

Drivers client wire protocol iPhone CocoaHTTPServer JS atoms iOS APIs

Slide 49

Slide 49 text

Drivers WS server wire protocol (over WS) Safari WebSocket client JS atoms

Slide 50

Slide 50 text

Deep dive Goal: Implement the ability to maximize the browser window Ruby client Firefox extension Automation atoms 1 2 3

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Questions? @jarib github.com/jarib jari@finn.no

Slide 53

Slide 53 text

github.com/holderdeord beta.holderdeord.no [email protected]