skullTest With ZOMBIES

ZOMBIES1 is an acronym and a useful test heuristic, especially for developers.

Testing is a complex activity, but using ZOMBIES helps catch easy-to-prevent bugs. Pick the low-hanging fruit, so to speak.

ZOM - Zero, One, Many

Zero and One are edge cases, and Many is the first generalization - if the function or module works correctly with 2 "things", it is likely to work with 3, 4, and more (though far from always).

Zero

For convenience and structure, "Zero" cases are grouped into in-memory and out-of-memory.

In-Memory "Zero" Cases*

  • Null / None references (standalone variables, inside List, Set, or Map/dict values)

  • Numeric zero values: 0, 0.0

  • NaN (Not a Number)

  • Empty or blank string ("", " ")

  • Empty collections: [], {}, empty Set or Map, empty Map values, empty JSON array/object

  • Default-constructed / uninitialized objects (all fields at defaults)

  • Boolean false (logical zero in some contexts)

*Although these originate in memory, zero values can propagate into or come back from external systems, and can occur in an out-of-memory context (see below).


Out-of-Memory (External) "Zero" Cases

  • Database query results:

    • No rows returned (SELECT ... yields an empty result set)

    • Aggregations yielding 0 (e.g., COUNT(*)=0)

  • File system / I/O:

    • Zero-length file

    • Empty stream or socket response

  • API / Service responses:

    • Empty JSON/XML response body

    • Valid response with an empty list or object

    • null or missing fields in the payload

  • Message queues / event buses:

    • No messages available (empty poll)

One

Exactly "one of the thing" is a frequent edge case too. Exactly one item in a shopping cart, one money transfer, one item in a List of Set.

Consider the loop below. It takes two values at a time and sums them up.

For example, given the input [1,2,3,4], it will compute 1+2, 3+4, and output [3, 7].

But it will fail with input containing just one element.

Many

"If it works with 2 things, it will work with more" is a good starting point as a generalization, but sometimes insufficient. Special, context-dependent values are important.

Even the trivial sum_pairs example above will fail given a collection with an odd number of elements.

"Odd" or "even" count is one example of how a special number may reveal a bug.

See EP&BVA for more special business, numerical, and non-numerical values.


B - Boundary Values

See EP&BVA.


I - Interfaces

Sometimes, programmers get so tangled up in the implementation details that they let implementation dictate or influence the interface (method/function signature, API endpoints, JSON contracts, etc.)

Interfaces exist to benefit the "client" (a human user, another program, a calling function).

This point suggests focusing on the interface first - its usability and clarity.

  • Working solo: practice TDD to produce cleaner interfaces. With tests, one sees how the function, class, or another smaller piece of code looks and feels when being used by the caller.

  • Working together: code/design reviews, providing an unimplemented interface to future users to provide feedback on


E - Exercise Exceptional Behavior

Sometimes known as "negative testing" - trigger failures, crashes, timeouts, and write code that is prepared to handle such events gracefully.

  • Files: absent, locked for reading/writing, interruption during read/write, corrupted content

  • Network: disconnected, timeout, slow response, invalid data received

  • User input: unexpected or invalid formats, empty input, extremely large input

  • System resources: low memory, disk full, CPU spikes

  • APIs / external services: unavailable, error responses, rate-limited, malformed responses

See Advanced State Testingarrow-up-right and Testing Failures and Errorsarrow-up-right for more ideas.


S - Simple Scenarios, Simple Solutions

A guiding tip that reflects the general TDD approach: when implementing something, imagine simple scenarios first (happy path), and write the simplest possible implementation for that first.

Iterate and handle harder scenarios with more complex code gradually.

References

  1. ZOMBIES was likely originally coined by James Grenning in his blog postarrow-up-right. See also "TDD Guided by ZOMBIES" YouTube videoarrow-up-right.

Last updated