6 ms·
Page Object (2013)
- a_t48 1y agoI'm not really a UI guy, but isn't this MVC (or some subset)?
- serial_dev 1y agoPage object is a useful model for writing maintainable tests
- vasusen 1y agoIt is quite popular in testing circles to write e2e tests that are easier to maintain. However, in practice I have found it to be quite useless due to the time it takes to write good page objects. QA teams usually rely on a complete POM before writing tests on it. I used to joke that by the time my team was done shipping a page object model, our product team would have changed the entire product again.
- JimDabell 1y agoThis seems like it’s reversing the M->V generation. You don’t want to write your tests explicitly for the minutiae of the markup you are generating, but you don’t want to bypass the view layer entirely and go straight to the model because then you aren’t testing what you intend to. So you build a new model from the view layer, and then test the model. If the markup changes enough that tests start failing, then you update the model instead of all the failing tests. I’m not certain that it buys enough to justify an extra layer of indirection in every front-end test though. Having a collection of selectors with meaningful names seems to get you about half the value without that extra layer.
- oweiler 1y agoThis 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.
- littlecranky67 1y agoI remember, for a while Cypress had in its documentations actually a warning about POs and recommended not to use them. I got curious as to why (because I am a big fan of POs) and dug deeper - I think at some point on a sales slide I found the reason "because POs have internal state". I started then to write my POs without any internal state (which you don't need with Typescripts property getters) and have luckily scaled my app with dozens os POs and hundred of tests. Later they removed that recommendation and seem to accept that people like POs.
- emmanueloga_ 1y agoPage 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 https://playwright.dev/docs/pom
- zikani_03 1y agoI am working on a tool[1] to try to make working with playwright a bit more ergonomic and approachable. Sorry to shamelessly plug but I'd love feedback on if it is even a good idea/direction. Hadn't considered the Page Object Model and will definitely have to consider how to incorporate that for those who want to do things that way. --- 1: https://github.com/zikani03/basi https://github.com/zikani03/basi
- michalc 1y agoVery much agree. It was a few years ago, and very AngularJS focused, but I posted something along these lines: https://charemza.name/blog/posts/angularjs/e2e/consider-not-using-page-objects-in-e2e-tests/ https://charemza.name/blog/posts/angularjs/e2e/consider-not-... In summary: having thing look cleaner at a glance is not helping if you’re (almost) always going to need to do more than glancing
- rullopat 1y agoSo if you have a page that is common between, lets say, 30-40 tests, you prefer to copy/paste the new selectors everywhere?
- pintxo 1y agoWell, if you have tests with 100+ lines of such explicitness, it becomes really hard to see the high level picture of „what is tested here“. As usually, there is a balance to be found.
- 1y ago
- movpasd 1y agoI 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.
- boxed 1y agoI 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.
- fergie 1y agoI'm confused about why this is on the front page of HN?
- kitd 1y agoFrom the Guidelines [1]: What to Submit On-Topic: Anything that good hackers would find interesting. That includes more than hacking and startups. If you had to reduce it to a sentence, the answer might be: anything that gratifies one's intellectual curiosity. Off-Topic: Most stories about politics, or crime, or sports, or celebrities, unless they're evidence of some interesting new phenomenon. Videos of pratfalls or disasters, or cute animal pictures. If they'd cover it on TV news, it's probably off-topic. This one seems reasonable. [1] https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- zabil 1y agoIn 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.
- adityaathalye 1y agoOP here. Ordinarily, I would agree with you, because PageObjects themselves are not composable, in languages belonging to the "Kingdom Of Nouns". However, the following design, thanks to Clojure's language design, helped address a rather nasty situation. A tightly scoped Domain Specific Language, over some Types of PageObjects, all of which compose arbitrarily (without breaking value semantics). So, if you wanted the `value` of a Modal box having all sorts of switches, form fields etc., you'd call `value` on it, and it would call `value` on all of its constituents, and return the immutable hash-map snapshot of whatever state it found. Cross-cutting concerns | v PageObject / DSL -> | open | close | open? | select | deselect | ... | |-----------------------+------+-------+-------+--------+----------+-----| | Dropdown | | | | | | | | Checkbox | | | | | | | | Switch | | | | | | | | Modal | | | | | | | | SearchList | | | | | | | | ... | | | | | | | Concrete example (in the deck and demo linked below): (defprotocol IPageObject "Each PageObject MUST implement the IPageObject protocol." (page-object [this]) (exists? [this]) (visible? [this])) And then an implementation like this: (defrecord Checkbox [target-css] IPageObject (page-object [this] this) (exists? [this] ;; webdriver check if target-css exists ) (visible? [this] ;; webdriver check if target-css is visible ) Selectable (select [this] ;; webdriver select the target ) (deselect [this] ;; webdriver undo selection ) (selected? [this] ;; webdriver return true if target selected ) Value (get-value [this] ;; webdriver return current selection state (selected? this))) Deck: https://github.com/adityaathalye/slideware/blob/master/designing_object_functional_system_IN-Clojure_2016.pdf https://github.com/adityaathalye/slideware/blob/master/desig... Talk + Demo: https://www.youtube.com/watch?v=hwoLON80ZzA&list=PLG4-zNACPCsNVwz3ohXKeoeQjRLoFsc7F&index=5 https://www.youtube.com/watch?v=hwoLON80ZzA&list=PLG4-zNACPC... I also commented about it here: https://news.ycombinator.com/item?id=45161410 https://news.ycombinator.com/item?id=45161410 (Clojure's solution to the Expression problem). That said, UI testing is a hot mess in general (especially for SPAs). I prefer to avoid automating anything but the "happy paths". IME, exploratory testing is better at sussing out corner cases, and "emergent" misbehaviours. So I do that, in addition to the "happy path" suites. Cue: James Bach et. al. https://www.satisfice.com/ https://www.satisfice.com/ Also I am warming up to server-generated HTML, because I can unit-test that, if I can use `hiccup` syntax + HTMX. In that case, I just make all request handlers spit out HTML fragments as Clojure data, and test those responses in my test suite.
- searls 1y agoI 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.
- jojohohanon 1y agoI’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.
- epolanski 1y agoPlaywright has replaced Selenium years ago. Playwright also implements fixtures and Page Object Model: https://playwright.dev/docs/pom https://playwright.dev/docs/pom