Skip to content

test: integration suite cleanup — graceful skip, explicit creds, dedupe, dynamic counts#404

Merged
axisrow merged 1 commit into
mainfrom
test/integration-suite-cleanup
May 28, 2026
Merged

test: integration suite cleanup — graceful skip, explicit creds, dedupe, dynamic counts#404
axisrow merged 1 commit into
mainfrom
test/integration-suite-cleanup

Conversation

@axisrow

@axisrow axisrow commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #396 — five fixes from the test-suite audit (2 High, 3 Medium):

High #1: setUpClass crashes on temporary API outage

The seven TestReadOnly* classes that probe the live API in
setUpClass (TestReadOnlyAdGroups, TestReadOnlyAds,
TestReadOnlyKeywords, TestReadOnlyDynamicFeedAdTargets,
TestReadOnlyLeads, TestReadOnlyBusinesses, TestReadOnlyAdVideos)
previously had no try/except — a transient API error gave an opaque
traceback instead of a clean skip. New helper
_skip_class_on_probe_failure catches any probe exception and raises
unittest.SkipTest (which setUpClass honours by skipping the whole
class).

High #2: invoke_get silently used the active direct-auth profile

direct_cli/auth.py:get_credentials gives the active direct auth
profile priority over YANDEX_DIRECT_TOKEN env var. The integration
suite previously passed no credentials to CliRunner.invoke, so on
any developer machine with an active profile the tests silently hit
production with profile creds. invoke_get now prepends
--token/--login (resolved via conftest._resolve_test_credentials)
to every CLI call — --token is priority 1 in the credential chain
and beats the profile, matching CLAUDE.md's inverted contract.

Medium #3: test_comprehensive.py partially duplicated test_cli.py

TestCLIHelp (and test_campaigns_help) were full duplicates of
classes in test_cli.py — removed. The remaining classes
(TestCommandsRegistered, TestUtils, TestOutputFormatters,
TestAuth, TestErrorHandling) cover surfaces NOT touched by
test_cli.py — kept.

Medium #5: hard-coded == 144 and == 112 in test_smoke_matrix.py

Adding any CLI command or WSDL operation broke the test with an
opaque message. Replaced with self-consistency checks that derive the
expected counts from the live Click registry and parsed WSDLs.

Medium #6: hard-coded == 83 in test_sandbox_write_audit.py

Same pattern: replaced with len(commands_for_category(WRITE_SANDBOX)).

Test plan

  • pytest --ignore=tests/test_integration.py --ignore=tests/test_v5_live_write.py --ignore=tests/test_v4_live_contracts.py — 1788 passed, 21 skipped, 0 failed.
  • pytest tests/test_integration.py -m integration — 32 passed against live API (read-only).
  • pytest tests/test_comprehensive.py tests/test_smoke_matrix.py tests/test_sandbox_write_audit.py — 44 passed.
  • flake8 tests/test_integration.py tests/test_comprehensive.py tests/test_smoke_matrix.py tests/test_sandbox_write_audit.py — clean.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 27, 2026 19:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@axisrow

axisrow commented May 28, 2026

Copy link
Copy Markdown
Owner Author

@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production.

@claude

claude Bot commented May 28, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 2m 43s —— View job


Claude PR Review

Focused on critical issues (bugs, security, logical errors, data loss, performance) per request. Verified the credential plumbing against direct_cli/auth.py and tests/conftest.py, the count derivations against direct_cli/smoke_matrix.py:237 (smoke_summary) and direct_cli/smoke_matrix.py:214 (_registered_cli_commands), and the probe-failure wrapping against the seven affected setUpClass callsites.

Verdict: No critical issues found. Ship it.

The five fixes are real and well-targeted. No bugs, security holes, logical errors, data-loss risks, or performance regressions surfaced.

Things I checked

