Code
Which parts of your own code deserve a test: private methods, getters, logging, migrations and other small pieces.
Most asked
Yes20
Test the concrete methods of an abstract class once, through a small subclass that exists only in the test, and test each real subclass for the methods it implements.
Give each API endpoint one HTTP-level test that sends a request and checks the status code and the response fields the client reads; leave edge cases to the tests of the service code behind the endpoint.
Write one test that loads the configuration file of every environment through your real loader and validates it, and do not assert individual configuration values.
Give each controller endpoint one HTTP-level test that sends a request and checks the status code and the response body; do not unit test controller methods by calling them with a mocked service.
Test each business rule in a CQRS command handler by sending the command through the mediator, with an in-memory fake repository or a test database, and asserting the saved state; do not write handler tests that only check which mocked methods the handler called.
Test each create, read, update and delete path you write with an integration test against a real database that writes a record, reads it back and checks every field; do not unit test CRUD code against a mocked repository.
Write one CI test that builds the production dependency injection container and creates every registered service, and do not write a test for each registration.
Give each event handler one test that fires the real event on the rendered control and checks the result the user sees; do not test a handler by calling its function directly.
Write one unit test for each exception your code throws on purpose and for each catch block that recovers from a failure, asserting the exception type or the state the handler leaves.
Test a helper function that holds its own logic with direct unit tests: call it with the main input and the edge inputs most likely to break, and assert on the return value.
Test every input validation rule your application declares, with one accepted and one rejected input per rule plus the request bodies that real clients send; do not test that the validation library's own checks work.
Test an internal class that holds logic with its own unit tests, and give the test project access to it instead of making the class public.
Write one test that your main error path logs the failure with its request ID, and do not assert on ordinary info and debug log lines.
Test each validation your model declares with one valid and one invalid record; do not test that the framework's own validators, such as Rails presence or Django MaxLengthValidator, work.
Test the rules you write into a model, such as validations, calculated values and query scopes, by saving and reading records in a test database; do not test the field declarations that the ORM maps for you.
Test every hand-written regular expression that validates or parses input in a product application, with a table of strings it must match and strings it must reject, run in CI.
Test a public static method that contains logic with direct unit tests: call it with the main input and the edge inputs most likely to break, and assert on the return value.
Test every business rule in the service layer with unit tests that replace the repositories with in-memory fakes and fix the clock; do not write separate tests for service methods that only forward a call to a repository.
Test a value object that checks rules or computes new values with plain unit tests: each rule at its boundary, each operation, and equality between two spellings of the same value.
Test a void method that changes state or sends something out: call it, then assert on the effect a caller can observe, such as the saved record, the new state of the object, or the message a fake receives.
No17
Do not test the status text that a program prints for the person running it; unit test the values that the text reports.
Do not write a test that asserts the value of a constant such as a page size or an upload limit; test the behaviour that reads it, with the expected result written as a literal from the requirement.
Do not test a constructor that only assigns arguments of different types to fields, or one the language generates; test the methods that use those fields.
Do not write unit tests for a DTO that only declares fields and generated accessors; check its JSON in the test of the endpoint that sends or receives it.
Do not write unit tests for an enum that only lists constants stored by name; let exhaustive switches make the compiler reject a new constant, and test the code that uses the enum.
Do not write tests for code that a widely used generator produces from a schema or annotations; test the code that calls the generated classes, and check the schema that feeds the generator in CI.
Do not write tests for getters and setters that only return or assign a field; test the code that uses the values.
Do not write tests that assert on implementation details such as internal calls, private state or call order; test the behaviour that callers can observe through the public interface.
Do not repeat the tests of an inherited method in every subclass; test the method once in the class that defines it, and test each subclass only for the methods it adds or overrides.
Do not write tests for an interface that only declares methods; test each class that implements it, with one shared contract test when several classes implement the same interface.
Do not write a unit test for a method that only forwards one value, or values of different types, to another method; test the code that calls it.
Do not write a test for a plain belongs_to, has_many or ForeignKey declaration; test the association options that decide what a delete removes or which rows come back.
Do not write tests that call private methods directly; test their behaviour through the public methods that call them.
Do not write tests that call protected methods directly; test their behaviour through the public methods of the base class and its subclasses.
Do not test a main method that only builds objects from arguments of different types and calls one entry point; move argument parsing and exit code logic into a function that you unit test.
Do not write tests for a toString() that only feeds log lines and the debugger; generate it, and test it only when users, stored data or other code read its output.
Do not write unit tests for branchless one-line wrappers and delegations that pass one value or values of different types; test the code that calls them.