State is the amount of information remembered by a system. In hardware, state is stored in registers and memory. In the eyes of a developer, state appears in variables and external resources such as files or databases. Simply speaking, the more variables and other “stuff” you need to take into account when writing a test, the more state there is. Consider a unit test of a pure function, something like:
There’s no state to consider here. On the other side of the scale are the integration or system tests that require hundreds of tuples in a database to execute. Tests of batch operations, like invoicing, various forms of dispatching, or just processing in bulk, need lots of data—complex state—before execution.
In unit tests, we can spot state by observing the setup logic. If the test requires a lot of setup code like parameters to constructors or complex invocations of any creational patterns, calls to setters, stub configuration, and forming relations between various program elements, we probably have a problem. (The exception being a truly complex domain.)
State is directly related to controllability. The more state, the lower the controllability. State is often at odds with parallelism and multi-threading.
In conclusion, from a developer testing perspective, one wants to keep the amount of state down as much as possible.