https://cypress.io logo
I've been having a dispute with a coworker over ho...
# best-practices
g
I've been having a dispute with a coworker over how many it() blocks we should have per spec file. I've read the best practices and am aware that you should "Add multiple assertions and don't worry about it" but I'm not entirely convinced. We also typically run our tests in headless mode from the command line so the argument that "You will always know (and can visually see) which assertion failed in a large test" doesn't really hold true. If you're not using a beforeEach, why not have a bunch of small it() within one spec file?
b
First thing I can think about having many 'small' it blocks would make it costly in time and feedback. I don't know in what situation you and your coworker are debating, but if the multiple it blocks you speak of are testing the same element on the same page, why go through an entire test set up again to test another part of the same element when you can do it all at once. I could be misreading your dispute.
m
one advice I have for you is one that I give to many people coming from unit testing and trying out e2e testing Always look for opportunities to tweak what test is already existing as opposed to writing partially duplicated tests for new specs. The reason Cucumber / Gherkin is not great is this duplication; if every feature was mapped to a spec, there would be much duplication between the specs. What matters from a test perspective is the beginning state of a test; if reaching that state is common, then it is an opportunity for a test enhancement vs partial test duplication. At which point, the only caveat becomes the test duration for parallelization concerns. for example, these 3 is really 1 test
this one does everything above
the next block is the same idea, they do exactly the same thing with less code and effort
because of the Cypress runner, you don’ t have to be concerned with having small tests for the sake of a small blast radius the way to go with Cypress is a different kind of flow
n
GG @magnificent-finland-58048, you just advanced to level 1!
g
But if we are running our tests 99% of the time in headless mode, then more tests--and therefore more names--would help us pinpoint where it is failing, wouldn't it?
l
Only sort of. Yes, with longer
it()
blocks the failure won't be as pinpoint precise at a glance in a test reporter like the Cypress Dashboard, but it's close enough. 99% of the time when I see a test failure the first thing I'm doing is attempting to run the test on my local test runner, at which point I no longer need that granular level of failure in the test reporter. I will concede that Cypress (and most testing platforms, for that matter) could benefit from a more granular divider for longer tests. Assertions aren't always a good fit for this because they tend to be too numerous and don't read well. To remedy this, I wrote my own custom command called
cy.checkpoint()
. It does a number of things, including: - Adding a clear log line with a custom message and a little βœ” next to it - Taking a screenshot and submitting it to a visual testing tool (Percy in my case) So for any given
it()
block I usually have a handful of clearly-communicated
cy.checkpoint()
lines (and a dozen non-obvious assertions).
The problem of "how many it() blocks?" is similar to "how should I name my folders/files/tests/blocks?" It's all about communication. If you have one assertion per
it()
block it'll be a giant impenetrable mess. Conversely, if your test is too large it becomes, again, a giant impenetrable mess. There's a balance somewhere. What I would avoid doing is making your test unreadable in an attempt to shave a few seconds off of execution time.
m
headless, or headed in CI what's the difference? You still get the same data & diagnosis from failures
you could separate parts of a longer it block with
cy.log('**foo**')
setup state -> do something -> make an assertion just have to make sure all that is within an it block
g
Interesting... This has given me a lot to think about. So if I understand correctly, a major driving factor about why it is best to have fewer individual tests is because of the set-up/tear-down between each one?
l
From a pure speed perspective I'm sure there's a cost but I'm not sure how much. My biggest beef with one-assertion-per-block would be readability and maintainability. 90% of the page would be boilerplate
it()
blocks repeated. But the discussion is almost beside the point... I have my doubts that many of your tests would even fit within this type of structure. Does your app really have no state you have to accumulate before your assertions? Must be nice πŸ™‚ If you are building up state in a
beforeEach()
block then there's your speed cost right there.
g
Ha, good point, it definite does
4 Views