{
  "id": 19050145,
  "title": "Freeze the Clock Before You Refactor: Characterization Tests for Impure Code",
  "url": "https://urgent.news/2026/11/09/freeze-the-clock-before-you-refactor-characterization-tests-for",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-09T00:21:34.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/hackrs_6393/freeze-the-clock-before-you-refactor-characterization-tests-for-impure-code-b0m"
  },
  "original_language": "en",
  "account": "Characterization tests for impure code focus on freezing behavior, rather than desired behavior. These tests are crucial for dealing with unseeds like wall clock dependencies. To begin, inventory impurity through text search rather than profiling. This is faster and more precise. Count the hits and record the number in the commit message. Each hit requires a strategy to pin it down. For process-local impurity like clock, RNG, UUIDs, and environment variables, in-process patching suffices. For external impurity such as network, database, and filesystem, recorded fixtures are necessary. The inventory doubles as a review checklist. Any unlisted impurity indicates a gap to watch for later. Next, insert a boundary module without altering the original code. Create a thin module that substitutes calls to the impure functions with their frozen counterparts. Implement the following methods: now_date() returns a fixed date string; new_id() returns a fixed UUID; pick(seq) returns the first item from the sequence; and env(key, default) returns the environment variable value or a default. Substitute these methods mechanically in the code. Run the code to ensure the substitution behaves identically to the original. Record the output as a golden file and assert against it in a test. This two-step process ensures the frozen behavior is verified before any changes are made. Finally, create a fixture to freeze the environment, ensuring the test environment remains consistent across runs.",
  "summary": "Legacy code is rarely untestable. It is usually just unseeded. A characterization test that reads the wall clock will flake on day two. So freeze the inputs first, then pin the outputs. This is the order that survives review. Below is a reproducible loop: inventory impurity, insert one text-only boundary, record behavior, freeze it, prove the test can fail, then make the smallest safe change. The…",
  "key_points": [
    "Characterization tests focus on freezing impure code behavior",
    "Inventory impurity via text search, not profiling",
    "Frozen behavior verified before code changes"
  ],
  "editors_take": "Prioritizing behavior preservation through characterization tests allows developers to stabilize unpredictable dependencies before attempting refactors, transforming messy legacy codebases into predictable environments for safer structural changes.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}