Playwright vs Selenium WebDriver Syntax Comparison by Example
Raw Selenium WebDriver with Ruby Binding is much better.
Update (2022–12–26): Check out the annotated version (by my father).
In my intern role early this year, I developed a set of automated test scripts. To be exact, 29 test cases, running reliably on a daily basis. My colleagues and managers were impressed.
I started with Selenium WebDriver with Rspec first. Later, I was told to use Playwright by the department’s test automation guru (of a large telecom company). As a 20-year-old fresh-out-of-Uni intern, of course, I listened. I did the Selenium Ruby version for new test scenarios first (much easier) and then converted it to Playwright. I also set up two build projects in the BuildWise CT server to run both versions daily.
This article will show the syntax difference between Playwright and Selenium, using a simple test case (login test) as an example.
Raw Selenium (Ruby):
driver.find_element(:id, username).send_keys("agileway")
driver.find_element(:name, username).send_keys("testwise")
driver.find_element(:xpath, "//input[@value='Sign in']").click
expect(driver.find_element(:tag_name, "body").text).to include("Signed in")
Playwright (JavaScript):
await driver.fill("#username", "agileway")
await driver.fill("#password", "testwise")
await driver.click("input:has-text('Sign in')")
await driver.textContent("body").then(function(body_text) {
assert(body_text.contains("Signed in"))
})
To me, the Selenium version is better. JS programmers might disagree, read on.
While I am a programmer myself, I have learned (from my father) that scripting automated tests shall be from an end-user’s perspective. After all, the purpose of automated end-to-end (via UI) testing is to test the app as an end-user would.
After putting on an end user’s hat, you might start to appreciate the Selenium version more.
- {Selenium} ✅
driver.find_element
is used four times (in each step), once you understand that, the rest is not much. - {Selenium} ✅ element locators are clearly stated, such as
:id
,:name
,:tag_name
,xpath
. - {Playwright} ❌ what is
await
? - {Playwright} ❌ why
then
andfunction
are used here? - {Playwright} ❌ I don’t like
})
- {Playwright} 😞 The word ‘
fill
’ may have different meanings, I preferenter_text
ortype
, …
Some might say, “Playwright offers more end-user-friendly syntax”. Wrong, we are not supposed to use the raw framework steps for the end-user anyway, for any framework (reason: hard to maintain).
The solution is to use a well-known test automation pattern and a best practice: Page Object Models (POM). After verifying the test steps are working, I quickly perform refactorings based on the Maintainable Automated Test Design in TestWise, to turn the previous raw version into this
LoginPage login_page = LoginPage.new(driver)
login_page.enter_username("agileway")
login_page.enter_password("testwise")
login_page.click_sign_in
expect(page_text).to include("Signed in")
For this example, it probably takes me 15 seconds in TestWise (with refactoring support).
Astute readers will think “I can write Playwright tests like this (using POM) as well”. Exactly! So, for better readability and maintainability, an automated test script is classified into two tiers.
The top-level (DSL using POM) can be written similarly for all frameworks. This means, for the bottom level (raw framework), we care less about human readability, such as fill
, but prefer consistency and technical clarity like Selenium WebDriver’s syntax, such as find_element(:name, …)
and send_keys
.
Some might argue, a few of the problematic items are JavaScript ones, not specific to Playwright. True, why do you have to script automated tests in JavaScript? Because the app is written in JavaScript? If so, the reason does not stand. We can write automated tests in Ruby for any website. If meeting the Definition of End-to-End Test Automation Success, the choice of framework or scripting language does not matter. However, that’s a big IF, as most UI test automation attempts failed.
From Microsoft Test Guru Alan Page, coauthor of “How We Test Software at Microsoft” book
“For 95% of all software applications, automating the GUI is a waste of time. For the record, I typed 99% above first, then chickened out. I may change my mind again”
- Alan’s blog (2008)“95% of the time, 95% of test engineers will write bad GUI automation just because it’s a very difficult thing to do correctly”.
- this interview (2015)
And from Robert C. Martin, co-author of the Agile Manifesto:“Automated testing through the GUI is intuitive, seductive, and almost always wrong!”
- his blog (in 2009)
From Gerald Weinberg, a software legend:“Testing is harder than developing. If you want to have good testing you need to put your best people in testing.”
- in podcast (2018)
While the above views are all quite negative, real Automated End-to-End (via GUI) is feasible though, just hard.
1. Selenium enables Facebook’s “release twice a day”
“Facebook is released twice a day, and keeping up this pace is at the heart of our culture. With this release pace, automated testing with Selenium is crucial to making sure everything works before being released.” — DAMIEN SERENI, Engineering Director at Facebook, at Selenium 2013 conference.
2. My father’s raw Selenium/Appium (in Ruby) test suites for all his apps.
- ClinicWise (2013-)
- WhenWise (2018 — )
- TestWise ( converted from rFormSpec to Appium in 2019 — )
So, automated end-to-end testing (via UI) is not easy, don’t make it harder by using the wrong framework or language because you are simply familiar with them. Again, testing is judged by the results. If you can achieve the objective End-to-End Test Automation Success, ignore others’ comments. But if not (>99% case, according to the above experts), maybe re-examine your options.
This is just the simplest test case. The nature of JavaScript will make it more complex for longer tests. Don’t just take my word for it, here is a slide by Douglas Crockford, author of “How JavaScript works?”, a world-renowned authority on JavaScript.
According to Douglas, JS is optimized for event handling, which is not the case for scripting sequential test scripts. The new JS features made it worse (see the slide). As for the bad parts, I really don’t like using Promises and Async/Await in automated test scripts.
When people asked me “how did you develop Playwright tests so quickly?” (I made the executable results publicly available on the BuildWise CT server), I answered: “I did in raw Selenium in Ruby first”.
By the way, Selenium and Playwright are the two approved test automation frameworks in this company.