CalcSnippets
Programming 3 min read

How to Write Tests for a New Function

Write useful tests for a new function by defining behavior, covering ordinary and edge inputs, checking failures, and keeping tests readable.

Choose test names that describe behavior a reader can recognize. Arrange the input, perform one meaningful action, and assert the result that matters to a user or caller. Include ordinary values first, then boundaries such as empty input, the smallest valid value, a large value, invalid data, and a dependency failure. Avoid testing private implementation details when a public behavior is available. Keep test data small and explain unusual fixtures. A failing test should tell you what broke without requiring a debugger for every line. Run the tests in a clean environment and check that time, locale, random order, and network access do not make results unreliable.

Define behavior before implementation

A test should explain what a function promises. Write the input, expected output, side effects, and errors in plain language before choosing a test framework. If the behavior is unclear, a green test can simply confirm an accidental implementation. Ask what a caller needs to rely on and what the function should refuse.

Start with an ordinary example that represents the main use. Use meaningful values rather than a pile of zeros and empty strings. Name the test after the behavior it protects. A person reading the failure later should understand the broken promise without opening the implementation first.

Cover boundaries and invalid input

Add cases for empty input, one item, the smallest allowed value, the largest practical value, duplicates, missing fields, wrong types, and unusual characters when those cases matter. Do not test every imaginable value without a reason. Choose boundaries where the algorithm, contract, security, or user expectation changes.

Test failure behavior explicitly. Does the function return an error, raise an exception, use a fallback, or refuse to change data? Check the error type and useful message without making a test depend on incidental wording. For functions that use time, randomness, files, or networks, control those dependencies so the test does not pass by accident.

Keep tests independent

Each test should create the state it needs and clean up after itself. Do not rely on the order in which tests happen to run. Use fixtures and helpers to remove repetition, but keep the important input and expected result visible. A clever helper that hides the assertion makes a test difficult to review.

Test the public behavior rather than private implementation details unless the private detail has its own important contract. Tests that assert every internal call can prevent safe refactoring. Prefer a small number of focused tests over one enormous scenario that fails for several possible reasons.

  • Use fixed clocks and deterministic random sources.
  • Keep test data free of real personal information.
  • Run tests locally and in the project's standard environment.
  • Write a regression test when fixing a discovered bug.

Review failures as documentation

When a test fails, read the actual and expected values before changing either. A failure may reveal a wrong requirement, a brittle assertion, or a real defect. Keep the test if it protects a meaningful behavior and update it only when the contract intentionally changes. Record why a non-obvious test exists.

Good tests make software easier to change. They describe promises, expose boundaries, and give developers a quick signal when behavior moves. The best test suite is not the one with the most lines; it is the one that protects the decisions users and other code depend on.

Run slower integration tests for boundaries that unit tests cannot represent. Confirm file formats, database behavior, permissions, and network contracts in a controlled environment. Do not replace all integration coverage with mocks because a mocked dependency can hide an incompatible real response. Match the test level to the risk of the behavior it protects.

Keep reading

Related guides