10 comments

[ 2.0 ms ] story [ 27.2 ms ] thread
I'm not really a UI guy, but isn't this MVC (or some subset)?
This is honestly the main reason I prefer Playwright to Cypress. Playwright leans heavily into using POs, while for some reason Cypress doesn't.

So in almost every project the Cypress tests are a procedural mess, while the Playwright tests are mostly well structured.

I know that Cypress has other patterns for dealing with this but they never seem to get applied.

Page Object Models trade off clarity for encapsulation. Concrete example [1]. They can make tests look "cleaner" but often obscure what's actually happening. For example:

    await page.getStarted(); // what does this actually do?
vs

    await page.locator('a', { hasText: 'Get started' }).first().click();
    await expect(page.locator('h1', { hasText: 'Installation' })).toBeVisible();
The second version is explicit and self-documenting. Tests don't always benefit from aggressive DRY, but I've seen teams adopt POMs to coordinate between SDETs and SWEs.

--

1: https://playwright.dev/docs/pom

I think this comes back to the idea of having a "UX model" that underlies the user interface, laying out its affordances clearly in code. In a modern application you're going to have complex UX logic and state that's distinct from the domain model as such and that deserves representation in the code.

In an MVC conception, the UX model becomes a top layer of abstraction of the domain model. It's a natural place to be because for modern apps, users expect "more than forms", i.e.: different ways of cutting up the domain data, presented in different ways, ...

This is something that component-based frontend frameworks struggle with a bit: the hierarchical layout of the DOM doesn't always reflect the interrelations in data between parts of a user experience. Prop drilling is just a reflection of this fact and perhaps it's why we're seeing a rise in the use of state stores. It's not really about state, that's just the technical symptom, it's really about providing a way of defining a (in-browser) data model based on the user experience itself rather than the particularities of the UI substrate.

I think the implementation details matter a ton here. I bet you can make this thing work and be useful, but you can also follow this blindly and have just an absolute mess.

I worked at a place where a well meaning QA tech rewrote the test suite to use page objects. It was a total mess and I undid most of that work in the end. It just moved a bunch of xpath expressions a long way from the rest of the test code, and it was all single use anyway.

I'm confused about why this is on the front page of HN?
In my experience, Page Objects sound neat in theory but end up as a leaky abstraction: they mix UI details with test logic, duplicate flows, and make even trivial UI changes ripple through dozens of files. What I’ve seen is indirection that hides test intent and bloats maintenance.

I also find them very developer-centric — testers get forced into upfront design work that doesn’t fit how they naturally test, and many struggle with it. I’ve had better results by expressing behavior directly and keeping UI concerns thin, instead of using a wrapper around page structure.

I also find them very developer-centric — testers get forced into upfront design work that doesn’t fit how they naturally test, and many struggle with it. I’ve had better results by expressing behavior directly and keeping UI concerns thin, instead of using a wrapper around page structure.

I'm sorry, but if your testers are not comfortable getting involved in the early design stages of your software in a 21st century world, then there's at least a 90% chance that their primary role at your company is perpetuating organizational dysfunction.

Most of my career has been defined by cleaning up the gargantuan messes the culture of "throw tickets over the wall to QA" created, and it has been very, very ugly. It defies common sense how culture around tools and processes for dev and ops roles continues to evolve over time, but for some reason testers are still trying to test software off in a silo, like it's released once or twice a year on CD-ROM.

I was doing a ton of agile, testing, and QA consulting in this era, and I feel like page objects worked well only in very narrow circumstances. Namely, QA departments where quality engineers were tasked with building very large and comprehensive automated UI tests (usually a bad idea) that exercised the same pages many, many times (also a bad idea, b/c extremely slow).

But anyway if you were in that situation, duplication of selectors and labels and other implementation details of a page that were liable to change across a bunch of tests was an _absolute nightmare_ to deal with when you'd get a massive report of failures with bad error messages and often incorrect stack traces. Being able to fix all those errors by changing a selector in a single page object governing all of them was indeed better than the alternative.

In the era of Cucumber, page objects were yet another level of indirection around what was a far-too-indirect process to provide the kind of feedback loop you'd need for it to be valuable. Especially as part of a development workflow.

I’m confused and think I don’t get it.

If a webpage is an iceberg, the buttons and menus and dropdowns are the visible part. If I understand this page object, that’s what he proposes testing.

But the bit I care about is the bit underneath that will compose REST calls from those UI elements and sometimes make subsequent REST calls from the result of the previous ones.

That is the tricky bit to test, and the bit where we *still* fall back to manual testing and recorded demos for qa.

I was hoping this was a suggestion for a better selenium.