High #2_prepend_credential_flags (tests/test_integration.py:60-86)

  • Correctly handles the only multi-token leading case in this file (--sandbox then subcommand at line 630). Insertion order produces [--sandbox, --token X, --login Y, agencyclients, get, …], all three top-level group options, which Click resolves correctly.
  • --token/--login are priority 1 in the chain (direct_cli/auth.py:get_credentials), so they correctly override an active developer profile — matches CLAUDE.md's inverted-credential contract.
  • When _REAL_TOKEN is None the function returns the args untouched, but every class that calls invoke_get is gated by @skip_if_no_token, so the no-token path is unreachable. Fine.
  • Token value is passed as a Python list argument to CliRunner.invoke (no shell), so no injection risk.

High #1_skip_class_on_probe_failure (tests/test_integration.py:88-100)

  • except Exception correctly leaves KeyboardInterrupt/SystemExit alone.
  • unittest.SkipTest raised from setUpClass is honoured by the runner and skips the whole class as intended.
  • One trade-off worth noting (not blocking): the catch is broad enough that a probe refactor that raises AttributeError/TypeError would be masked as a "transient API outage" in CI rather than failing loudly. If a probe regression slips in, it'll show up as a chronic skip. Mentioning so the team is aware — not asking for changes.

Medium #5/#6 — dynamic count derivation (tests/test_smoke_matrix.py:60-110, tests/test_sandbox_write_audit.py:33-40)

  • Walked the derivation against smoke_matrix.py:237-261 end-to-end:
    • total_cli_groupslen(cli.commands)
    • total_cli_subcommands → test sums dict items, impl builds a set keyed on (group, command); since dict iteration produces no duplicate pairs, set-count == sum-count ✓
    • api_cli_subcommands → both exclude only "auth"
    • wsdl_services, api_services_total, wsdl_operations → identical formulas on both sides ✓
  • These are now tautological in the sense that bugs in smoke_summary could pass undetected, but the strict invariant lives in test_smoke_matrix_covers_every_cli_subcommand_once (line 49), which still gates the matrix↔CLI mapping. Net regression-detection is roughly equivalent: the old magic numbers caught any drift but with an opaque message; the new self-consistency check still catches the same class of bug via the coverage test, just with a usable failure message.
  • test_sandbox_write_audit.pyassert len(rows) == expected_total still catches an audit script that under/over-counts vs the matrix. The check that mattered is preserved.

Medium #3 — dedup in tests/test_comprehensive.py

  • Confirmed TestCLIHelp and test_campaigns_help were faithful duplicates of test_cli.py:TestCLI::test_cli_help and equivalents. Other classes in this file (TestCommandsRegistered, TestUtils, TestOutputFormatters, TestAuth, TestErrorHandling) cover surfaces not touched by test_cli.py. Safe deletion.

Checklist

  • Read the diff (git diff origin/main...HEAD)
  • Review tests/test_integration.py — credential plumbing & probe-failure skip
  • Review tests/test_smoke_matrix.py — dynamic count derivation
  • Review tests/test_sandbox_write_audit.py — dynamic count derivation
  • Review tests/test_comprehensive.py — dedup
  • Post review findings
    • Branch: test/integration-suite-cleanup

…pe, dynamic counts

