4.9 KiB
Improve Test Coverage Plan
Motivation
The passKit codebase has ~100 test methods but critical components that will be heavily refactored (for multi-store support and other changes) have little or no test coverage. Adding regression tests now prevents silent breakage during future work.
This is standalone — it should be done before any other refactoring.
Current Test Coverage
Well-tested areas
- Password parsing (
Password,Parser,AdditionField, OTP,TokenBuilder) — ~40 tests PGPAgent— 8 tests covering multiple key types, error cases, passphrase handlingPasswordGenerator— 8 testsGitRepository— 8 tests (uses real temp git repos on disk)GitCredential— 6 tests (SSH test is skipped/"failed in CI")PasswordEntityCore Data operations — 6 tests (uses in-memory store viaCoreDataTestCase)KeyFileManager— 7 testsQRKeyScanner— 6 tests- String/Array extensions — 6 tests
Critical gaps (zero tests)
| Component | Notes |
|---|---|
PasswordStore (36 methods) |
Only 1 integration test that clones from GitHub. No unit tests for pull, push, add, delete, edit, decrypt, encrypt, reset, erase, eraseStoreData, deleteCoreData, fetchPasswordEntityCoreData, initPasswordEntityCoreData. |
AppKeychain |
Zero tests. Only exercised indirectly via DictBasedKeychain mock. |
PersistenceController / Core Data stack |
Only the isUnitTest: true path is exercised. No tests for reinitializePersistentStore, deletePersistentStore, error recovery. |
Services (PasswordDecryptor, PasswordEncryptor, PasswordManager, PasswordNavigationDataSource) |
Zero tests. Core business logic that ties PasswordStore + PGPAgent together. |
| All view controllers (28+) | Zero tests. No UI test target exists. |
| AutoFill / Share / Shortcuts extensions | Zero tests. No test targets for extensions. |
PasscodeLock |
Zero tests. Security-critical. |
Test infrastructure that already exists
CoreDataTestCase— base class with in-memoryPersistenceController(reusable)DictBasedKeychain— in-memoryKeyStoremock (reusable)TestPGPKeys— PGP key fixtures for RSA2048, RSA4096, ED25519, NISTP384, multi-key sets
Implementation
1. PasswordStore unit tests (highest priority)
The single existing test (testCloneAndDecryptMultiKeys) depends on network access. Add offline unit tests using a local git repo fixture:
- Setup/teardown: Create a temp directory,
git init, add.gpg-id+ encrypted.gpgfiles, so tests don't need network. - Test
initPasswordEntityCoreData: Clone a local fixture repo → verify correctPasswordEntitytree in Core Data (names, paths, directories, parent-child relationships). - Test
deleteCoreData: Populate, then delete, verify empty. - Test
eraseStoreData: Verify repo directory deleted, Core Data cleared, git handle nil'd. - Test
erase: Verify full cleanup (keychain, defaults, passcode, PGP state). - Test
fetchPasswordEntityCoreData: Verify fetch with parent filter, withDir filter. - Test encrypt → save → decrypt round-trip: Using
DictBasedKeychain+ test PGP keys + local repo. - Test
add/delete/edit: Verify filesystem + Core Data + git commit. - Test
reset: Verify Core Data rebuilt to match filesystem after git reset.
2. PasswordEntity relationship tests
Extend PasswordEntityTest (already uses CoreDataTestCase):
- Test
initPasswordEntityCoreDataBFS walk: Create a temp directory tree with.gpgfiles, call the static method, verify entity tree matches filesystem. - Test that
.gpgextension is stripped from names but non-.gpgfiles keep their names. - Test hidden files are skipped.
- Test empty directories.
3. AppKeychain tests
Basic tests against the real Keychain API (or a test wrapper):
- Test
add/get/removeContentround-trip. - Test
removeAllContent. - Test
contains. - Test
removeAllContent(withPrefix:)— this method already exists and will be useful for per-store cleanup.
4. PersistenceController tests
- Test
reinitializePersistentStore— verify existing data is gone after reinit. - Test model loading — verify the
.momdloads correctly.
5. Test infrastructure: local git repo fixture builder
A helper that creates a temp git repo with configurable .gpg-id, encrypted .gpg files, and directory structure. Replaces the current network-dependent clone in PasswordStoreTest.
Implementation Order
All steps are independent and can be done in parallel:
| Step | Description |
|---|---|
| 1 | PasswordStore unit tests (offline, local git fixture) |
| 2 | PasswordEntity BFS walk + relationship tests |
| 3 | AppKeychain tests |
| 4 | PersistenceController tests |
| 5 | Local git repo fixture builder (prerequisite for step 1) |