Extend Function Behaviour with Optional Parameters in Automated E2E Scripts
Without breaking existing test scripts
In the article “Using Default Parameter Values in Automated E2E Test Scripts with Ruby,” I discussed how to leverage function default parameter values in E2E test scripts. Here, I will showcase a specific (and simple) technique for extending functions that my father taught me — one that is both practical and frequently used.
In E2E scripting, following Maintainable Automated Test Design, we define reusable helper functions and page functions (in POM).
These two functional test design patterns are applicable to nearly any programming language; here, I demonstrate them using the Ruby language.
1. Reusable helper functions
Example:
def login(username, password)
driver.find_element(:id, "username").sendkeys(username)
driver.find_element(:id, "password").sendkeys(password)
driver.find_element(:input, "//input[@value='Sign in']").click
end
2. Page Functions (in page object model)
Example:
it "User can enter passenger details" do
sign_in("agileway", "testwise")
flight_page = FlightPage.new(driver)
flight_page.select_oneway_trip
flight_page.select_from_city("Sydney")
flight_page.select_to_city("New York")
flight_page.click_continue
passenger_page = PassengerPage.new(driver)
passenger_page.enter_first_name("Bob")
passenger_page.enter_last_name("Tester")
passenger_page.click_next
expect(driver.find_element(:name, "holder_name")["value"]).to eq("Bob Tester")
end
Along the way, we often found the need to extend those functions. For instance, add checking “remember me” in the login function.
def login(username, password)
driver.find_element(:id, "username").sendkeys(username)
driver.find_element(:id, "password").sendkeys(password)
driver.find_element(:input, "//input[@value='Sign in']").click
end
def login_with_remember_me(username, password)
driver.find_element(:id, "username").sendkeys(username)
driver.find_element(:id, "password").sendkeys(password)
driver.find_element(:id, "remember_me").click # optional
driver.find_element(:input, "//input[@value='Sign in']").click
end
The reasoning behind creating a separate login_with_remember_me
function: keep the old login
function unchanged, as it is used in many test scripts.
The above implementation is flawed because it violates the DRY (Don’t Repeat Yourself) principle, resulting in maintenance issues.
A good solution is to add an optional parameter to the login
function.
def login(username, password, remember_me = false)
driver.find_element(:id, "username").sendkeys(username)
driver.find_element(:id, "password").sendkeys(password)
if remember_me
driver.find_element(:id, "remember_me").click
end
driver.find_element(:input, "//input[@value='Sign in']").click
end
Yes, the above works, but it’s not optimal. Why? Two reasons:
1. The test script is less readable.
login("agileway", "testwise") # old way, still works. ✓
# ...
login("agileway", "testwise", true) # check the remember me
The second one is not good, end users will puzzle, “What does true mean here?”
2. Hard to extend further.
Imagine the website now added two radio buttons for “customer login” and “staff login”. The test script may end up like below:
login("agileway", "testwise", false, true) # staff login, without remember me
It works, but is not good.
My father’s solution
Keep reading with a 7-day free trial
Subscribe to The Agile Way to keep reading this post and get 7 days of free access to the full post archives.