Scaladays 2014 introduction to scalatest selenium dsl
-
Upload
matthew-farwell -
Category
Software
-
view
887 -
download
1
description
Transcript of Scaladays 2014 introduction to scalatest selenium dsl
SCALATEST SELENIUM DSLScala days 2014 - Berlin
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
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
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.
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"));
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")
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
OUR APPLICATION• https://github.com/matthewfarwell/scaladays-2014-selenium
$ sbt> re-start- Run tests from Eclipse
$ sbt> re-start> test
A REAL TESTval 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
ADDING EVENTUALLYeventually { 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('empty)
find("userUsername_2").get.text should be("matthew")}
- UserSpec2.scala
GETTING / SETTING VALUESgo 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
GETTING / SETTING VALUESpwdField("password").value = "hello world"
pwdField("confirmPassword").value = "hello world"
find("error").get.text should be("Passwords do not match")
- UserSpec3.scala
DEBUGGINGcapture to "foo.png"
println(currentUrl)
println(pageSource)
withScreenshot { // some stuff // if ModifiableMessage is thrown, screenshot is taken}
DEBUGGING - REPORTERSevent match { case e: TestFailed => { val name = e.testName web.captureTo(s"${name}.png") println(web.pageSource) }}
- Common.scala
OTHER INPUT TYPES• textField• pwdField• checkBox• radioButton• singleSel, multiSel
• HTML5 - emailField, colorField, dateField, dateTimeField, dateTimeLocalField, monthField, numberField, rangeField, searchField, telField, timeField, urlField, weekField
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
PAGE OBJECT PATTERNclass HomePage extends Page { val url = "localhost:9100/index.html"}
val homePage = new HomePage
go to homePage
COOKIESadd cookie ("cookie_name", "cookie_value")
cookie("cookie_name").value should be ("cookie_value")
delete cookie "cookie_name"
ALERTS, FRAMES, WINDOWSswitch to alert
switch to frame(0) // switch by indexswitch to frame("name") // switch by name
switch to window(windowHandle)
switch to activeElementswitch to defaultContent
NAVIGATIONgoBack()
goForward()
reloadPage()
JAVASCRIPTgo 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")
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
INTEGRATION• A lot of the time, we would like to assert something which isn't available
through the HTML front end
INTEGRATION TESTINGeventually { 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
MULTI-BROWSER TESTINGabstract 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
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
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.
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")}
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")}
ME AGAIN• Matthew Farwell
• Twitter: @matthewfarwell
• Blog: http://randomallsorts.blogspot.ch/
• Scalastyle: http://www.scalastyle.org
• sbt in Action: http://manning.com/suereth2