Testing ======= Running Tests ------------- Run the full test suite with parallel execution and coverage: .. code-block:: bash pytest -n auto --cov Run a single test file: .. code-block:: bash pytest tests/test_url_utils.py -v Run with coverage report: .. code-block:: bash pytest --cov --cov-report=html open htmlcov/index.html Coverage Target --------------- We target **90% line coverage** across the entire codebase. Writing Tests ------------- All tests live in ``tests/``. We follow TDD (Red-Green-Refactor): 1. Write a failing test that specifies the expected behavior. 2. Implement the minimum code to make the test pass. 3. Refactor while keeping tests green. All HTTP interactions are mocked using the ``responses`` library — the test suite must not make real network requests. Test Structure -------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Test file - What it tests * - ``test_url_utils.py`` - URL normalization, prefix matching, depth * - ``test_config.py`` - Config loading, YAML parsing, CLI override * - ``test_classifier.py`` - URL decision tree, asset type classification * - ``test_http_client.py`` - HTTP requests, retries, redirects, SSL * - ``test_html_parser.py`` - Link extraction, anchor collection * - ``test_results.py`` - Thread-safe results aggregation * - ``test_report.py`` - All report sections * - ``test_crawler.py`` - End-to-end crawl scenarios * - ``test_cli.py`` - Argument parsing, exit codes * - ``test_progress.py`` - Progress reporter