functional web tests with geb - andre steingress · functional web tests with geb andre steingress....

38
FÕÒŃÔPŎÑŇÒ PÌMŒ PÑǾPÒ PÕÑŒ PŘÕÑ Functional Web Tests with Geb Andre Steingress

Upload: others

Post on 30-May-2020

9 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑ

Functional Web Tests with GebAndre Steingress

Page 2: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑAndre Steingress

• @sternegross

• Groovy, Grails, JEE, Spring Portfolio, Android• GContracts - Design by Contract (tm) for Groovy

• http://blog.andresteingress.com• GroovyMag, JavaMagazin (German)

2

Page 3: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑFunctional Web Testing

3

Model View Controller

Domain Class JSP/GSP/Template Controller Class

Unit Test Unit/Integration Test

Page 4: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑSelenium Web Application Testing System

• tool suite for testing web applications• ThoughtWorks

• 2004: JavaScript-based Selenium Core (Jason Huggins)• 2006: Google introduces WebDriver (Simon Stewart)• 2008: Selenium & WebDriver => „Selenium 2“

4

Page 5: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑSelenium Tool Suite

• Selenium 2 (aka Selenium Web Driver)– Browser Support

• Firefox, Chrome, IE

– Pure Java• HtmlUnit http://htmlunit.sourceforge.net/

http://code.google.com/p/selenium/wiki/HtmlUnitDriver

– iOs/Android• Experimental

5

WebDriver driver = new HtmlUnitDriver();

Page 6: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑ

• Selenium 2 (aka Selenium Web Driver)– supports the WebDriver API– supports Selenium 1 Tests using WebDriver API underneath

6

Selenium Tool Suite

WebDriver driver = new FirefoxDriver();

driver.get("http://www.google.com");

WebElement element = driver.findElement(By.name("q"));element.sendKeys("Con-fess 2011");element.submit();

System.out.println("Page title is: " + driver.getTitle()); driver.quit();

Page 7: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑSelenium 2 API - Quick Overview

• All RemoteWebDriver descendants implement– JavaScriptExecutor

• executeScript(String script, Object... args)• executeAsyncScript(String script, Object... args)

– FindsById• findElementById(String using)

– FindsByName• findElementsByName(String using)

– FindsByClassName• ...

– FindsByCssSelector• ...

– FindsByLinkText– ...

7

Page 8: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑFirefoxDriver

8

Page 9: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑChromeDriver

• FirefoxDriver extends RemoteWebDriver

• FirefoxDriver works with– FirefoxCommandExecutor– FirefoxBinary

• Example

call to String getTitle()

9

Page 10: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑChromeDriver

10

public String getTitle() { return execute(„getTitle“).getValue().toString();}

WebDriver driver = new FirefoxDriver();

// ...

System.out.println("Page title is: " + driver.getTitle());

Get the current page title

Page 11: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑFirefoxDriver

11

JsonCommand commandToPopulate = nameToJson.get(command.getMethodName());

String commandStringToSend = commandToPopulate.populate(command.getParameters());socket.getOutputStream().write(fillTwoHundredWithJson(commandStringToSend));socket.getOutputStream().flush();

// ...executor.execute(command);// ...

Let‘s connect using a Firefox extension

Page 12: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑInternetExplorerDriver

12

How does InternetExplorerDriver work?

Page 13: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑInternetExplorerDriver

13

You don‘t wanna know. Trust me.

Page 14: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑIntroduction to Geb (it‘s „Jeb“)

• http://geb.codehaus.org/• https://github.com/geb/geb

• Apache 2 License

• Version (08.04.11): 0.5.1

14

Page 15: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑIntroduction to Geb

15

+ (+)

Page 16: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑIntroduction to Geb

16

+ (+)

+

JUnit3

JUnit4

Spock

EasyB

Grails

Page 17: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑGroovy

• dynamic jvm language• reducing Java „boilerplate“ code

• DSL friendliness with closures• seamless integration with Java libraries and classes

17

Page 18: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑGroovy

• dynamic jvm language• reducing Java „boilerplate“ code

• DSL friendliness with closures• seamless integration with Java libraries and classes

18

Page 19: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑGroovy

19

„A domain-specific language is a language dedicated to a particular problem domain.“

