SCALATEST SELENIUM DSL
Scala days 2014 - Berlin
MATTHEW FARWELL
• Over 20 years development experience
• Project Lead on Scalastyle, style checker for Scala http://www.sc...
GOALS
• Present the Selenium DSL
• Show how it simplifies the writing of selenium tests.
• Show how it can be used to test...
SELENIUM
• Selenium automates browsers.
• Firefox, Chrome, Internet Explorer, Safari, Opera, HtmlUnit
• Selenium has inter...
EXAMPLE (JAVA)
final WebDriver driver = new FirefoxDriver();
Wait<WebDriver> wait = new WebDriverWait(driver, 30);
driver....
EXAMPLE (PYTHON)
driver = webdriver.Firefox()
driver.get("http://www.google.ch")
elem = driver.find_element_by_name("q")
e...
EXAMPLE (SCALA)
go to "http://www.google.ch/"
textField("q").value = "Farwell"
click on "btnG"
eventually {
val t = find(t...
OUR APPLICATION
• https://github.com/matthewfarwell/scaladays-2014-selenium
$ sbt
> re-start
- Run tests from Eclipse
$ sb...
A REAL TEST
val baseUrl = "http://localhost:9100/"
"slash" should "redirect to admin index.html" in {
go to baseUrl
curren...
ADDING EVENTUALLY
eventually {
find("userUsername_2").get.text should be("matthew")
}
- UserSpec2.scala
ADDING EVENTUALLY (2)
eventually {
find("pageTitle").get.text should be("Users")
textField("userSearch").value should be('...
GETTING / SETTING VALUES
go to (baseUrl + "admin/index.html#/users")
eventually {
click on "userEdit_2"
}
eventually {
val...
GETTING / SETTING VALUES
pwdField("password").value = "hello world"
pwdField("confirmPassword").value = "hello world"
find...
DEBUGGING
capture to "foo.png"
println(currentUrl)
println(pageSource)
withScreenshot {
// some stuff
// if ModifiableMess...
DEBUGGING - REPORTERS
event match {
case e: TestFailed => {
val name = e.testName
web.captureTo(s"${name}.png")
println(we...
OTHER INPUT TYPES
• textField
• pwdField
• checkBox
• radioButton
• singleSel, multiSel
• HTML5 - emailField, colorField, ...
XPATH LOOKUPS
"list" should "default to 10 items" in {
go to (baseUrl + "admin/index.html#/users")
eventually {
val xp = "...
PAGE OBJECT PATTERN
class HomePage extends Page {
val url = "localhost:9100/index.html"
}
val homePage = new HomePage
go t...
COOKIES
add cookie ("cookie_name", "cookie_value")
cookie("cookie_name").value should be ("cookie_value")
delete cookie "c...
ALERTS, FRAMES, WINDOWS
switch to alert
switch to frame(0) // switch by index
switch to frame("name") // switch by name
sw...
NAVIGATION
goBack()
goForward()
reloadPage()
JAVASCRIPT
go to (host + "index.html")
val result1 = executeScript("return document.title;")
result1 should be ("Test Titl...
INTEGRATION TESTING
// create a new user
click on "newUser"
textField("username").value = "user"
// etc.
click on "submit"...
INTEGRATION
• A lot of the time, we would like to assert something which isn't available
through the HTML front end
INTEGRATION TESTING
eventually {
val after = Services.listUsers().unmarshall
after.size should be(before.size + 1)
val u =...
MULTI-BROWSER TESTING
abstract class UserSpecBase with Driver {
// tests here
}
class UserSpecChrome extends UserSpecBase ...
OUR CONTEXT
• Lots of legacy code, partially tested with selenium in Java / Python.
• Lots of new code, which has been tes...
OUR EXPERIENCE
• DSL is good for walking through a test – clearer and more readable than the
Java equivalent
• We have tes...
WHAT WE'D LIKE TO IMPROVE
IMPLICIT EVENTUALLY
eventually {
click on "userEdit_2"
}
eventually {
textField("foo").get.value...
WHAT WE'D LIKE TO IMPROVE
SLOWING DOWN
eventually {
click on "userEdit_2"
}
eventually {
textField("foo").get.value should...
ME AGAIN
• Matthew Farwell
• Twitter: @matthewfarwell
• Blog: http://randomallsorts.blogspot.ch/
• Scalastyle: http://www....
Prochain SlideShare
Chargement dans... 5
×

Scaladays 2014 introduction to scalatest selenium dsl

2,954

Published on

Selenium is a technology used to test web sites by firing up a browser and then interacting with a web site. It can be used from a number of languages - Java, Python, Ruby. Scalatest 2.0 introduced a DSL which simplifies the writing of tests in Selenium. More importantly, it simplifies the process of reading and understanding the tests. It becomes easier to walk through a test with a semi-technical person.

We present a introduction where we test an application with heavy use of Javascript using the DSL, along with advantages and disadvantages of the approach that we took. We also look to the future to see what could be done better.

Published in: Logiciels, Technologies
0 commentaires
8 mentions J'aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Total des vues
2,954
Sur Slideshare
0
À partir des ajouts
0
Nombre d'ajouts
4
Actions
Partages
0
Téléchargements
32
Commentaires
0
J'aime
8
Ajouts 0
No embeds

No notes for slide
  • No loop – just an example
  • Find returns an Option
  • Transcript of "Scaladays 2014 introduction to scalatest selenium dsl"

    1. 1. SCALATEST SELENIUM DSL Scala days 2014 - Berlin
    2. 2. MATTHEW FARWELL • Over 20 years development experience • Project Lead on Scalastyle, style checker for Scala http://www.scalastyle.org • Contributor to various open source projects, notably Scalatest, JUnit, Scala- IDE • Co-author with Josh Suereth of "sbt in Action" http://manning.com/suereth2/ • https://github.com/matthewfarwell/scaladays-2014-selenium
    3. 3. GOALS • Present the Selenium DSL • Show how it simplifies the writing of selenium tests. • Show how it can be used to test a javascript heavy application • Show how it can be integrated with other tests to make more useful integration tests • The future, well what I would like anyway
    4. 4. SELENIUM • Selenium automates browsers. • Firefox, Chrome, Internet Explorer, Safari, Opera, HtmlUnit • Selenium has interfaces for Java, Python, Ruby, etc. • We'll be looking at from the point of view of testing • But we could use it for other stuff – automation of administration for example.
    5. 5. EXAMPLE (JAVA) final WebDriver driver = new FirefoxDriver(); Wait<WebDriver> wait = new WebDriverWait(driver, 30); driver.get("http://www.google.ch/"); driver.findElement(By.name("q")).sendKeys("Matthew Farwell"); driver.findElement(By.name("btnG")).click(); wait.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver webDriver) { return webDriver.findElement(By.id("resultStats")) != null; }}); boolean b = driver.findElement(By.tagName("body")) .getText().contains("farwell.co.uk"); System.out.println((found ? "You are famous" : "Not famous enough, sorry"));
    6. 6. EXAMPLE (PYTHON) driver = webdriver.Firefox() driver.get("http://www.google.ch") elem = driver.find_element_by_name("q") elem.send_keys("Farwell") elem.send_keys(Keys.RETURN) assert "farwell.co.uk" in driver.find_by_element_id("body")
    7. 7. EXAMPLE (SCALA) go to "http://www.google.ch/" textField("q").value = "Farwell" click on "btnG" eventually { val t = find(tagName("body")).get.text } t should include("farwell.co.uk") println("Yay, you are famous") - AmIFamousScala.scala
    8. 8. OUR APPLICATION • https://github.com/matthewfarwell/scaladays-2014-selenium $ sbt > re-start - Run tests from Eclipse $ sbt > re-start > test
    9. 9. A REAL TEST val baseUrl = "http://localhost:9100/" "slash" should "redirect to admin index.html" in { go to baseUrl currentUrl should be (baseUrl + "admin/index.html#/users") find("pageTitle").get.text should be("Users") textField("userSearch").value should be('empty) find("userUsername_2").get.text should be("matthew") } - UserSpec1.scala
    10. 10. ADDING EVENTUALLY eventually { find("userUsername_2").get.text should be("matthew") } - UserSpec2.scala
    11. 11. ADDING EVENTUALLY (2) eventually { find("pageTitle").get.text should be("Users") textField("userSearch").value should be('empty) find("userUsername_2").get.text should be("matthew") } - UserSpec2.scala
    12. 12. GETTING / SETTING VALUES go to (baseUrl + "admin/index.html#/users") eventually { click on "userEdit_2" } eventually { val tf = textField("userFullname") tf.value should be("Matthew Farwell") tf.isEnabled should be (true) } textField("userFullname").value = "Matthew Farwell is great" - UserSpec3.scala
    13. 13. GETTING / SETTING VALUES pwdField("password").value = "hello world" pwdField("confirmPassword").value = "hello world" find("error").get.text should be("Passwords do not match") - UserSpec3.scala
    14. 14. DEBUGGING capture to "foo.png" println(currentUrl) println(pageSource) withScreenshot { // some stuff // if ModifiableMessage is thrown, screenshot is taken }
    15. 15. DEBUGGING - REPORTERS event match { case e: TestFailed => { val name = e.testName web.captureTo(s"${name}.png") println(web.pageSource) } } - Common.scala
    16. 16. OTHER INPUT TYPES • textField • pwdField • checkBox • radioButton • singleSel, multiSel • HTML5 - emailField, colorField, dateField, dateTimeField, dateTimeLocalField, monthField, numberField, rangeField, searchField, telField, timeField, urlField, weekField
    17. 17. XPATH LOOKUPS "list" should "default to 10 items" in { go to (baseUrl + "admin/index.html#/users") eventually { val xp = "//tr//td[starts-with(@id, 'userUsername_')]" val tds = findAll(xpath(xp)).map(_.text).toList tds.size should be(10) } } - UserSpec5.scala
    18. 18. PAGE OBJECT PATTERN class HomePage extends Page { val url = "localhost:9100/index.html" } val homePage = new HomePage go to homePage
    19. 19. COOKIES add cookie ("cookie_name", "cookie_value") cookie("cookie_name").value should be ("cookie_value") delete cookie "cookie_name"
    20. 20. ALERTS, FRAMES, WINDOWS switch to alert switch to frame(0) // switch by index switch to frame("name") // switch by name switch to window(windowHandle) switch to activeElement switch to defaultContent
    21. 21. NAVIGATION goBack() goForward() reloadPage()
    22. 22. JAVASCRIPT go to (host + "index.html") val result1 = executeScript("return document.title;") result1 should be ("Test Title") val result2 = executeScript("return 'Hello ' + arguments[0]", "ScalaTest") result2 should be ("Hello ScalaTest")
    23. 23. INTEGRATION TESTING // create a new user click on "newUser" textField("username").value = "user" // etc. click on "submit" // how do we test that the user has been created? - UserSpec4.scala
    24. 24. INTEGRATION • A lot of the time, we would like to assert something which isn't available through the HTML front end
    25. 25. INTEGRATION TESTING eventually { val after = Services.listUsers().unmarshall after.size should be(before.size + 1) val u = after.find(_.username == "user").get u.fullName should be(Some("Mr. User")) u.id should not be (None) } - UserSpec4.scala
    26. 26. MULTI-BROWSER TESTING abstract class UserSpecBase with Driver { // tests here } class UserSpecChrome extends UserSpecBase with Chrome class UserSpecFirefox extends UserSpecBase with Firefox class UserSpecSafari extends UserSpecBase with Safari - UserSpec6.scala
    27. 27. OUR CONTEXT • Lots of legacy code, partially tested with selenium in Java / Python. • Lots of new code, which has been tested with Scalatest selenium DSL • A simple click on a web page can have effects way beyond CRUD • Selenium used for testing pure HTML, GWT, Angular JS applications
    28. 28. OUR EXPERIENCE • DSL is good for walking through a test – clearer and more readable than the Java equivalent • We have tests written by "developers" and "testers" • Consistent tests – we use Scalatest for unit tests, UI tests and integration tests. • Selenium DSL is integrated into Scalatest • Always have ids on elements • Our integration tests work with heterogeneous actions in the same test: • we can perform an action in the Browser, • then check call rest service, • then check the database, • call a command via ssh on a remote machine.
    29. 29. WHAT WE'D LIKE TO IMPROVE IMPLICIT EVENTUALLY eventually { click on "userEdit_2" } eventually { textField("foo").get.value should be ("bar") } eventually { click on "btn" } eventually { textField("baz").get.value should be ("flobble") }
    30. 30. WHAT WE'D LIKE TO IMPROVE SLOWING DOWN eventually { click on "userEdit_2" } eventually { textField("foo").get.value should be ("bar") } eventually { click on "userEdit_2" } eventually { textField("foo").get.value should be ("bar") }
    31. 31. ME AGAIN • Matthew Farwell • Twitter: @matthewfarwell • Blog: http://randomallsorts.blogspot.ch/ • Scalastyle: http://www.scalastyle.org • sbt in Action: http://manning.com/suereth2
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×