{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4543253a",
   "metadata": {},
   "source": [
    "# Testing\n",
    "\n",
    "`braincell` uses **pytest** with `unittest.TestCase` classes. The test suite is\n",
    "the safety net for a numerically delicate library, so the conventions below are\n",
    "project rules, not suggestions.\n",
    "\n",
    "## Running the tests\n",
    "\n",
    "```bash\n",
    "pytest braincell/\n",
    "```\n",
    "\n",
    "`pytest.ini` sets `testpaths = braincell` and excludes `legacy` and `develop`.\n",
    "Two environment defaults are applied automatically by the root `conftest.py`:\n",
    "\n",
    "- `JAX_PLATFORMS=cpu` — JAX is forced onto CPU so tests are deterministic and\n",
    "  don't depend on a GPU.\n",
    "- `MPLBACKEND=Agg` — matplotlib runs headless so visualization tests don't open\n",
    "  windows.\n",
    "\n",
    "## Test file naming — mandatory\n",
    "\n",
    "Every test module **must**:\n",
    "\n",
    "- be named `*_test.py` (not `test_*.py`, not bare `test.py`), and\n",
    "- sit **next to the source file it covers**.\n",
    "\n",
    "```text\n",
    "braincell/io/neuromorpho/client.py\n",
    "braincell/io/neuromorpho/client_test.py   ← its test, co-located\n",
    "```\n",
    "\n",
    "When a module is split across several source files, give each its own sibling\n",
    "`*_test.py`. The `tests/` directory at the repo root is an empty placeholder —\n",
    "do not put tests there.\n",
    "\n",
    "## Shared test helpers\n",
    "\n",
    "Helpers that are **not themselves tests** go in a private, leading-underscore\n",
    "file (e.g. `_testing.py`) inside the same package, so pytest does not collect\n",
    "them. For example, `braincell/io/neuromorpho/_testing.py` provides fake\n",
    "HTTP doubles used across that package's tests.\n",
    "\n",
    "## The bug-fixing workflow\n",
    "\n",
    "The project rule for bugs is:\n",
    "\n",
    "> **Write a test that reproduces the bug, then fix until the test passes.**\n",
    "\n",
    "This guarantees the bug stays fixed and documents the expected behavior.\n",
    "\n",
    "## Test fixtures\n",
    "\n",
    "Morphology fixtures (SWC + ASC) live in\n",
    "`examples/multi_compartment/morpho_files/`. IO tests locate them relative to the\n",
    "test file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "002dbe8b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "MORPHO_DIR = Path(__file__).resolve().parents[2] / \"examples\" / \"multi_compartment\" / \"morpho_files\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63935141",
   "metadata": {},
   "source": [
    "## See also\n",
    "\n",
    "- {doc}`contributing` — the overall development workflow.\n",
    "- {doc}`extending` — testing a new channel or integrator."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
