Files
bot-bottle/tests
didericis 70a22fa210
test / run tests/run_tests.py (pull_request) Successful in 21s
refactor: rename platform abstraction to backend
Across the package:
  - claude_bottle/platform/         -> claude_bottle/backend/
  - platform/docker/platform.py     -> backend/docker/backend.py
  - class BottlePlatform            -> BottleBackend
  - class DockerBottlePlatform      -> DockerBottleBackend
  - get_bottle_platform()           -> get_bottle_backend()
  - env var CLAUDE_BOTTLE_PLATFORM  -> CLAUDE_BOTTLE_BACKEND
  - dict _PLATFORMS                 -> _BACKENDS

"Backend" is shorter and more established as the term for a
pluggable strategy-pattern implementation. "Platform" was vague
(could mean OS, hardware, cloud) and mildly redundant — Docker is
itself a platform.

The previous PRD section claiming "the Backend protocol was
rejected" referred to a low-level run/exec/cp/network_connect
protocol; the name was never the reason. The PRD is updated to
describe that rejected design by shape rather than by name.

The bottle/agent concepts and the manifest schema are unchanged.
2026-05-10 23:59:38 -04:00
..

Tests

Plain-Python test suite using stdlib unittest. No external dependencies. Unit tests run anywhere Python 3 is present; integration tests need Docker and skip cleanly otherwise.

Layout

tests/
  run_tests.py                    # entry point
  fixtures.py                     # JSON manifest builders
  _docker.py                      # docker-availability skip helper
  test_pipelock_naming.py         # unit
  test_pipelock_classify.py       # unit
  test_pipelock_allowlist.py      # unit
  test_pipelock_yaml.py           # unit
  test_pipelock_image.py          # integration
  test_pipelock_sidecar_smoke.py  # integration
  test_dry_run_plan.py            # integration
  test_orphan_cleanup.py          # integration

Running

tests/run_tests.py                                  # everything
tests/run_tests.py unit                             # unit only
tests/run_tests.py integration                      # integration only
tests/run_tests.py tests/test_pipelock_yaml.py      # one file

You can also run via python -m unittest:

python -m unittest discover -s tests
python -m unittest tests.test_pipelock_yaml

What the integration tests cover

  • test_pipelock_image.py — the pinned digest is reachable, ENTRYPOINT is /pipelock, and CMD includes run.
  • test_pipelock_sidecar_smoke.pydocker create + docker cp the generated YAML to /etc/pipelock.yaml + docker start, then probe /health.
  • test_dry_run_plan.pycli.py start --dry-run shows the resolved egress allowlist and creates zero docker resources.
  • test_orphan_cleanup.py — network_remove and pipelock_stop are idempotent against missing resources, so the EXIT trap can call them unconditionally.

What's NOT covered

  • claude_bottle/ssh.py end-to-end (would need a fake SSH host inside the container).
  • A live SSH-through-pipelock tunnel against a real Tailscale-style IP.
  • DLP false-positive measurements.
  • TLS handling / cert pinning behavior.

Adding a test

  1. Pick a filename: test_<topic>.py. Add it to INTEGRATION_NAMES in run_tests.py if it needs Docker.
  2. Boilerplate:
    import unittest
    
    from claude_bottle.<module> import <symbol>
    
    class TestThing(unittest.TestCase):
        def test_x(self):
            ...
    
    if __name__ == "__main__":
        unittest.main()
    
  3. For Docker-dependent tests, decorate the class with @skip_unless_docker() from tests._docker.