Five fixes from the test-suite audit (issue #396):

1. setUpClass robustness — every TestReadOnly* class whose setUpClass
   calls a live-API probe (campaign, business, leads-turbo-page,
   advideo probes) now wraps the call in _skip_class_on_probe_failure
   so a temporary API outage raises unittest.SkipTest instead of
   crashing the class with an opaque traceback.

2. Explicit credentials — invoke_get now prepends --token/--login
   (resolved via conftest._resolve_test_credentials) to every CLI
   call. Per direct_cli/auth.py:get_credentials, the active
   direct-auth profile has priority over the YANDEX_DIRECT_TOKEN env
   var; without explicit flags the integration suite would silently
   fall through to a developer's production profile when env vars
   were unset. Matches CLAUDE.md's inverted credential-resolution
   contract for tests.

3. test_comprehensive.py dedup — the TestCLIHelp class (full
   duplicate of test_cli.py) is gone. Unique classes (Utils,
   OutputFormatters, Auth credential chain, ErrorHandling,
   TestCommandsRegistered) are kept; they cover code paths not
   exercised elsewhere.

4. test_smoke_matrix.py — replaced hard-coded ``== 144`` and
   ``== 112`` with self-consistency checks: every expected count is
   derived from the live Click registry and parsed WSDLs.

5. test_sandbox_write_audit.py — replaced hard-coded ``== 83`` with
   ``len(commands_for_category(WRITE_SANDBOX))``.

All non-live tests pass (1788 passed, 21 skipped). Lint clean.

Closes #396.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@axisrow axisrow force-pushed the test/integration-suite-cleanup branch from cd2c8ad to 6fc93b7 Compare May 28, 2026 02:57
@axisrow

axisrow commented May 28, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto post-#401/#403 main (CHANGELOG conflicts resolved by appending Tests block under 0.3.14). No code changes vs. previous SHA. @claude review.

@claude

claude Bot commented May 28, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 1m 28s —— View job


Claude PR Re-review (post-rebase)

  • Confirm diff vs origin/main matches the previously-reviewed set of code changes
  • Confirm CHANGELOG conflict was resolved cleanly (Tests block appended under 0.3.14)
  • Re-validate the four critical-path checks from the prior review
  • Post updated verdict

Verdict: No critical issues found. Rebase looks clean — ship it.

What changed since the prior review

Only CHANGELOG.md materially differs from the previously-reviewed SHA. The other four files (tests/test_integration.py, tests/test_comprehensive.py, tests/test_smoke_matrix.py, tests/test_sandbox_write_audit.py) carry the same code I checked before. Totals still +173 / −39 across 5 files.

CHANGELOG resolution check

The Tests block is appended under the existing 0.3.14 heading (CHANGELOG.md:41-65), after the Breaking changes / Added / Closes #360. sections introduced by #399/#400/#401/#403. Nothing from those PRs was overwritten:

Single-version block, single Closes line per concern — matches the file's existing format.

Critical-path checks re-validated

All four findings from my prior review still hold against the rebased SHA:

  1. _prepend_credential_flags + _invoke_env (tests/test_integration.py:60-87): credentials are passed as both --token/--login CLI flags (priority 1) and env vars — belt-and-suspenders. The --sandbox insertion-order branch is intact (lines 80-83); --sandbox stays attached to the top-level group and credential flags slot in before the subcommand. Token is a list arg to CliRunner.invoke, no shell, no injection risk.
  2. _skip_class_on_probe_failure (tests/test_integration.py:89-102): unchanged. Broad-Exception catch still leaves KeyboardInterrupt/SystemExit alone. Skip is honoured by setUpClass. Same caveat as before — a probe refactor raising AttributeError/TypeError would be masked as a "transient outage" and shown as a chronic skip; not a blocker.
  3. Dynamic count derivation (tests/test_smoke_matrix.py, tests/test_sandbox_write_audit.py): formulas still match smoke_matrix.py:smoke_summary exactly; the strict invariant in test_smoke_matrix_covers_every_cli_subcommand_once still gates the matrix↔CLI mapping. No regression in detection coverage; just better failure messages.
  4. test_comprehensive.py dedup: TestCLIHelp removed, surviving classes (TestCommandsRegistered, TestUtils, TestOutputFormatters, TestAuth, TestErrorHandling) still cover surfaces not touched by test_cli.py.

Nothing in the rebase resurrected an issue; the audit-fix story is intact.
• Branch: test/integration-suite-cleanup

@axisrow axisrow merged commit e79c6bd into main May 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Аудит тестов: 20 проблем (2 High, 7 Medium, 11 Low)

2 participants