You write five tests for the contacts page. Every one starts with the same two lines: log in, open the page. Copying them is tedious, and when the login flow changes you edit five places.
Hooks solve this. A hook is code that runs around your tests automatically.
describe('contacts', () => {
beforeEach(() => {
cy.visit('/contacts');
});
it('shows the contact list', () => {
cy.get('[data-testid="contact-row"]').should('have.length.greaterThan', 0);
});
it('can search', () => {
cy.get('[data-testid="search"]').type('Dana');
});
});
beforeEach runs before each test in the block. Both tests start on the contacts page without repeating the line.
There are four hooks:
beforeEachruns before every test. This is the one you will use almost always.afterEachruns after every test. Used for cleanup.beforeruns once, before the first test in the block.afterruns once, after the last test.
Now the part that actually matters, because choosing between before and beforeEach is a decision about whether your tests stay independent.
beforeEach keeps tests independent. before can destroy that.
Say you use before to create one contact, and three tests share it. Test 1 renames it. Test 2 now finds a contact with an unexpected name and fails. Worse, test 2 passes when you run it alone, so the failure looks random and impossible to reproduce.
That is an order dependency, and it is the single most common cause of a suite that behaves differently on a build server.
So the rule: use beforeEach unless you have measured a reason not to. The setup runs more times, which costs seconds. Order dependencies cost days.
Two more things worth knowing early.
Cypress clears state between tests by default. Cookies and localStorage are wiped, so each test starts logged out. That is a deliberate design choice in favour of independence, and it is why naive login-in-before does not survive.
Do not put assertions in hooks. When a hook fails, the failure is reported against a test that has not really run, and the message points at the wrong place. Hooks arrange. Tests assert.
Remember this: beforeEach by default, and never let one test depend on what another one left behind.
Reference: Writing and Organizing Tests.