DEV Community

loading...
Cover image for Automation In Scala: Basic Selenium Tests

Automation In Scala: Basic Selenium Tests

Oleksandr Romanov
Passionate about engineering productivity via automation and education. Opinions are my own.
Originally published at alexromanov.github.io Updated on ・3 min read

Scala in test automation

Scala programming language provides a good mix between functional and object-oriented programming. It is used in projects, where pure functions and functional paradigms are crucial.

But how Selenium tests look like in Scala?

ScalaTest

The most widespread testing framework in Scala is ScalaTest. It provides a lot of functionality for writing unit and integration tests.

Implementation

As for the experiment, we will write a couple of UI tests for the current blog.

In order to implement the first basic tests you can follow the steps:

    libraryDependencies += "org.scalatestplus" %% "selenium-3-141" % "3.2.7.0" % "test"
    libraryDependencies += "org.scalatest" %% "scalatest-flatspec" % "3.2.7" % "test"
    libraryDependencies += "org.scalatest" %% "scalatest-shouldmatchers" % "3.2.7" % "test"
    libraryDependencies += "com.google.guava" % "guava" % "30.1.1-jre"

Enter fullscreen mode Exit fullscreen mode
  • Add pages objects. In our case, it will be all main pages for the blog: Home Page, Contact Page, About Page.
    class HomePage(implicit val driver: ChromeDriver) extends Page {
        val url = "https://alexromanov.github.io/"

        val homePageLink: String = "//a[@href=\"/\"]"
        val aboutPageLink: String = "//a[@href=\"/about/\"]"
        val contactPageLink: String = "//a[@href=\"/contact/\"]"
    }
Enter fullscreen mode Exit fullscreen mode

If you want to have an access to "go to page" functionality in tests, you can extend your page class from Page trait and add URL variable.

  • Add class with tests
    class BlogTest extends AnyFlatSpec with BeforeAndAfterAll with Matchers with Eventually with WebBrowser {

        implicit val webDriver: ChromeDriver = {
            System.setProperty("webdriver.chrome.driver", "C:\\tools\\chromedriver_win32\\chromedriver.exe")
            new ChromeDriver()
        }

        "User" should "be able to view latest blog post" in {
            val homePage = new HomePage
            go to homePage

            val posts = findAll(CssSelectorQuery("div.post-preview")).toList
            posts should have size 5

            val latestPost = posts.head
            latestPost.text should not be empty
        }

        "User" should "be able to open Contact Page" in {
            val homePage = new HomePage
            go to homePage
            homePage.url should equal (currentUrl)

            click on xpath(homePage.contactPageLink)
            eventually {
                currentUrl != homePage.url
            }

            val contactPage = new ContactPage
            contactPage.url should equal (currentUrl)
        }

        "User" should "be able to send message to author" in {
            val contactPage = new ContactPage
            go to contactPage
            contactPage.url should be (currentUrl)

            textField(contactPage.nameField).value = "Reader"

            click on id(contactPage.emailField)
            enter("reader@mail.com")

            click on id(contactPage.phoneField)
            enter( "123456789")

            textArea(contactPage.messageField).value = "Hello Author"

            click on cssSelector(contactPage.sendButton)
        }

        override def afterAll(): Unit = {
            quit()
        }
    }
Enter fullscreen mode Exit fullscreen mode

For tests we use AnyFlatSpec and Should Matchers. It allows us to write assertions in a readable format with the Should keyword.

ScalaTest-Selenium provides a very nice wrapper against WebDriver. You just need to add WebBrowser trait. As a result, you will have methods such as "click on id()", "enter()", "close()", etc.

It also defines Webdriver instance as implicit value - so you don't need to pass driver whenever it is used (in tests or pages).

For adding an additional before and after logic we need to add the BeforeAndAfterAll trait and override desired methods. In our case, the afterAll() method is overridden - it will quit the driver after tests are finished.

Conclusion

As you can see, UI tests in Scala are very close to human-readable format with using Should matches and scalatest-selenium traits.

ScalaTest-Selenium provides a nice wrapper of WebDriver, but it is not extensible at first sight. Maybe, it will require a complete framework re-write.

But for simple UI tests, it is more than enough.

In the next articles, we will see even more interesting use cases of using Scala in test automation (also with Selenium)

Full code samples can be found at src/test/scala/ui package in code samples.

Discussion (0)