Page 20: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑ

20

DEMO

Groovy

Page 21: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑA Simple Content Test

• Content Testing„execute tests on the static content of a web page“

• e.g.: a single click on a menu item has to activate that menu item

21

Page 22: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑA Simple Content Test

22

DEMO

Page 23: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑWriting Functional Tests

• Functional Testing„execute tests on a specific functionality of the web application“

• Examples– Login– Registration– User Account Settings– Permissions– etc.

23

Page 24: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑTesting Web Forms

• Set Input Fields

• Read Input Fields

24

$('input', name: 'query').value('test')

$('input', name: 'query').value()

What about checkboxes, readio and select?

checkbox: value() is true or false

radio: value() is the radio button String value

select: value() has one or more (multi-select) String values

Page 25: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑTesting Web Forms

• Submit

25

$('input[value=Search]').click()

Page 26: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑTesting Ajax

• Browser exposes a js object reference

– implements the JavaScriptExecutor interface

– access to global JS variables

– call to JS functions– execute arbitrary JS code

• Helper methods for waiting

26

def waitFor(Double timeoutSeconds, Double intervalSeconds, Closure condition)def waitFor(Double timeoutSeconds, Closure condition)def waitFor(Closure condition)

waitFor { $("p.statusMsg").text() == "Asynchronous Operation Success!" }

Page 27: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑThe Page Object Pattern

27

// ...def menu_elements = $(“div#navigation ul li a”)// ...def active_menu_elements = menu_elements.filter(“.active”)//...def active_menu_element = active_menu_elements[0]//...

How to reuse this stuff?

• Definition

• geb.Page

„encapsulates and centralises page content structure, allowing tests to focus on behaviour.“

Page 28: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑThe Page Object Pattern

28

// ...def menu_elements = $(“div#navigation ul li a”)// ...def active_menu_elements = menu_elements.filter(“.active”)//...def active_menu_element = active_menu_elements[0]//...

How to reuse this stuff?

• Definition

• geb.Page

„encapsulates and centralises page content structure, allowing tests to focus on behaviour.“

Page 29: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑThe Page Object Pattern

29

class GebHomepage extends geb.Page {

static url = "http://geb.codehaus.org" static content = { menu_elements { $("div#navigation ul li a") } active_menu_element { $("div#navigation ul li a[class=active]", 0) // better menu_elements.filter(".active") // groovier menu_elements.find { it.hasClass("active") } } }}

Page 30: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑ

30

Browser.drive(GebHomePage) { assert active_menu_element.text() == 'Home'}

The Page Object Pattern

or

Browser.drive { to GebHomepage

assert active_menu_element.text() == 'Home'}

Page 31: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑThe Page Object Pattern

31

• Content DSL

• Inheritance

• LifeCycle Hooks– onLoad– onUnload

Page 32: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑModules

• Definition

• geb.Module

32

„Re-usable definitions of content that can be used across multiple pages.“

Page 33: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑModules

33

class ExampleModule extends Module {

static content = { button { $("input", type: "submit") } }}

class ExamplePage extends Page { static content = { theModule { module ExampleModule } }}

Module

Page

Page 34: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑModules

34

Browser.drive { to ExamplePage theModule.button.click()}

Page 35: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑCRUD Example

• https://github.com/geb/geb-example-grails

35

DEMO

Page 36: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑSummary

• Version 0.6 will be out soon :)

• Clone Geb from Github– https://github.com/geb/geb/downloads

• The Book of Geb– http://geb.codehaus.org/manual/latest/

• Grab it!

36

@Grapes([ @Grab("org.codehaus.geb:geb-core:latest.release"), @Grab("org.seleniumhq.selenium:selenium-firefox-driver:latest.release")])

Page 37: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑAny Questions?

37

Page 38: Functional Web Tests with Geb - Andre Steingress · Functional Web Tests with Geb Andre Steingress. FÕŃÒÔP&ŎÑ&ŇPÌÒ& MŒPÑǾPP&ÑÒÕŒ&PŘÑÕAndre Steingress • @sternegross

FÕÒŃÔ  PŎ  ÑŇÒP  ÌMŒPÑǾ  PÒPÕÑ  ŒPŘÕÑ

38

Thank you!

[email protected]