test: strengthen assertions and cover Mix tasks - #218
Conversation
Test coverage comparison
Measured on Elixir 1.20.4 / OTP 29 with seed The SDK coverage increase comes from eight new Mix-task tests. Strengthened existing assertions also detect regressions without increasing runtime-module line coverage. Seven deliberate production mutations were detected by the new or repaired tests, then fully restored. The SDK now exceeds Mix’s default 90% coverage threshold. Adapter coverage remains below that threshold despite all six tests passing. The 18 live integration tests remained excluded before and after. Other Elixir/OTP versions were not measured locally. |
|
[Low risk] Test suite improvements and assertion strengthening. The PR appears safe to merge; no new actionable issue or outstanding finding was identified. Reviews (2) · Last reviewed commit: "test: distinguish request timeout cleanu..." |
posthog-elixir Compliance ReportDate: 2026-09-27T14:26:11.947467+00:00
|
| Test | Status | Duration |
|---|---|---|
| Format Validation.Event Has Required Fields | ✅ | 608ms |
| Format Validation.Event Has Uuid | ✅ | 609ms |
| Format Validation.Event Has Lib Properties | ✅ | 609ms |
| Format Validation.Distinct Id Is String | ✅ | 609ms |
| Format Validation.Token Is Present | ✅ | 608ms |
| Format Validation.Custom Properties Preserved | ✅ | 608ms |
| Format Validation.Event Has Timestamp | ✅ | 608ms |
| Format Validation.Non Utc Event Timestamp Is Converted To Utc | ❌ | 609ms |
| Retry Behavior.Retries On 503 | ✅ | 5614ms |
| Retry Behavior.Does Not Retry On 400 | ✅ | 2611ms |
| Retry Behavior.Does Not Retry On 401 | ✅ | 2610ms |
| Retry Behavior.Respects Retry After Header | ✅ | 5614ms |
| Retry Behavior.Implements Backoff | ✅ | 15624ms |
| Retry Behavior.Retries On 500 | ✅ | 5615ms |
| Retry Behavior.Retries On 502 | ✅ | 5613ms |
| Retry Behavior.Retries On 504 | ✅ | 5615ms |
| Retry Behavior.Max Retries Respected | ✅ | 15624ms |
| Deduplication.Generates Unique Uuids | ✅ | 615ms |
| Deduplication.Preserves Uuid On Retry | ✅ | 5613ms |
| Deduplication.Preserves Uuid And Timestamp On Retry | ✅ | 10620ms |
| Deduplication.Preserves Uuid And Timestamp On Batch Retry | ✅ | 5614ms |
| Deduplication.No Duplicate Events In Batch | ✅ | 613ms |
| Deduplication.Different Events Have Different Uuids | ✅ | 609ms |
| Compression.Sends Gzip When Enabled | ✅ | 607ms |
| Batch Format.Uses Proper Batch Structure | ✅ | 608ms |
| Batch Format.Flush With No Events Sends Nothing | ✅ | 606ms |
| Batch Format.Multiple Events Batched Together | ✅ | 611ms |
| Error Handling.Does Not Retry On 403 | ✅ | 2609ms |
| Error Handling.Does Not Retry On 413 | ✅ | 2611ms |
| Error Handling.Retries On 408 | ✅ | 5615ms |
Failures
format_validation.non_utc_event_timestamp_is_converted_to_utc
Event 0 field 'timestamp' instant '2026-09-27T14:24:27.955157Z' != expected '2025-01-02T03:04:05Z'
Feature_Flags Tests
View Details
| Test | Status | Duration |
|---|---|---|
| Request Payload.Request With Person Properties Device Id | ✅ | 6ms |
| Request Payload.Flags Request Uses V2 Query Param | ✅ | 5ms |
| Request Payload.Flags Request Hits Flags Path Not Decide | ✅ | 5ms |
| Request Payload.Flags Request Omits Authorization Header | ✅ | 5ms |
| Request Payload.Token In Flags Body Matches Init | ✅ | 5ms |
| Request Payload.Groups Round Trip | ✅ | 4ms |
| Request Payload.Groups Default To Empty Object | ❌ | 5ms |
| Request Payload.Disable Geoip False Propagates As Geoip Disable False | ✅ | 4ms |
| Request Payload.Disable Geoip Omitted Defaults To False | ❌ | 5ms |
| Request Payload.Flag Keys To Evaluate Contains Only Requested Key | ✅ | 4ms |
| Request Lifecycle.No Flags Request On Init Alone | ✅ | 2ms |
| Request Lifecycle.No Flags Request On Normal Capture | ✅ | 607ms |
| Request Lifecycle.Two Flag Calls Produce Two Remote Requests | ✅ | 9ms |
| Request Lifecycle.Mock Response Value Is Returned To Caller | ❌ | 4ms |
| Retry Behavior.Retries Flags On 502 | ❌ | 308ms |
| Retry Behavior.Retries Flags On 504 | ❌ | 309ms |
| Side Effect Events.Get Feature Flag Captures Feature Flag Called Event | ❌ | 608ms |
Failures
request_payload.groups_default_to_empty_object
Field 'groups' not found in /flags request body at path 'groups'. Available keys: ['api_key', 'distinct_id', 'flag_keys_to_evaluate']
request_payload.disable_geoip_omitted_defaults_to_false
Field 'geoip_disable' not found in /flags request body at path 'geoip_disable'. Available keys: ['api_key', 'distinct_id', 'flag_keys_to_evaluate']
request_lifecycle.mock_response_value_is_returned_to_caller
Last action result missing field 'value'. Keys: ['error', 'success']
retry_behavior.retries_flags_on_502
Last action result missing field 'value'. Keys: ['error', 'success']
retry_behavior.retries_flags_on_504
Last action result missing field 'value'. Keys: ['error', 'success']
side_effect_events.get_feature_flag_captures_feature_flag_called_event
Expected 1 events with name '$feature_flag_called', got 0
💡 Motivation and Context
Several tests could pass without proving the behavior named in the test. Partial map matches allowed context or metadata leaks. Feature-flag deduplication hid whether
send_event: falseworked. Loader tests did not verify that blocked request workers stopped, and a short polling interval could consume responses intended for manual refreshes.This PR strengthens those assertions, checks exact variant/payload pairs, and uses message-processing barriers where a sleep or negative assertion was not enough. It also adds eight tests for the public API snapshot and source-packaging Mix tasks, fixes the manual capture example, and restores the original Logger configuration after manual tests.
The loader test explicitly waits for request-timeout cleanup before testing bounded shutdown and provider cleanup. It does not claim that shutdown immediately cancels an in-flight request. A 1-second request-timeout experiment confirmed that shutdown waits for that timeout.
There are no SDK implementation changes or deleted tests.
💚 How did you test it?
On Elixir 1.20.4 and OTP 29:
Coverage uses the unchanged Mix defaults, including Mix tasks and compiled test support. The coverage increase comes from the new Mix-task tests. Stronger assertions improve regression detection without changing runtime-module line coverage. Adapter coverage remains below Mix's default 90% threshold.
0and424242. All 18 live integration cases remained excluded. The changed manual integration examples were not run against live services.mix format --check-formatted,mix credo --strict,mix compile --warnings-as-errors,mix posthog.public_api --check,mix hex.build, andgit diff --checkpassed.origin/mainreported no actionable findings at363433584828dd1dec8167334ec3a3e1a94a431d.sdk_compliance_adapter/README.md.📝 Checklist
If releasing new changes
sampo addto generate a changeset file. Not needed for test-only changes.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Pi audited the tests in a dedicated worktree, using three read-only subagent audits, local shell tools, and the autoreview helper. The changes retain existing tests and strengthen their assertions rather than removing coverage. Local coverage and controlled mutations were used to check the result. No public session link is available.
The work was directed by @marandaneto and requires human review. No production behavior or coverage thresholds were changed. Live integration validation and some broader concurrency coverage remain follow-ups.