> For the complete documentation index, see [llms.txt](https://engineering.umh.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://engineering.umh.app/engineering/development-process/how-to-build/testing.md).

# Testing

Your tests cover the error paths too. For a persistent transient error or a persistent error, a test checks that the [user](/product/who-we-build-for.md#our-users) sees it and, if UMH has to fix it, that it reaches [Sentry](https://sentry.io), as questions 2 and 3 in [Error management](/engineering/development-process/how-to-build/coding-standards/architecture/error-management.md#questions-for-every-error) describe.

Customers run older versions of [umh-core](https://docs.umh.app/) and [benthos-umh](https://docs.umh.app/benthos-umh), with all kinds of weird configurations and feature flag settings. Your change has to work with all of them.

When you test the data infrastructure, consider the kinds of edge cases that [Designing Data-Intensive Applications](https://dataintensive.net/) (2nd edition) describes. For example:

* Time: event time and processing time differ, device clocks are wrong or disagree, and messages arrive late or out of order (chapter 12, "Reasoning About Time", and chapter 9, "Unreliable Clocks").
* Delivery: a message arrives twice, for example because a consumer crashed after processing it and before committing its offset (chapter 12, "Acknowledgments and redelivery" and "Idempotence").
* Partial failures and restarts: a write lands halfway, a process crashes between the write and the commit, and state held only in memory is lost on restart (chapter 9, "Faults and Partial Failures", and chapter 12, "Rebuilding state after a failure").
* Overload: a consumer is slower than its producer, so a queue fills up and either drops messages or blocks (chapter 12, "When consumers cannot keep up with producers").
* Concurrency: data races and deadlocks inside a process, two writers where the last write silently wins (chapter 6, "Last write wins (discarding concurrent writes)"), and logic that reads a value and writes it back without an atomic update, so a parallel message changes the value in between (chapter 8, "The Meaning of ACID" and "Preventing Lost Updates").
* Evolution: an old and a new version read or write the same data (chapter 5, "Different values written at different times").

## Beyond regression tests

For a [one-way door](/engineering/development-process/how-to-build.md#one-way-doors), consider these tests in addition to regression tests. Each of these finds a different kind of gap:

* **Mutation testing** makes small changes to your code, such as flipping a condition or deleting a line, and runs your tests against each modified version. If no test fails for a modified version, your tests have a gap, or that line of code does nothing. Run it on the code you changed, not on the whole repository. For Go there is [Gremlins](https://github.com/go-gremlins/gremlins), for TypeScript [Stryker](https://stryker-mutator.io).
* **Fault injection** makes the parts around your code fail on purpose, such as a lost answer, a dropped connection or a crashed process. It shows whether your code keeps its [delivery guarantees](/engineering/development-process/how-to-build/coding-standards/architecture/data-integrity/delivery-guarantees.md): no message lost or processed twice.
* **Property-based testing** generates many inputs and checks a property that must hold for all of them. For example, decoding an encoded message returns the original.
* **Formal verification** proves that a property is true for a design in every possible case, for example with [TLA+](https://lamport.azurewebsites.net/tla/tla.html).

A refactoring of a one-way door is still a one-way door, so consider these tests for it too.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://engineering.umh.app/engineering/development-process/how-to-build/testing.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
