Archive note
A working method for automated tests in Drupal
How to plan a test, choose assertions, and keep a suite readable when the codebase keeps moving.
Automated tests are often introduced as a safety net. That description is true but incomplete. A good suite is also a specification, a teaching tool, and a record of the decisions a project has already made.
Begin with one sentence
Write the behaviour you want to protect as a plain sentence: "An editor can publish a page without approving it first." That sentence becomes the name of the test. If the name needs three clauses, the test is probably covering three behaviours and should be split.
Choose the smallest useful check
An assertion is valuable when it fails for one clear reason. Checking that a page loads, that a status message appears, and that a database row changed in the same test makes failure analysis harder. Pick the outcome closest to the user action and assert that. Add the other checks in their own tests.
Resist the urge to assert everything you can observe. A suite that fails for cosmetic reasons will be ignored, and an ignored suite is worse than no suite because it creates false confidence.
Build the world inside the test
Tests should not depend on content that happened to exist in a development database. Create the user, create the content, assign the permission, then act. This makes the test portable and documents the minimum conditions for the behaviour.
Keep helper functions small and named after the intent. A helper called "make an editor" is easier to trust than a block of setup code repeated in a dozen places.
Make failure messages kind
The person reading a failure is usually tired and often not the person who wrote the test. Assertions should include enough context to identify the expected and actual state. A message that says "expected published, received draft" saves more time than a stack trace alone.
Run the new test before the fix. Watch it fail for the reason you expect. Then apply the fix and watch it pass. A test that has never failed has not yet proved anything.
Keep the suite visible
A suite that only runs on one machine is a private ritual. Put it in the shared workflow, make the result easy to find, and treat a red run as a normal part of the day rather than an emergency. The goal is a habit of checking, not a perfect record.
The same ideas apply in PHPUnit and in any later testing tool. The names change; the discipline does not.
A short checklist
- Does the test name describe one behaviour?
- Does it create its own data?
- Will the failure message explain what went wrong?
- Does it run without a manual setup step?
- Would a new contributor understand it in a minute?
The tools will change. The method survives: describe the behaviour, build the smallest world it needs, and check the result in a way that another person can read.