TunnelVision

04 — Testing strategy

The design goal is that almost everything is testable on the Simulator, and only the two device-only surfaces (the packetFlow read/write loop and the live TLS handshake against a real server) require hardware. Structure code so the untestable part is a thin adapter over tested logic.

The pyramid

     device smoke tests   (M7/M8, manual + minimal automated, on hardware)
   ────────────────────────────────────────────────────────
     integration tests    (store + IPC + parser wired together, Simulator)
   ────────────────────────────────────────────────────────
     unit tests           (parsers, reassembly, pcap, models, store — Simulator)

What each layer covers

Unit tests (the bulk)

Integration tests

Looking at the app on the Simulator (M11)

Unit tests are not the only thing that has to run without hardware — Dynamic Type, VoiceOver and Instruments all need a person driving a populated app. And a Simulator launch is empty: the extension is the only writer of the history database, the capture directory and the live ring, and it does not run there. So the screens worth looking at (Timeline and its scrub bar, Flow Inspector, the packet screen, Captures, the Dashboard’s history) do not exist until something puts data in the shared container.

Shared/Fixtures does that — a Debug-only, seed-deterministic synthetic capture, scripted to cover every screen state rather than sampled — and FixtureSeeder writes it into the shared container. Launch the app with -TVSeedFixture (Xcode scheme arguments, or xcrun simctl launch --console-pty <device> com.juanmmm21.tunnelvision -TVSeedFixture) and it prints what it wrote. Seeding replaces rather than accumulates, so it can be repeated, and the fixed seed is what makes a before/after with Instruments measure the same work. See ../../Shared/Fixtures/README.md.

The live feed stays flat regardless: the ring is an SPSC channel whose single producer is the extension, and faking it from the app would mean writing from the producer end of a contract that says there is only one. That half waits for hardware.

Device smoke tests (M7/M8)

Cannot run on Simulator. Documented, semi-automated:

Fixtures

Store captured packet fixtures under TunnelVisionTests/Fixtures/ as small .pcap files, one concern per file (e.g. ipv4-tcp-syn.pcap, ipv6-udp.pcap, tcp-out-of-order.pcap). Generate them with tcpdump/Wireshark and keep them tiny. Never commit real personal traffic — synthesize or scrub fixtures.

Determinism and time

Performance and memory as tests

Running

xcodebuild test -scheme TunnelVision \
  -destination 'platform=iOS Simulator,name=iPhone 16'

Run them through the scheme, which is what carries the pinned locale. -testLanguage/ -testRegion override it, and CopyLocaleTests will say so rather than let the run look clean.

Tests are green before every push — this is enforced by the coding standards and CI.