0 votes
1 view
in Devops and Agile by (15.5k points)

With Test Automation's Page Object Model we link pages together like this:

WebDriver driver = new WebDriver()

HomePage homePage = new HomePage(driver);

LoginPage loginPage = homePage.GoToLoginPage();

WelcomePage welcomePage = loginPage.Login();

etc

etc

The big benefit of this is if the Devs change the homepage so it no longer links to the login page, I can update my homepage class and see all the tests I need to update (with errors) before even running a test.

With Gherkin, however, each row above would form a separate 'Step' and therefore a separate method. Therefore, how can this linking be done?

Is the only way to place instances of the page object classes (e.g. homePage, login page, etc) into a cross gherkin statement persistent store (e.g. like a specflow POCO or 'World')?

1 Answer

0 votes
by (43.1k points)

When it comes to most websites (where URLs can be used), in my opinion, it is best practice to simply use the URL instead of action to get to that same URL.

For instance:

# Suggested by OP:

driver = Selenium::Webdriver.for :chrome, prefs: prefs

homepage = Homepage.new(driver)

login = homepage.go_to_login

welcome = login.log_in_as('dave4429')

 

# My Suggestion:

homepage = Url.new('/')

login = Url.new('/login')

welcome = Url.new('/welcome')

This means that you start from a URL instead of having to start at the homepage for every test. You would still have the methods that you suggested, but they would be used in other areas, in order to make sure that the user can access the page through means other than the URL.

However, this is not a one-stop-shop solution. With mobile and desktop applications, your only option may be to go through the home screen, in which case, the method you suggested is definitely the one to go for.

"Page objects themselves should never make verifications or assertions. This is part of your test and should always be within the test’s code, never in a page object."

The example I gave was a very basic one, and I would most likely wrap these into modules and classes, to enable coding like this:

google = Project::Pages::Google.new

google.search_for('Hello, World!')

expect(google.found_result?).to_equal(true)

Edit#1

In addition to this, you seem to have a misconception about how Cucumber works with Gherkin.

You can have multiple lines of code per step, as the step itself is a description of the actions within the step.

For instance:

Given I am logged in as "XYZ123"

When I submit the "Contact Us" form with the following data:

   | XYZ123@example.com | XYZ Peter | I want to find out more about your Data Protection services, can I talk to a staff member or get a PDF? | Then an email should be sent to "support@example.com" with the details specified

The definition for the "When" may look like this:

When(/^I have submitted the "Contact Us" form with the following data:$/) do |table|

  rows = table.raw

  row = rows[0]

 

  contact_us.fill_form({email: row[0], username: row[1], message: row[2]})

  contact_us.submit_message

  expect(browser.title).to_equal("Message Sent!")

end

//It all depends on how much you break down the steps within the definition.

Edit #2

It's also clear to me that you want to do method chaining, something in the way of contact_us.fill_form({email: row[0], username: row[1], message: row[2]}).submit_message, which again, isn't out of the question while using the techniques that I'm suggesting, but the question of whether this chaining should be for each individual page, or whether everything should be included in one class or module, can only be answered by your needs.

It's just my opinion that this would put too much into a single class, and that breaking down that class will allow for more control to be given to the testers, and the less redundant code will be written.

...