The Great Locator Location Debate
Even though Py.Saunter in opinionated, there is some wiggle room in certain areas (much like you have the Fat vs. Skinny Controller debate in Rails). One of the wiggle areas is around locators and how they are accessed inside your Page Objects. Depending on who you talk to, they will recommend that you either have your locators set Globally in your framework or Locally in the page objects. (Or like me they started at one and converted to the other.)
When I wrote about Page Objects for the Pragmatic Magazine I recommended taking a Global approach to locators using whatever mechanism your language provides for its i18n strings. One of the appeals of this is that when a locator changes there is exactly one file that needs to be changed and your Page Objects functionality will be restored without actually having to change them. The other appeal I hear often is that ‘non-techies can just edit this non-code file with changes’.
Taking them in opposite order, the non-code reason always seems to be a cowardly one — either the person who would be making the change is scared of code or someone other person is being scared for them. In both cases the solution is a training/communication one. Spend some time with the person and show them what part of which files need to be changed. If they are smart enough to figure out a complex css selector, they are smart enough to only change dictionary values without changing any other code in a file.
Py.Saunter provides a different error message for failed locator interactions that so the person interpreting the results will be able to quickly identify both the source of the breakage and where to update with the fixed locator.
The big problem with Global locators however is that it is so easy to ‘cheat’ and use a locator that is outside of your actual Page Object (often during page transitions with AJAX synchronization). This flies in the face of one of the heuristics of Page Objects — locators belong in one, and only one Page Object.
The solution to the leakiness of the Global system is to do things locally. In the python situation, it is a Dictionary that has module scope for that Page Objects and its Elements. Yes; there is no trying to hide that there is code being executed, but writing [good] Se scripts is code. There is no escaping it. And with a bit of coaching and some well placed comments, pretty much anyone can update locators when necessary.
<pre lang="python"># update locators here. do not change the name (left); only the value (right)
locators = {
"collar style": 'css=a[title="REPLACE"]',
"results": 'css=.count',
"throbber": 'id=PreferenceThrob'
}
It is certainly possible to manage your locators globally in Page Objects that are used by Py.Saunter (or any other Se framework). But I wouldn’t. The coupling of the locators with the Page Objects should be a tight one and the desire to break that model should be a trigger that perhaps your object model is not as complete as you thought it was.