Scala, WebDriver and the Page Object Pattern
We’re using WebDriver on my project to automate our functional tests and as a result are using the Page Object pattern to encapsulate each page of the application in our tests.
We’ve been trying to work out how to effectively reuse code since some of the pages have parts of them which work exactly the same as another page.
For example we had a test similar to this…
class FooPageTests extends Spec with ShouldMatchers with FooPageSteps {
it("is my dummy test") {
...
then(iShouldNotSeeAnyCommonLinks())
}
}
…where FooPageSteps extends CommonSteps which contains the common assertions:
trait FooPageSteps extends CommonSteps {
override val page = new FooPage(driver)
}
trait CommonSteps {
val page : FooPage
val driver: HtmlUnitDriver
def iShouldNotSeeAnyCommonLinks() {
page.allCommonLinks.isEmpty should equal(true)
}
}
FooPage looks like this:
class FooPage(override val driver:WebDriver) extends Page(driver) with CommonSection {
}
abstract class Page(val driver: WebDriver) {
def title(): String = driver.getTitle;
}
trait CommonSection {
val driver:WebDriver
def allCommonLinks:Seq[String] = driver.findElements(By.cssSelector(".common-links li")).map(_.getText)
}
We wanted to reuse CommonSteps for another page like so:
trait BarPageSteps extends CommonSteps {
override val page = new BarPage(driver)
}
class BarPage(override val driver:WebDriver) extends Page(driver) with CommonSection {
}
But that means that we need to change the type of page in CommonSteps to make it a bit more generic so it will work for BarPageSteps too.
Making it of type Page is not enough since we still need to be able to call the allCommonLinks which is mixed into FooPage by CommonSection.
We therefore end up with the following:
trait CommonSteps {
val page : Page with CommonSection
val driver: HtmlUnitDriver
def iShouldNotSeeAnyCommonLinks() {
page.allCommonLinks.isEmpty should equal(true)
}
}
We’re able to mix in CommonSection just for this instance of Page which works pretty well for allowing us to achieve code reuse in this case!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.