---
title: "Test behaviour through the public · Agent Wranglers"
url: https://agentwranglers.se/playbook/testing/unit-tests/unit-behaviour
updated: 2026-10-20
licence: "All rights reserved"
---

# Test behaviour through the public interface

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Unit tests](https://agentwranglers.se/playbook/testing/unit-tests)
- Rule: A unit test calls a function or class the way callers do, and checks what it returns or changes.
- How: Test through the public function, the public methods or the HTTP interface. Mock only things you do not own, such as a payment provider, never your own classes. Name each test after the behaviour, not the method. A test should survive any refactoring that keeps the behaviour the same.
- Check: Refactor the inside of a function without changing its results. No test needs to change. No test calls a private method, for example through reflection, `@ts-expect-error` or a Python `_private` name.

Example:

```js
// Bad: tied to a private helper
test('calls _roundCents', () => { /* spies on internals */ });

// Good: tied to behaviour, with money in whole cents
test('a 10% discount on 19.99 gives 17.99', () => {
  expect(applyDiscount(1999, 10)).toBe(1799);
});
```

```python
# pytest: named after the behaviour, calls only the public function
def test_a_10_percent_discount_on_19_99_gives_17_99():
    assert apply_discount(1999, 10) == 1799
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers testing playbook: https://agentwranglers.se/playbook/testing/unit-tests/unit-behaviour`.

- Next: [Fake the clock and the network in unit tests](https://agentwranglers.se/playbook/testing/unit-tests/unit-deterministic)
- [Unit tests](https://agentwranglers.se/playbook/testing/unit-tests)
