cypress e2e tests: page objects vs application actions vs custom commands

Should you use Application Actions when writing cypress tests? Or is the Page Objects pattern better? Or neither and just write tests and use cypress custom commands to share common selectors and user actions?

Page Objects is a well established pattern. Create classes for pages in your app and put selectors in those classes. Then in your test use (and reuse) the page object classes methods to simulate user actions such as fill in a field or submit a form. This centralizes and reuses selector code.

Application Actions pattern exposes the applications model as a property on window which can be directly edited in cypress test code. Now test setup to add todos so they can be toggled becomes basically like so: `window.appModel.addToDos([{}, {}])`

The author provides examples of how to use Application actions including with async operations.

Faster setup results in faster tests. And per the author better organized app code.

The Application Actions post link argues that Page Objects are a "bad practice". Because page objects are hand to maintain, introduce additional state, fallback to conditional login when supporting multiple use cases (anti-pattern), slow down tests because have to go through the ui to setup. I think these can be debated e.g. going through the ui is not a page object feature per se, using cypress custom commands does the same thing. And falling back to conditional logic can avoided.

The author then shows a cypress test which has to add todos in the UI using cypress before can test checking "complete all todos". Point being: the majority of the tests runtime is taken up with test setup. Which may be repeated in multiple tests. Which makes tests slow.

I typically write cypress tests and create custom commands. But there is still some selection and user action duplication, which could be reduced with page objects. 

Application Actions exposing model or methods via window feels like an anti pattern when a goal is to test the user interface (but I get that testing the same user interface again and again is a waste). 

But more importantly there are other ways to setup data, for example our apps typically fetch data and we typically mock api responses to test various scenarios. So in my experience the setup "problem" is not really a problem (and we do want to test down to api calls and api returns).

But slow cypress tests is a legit concern. As an app adds features and we want to add more cypress tests then one can end up making tradeoffs and begin to limit cypress to "most important" tests in the interests of limiting cypress runtime. There are ways to improve runtimes such as running cypress tests in parallel which has yielded a very big improvement. Plus other best practices such as don't unnecessarily wait.

As devs we also need to consider how to use the "testing pyramid". We should preferr to write more integration and/or component tests as well as unit test which run faster than cypress tests. Use cypress to cover e2e tests and other kinds of tests, cypress antipattern





Comments

Popular posts from this blog

angular js protractor e2e cheatsheet

angularjs ui-router query string parameter support

Notes on interview with Kent Beck about AI and why it's like a "genie"