Skip to content

Tony/bur-33-task-11-develop-unit-and-integration-test-suite#54

Merged
tonyblank merged 17 commits intomainfrom
tony/bur-33-task-11-develop-unit-and-integration-test-suite
Jun 13, 2025
Merged

Tony/bur-33-task-11-develop-unit-and-integration-test-suite#54
tonyblank merged 17 commits intomainfrom
tony/bur-33-task-11-develop-unit-and-integration-test-suite

Conversation

@tonyblank
Copy link
Owner

@tonyblank tonyblank commented Jun 12, 2025

  • Introduced additional markers in pytest.ini for authentication, resilience, and performance tests to enhance test organization and execution.
  • This update aims to facilitate better categorization of tests and improve overall test suite maintainability.

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive integration tests for real GitHub API covering authentication flows, end-to-end workflows, network resilience, rate limiting, error recovery, and performance monitoring.
    • Added fixtures and utilities to support integration testing with real APIs, including network simulation, performance monitoring, cleanup helpers, and conditional slow test skipping.
    • Enhanced test data generation and performance baseline fixtures for dynamic and performance-related tests.
    • Added extensive unit tests for utility functions, model edge cases, validators, formatters, CLI commands (fetch, reply, resolve, schema), and services covering input validation, error handling, output formatting, and integration.
    • Applied consistent pytest markers across unit and integration test classes for improved test categorization and selective execution.
    • Added output format support ("pretty" and "json") to pull request selection and fetch services, improving CLI interaction modes and output routing.
    • Added detailed unit tests for CLI core, context handling, error management, environment variable parsing, and main entry point behavior.
    • Introduced new tests for format selection utilities and schema validator edge cases.
  • Bug Fixes

    • Improved test output readability by setting a default traceback style for test runs.
    • Fixed error message formatting for clearer and consistent exception string conversion.
  • Documentation

    • Added detailed documentation for the test framework and real API integration tests, including setup instructions, test categorization, and best practices.
    • Added READMEs for unit command tests and real API integration tests.
  • Chores

    • Updated pytest configuration for marker definitions, test collection, and path settings.
    • Enhanced CI workflow environment with GitHub token for authenticated test runs.
    • Revised example environment variables to focus on testing and API interaction parameters.
    • Added python-dotenv dependency for environment variable management.
    • Simplified development dependencies in requirements and pyproject.toml by removing many pytest plugins and adding system utilities.
    • Updated CI workflows to separate integration tests and adjust caching and install commands.
    • Added new pre-commit checks for trailing whitespace and end-of-file fixes in CI scripts.
    • Removed deprecated files and updated Makefile to unify commands under uv tool.
  • Refactor

    • Renamed validation function related to reply content warnings for clarity.
    • Adjusted import paths for node ID validation functions in service code.
    • Routed user-facing output to standard error in JSON mode to avoid polluting output streams.
    • Modified fetch service and PR selector to accept and handle output format parameter for better mode distinction.
    • Modernized type annotations across codebase to use Python 3.9+ built-in generic types (list, dict, tuple) instead of typing imports.
    • Simplified control flow by removing redundant else blocks and pass statements.
    • Standardized exception message formatting to use {e!s} for consistent string conversion.

Tony Blank and others added 5 commits June 11, 2025 16:58
…tions

- Updated `conftest.py` to include a new `test_data_generator` fixture for creating varied test data sets and a `performance_baseline` fixture for establishing performance expectations.
- Added integration and unit markers to various test classes across the test suite to improve test categorization and execution.
- Enhanced the `TestFetchCLI` and formatter tests with appropriate markers for better organization and clarity.

These changes aim to improve the maintainability and performance tracking of the test suite.
…est-framework-and-test-structure

Enhance test suite with additional fixtures and performance configurations
- Added comprehensive unit tests for utility functions, including `parse_datetime` and `emit_error`, to ensure robust error handling and validation.
- Introduced new edge case tests for model classes, specifically `ReviewThread`, `Comment`, and `PullRequest`, to improve coverage and validate behavior with various input scenarios.
- Updated existing tests to include unit markers for better organization and execution.

These changes aim to strengthen the reliability and maintainability of the test suite.
…t-tests-for-models-and-utilities

Tony/bur-62-task-112-create-unit-tests-for-models-and-utilities
- Introduced additional markers in `pytest.ini` for authentication, resilience, and performance tests to enhance test organization and execution.
- This update aims to facilitate better categorization of tests and improve overall test suite maintainability.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 12, 2025

Walkthrough

This monstrous PR dumps a truckload of changes into your test suite: it slaps new pytest markers all over the place, vomits out piles of new and improved documentation, injects a horde of new fixtures and utilities for integration and performance testing, and births a whole litter of real API integration tests. Unit tests get more thorough, edge cases are hammered, and everything is marked, documented, and ready for CI/CD. No exported code entities were harmed—just test infrastructure and docs got the beating.

Changes

Files/Paths Change Summary
pytest.ini Added new pytest markers: auth, resilience, performance. Removed ignored paths, fixed pythonpath, cleaned obsolete options.
tests/README.md Added big-ass documentation on test framework, markers, fixtures, best practices, and CI/CD.
tests/conftest.py Removed custom marker logic in pytest_configure; added fixtures: test_data_generator, performance_baseline.
tests/integration/conftest.py Added a goddamn arsenal of fixtures for integration with real GitHub API, network simulation, cleanup, and performance monitoring.
tests/integration/cli/test_fetch_cli.py Added @pytest.mark.integration and @pytest.mark.cli to TestFetchCLI.
tests/integration/real_api/README.md Added detailed README for real API integration tests, setup, running, markers, CI, and dev practices.
tests/integration/real_api/__init__.py Added docstring describing the real API integration test package.
tests/integration/real_api/test_authentication_flows.py Added comprehensive integration tests for GitHub authentication, permissions, error handling, and environment simulation.
tests/integration/real_api/test_end_to_end_workflows.py Added end-to-end workflow integration tests for PR review cycles, bulk ops, error recovery, and edge cases.
tests/integration/real_api/test_network_resilience.py Added integration tests for network resilience, rate limiting, error recovery, and concurrency.
tests/integration/real_api/test_performance_monitoring.py Added integration tests for performance, scalability, resource usage, and long-running stability.
tests/unit/formatters/test_formatters.py Added @pytest.mark.formatter and @pytest.mark.unit to all test classes.
tests/unit/formatters/test_json_formatter.py Added tests for safe serialization fallback and error handling in JSON formatter.
tests/unit/formatters/test_pretty_formatter.py Updated type hints and exception formatting in pretty formatter tests.
tests/unit/formatters/test_format_interfaces.py Updated type annotations in mock formatter class.
tests/unit/formatters/test_color_and_terminal.py Simplified environment variable removal in test.
tests/unit/formatters/test_comprehensive_formatting.py Reordered imports, no logic changes.
tests/unit/models/test_model_edge_cases.py Added new unit tests hammering edge cases for models and validation utilities.
tests/unit/models/test_models.py Added @pytest.mark.model, @pytest.mark.unit, and @pytest.mark.slow to relevant test classes; added type validation edge cases.
tests/unit/services/test_fetch_service.py Added @pytest.mark.service, @pytest.mark.unit, and @pytest.mark.integration to test classes.
tests/unit/services/test_github_service.py Added extensive error and edge case tests for GitHubService, including subprocess error simulations and reply strategy tests.
tests/unit/services/test_reply_service.py Added comprehensive tests for ReplyService post_reply and error handling.
tests/unit/services/test_resolve_service.py Added error coverage tests for resolve and unresolve thread mutations.
tests/unit/test_command_utils.py Added @pytest.mark.unit to all test classes; removed redundant pass.
tests/unit/test_utils.py Added new unit/integration tests for utility functions: parse_datetime, emit_error, and MAX_PR_NUMBER.
tests/unit/test_cli.py Added comprehensive unit tests for CLI group, commands, context, error handling, environment variables, integration, and edge cases.
tests/unit/test_format_selection.py Added tests for formatter registration, output formatting, and CLI option creation utilities.
tests/unit/validators/test_node_id_validation.py Added @pytest.mark.validator and @pytest.mark.unit to all test classes.
tests/unit/validators/test_schema_validator.py Added edge case tests for schema validator cache handling and schema loading.
tests/unit/validators/test_validation.py Added extensive unit tests for validation functions and classes in the validation module.
tests/unit/parsers/test_parsers.py Added extensive error and edge case tests for GraphQL response parsing and validation.
tests/unit/parsers/test_graphql_queries.py Updated cursor validation test to expect exception on empty string.
tests/integration/cli/test_reply_cli.py Improved assertion message formatting.
tests/integration/cli/test_resolve_cli.py Reordered imports, no logic changes.
tests/integration/test_schema_validation_integration.py Reordered imports, no logic changes.
tests/test_validation.py Updated imports and calls from check_reply_content_warnings to validate_reply_content_warnings.
.github/workflows/ci.yml Added GH_TOKEN env var from secret to test job for authenticated API access during CI.
.github/workflows/ci-uv.yml Added new CI workflow using uv tool for linting, testing, and coverage across Python versions.
Makefile Refactored all commands to use uv tool for dependency management, testing, linting, and dev utilities; added new dependency targets.
scripts/ci_check.py Added trailing whitespace and end-of-file fixer checks; updated test run log message.
scripts/test_config.py Updated type annotations and import order.
src/toady/cli.py Simplified exception handling control flow in main().
src/toady/commands/fetch.py Modified FetchService instantiation to accept output_format parameter.
src/toady/commands/reply.py Updated type hints and simplified dict key checks.
src/toady/commands/resolve.py Updated type hints; removed redundant else clause.
src/toady/commands/schema.py Changed exception message formatting style; updated type hints.
src/toady/error_handling.py Updated error detail display conditional on debug env var; refined type hints.
src/toady/exceptions.py Updated type hints to use built-in generics.
src/toady/formatters/format_interfaces.py Updated type hints to built-in generics; improved serialization fallback logic; refined exception message formatting.
src/toady/formatters/format_selection.py Updated type hints and cast usage.
src/toady/formatters/formatters.py Updated type hints; simplified control flow in output formatting.
src/toady/formatters/json_formatter.py Updated type hints; improved exception message formatting; added safe serialization tests.
src/toady/formatters/pretty_formatter.py Updated type hints; improved exception message formatting; simplified control flow.
src/toady/models/models.py Updated type hints; improved exception message formatting in validation.
src/toady/parsers/graphql_parser.py Updated type hints to built-in generics; reordered imports.
src/toady/parsers/graphql_queries.py Updated type hints; changed cursor validation to raise on empty string; refined exception formatting.
src/toady/parsers/parsers.py Updated type hints; improved exception formatting; removed redundant pass and else blocks.
src/toady/services/fetch_service.py Added output_format parameter to constructor; updated type hints; simplified control flow.
src/toady/services/github_service.py Updated type hints; fixed relative import paths; removed redundant pass statements; simplified control flow.
src/toady/services/pr_selector.py Added output_format parameter; supported JSON mode output; routed output to stderr in JSON mode; updated type hints.
src/toady/services/reply_service.py Updated type hints; removed redundant pass statements.
src/toady/services/resolve_service.py Updated type hints; improved exception message formatting.
src/toady/utils.py Improved exception message formatting.
src/toady/validators/node_id_validation.py Updated type hints; reordered imports.
src/toady/validators/schema_validator.py Updated type hints; reordered imports; simplified control flow; improved exception formatting.
src/toady/validators/validation.py Renamed function; updated type hints; simplified error handling.
.env.example Removed old API key placeholders; added new env vars for test repo, PR, timeouts, rate limits, retries, and GitHub token placeholder.
requirements-dev.txt Removed entirely; dev dependencies moved to pyproject.toml.
pyproject.toml Increased minimum Python to 3.9; updated dependencies; refined linting and pytest config; added new dev and test extras.

Sequence Diagram(s)

sequenceDiagram
    participant Tester
    participant Pytest
    participant Fixtures
    participant GitHubAPI

    Tester->>Pytest: Run tests with markers (e.g., integration, performance)
    Pytest->>Fixtures: Setup fixtures (auth, network, performance, etc.)
    Fixtures->>GitHubAPI: Perform real API calls (auth, fetch, etc.)
    GitHubAPI-->>Fixtures: Return data or errors
    Fixtures-->>Pytest: Provide data, simulate network, monitor performance
    Pytest-->>Tester: Report results with marker-based filtering
Loading

Possibly related PRs

  • tonyblank/toady-cli#30: Also fucks with pytest.ini markers and slaps in shared fixtures—directly related to test configuration and marker hell.
  • tonyblank/toady-cli#40: Adds interactive PR selection and initial PRSelector class, related to output format handling in this PR.
  • tonyblank/toady-cli#15: Introduces JSON and pretty output formatting for fetch command, related to output format integration here.

Poem

Oh, you filthy test suite, now marked to the bone,
With docs so damn thorough, you’ll never be alone.
New fixtures, new markers, integration galore—
Real API pain? Bring it, you whore.
Edge cases, resilience, performance on blast—
This code review’s over. Ship it fast.
🖕💩

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch tony/bur-33-task-11-develop-unit-and-integration-test-suite
  • Post Copyable Unit Tests in Comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

♻️ Duplicate comments (4)
tests/integration/real_api/test_authentication_flows.py (1)

19-21: ⚠️ Potential issue

Fix unknown pytest marks

Same issue as the previous file - auth marker needs to be registered.

Add to pytest.ini:

+    auth: marks tests as authentication tests
🧰 Tools
🪛 GitHub Actions: CI

[warning] 19-21: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', and 'auth' used (lines 19-21).

tests/integration/real_api/test_performance_monitoring.py (1)

22-25: ⚠️ Potential issue

Fix unknown pytest mark

The performance marker needs to be registered.

Add to pytest.ini:

+    performance: marks tests as performance tests
🧰 Tools
🪛 GitHub Actions: CI

[warning] 22-25: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', 'performance', and 'slow' used (lines 22-25).

tests/integration/real_api/test_network_resilience.py (2)

18-21: ⚠️ Potential issue

Fix unknown pytest mark

The resilience marker needs to be registered.

Add to pytest.ini:

+    resilience: marks tests as resilience tests
🧰 Tools
🪛 GitHub Actions: CI

[warning] 18-21: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', and 'resilience' used (lines 18-21).


260-264: ⚠️ Potential issue

Fix missing GH_TOKEN in CI

Same issue as in authentication tests - GH_TOKEN is not set in GitHub Actions.

🧹 Nitpick comments (9)
tests/unit/formatters/test_formatters.py (1)

7-8: Add formatter marker to pytest.ini

formatter (and again unit) are unknown to pytest right now.
Register them just like the others to avoid warnings.

Also applies to: 18-19, 106-107, 257-258, 301-302, 391-392

tests/unit/models/test_models.py (1)

12-13: Register model and (optionally) slow markers

model isn’t declared; slow might be supplied by pytest-slow-plugin, but if you’re not using it you still need to declare it. Add:

# pytest.ini
 markers =
     ...
+    model: unit tests focusing on dataclass validation / serialization
+    slow: resource-heavy tests (can be deselected with -m "not slow")

Also applies to: 494-495, 776-777, 977-978, 1136-1137, 1286-1289, 1362-1364

🧰 Tools
🪛 GitHub Actions: CI

[warning] 12-1288: PytestUnknownMarkWarning: Unknown pytest marks 'model', 'unit', and 'slow' used in multiple test classes.

tests/unit/services/test_fetch_service.py (1)

15-17: Stop double-stacking identical markers.

Slapping both @pytest.mark.service and @pytest.mark.unit on the same damn class makes zero sense—pick one hierarchy or the other.

🧰 Tools
🪛 GitHub Actions: CI

[warning] 15-354: PytestUnknownMarkWarning: Unknown pytest marks 'service', 'unit', and 'integration' used in multiple test classes.

tests/README.md (2)

9-22: Code fences need a damn language tag.

markdownlint (MD040) is whining because this fence lacks a language. Add text (or none) so lint stays quiet.

-```
+```text
 tests/
 ├── conftest.py              # Shared fixtures and configuration
 ...

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

9-9: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

---

`185-186`: **Missing newline at EOF.**

Your file tripped the end-of-file fixer hook. Chuck a single newline at the very end and be done with it.

</blockquote></details>
<details>
<summary>tests/integration/real_api/README.md (1)</summary><blockquote>

`1-278`: **Trailing-newline & random grammar crap.**

Pre-commit had to autocorrect the missing newline. Keep one blank line at EOF so hooks stop moaning.  
Also, tiny grammar nit: “Use appropriate environment configuration” → “to use”. Not blocking, but tidy it up if you touch the file again.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~132-~132: Loose punctuation mark.
Context: ...ytest Markers  - `@pytest.mark.real_api`: Tests that make actual GitHub API calls...

(UNLIKELY_OPENING_PUNCTUATION)

---

[grammar] ~257-~257: Did you mean “to Use”?
Context: ...low tests separately when needed** 5. **Use appropriate environment configuration**...

(MISSING_TO_BEFORE_A_VERB)

</details>
<details>
<summary>🪛 GitHub Actions: CI</summary>

[error] 1-1: Pre-commit hook 'end-of-file-fixer' failed and modified this file to fix end of file issues.

</details>

</details>

</blockquote></details>
<details>
<summary>tests/integration/real_api/test_end_to_end_workflows.py (1)</summary><blockquote>

`24-207`: **Consider refactoring to reduce method complexity**

This method has 7 arguments and 67 statements, exceeding recommended limits. While the comprehensive testing is valuable, consider breaking it down into smaller helper methods.


Consider extracting workflow steps into helper methods:

```python
def _create_test_comment_if_needed(self, threads_data, pr_number, repo_full_name, integration_test_cleanup, rate_limit_aware_delay):
    """Create a test comment if no unresolved threads exist."""
    if not threads_data:
        # Extract lines 63-101 into this method
        ...
        
def _verify_thread_resolution(self, integration_cli_runner, pr_number, thread_id):
    """Verify that a thread is marked as resolved."""
    # Extract lines 173-198 into this method
    ...
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)

tests/integration/real_api/test_authentication_flows.py (1)

209-232: Incomplete test implementation

This test sets up an invalid token but doesn't actually test the behavior. The comment acknowledges this limitation.

Would you like me to help implement a proper test for unauthenticated behavior? We could:

  1. Temporarily unset the GH_TOKEN environment variable
  2. Test that commands fail with appropriate auth errors
  3. Restore the original environment
tests/integration/real_api/test_network_resilience.py (1)

197-201: Remove unnecessary else after break

The else block is unnecessary since the if block contains a break statement.

-                if "rate limit" in result.output.lower():
-                    print(f"Hit rate limit on request {i+1}")
-                    break
-                else:
-                    print(f"Request {i+1} failed for other reason: {result.output}")
+                if "rate limit" in result.output.lower():
+                    print(f"Hit rate limit on request {i+1}")
+                    break
+                print(f"Request {i+1} failed for other reason: {result.output}")
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 197-201: Unnecessary "else" after "break", remove the "else" and de-indent the code inside it

(R1723)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6042869 and 8213a9e.

📒 Files selected for processing (18)
  • pytest.ini (1 hunks)
  • tests/README.md (1 hunks)
  • tests/conftest.py (2 hunks)
  • tests/integration/cli/test_fetch_cli.py (1 hunks)
  • tests/integration/conftest.py (1 hunks)
  • tests/integration/real_api/README.md (1 hunks)
  • tests/integration/real_api/__init__.py (1 hunks)
  • tests/integration/real_api/test_authentication_flows.py (1 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
  • tests/integration/real_api/test_network_resilience.py (1 hunks)
  • tests/integration/real_api/test_performance_monitoring.py (1 hunks)
  • tests/unit/formatters/test_formatters.py (6 hunks)
  • tests/unit/models/test_model_edge_cases.py (1 hunks)
  • tests/unit/models/test_models.py (7 hunks)
  • tests/unit/services/test_fetch_service.py (4 hunks)
  • tests/unit/test_command_utils.py (3 hunks)
  • tests/unit/test_utils.py (1 hunks)
  • tests/unit/validators/test_node_id_validation.py (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
tests/conftest.py (1)
src/toady/models/models.py (2)
  • ReviewThread (39-317)
  • Comment (321-609)
tests/integration/real_api/test_performance_monitoring.py (1)
tests/integration/conftest.py (10)
  • integration_cli_runner (119-126)
  • verify_test_pr_exists (165-212)
  • performance_monitor (310-370)
  • start_timing (320-327)
  • stop_timing (329-341)
  • skip_if_slow (400-403)
  • assert_performance_threshold (351-368)
  • temp_cache_dir (130-137)
  • network_simulation (268-306)
  • simulate_slow_connection (284-290)
tests/integration/conftest.py (2)
src/toady/services/github_service.py (1)
  • GitHubService (134-704)
tests/conftest.py (1)
  • runner (22-24)
🪛 GitHub Actions: CI
tests/unit/validators/test_node_id_validation.py

[warning] 19-292: PytestUnknownMarkWarning: Unknown pytest marks 'validator' and 'unit' used in multiple test classes.

tests/integration/cli/test_fetch_cli.py

[warning] 12-13: PytestUnknownMarkWarning: Unknown pytest marks 'integration' and 'cli' used (lines 12-13).

tests/unit/formatters/test_formatters.py

[warning] 18-19: PytestUnknownMarkWarning: Unknown pytest marks 'formatter' and 'unit' used (lines 18-19).

tests/unit/test_command_utils.py

[warning] 16-102: PytestUnknownMarkWarning: Unknown pytest mark 'unit' used in multiple test functions.

tests/unit/services/test_fetch_service.py

[warning] 15-354: PytestUnknownMarkWarning: Unknown pytest marks 'service', 'unit', and 'integration' used in multiple test classes.

tests/unit/models/test_models.py

[warning] 12-1288: PytestUnknownMarkWarning: Unknown pytest marks 'model', 'unit', and 'slow' used in multiple test classes.

tests/unit/models/test_model_edge_cases.py

[warning] 11-185: PytestUnknownMarkWarning: Unknown pytest marks 'model' and 'unit' used in multiple test classes.

tests/integration/real_api/README.md

[error] 1-1: Pre-commit hook 'end-of-file-fixer' failed and modified this file to fix end of file issues.

tests/integration/real_api/test_end_to_end_workflows.py

[warning] 18-20: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', and 'slow' used (lines 18-20).

tests/unit/test_utils.py

[warning] 14-445: PytestUnknownMarkWarning: Unknown pytest mark 'unit' used in multiple test functions.

tests/integration/real_api/test_performance_monitoring.py

[warning] 22-25: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', 'performance', and 'slow' used (lines 22-25).

tests/integration/conftest.py

[error] 73-99: UnboundLocalError in github_api_health_check fixture: cannot access local variable 'json' where it is not associated with a value. This occurs in multiple test setups due to improper exception handling of json.JSONDecodeError.


[warning] 1-1: PytestCollectionWarning: cannot collect test class 'TestConfig' because it has a init constructor (scripts/test_config.py:22).

tests/integration/real_api/test_network_resilience.py

[error] 264-294: Test failure in test_rate_limit_status_monitoring: GitHub CLI command 'gh api rate_limit' returned exit code 4. Error message indicates missing GH_TOKEN environment variable for GitHub CLI in GitHub Actions workflow.


[warning] 18-21: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', and 'resilience' used (lines 18-21).

tests/integration/real_api/test_authentication_flows.py

[error] 73-92: Test failure in test_repository_access_permissions: GitHub CLI command 'gh api repos/toady-test/integration-testing' returned exit code 4. Error message indicates missing GH_TOKEN environment variable for GitHub CLI in GitHub Actions workflow.


[warning] 19-21: PytestUnknownMarkWarning: Unknown pytest marks 'integration', 'real_api', and 'auth' used (lines 19-21).

🪛 markdownlint-cli2 (0.17.2)
tests/README.md

9-9: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🪛 LanguageTool
tests/integration/real_api/README.md

[uncategorized] ~132-~132: Loose punctuation mark.
Context: ...ytest Markers - @pytest.mark.real_api: Tests that make actual GitHub API calls...

(UNLIKELY_OPENING_PUNCTUATION)


[grammar] ~257-~257: Did you mean “to Use”?
Context: ...low tests separately when needed** 5. Use appropriate environment configuration...

(MISSING_TO_BEFORE_A_VERB)

🪛 Pylint (3.3.7)
tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)


[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

tests/unit/test_utils.py

[refactor] 15-15: Too few public methods (1/2)

(R0903)


[refactor] 25-25: Too many public methods (22/20)

(R0904)


[refactor] 396-396: Too few public methods (0/2)

(R0903)

tests/integration/real_api/test_performance_monitoring.py

[refactor] 29-29: Too many local variables (17/15)

(R0914)


[refactor] 490-490: Too many local variables (16/15)

(R0914)


[refactor] 557-557: Too many local variables (17/15)

(R0914)

tests/integration/conftest.py

[refactor] 42-42: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 165-165: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 414-414: Either all return statements in a function should return an expression, or none of them should.

(R1710)

tests/integration/real_api/test_network_resilience.py

[refactor] 197-201: Unnecessary "else" after "break", remove the "else" and de-indent the code inside it

(R1723)

🔇 Additional comments (8)
pytest.ini (1)

43-45: These fucking markers look solid!

Nice job adding categorization for auth, resilience, and performance tests. Keeps shit organized.

tests/conftest.py (3)

15-18: Clean fucking optimization for traceback output!

Setting default traceback style is a nice touch for cleaner test output.


362-396: This test data generator is fucking brilliant!

Love the flexibility with status handling and the attached method for generating comments. Clever shit right there.


399-407: Sensible fucking baselines!

These performance thresholds look reasonable for catching performance regressions.

tests/integration/conftest.py (1)

267-371: This testing infrastructure is fucking amazing!

The network simulator and performance monitor are goddamn beautiful. Perfect for testing real-world scenarios and catching performance regressions.

tests/integration/real_api/__init__.py (1)

1-5: Nothing to fucking complain about here.

tests/unit/test_command_utils.py (1)

16-16: Good shit marking these as unit tests!

The pipeline's bitching about unknown markers, but that's bullshit - they're defined in pytest.ini. Probably a test discovery timing issue.

Also applies to: 53-53, 102-102

🧰 Tools
🪛 GitHub Actions: CI

[warning] 16-102: PytestUnknownMarkWarning: Unknown pytest mark 'unit' used in multiple test functions.

tests/integration/real_api/test_performance_monitoring.py (1)

89-140: Well-implemented memory monitoring with psutil

Good defensive programming by checking if psutil is available and skipping the test if not. The memory leak detection logic is sound.

- Updated `pytest.ini` to streamline configuration, changing `[tool:pytest]` to `[pytest]` and correcting `python_paths` to `pythonpath`.
- Added environment variable `GH_TOKEN` in the CI workflow for GitHub authentication.
- Modified `ci_check.py` to exclude integration tests from the pytest run.
- Adjusted import paths in `github_service.py` to reflect the new module structure.
- Renamed `check_reply_content_warnings` to `validate_reply_content_warnings` for clarity and updated corresponding tests.
- Cleaned up imports in `conftest.py` to remove redundancy.

These changes aim to improve test organization, CI functionality, and code clarity.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
tests/test_validation.py (2)

22-23: Update class/docstring names to match the renamed helper

You switched the import to validate_reply_content_warnings, but the test class is still called TestCheckReplyContentWarnings and its docstrings still mention check rather than validate. Renaming those will avoid confusion for future readers.

-class TestCheckReplyContentWarnings:
+class TestValidateReplyContentWarnings:

Same for the short docstring on line 585.


589-620: Consider consolidating repeated calls into a parametrized test

All six test cases exercise the same helper with different inputs/expected substrings. Using @pytest.mark.parametrize would shrink boilerplate and surface failures more cleanly:

-    def test_mention_warning(self):
-        ...
-    def test_repetitive_content_warning(self):
-        ...
-    ...
+    @pytest.mark.parametrize(
+        ("body", "expect_in", "expected_len"),
+        [
+            ("This is a normal reply", [], 0),
+            ("@user this is a mention", ["mention users"], 1),
+            ("aaaaaaaaaaaaaaaa", ["repetitive content"], 1),
+            ("THIS IS ALL CAPS CONTENT", ["ALL CAPS"], 1),
+            ("What?!?!?! Why?!?!?!", ["excessive punctuation"], 1),
+            ("@USER WHAT?!?!?! WHY?!?!?!",
+             ["mention users", "ALL CAPS", "excessive punctuation"], 3),
+        ],
+    )
+    def test_reply_content_warnings(self, body, expect_in, expected_len):
+        warnings = validate_reply_content_warnings(body)
+        for phrase in expect_in:
+            assert any(phrase in w for w in warnings)
+        assert len(warnings) == expected_len

Cleaner, less duplication.

tests/integration/conftest.py (2)

54-55: Kill the duplicate json imports, damn it.

You’re yanking json into scope three separate times. Slam that import once at the top of the file and be done with it—cleaner and microscopically faster.

Also applies to: 199-201, 429-431


248-263: Back-off math can nuke your test run.

base_delay * (2**attempt) explodes quickly (1 → 2 → 4 s …). With max_retry_attempts==3 you’re fine, but crank that env var and you’ll be staring at your screen for ages. Cap the total or switch to min(exponent, MAX_SLEEP).

tests/integration/real_api/README.md (1)

130-137: Minor typo & punctuation.

“Pytest Markers -” → drop the stray space before the hyphen. While you’re at it, the table header could use a period for consistency.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~132-~132: Loose punctuation mark.
Context: ...ytest Markers - @pytest.mark.real_api: Tests that make actual GitHub API calls...

(UNLIKELY_OPENING_PUNCTUATION)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8213a9e and 94f61e3.

📒 Files selected for processing (8)
  • .github/workflows/ci.yml (1 hunks)
  • pytest.ini (2 hunks)
  • scripts/ci_check.py (1 hunks)
  • src/toady/services/github_service.py (3 hunks)
  • src/toady/validators/validation.py (1 hunks)
  • tests/integration/conftest.py (1 hunks)
  • tests/integration/real_api/README.md (1 hunks)
  • tests/test_validation.py (2 hunks)
✅ Files skipped from review due to trivial changes (3)
  • .github/workflows/ci.yml
  • src/toady/validators/validation.py
  • src/toady/services/github_service.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • pytest.ini
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/test_validation.py (1)
src/toady/validators/validation.py (1)
  • validate_reply_content_warnings (866-893)
tests/integration/conftest.py (2)
src/toady/services/github_service.py (1)
  • GitHubService (134-704)
tests/conftest.py (1)
  • runner (22-24)
🪛 LanguageTool
tests/integration/real_api/README.md

[uncategorized] ~132-~132: Loose punctuation mark.
Context: ...ytest Markers - @pytest.mark.real_api: Tests that make actual GitHub API calls...

(UNLIKELY_OPENING_PUNCTUATION)


[grammar] ~257-~257: Did you mean “to Use”?
Context: ...low tests separately when needed** 5. Use appropriate environment configuration...

(MISSING_TO_BEFORE_A_VERB)

🪛 Pylint (3.3.7)
tests/integration/conftest.py

[refactor] 42-42: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 165-165: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 414-414: Either all return statements in a function should return an expression, or none of them should.

(R1710)

⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: test (macos-latest, 3.10)
  • GitHub Check: test (macos-latest, 3.12)
  • GitHub Check: test (macos-latest, 3.11)
  • GitHub Check: test (macos-latest, 3.9)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.8)
  • GitHub Check: test (ubuntu-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (ubuntu-latest, 3.12)
  • GitHub Check: test (ubuntu-latest, 3.10)
  • GitHub Check: test (ubuntu-latest, 3.9)
🔇 Additional comments (1)
scripts/ci_check.py (1)

204-206: Exclude the right crap.

You skip integration tests, but the new suite is tagged real_api, auth, etc. Consider -m "not integration and not real_api" (or similar) so the CI doesn’t choke on live-API calls.

- Updated `.env.example` to include new test-related environment variables for integration testing.
- Added `python-dotenv` dependency in `requirements-dev.txt` for loading environment variables.
- Modified CI workflow to utilize new environment variables for testing configuration.
- Refactored `fetch.py` and `pr_selector.py` to support output format options for better user experience.
- Improved error handling in `pr_selector.py` for JSON mode to prevent interactive prompts.

These changes aim to streamline the testing process and improve the flexibility of the CI setup.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/toady/services/pr_selector.py (3)

18-28: Lower-case once, reuse everywhere

output_format == "json" will fail when the CLI receives "JSON"/"Json". Call .lower() once in the ctor and store the normalised value; all later checks then work.


48-58: Returning None silently loses context

In JSON mode with multiple PRs you write an error message then return None, causing the caller to treat it as a user cancel. That swallows the “this is actually an error” signal. Consider raising a dedicated exception (e.g. InteractiveSelectionNotSupported) so the command can exit with a non-zero code in CI.


74-80: Redundant blank echoes

click.echo(err=self.is_json_mode) prints empty lines to stderr. Not harmful, but costs a pointless write. Replace with if not self.is_json_mode: click.echo() for clarity.

tests/integration/real_api/test_end_to_end_workflows.py (1)

208-246: skip_if_slow fixture unused

The fixture is requested but never referenced, so PyTest will still execute the heavy test when TOADY_SKIP_SLOW_TESTS=true. Add skip_if_slow early in the body or drop the parameter.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94f61e3 and 5408154.

📒 Files selected for processing (9)
  • .env.example (1 hunks)
  • .github/workflows/ci.yml (1 hunks)
  • requirements-dev.txt (1 hunks)
  • scripts/ci_check.py (1 hunks)
  • src/toady/commands/fetch.py (1 hunks)
  • src/toady/services/fetch_service.py (1 hunks)
  • src/toady/services/pr_selector.py (5 hunks)
  • tests/integration/conftest.py (1 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • requirements-dev.txt
  • .env.example
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/ci_check.py
  • .github/workflows/ci.yml
🧰 Additional context used
🧠 Learnings (1)
tests/integration/real_api/test_end_to_end_workflows.py (2)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
🧬 Code Graph Analysis (2)
src/toady/commands/fetch.py (1)
src/toady/services/fetch_service.py (1)
  • FetchService (21-354)
tests/integration/conftest.py (2)
src/toady/services/github_service.py (1)
  • GitHubService (134-704)
tests/conftest.py (1)
  • runner (22-24)
🪛 Pylint (3.3.7)
tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)


[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

tests/integration/conftest.py

[refactor] 51-51: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 196-196: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 445-445: Either all return statements in a function should return an expression, or none of them should.

(R1710)

⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: test (macos-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (ubuntu-latest, 3.12)
  • GitHub Check: test (macos-latest, 3.10)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (macos-latest, 3.9)
  • GitHub Check: test (macos-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: test (ubuntu-latest, 3.9)
  • GitHub Check: test (ubuntu-latest, 3.11)
  • GitHub Check: test (ubuntu-latest, 3.10)
🔇 Additional comments (2)
src/toady/commands/fetch.py (1)

138-142: Pass-through of output_format looks fine but watch other call sites

FetchService now expects an output_format param. This call site was updated, but double-check other instantiations (e.g. tests, utilities) to avoid silent fallback to "pretty" when JSON was intended.

tests/integration/conftest.py (1)

51-111: Mixed return / skip paths trigger Pylint R1710

github_api_health_check sometimes returns True, otherwise always raises pytest.skip, satisfying control-flow expectations. The diagnostic can safely be ignored or silenced with # pylint: disable=R1710.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 51-51: Either all return statements in a function should return an expression, or none of them should.

(R1710)

- Added validation for the `output_format` parameter in `FetchService` to ensure only supported formats ("json" or "pretty") are accepted, raising a ValueError for unsupported formats.
- Updated `PRSelector` to suppress output in JSON mode, preventing compatibility issues and ensuring cleaner output handling.
- Adjusted test cases in `test_end_to_end_workflows.py` to accommodate changes in output handling and improve error reporting for JSON decoding.

These changes aim to enhance user experience and maintain output integrity across different modes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/integration/real_api/test_end_to_end_workflows.py (2)

24-41: This test is a god-damn monolith – break it the hell up.

test_complete_review_cycle_workflow crams fetching, commenting, replying, resolving, verification and perf timing into one 200-line beast. When it fails, you’ll be spelunking through a mountain of shit to see which step blew up.

Extract helper funcs (e.g. fetch_threads, post_reply, resolve_thread, assert_resolved) or split into smaller tests. Your future self will thank you, and pylint will stop whining about “too many statements / locals”.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)


208-216: Fixture skip_if_slow is hauled in but never used – dead weight.

If the fixture’s sole purpose is to skip inside itself, cool, but if not, drop it from the arg list to shut up the “unused argument” noise.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5408154 and da55284.

📒 Files selected for processing (3)
  • src/toady/services/fetch_service.py (1 hunks)
  • src/toady/services/pr_selector.py (6 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/toady/services/fetch_service.py
  • src/toady/services/pr_selector.py
🧰 Additional context used
🧠 Learnings (1)
tests/integration/real_api/test_end_to_end_workflows.py (2)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
🪛 Pylint (3.3.7)
tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)


[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: test (macos-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: test (macos-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (macos-latest, 3.9)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (macos-latest, 3.10)
  • GitHub Check: test (ubuntu-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (ubuntu-latest, 3.9)
  • GitHub Check: test (ubuntu-latest, 3.12)
  • GitHub Check: test (ubuntu-latest, 3.10)
🔇 Additional comments (3)
tests/integration/real_api/test_end_to_end_workflows.py (3)

65-82: Double-check the comment-creation output or you’ll delete the wrong damn thing.

gh pr comment … is assumed to spit the comment URL on stdout, and you shove that straight into cleanup. Depending on the user’s gh-CLI version and locale, stdout might be a friendly sentence (“Created comment https://…”) instead of a clean URL.

At minimum, parse the JSON output:

-            create_result = subprocess.run(
-                ["gh", "pr", "comment", str(pr_number), "--repo", repo_full_name, "--body", test_comment_body],
-                capture_output=True, text=True, timeout=30,
-            )
+            create_result = subprocess.run(
+                [
+                    "gh", "pr", "comment",
+                    str(pr_number),
+                    "--repo", repo_full_name,
+                    "--body", test_comment_body,
+                    "--json", "url",               # guarantees machine-readable output
+                    "--jq", ".url"
+                ],
+                capture_output=True,
+                text=True,
+                timeout=30,
+            )

Then hand the parsed URL to your cleanup job.


333-337: Nice guard against Click-7 vs 8 – solid.

Using getattr(result, "stdout", result.output) prevents that nasty AttributeError. No complaints here.


403-411: gh api DELETE might puke on a full URL – slice the endpoint, champ.

gh api expects a path like /repos/owner/repo/pulls/comments/123456. Feeding it the raw https://github.com/... can 404. Consider:

-            subprocess.run(
-                ["gh", "api", "--method", "DELETE", comment_url],
+            endpoint=${comment_url#https://api.github.com}
+            subprocess.run(
+                ["gh", "api", "--method", "DELETE", endpoint],

or just call gh pr comment --delete with the ID. Verify this before the cleanup silently fails and leaves test litter.

- Introduced a new test suite for the CLI module, covering group setup, version display, command registration, context handling, and error handling.
- Added unit tests for command modules including `fetch`, `reply`, `resolve`, and `schema`, focusing on core logic, parameter validation, error handling, and service integration.
- Enhanced test coverage with edge cases and boundary conditions to ensure robust functionality across various scenarios.
- Updated documentation for command unit tests to reflect the new structure and coverage details.

These changes aim to improve the reliability and maintainability of the CLI and command modules, ensuring a solid foundation for future development.
@tonyblank
Copy link
Owner Author

@coderabbitai review

- Transitioned development dependencies from `requirements-dev.txt` to `pyproject.toml` for improved management and clarity.
- Updated CI workflow to install dependencies using the new `pyproject.toml` format, enhancing compatibility and streamlining the installation process.
- Removed deprecated entries from `requirements-dev.txt`, marking it for backward compatibility only.
- Adjusted caching keys in CI to reflect changes in dependency management.

These changes aim to modernize the project structure and improve the efficiency of the CI pipeline.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
pyproject.toml (1)

166-167: ⚠️ Potential issue

pytest-timeout is gone – these damn options will explode

You nuked the pytest-timeout plugin from dependencies, yet the timeout keys stay while --strict-config is enabled. Pytest will puke with “unknown config option” and fail the whole suite.

Either yank the lines or add the plugin back.

🧹 Nitpick comments (7)
.github/workflows/ci.yml (1)

102-104: Stop sweeping test failures under the rug

continue-on-error: true lets busted integration tests quietly pass. If these real-API checks matter, make the pipeline fail so we actually catch the fuck-ups; otherwise run them as a separate, optional workflow.

tests/unit/commands/README.md (1)

3-4: Drop the redundant crap

“CLI interface” – the “I” already stands for interface, genius. Trim to “CLI”.

🧰 Tools
🪛 LanguageTool

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ... core command logic without testing the CLI interface directly. ## Structure - `init.py...

(ACRONYM_TAUTOLOGY)

tests/unit/commands/test_reply.py (3)

75-78: Don’t return a bloody Mock when a plain string will do, mate.

mock_validator.validate_id.return_value = Mock(value="numeric") is pointless. The production code only cares about the return value itself, not a .value attr. Just make it return "numeric" and keep the mocking simple (and faster).


494-506: Mock the damn click.Context with a spec, not a shapeless blob.

ctx = Mock() gives you a formless mock that may silently swallow bad attribute access. Use Mock(spec=click.Context) so the test blows up if _show_id_help tries to touch some non-existent attribute. Keeps the suite honest.


927-930: Stop copy-pasting this runner fixture all over the place.

You’ve got the exact same runner() factory littered across multiple test modules. Chuck it into tests/conftest.py once and let pytest handle the damn sharing. Less duplication, fewer headaches.

tests/unit/commands/test_fetch.py (2)

204-206: This assertion is fragile as hell.

assert_called_once_with(pr_number=456, include_resolved=True, threads_limit=50) assumes the fetch command never forwards include_drafts or any future kwarg. One extra parameter and this test explodes for no good reason. Stick to assert_called_once() then inspect call_args[1] for the few keys you actually care about.


730-733: Again with the runner clone-army…

Same rant as in test_reply.py: centralize this CliRunner fixture in tests/conftest.py and quit duplicating it like rabbits.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da55284 and 4e13870.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml (2 hunks)
  • pyproject.toml (1 hunks)
  • requirements-dev.txt (1 hunks)
  • tests/unit/commands/README.md (1 hunks)
  • tests/unit/commands/__init__.py (1 hunks)
  • tests/unit/commands/test_fetch.py (1 hunks)
  • tests/unit/commands/test_reply.py (1 hunks)
  • tests/unit/commands/test_resolve.py (1 hunks)
  • tests/unit/commands/test_schema.py (1 hunks)
  • tests/unit/test_cli.py (1 hunks)
  • tests/unit/validators/test_validation.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/unit/commands/init.py
🧰 Additional context used
🧬 Code Graph Analysis (4)
tests/unit/commands/test_fetch.py (5)
src/toady/cli.py (1)
  • cli (23-89)
tests/unit/test_cli.py (1)
  • runner (477-479)
tests/unit/commands/test_reply.py (1)
  • runner (927-929)
tests/unit/commands/test_resolve.py (1)
  • runner (1003-1005)
src/toady/services/fetch_service.py (1)
  • fetch_review_threads_with_pr_selection (296-362)
tests/unit/commands/test_reply.py (7)
src/toady/commands/reply.py (9)
  • reply (497-615)
  • _build_json_reply (250-292)
  • _handle_reply_error (333-461)
  • _print_pretty_reply (211-247)
  • _show_id_help (28-92)
  • _show_progress (320-330)
  • _show_warnings (295-317)
  • _validate_reply_args (160-208)
  • validate_reply_target_id (95-157)
src/toady/services/reply_service.py (1)
  • ReplyRequest (23-29)
src/toady/validators/node_id_validation.py (1)
  • validate_id (181-209)
tests/unit/validators/test_validation.py (2)
  • test_repetitive_content_warning (1397-1408)
  • test_no_warnings_for_normal_content (1358-1369)
tests/unit/test_cli.py (1)
  • runner (477-479)
tests/unit/commands/test_fetch.py (1)
  • runner (731-733)
tests/unit/commands/test_resolve.py (1)
  • runner (1003-1005)
tests/unit/commands/test_schema.py (4)
src/toady/commands/schema.py (6)
  • schema (25-28)
  • _display_query_validation_results (404-459)
  • _display_summary_report (322-401)
  • _has_critical_errors (462-509)
  • check (240-319)
  • validate (48-138)
src/toady/exceptions.py (1)
  • ToadyError (71-120)
src/toady/validators/schema_validator.py (4)
  • SchemaValidationError (22-40)
  • fetch_schema (142-193)
  • generate_compatibility_report (558-588)
  • validate_query (219-273)
tests/unit/test_cli.py (1)
  • runner (477-479)
tests/unit/test_cli.py (5)
src/toady/cli.py (1)
  • cli (23-89)
src/toady/exceptions.py (1)
  • ToadyError (71-120)
tests/unit/commands/test_fetch.py (1)
  • runner (731-733)
tests/unit/commands/test_reply.py (1)
  • runner (927-929)
tests/unit/commands/test_resolve.py (1)
  • runner (1003-1005)
🪛 Pylint (3.3.7)
tests/unit/commands/test_fetch.py

[refactor] 61-61: Too many arguments (6/5)

(R0913)


[refactor] 61-61: Too many positional arguments (6/5)

(R0917)


[refactor] 87-87: Too many arguments (6/5)

(R0913)


[refactor] 87-87: Too many positional arguments (6/5)

(R0917)

tests/unit/commands/test_reply.py

[refactor] 489-489: Too few public methods (1/2)

(R0903)

🪛 LanguageTool
tests/unit/commands/README.md

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ... core command logic without testing the CLI interface directly. ## Structure - `init.py...

(ACRONYM_TAUTOLOGY)


[uncategorized] ~14-~14: Possible missing comma found.
Context: ...c/toady/commands/fetch.py`) with 95.71% coverage including: #### Test Classes: 1. **Te...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
tests/unit/commands/README.md

16-16: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test (windows-latest, 3.12)
🔇 Additional comments (2)
requirements-dev.txt (1)

1-8: All good – just a legacy note

File is deprecated, message is clear.

tests/unit/validators/test_validation.py (1)

1-10: Monstrous test suite looks solid

The gargantuan validator tests read fine – nothing obvious to bitch about.

- Updated `pyproject.toml` to adjust `python-dotenv` and `types-click` versions for better compatibility.
- Removed the deprecated `requirements-dev.txt` file, consolidating dependency management within `pyproject.toml`.
- Added new checks in `ci_check.py` for trailing whitespace and proper end-of-file formatting to improve code quality.
- Updated tests to reflect the removal of `requirements-dev.txt` and improved error messages in schema validation tests.

These changes aim to streamline dependency management and enhance code quality checks in the CI pipeline.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/unit/commands/test_schema.py (1)

221-221: Line length exceeds Ruff default (E501)

These literal-string assertions run 90 chars and trigger E501. If E501 isn’t globally disabled for tests, wrap the string or split it to keep ≤ 88 chars, or add # noqa: E501 locally.

Also applies to: 374-374, 530-530, 704-704

🧰 Tools
🪛 Ruff (0.11.9)

221-221: Line too long (90 > 88)

(E501)

tests/unit/commands/README.md (1)

3-3: Minor wording nit

“CLI interface” is tautological; consider dropping “interface” to read “testing the CLI directly.”

🧰 Tools
🪛 LanguageTool

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ... core command logic without testing the CLI interface directly. ## Structure - `init.py...

(ACRONYM_TAUTOLOGY)

tests/unit/test_cli.py (1)

254-259: Readability of combined context managers

with patch.dict(...), pytest.raises(...): is valid but easy to misread. Consider nesting or using a single with per context manager for clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e13870 and 57c1bbb.

📒 Files selected for processing (7)
  • pyproject.toml (1 hunks)
  • requirements-dev.txt (0 hunks)
  • scripts/ci_check.py (3 hunks)
  • tests/test_setup.py (0 hunks)
  • tests/unit/commands/README.md (1 hunks)
  • tests/unit/commands/test_schema.py (1 hunks)
  • tests/unit/test_cli.py (1 hunks)
💤 Files with no reviewable changes (2)
  • tests/test_setup.py
  • requirements-dev.txt
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/unit/test_cli.py (5)
src/toady/cli.py (1)
  • cli (23-89)
src/toady/exceptions.py (1)
  • ToadyError (71-120)
tests/unit/commands/test_fetch.py (1)
  • runner (731-733)
tests/unit/commands/test_reply.py (1)
  • runner (927-929)
tests/unit/commands/test_resolve.py (1)
  • runner (1003-1005)
🪛 Ruff (0.11.9)
tests/unit/commands/test_schema.py

221-221: Line too long (90 > 88)

(E501)


374-374: Line too long (90 > 88)

(E501)


530-530: Line too long (90 > 88)

(E501)


704-704: Line too long (90 > 88)

(E501)

🪛 LanguageTool
tests/unit/commands/README.md

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ... core command logic without testing the CLI interface directly. ## Structure - `init.py...

(ACRONYM_TAUTOLOGY)


[uncategorized] ~14-~14: Possible missing comma found.
Context: ...c/toady/commands/fetch.py`) with 95.71% coverage including: #### Test Classes: 1. **Te...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
tests/unit/commands/README.md

16-16: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

🔇 Additional comments (1)
scripts/ci_check.py (1)

236-269: Verify local availability of the dedicated pre-commit hooks

pre-commit run trailing-whitespace … and end-of-file-fixer … will error out if those hooks aren’t installed locally (e.g., dev machine without pre-commit install). Because run_pre_commit_hooks is omitted from the fast pipeline, the fast path has no installation step. Please confirm the hooks are guaranteed to exist or add an install/update step before running them.

Also applies to: 400-401

Tony Blank and others added 3 commits June 13, 2025 08:41
- Fixed 9 failing unit tests with updated error message expectations
- Updated parser tests to match actual behavior (empty comment handling, datetime validation)
- Fixed service tests with correct exception types
- Reinstalled pre-commit hooks with proper uv integration
- Auto-formatted files with black pre-commit hook

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Removed Python 3.8 from the CI matrix in `.github/workflows/ci-uv.yml` and `.github/workflows/ci.yml` to streamline testing environments.
- Adjusted `envlist` in `pyproject.toml` to reflect the updated Python versions.
- Enhanced the `TestRateLimitHandling` class in `test_network_resilience.py` to skip tests if GitHub CLI is not authenticated, improving test reliability in CI environments.

These changes aim to modernize the CI setup and ensure more robust testing practices.
- Eliminated the conditional statement that restricted the integration test job to specific events, simplifying the CI configuration.
- This change aims to ensure that integration tests run consistently without being tied to specific GitHub events, enhancing the reliability of the CI process.
@tonyblank
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🔭 Outside diff range comments (3)
src/toady/validators/node_id_validation.py (1)

1-10: 🛠️ Refactor suggestion

⚠️ Potential issue

Fix your damn generics – this explodes on Python 3.8

list[str] and set[GitHubEntityType] only resolve without puking starting in 3.9.
Your CI matrix still drags along 3.8, so importing this module will raise TypeError: 'type' object is not subscriptable.

Shove in the future-annotations import (or back-pedal to List/Set) before the rest of the file:

+from __future__ import annotations

Dump it right after the docstring to shut 3.8 up and keep the rest of the modern typing candy.

Also applies to: 69-80

pyproject.toml (1)

276-283: 🛠️ Refactor suggestion

tox matrix contradicts supported Python

requires-python = ">=3.9" but tox still lists py38.
Drop 3.8 or lower the minimum version to avoid CI failures.

src/toady/commands/schema.py (1)

110-118: ⚠️ Potential issue

Using sys.exit inside library-ish code? Yikes.

Bailing out right here means this function can’t be unit-tested without monkey-patching sys.exit. Return an exit-code or raise a custom CommandAborted instead, then let the CLI entry-point handle the actual exit.

♻️ Duplicate comments (4)
pyproject.toml (1)

57-58: ⚠️ Potential issue

Stub version now mismatches Click again

click>=8.1.7 pairs with types-click>=8.1.0.
Downgrading stubs to 7.1.8 will bring back mypy incompatibility.

-    "types-click>=7.1.8",
+    "types-click>=8.1.0",
tests/unit/commands/test_resolve.py (1)

117-122: ⚠️ Potential issue

Incorrect patch target re-introduced

_validate_resolve_parameters() imports validate_limit from toady.commands.resolve, not from toady.command_utils.
Patching the wrong symbol means the real function isn’t mocked and the test may blow up with ModuleNotFoundError.

-@patch("toady.command_utils.validate_limit")
+@patch("toady.commands.resolve.validate_limit")
tests/integration/conftest.py (1)

64-113: 🛠️ Refactor suggestion

Move json import outside the try-block

json.JSONDecodeError is caught in the except, but json is only imported inside the try.
If anything fails before that import runs (e.g. subprocess.TimeoutExpired), you’ll hit UnboundLocalError.

-    import json
-
-    try:
+    import json
+    try:
         # … rest of code …

Then drop the inner import json at line 231/461 as well to avoid duplicate imports.
This was flagged in a prior review—let’s kill it everywhere.

tests/integration/real_api/test_end_to_end_workflows.py (1)

190-199: Same bloody mistake – use the guarded stdout

You fixed it once, but lines 192-199 still assume result.output.
Wrap it with the getattr guard or expect CI to punch you in the gut again.

🧹 Nitpick comments (16)
.github/workflows/ci-uv.yml (1)

41-44: Codecov action v3 is a crusty fossil

codecov/codecov-action@v3 can choke on the latest runners (see actionlint gripe).
Bump to @v4 before it embarrasses your pipeline.

-      uses: codecov/codecov-action@v3
+      uses: codecov/codecov-action@v4
🧰 Tools
🪛 actionlint (1.7.7)

42-42: the runner of "codecov/codecov-action@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

tests/unit/parsers/test_parsers.py (1)

4-5: Redundant import

from typing import Any is the only name imported and is still required after switching to dict[str, Any], but if no other typing symbols are used in this file consider narrowing to:

from typing import Any

(or drop the import entirely if Any is no longer referenced).

tests/unit/services/test_resolve_service.py (1)

820-834: Pathological response still triggers KeyError early

You craft a response missing the thread key to provoke the “no thread data returned” path, but ResolveService.resolve_thread dereferences ["thread"] only after ensuring the mutation key exists.
If future implementation details shift, this test might instead raise KeyError and fail.
Consider using the public helper (_handle_mutation_response or similar) or asserting generically on ResolveServiceError without the exact message to keep the test resilient to refactors.

tests/unit/services/test_reply_service.py (1)

333-345: Coupling tests to private fallback implementation

Patching _post_reply_fallback_rest ties the test to a private helper that could be renamed or inlined.
A more future-proof approach is to assert that github_service.post_reply was not called when a numeric ID is supplied and that the public post_reply returns the expected result.
This keeps the test focused on observable behaviour, not internals.

tests/unit/test_utils.py (1)

193-208: Patch path brittle

patch("toady.utils.datetime") replaces the imported datetime class.
If utils.parse_datetime ever starts doing import datetime as dt the patch will silently miss. Consider patching the specific strptime attribute instead:

-with patch("toady.utils.datetime") as mock_datetime:
-    mock_datetime.strptime.side_effect = ValueError("test parsing error")
+with patch("toady.utils.datetime.strptime", side_effect=ValueError("test parsing error")):
     ...
tests/unit/commands/test_reply.py (1)

674-742: Minor readability tip

Decorator order already correct, but adding a short comment avoids head-scratching:

# param order: mock_resolve_format, mock_service_class, runner
@patch("toady.commands.reply.ReplyService")
@patch("toady.commands.reply.resolve_format_from_options")
src/toady/formatters/format_interfaces.py (1)

158-163: Repeated import inside hot path

json is imported on every fallback; move it to module level to avoid tiny but needless overhead:

-from typing import Any, Optional, Union
+from typing import Any, Optional, Union
+import json
...
-    try:
-        import json
+    try:
src/toady/formatters/pretty_formatter.py (1)

561-578: Pylint is right—this helper is ballooning

_format_table cracks the 20-local-vars and 13-branch thresholds. Readability is already strained.

Consider extracting:

  1. header/width calculation
  2. row rendering
    into private helpers to keep the cyclomatic complexity sane.

Not urgent for functionality but future maintainers will thank you.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 561-561: Too many local variables (20/15)

(R0914)


[refactor] 561-561: Too many branches (13/12)

(R0912)

tests/unit/test_cli.py (1)

473-476: Duplicate runner fixture – drop it to avoid confusion

tests/conftest.py already exports an identically-named runner fixture.
Redefining it here shadows the global one and risks diverging behaviour later.
Delete these lines and import the shared fixture instead.

src/toady/parsers/parsers.py (1)

559-577: Redundant error branch – simplify to a single raise

Lines 571-576 raise the same validation error already handled at 577-582, inflating cyclomatic complexity for no gain.
Delete the inner block and keep one definitive raise create_validation_error(...).

src/toady/error_handling.py (1)

9-10: Tiny import nit

sys now sits between std-enum and typing. It’s harmless, but the import order looks like a drunk octopus arranged it. Chuck sys up top with the other stdlib junk or run isort and be done with it.

src/toady/commands/schema.py (1)

60-72: Copy-pasted try/except hell – DRY this shit

Every damn block re-wraps GitHubSchemaValidator(...) with the same FileOperation/ConfigurationError boilerplate. Factor that into a helper so we don’t scroll past the same 10 lines six times. Your future self will thank you instead of cursing you.

tests/unit/test_format_selection.py (1)

49-52: Dead code makes the test smell like ass

Inside the with patch.dict(..., clear=True) block the env is already nuked; the manual del os.environ[...] dance is pointless noise. Axe it.

src/toady/formatters/formatters.py (1)

22-35: Missing type guard means None will crash hard

OutputFormatter.format_threads assumes threads is a list, then punts to JSON/Pretty. If someone passes None you’ll get a blow-up later. Do a cheap if not threads: early and return "[]" or "No review threads found." instead of a face-plant.

tests/integration/real_api/test_authentication_flows.py (1)

49-53: Pointless class attribute – nuke it

self.current_user_login is set but never read anywhere.
Dead code = dead weight. Drop the assignment or wire it into another test.

Makefile (1)

1-3: Missing .PHONY: all

Lots of targets, but the traditional all phony is MIA, tripping checkmake.
Add it or silence the linter warnings.

🧰 Tools
🪛 checkmake (0.2.2)

[warning] 3-3: Missing required phony target "all"

(minphony)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57c1bbb and 5b68a1e.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (60)
  • .github/workflows/ci-uv.yml (1 hunks)
  • Makefile (4 hunks)
  • pyproject.toml (3 hunks)
  • scripts/ci_check.py (7 hunks)
  • scripts/test_config.py (3 hunks)
  • src/toady/cli.py (1 hunks)
  • src/toady/commands/reply.py (5 hunks)
  • src/toady/commands/resolve.py (8 hunks)
  • src/toady/commands/schema.py (18 hunks)
  • src/toady/error_handling.py (3 hunks)
  • src/toady/exceptions.py (3 hunks)
  • src/toady/formatters/format_interfaces.py (16 hunks)
  • src/toady/formatters/format_selection.py (6 hunks)
  • src/toady/formatters/formatters.py (5 hunks)
  • src/toady/formatters/json_formatter.py (19 hunks)
  • src/toady/formatters/pretty_formatter.py (15 hunks)
  • src/toady/models/models.py (13 hunks)
  • src/toady/parsers/graphql_parser.py (12 hunks)
  • src/toady/parsers/graphql_queries.py (5 hunks)
  • src/toady/parsers/parsers.py (23 hunks)
  • src/toady/services/fetch_service.py (9 hunks)
  • src/toady/services/github_service.py (11 hunks)
  • src/toady/services/pr_selection.py (5 hunks)
  • src/toady/services/pr_selector.py (7 hunks)
  • src/toady/services/reply_service.py (9 hunks)
  • src/toady/services/resolve_service.py (18 hunks)
  • src/toady/utils.py (4 hunks)
  • src/toady/validators/node_id_validation.py (3 hunks)
  • src/toady/validators/schema_validator.py (21 hunks)
  • src/toady/validators/validation.py (8 hunks)
  • tests/conftest.py (2 hunks)
  • tests/integration/cli/test_fetch_cli.py (1 hunks)
  • tests/integration/cli/test_reply_cli.py (1 hunks)
  • tests/integration/cli/test_resolve_cli.py (1 hunks)
  • tests/integration/conftest.py (1 hunks)
  • tests/integration/real_api/test_authentication_flows.py (1 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
  • tests/integration/real_api/test_network_resilience.py (1 hunks)
  • tests/integration/real_api/test_performance_monitoring.py (1 hunks)
  • tests/integration/test_schema_validation_integration.py (1 hunks)
  • tests/unit/commands/test_fetch.py (1 hunks)
  • tests/unit/commands/test_reply.py (1 hunks)
  • tests/unit/commands/test_resolve.py (1 hunks)
  • tests/unit/commands/test_schema.py (1 hunks)
  • tests/unit/formatters/test_color_and_terminal.py (2 hunks)
  • tests/unit/formatters/test_comprehensive_formatting.py (1 hunks)
  • tests/unit/formatters/test_format_interfaces.py (2 hunks)
  • tests/unit/formatters/test_formatters.py (7 hunks)
  • tests/unit/formatters/test_json_formatter.py (2 hunks)
  • tests/unit/formatters/test_performance_and_memory.py (1 hunks)
  • tests/unit/models/test_models.py (9 hunks)
  • tests/unit/parsers/test_parsers.py (5 hunks)
  • tests/unit/services/test_github_service.py (3 hunks)
  • tests/unit/services/test_reply_service.py (1 hunks)
  • tests/unit/services/test_resolve_service.py (1 hunks)
  • tests/unit/test_cli.py (1 hunks)
  • tests/unit/test_command_utils.py (3 hunks)
  • tests/unit/test_format_selection.py (2 hunks)
  • tests/unit/test_utils.py (1 hunks)
  • tests/unit/validators/test_schema_validator.py (2 hunks)
✅ Files skipped from review due to trivial changes (17)
  • tests/unit/formatters/test_performance_and_memory.py
  • src/toady/cli.py
  • tests/integration/cli/test_reply_cli.py
  • tests/integration/test_schema_validation_integration.py
  • tests/integration/cli/test_resolve_cli.py
  • tests/unit/formatters/test_comprehensive_formatting.py
  • scripts/test_config.py
  • tests/unit/formatters/test_format_interfaces.py
  • src/toady/validators/schema_validator.py
  • src/toady/services/pr_selection.py
  • src/toady/exceptions.py
  • src/toady/formatters/format_selection.py
  • src/toady/commands/resolve.py
  • src/toady/parsers/graphql_parser.py
  • src/toady/commands/reply.py
  • src/toady/services/reply_service.py
  • src/toady/formatters/json_formatter.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • tests/unit/test_command_utils.py
  • tests/integration/cli/test_fetch_cli.py
  • tests/conftest.py
  • scripts/ci_check.py
  • tests/unit/models/test_models.py
  • tests/unit/formatters/test_formatters.py
  • src/toady/services/fetch_service.py
  • src/toady/services/pr_selector.py
  • src/toady/validators/validation.py
  • src/toady/services/github_service.py
👮 Files not reviewed due to content moderation or server errors (1)
  • tests/unit/commands/test_fetch.py
🧰 Additional context used
🧠 Learnings (4)
tests/integration/real_api/test_authentication_flows.py (1)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_authentication_flows.py:66-73
Timestamp: 2025-06-12T01:25:58.548Z
Learning: Real-API integration tests depend on the GH_TOKEN environment variable; CI workflow now sets `env.GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` in `.github/workflows/ci.yml`.
tests/integration/real_api/test_end_to_end_workflows.py (2)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
pyproject.toml (1)
Learnt from: tonyblank
PR: tonyblank/toady-cli#1
File: requirements-dev.txt:13-13
Timestamp: 2025-06-06T19:58:46.962Z
Learning: Type stub packages like types-click should be version-pinned to match their corresponding runtime packages (e.g., if Click is >=8.1.0, then types-click should also be >=8.1.0) to ensure type compatibility and reproducible environments.
tests/unit/test_utils.py (2)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
🧬 Code Graph Analysis (8)
src/toady/formatters/format_interfaces.py (5)
src/toady/formatters/format_selection.py (4)
  • format_threads (40-42)
  • format_array (54-55)
  • format_primitive (58-59)
  • format_error (62-63)
src/toady/formatters/json_formatter.py (5)
  • format_threads (44-84)
  • format_array (148-187)
  • format_primitive (189-206)
  • format_error (208-232)
  • _safe_serialize (325-385)
tests/unit/formatters/test_format_interfaces.py (4)
  • format_threads (26-28)
  • format_array (34-36)
  • format_primitive (38-40)
  • format_error (42-44)
src/toady/models/models.py (5)
  • ReviewThread (39-317)
  • Comment (321-609)
  • to_dict (198-222)
  • to_dict (470-499)
  • to_dict (805-823)
src/toady/exceptions.py (1)
  • to_dict (107-120)
tests/unit/validators/test_schema_validator.py (2)
tests/integration/test_schema_validation_integration.py (1)
  • validator (36-39)
src/toady/validators/schema_validator.py (3)
  • GitHubSchemaValidator (43-587)
  • _is_cache_valid (91-104)
  • _load_cached_schema (106-121)
src/toady/models/models.py (5)
src/toady/formatters/format_interfaces.py (1)
  • to_dict (256-268)
src/toady/exceptions.py (1)
  • to_dict (107-120)
tests/unit/formatters/test_json_formatter.py (6)
  • to_dict (153-154)
  • to_dict (216-217)
  • to_dict (315-316)
  • to_dict (632-633)
  • to_dict (712-713)
  • to_dict (732-733)
tests/unit/formatters/test_performance_and_memory.py (1)
  • to_dict (483-484)
tests/unit/formatters/test_comprehensive_formatting.py (1)
  • to_dict (390-391)
tests/unit/test_cli.py (3)
src/toady/cli.py (2)
  • cli (23-89)
  • main (99-118)
src/toady/exceptions.py (1)
  • ToadyError (71-120)
tests/conftest.py (1)
  • runner (22-24)
tests/integration/real_api/test_network_resilience.py (3)
src/toady/cli.py (1)
  • cli (23-89)
tests/integration/conftest.py (9)
  • verify_test_pr_exists (197-244)
  • performance_monitor (342-402)
  • start_timing (352-359)
  • stop_timing (361-373)
  • api_retry_helper (263-296)
  • rate_limit_aware_delay (248-259)
  • skip_if_slow (432-435)
  • assert_performance_threshold (383-400)
  • integration_test_config (23-48)
src/toady/parsers/graphql_queries.py (2)
  • limit (67-82)
  • limit (317-332)
tests/unit/commands/test_resolve.py (9)
src/toady/commands/resolve.py (13)
  • resolve (621-740)
  • _display_summary (175-216)
  • _fetch_and_filter_threads (28-60)
  • _handle_bulk_resolve (326-377)
  • _handle_bulk_resolve_error (260-323)
  • _handle_confirmation_prompt (63-106)
  • _handle_single_resolve (544-573)
  • _handle_single_resolve_error (474-541)
  • _handle_single_resolve_success (455-471)
  • _process_threads (109-172)
  • _show_single_resolve_progress (441-452)
  • _validate_and_prepare_thread_id (417-438)
  • _validate_resolve_parameters (380-414)
src/toady/exceptions.py (7)
  • GitHubAPIError (338-367)
  • GitHubAuthenticationError (313-335)
  • GitHubRateLimitError (402-431)
  • ResolveServiceError (604-618)
  • ThreadNotFoundError (621-646)
  • ThreadPermissionError (649-674)
  • FetchServiceError (541-556)
src/toady/services/fetch_service.py (2)
  • FetchServiceError (15-16)
  • fetch_review_threads_from_current_repo (122-153)
src/toady/models/models.py (1)
  • is_resolved (304-310)
src/toady/services/resolve_service.py (2)
  • resolve_thread (34-134)
  • unresolve_thread (136-236)
tests/conftest.py (1)
  • runner (22-24)
tests/unit/commands/test_fetch.py (1)
  • runner (731-733)
tests/unit/commands/test_reply.py (1)
  • runner (927-929)
tests/unit/test_cli.py (1)
  • runner (474-476)
src/toady/commands/schema.py (1)
src/toady/exceptions.py (2)
  • ConfigurationError (167-192)
  • FileOperationError (195-227)
tests/unit/test_utils.py (4)
src/toady/exceptions.py (1)
  • ValidationError (123-164)
src/toady/utils.py (2)
  • emit_error (105-143)
  • parse_datetime (12-102)
tests/unit/formatters/test_format_interfaces.py (1)
  • NonSerializable (176-178)
tests/unit/formatters/test_json_formatter.py (1)
  • NonSerializable (505-507)
🪛 checkmake (0.2.2)
Makefile

[warning] 9-9: Target body for "help" exceeds allowed length of 5 (40).

(maxbodylength)


[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 166-166: Target body for "clean" exceeds allowed length of 5 (12).

(maxbodylength)

🪛 Pylint (3.3.7)
tests/unit/formatters/test_json_formatter.py

[refactor] 653-653: Too few public methods (0/2)

(R0903)


[refactor] 672-672: Too few public methods (0/2)

(R0903)


[refactor] 690-690: Too few public methods (0/2)

(R0903)

src/toady/formatters/formatters.py

[refactor] 37-37: Too few public methods (1/2)

(R0903)


[refactor] 187-187: Too many local variables (17/15)

(R0914)


[refactor] 187-187: Too many branches (13/12)

(R0912)

tests/integration/real_api/test_performance_monitoring.py

[refactor] 29-29: Too many local variables (17/15)

(R0914)


[refactor] 490-490: Too many local variables (16/15)

(R0914)


[refactor] 557-557: Too many local variables (17/15)

(R0914)

tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (25/15)

(R0914)


[refactor] 24-24: Too many statements (67/50)

(R0915)


[refactor] 208-208: Too many arguments (7/5)

(R0913)


[refactor] 208-208: Too many positional arguments (7/5)

(R0917)

tests/unit/commands/test_fetch.py

[refactor] 61-61: Too many arguments (6/5)

(R0913)


[refactor] 61-61: Too many positional arguments (6/5)

(R0917)


[refactor] 87-87: Too many arguments (6/5)

(R0913)


[refactor] 87-87: Too many positional arguments (6/5)

(R0917)

src/toady/formatters/pretty_formatter.py

[refactor] 43-43: Too many local variables (20/15)

(R0914)


[refactor] 561-561: Too many local variables (20/15)

(R0914)


[refactor] 561-561: Too many branches (13/12)

(R0912)

src/toady/commands/schema.py

[refactor] 322-322: Too many branches (18/12)

(R0912)


[refactor] 404-404: Too many branches (14/12)

(R0912)

src/toady/parsers/parsers.py

[refactor] 82-82: Too many local variables (23/15)

(R0914)


[refactor] 196-196: Too many local variables (17/15)

(R0914)

tests/integration/conftest.py

[refactor] 52-52: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 197-197: Either all return statements in a function should return an expression, or none of them should.

(R1710)


[refactor] 446-446: Either all return statements in a function should return an expression, or none of them should.

(R1710)

tests/unit/commands/test_reply.py

[refactor] 489-489: Too few public methods (1/2)

(R0903)

tests/unit/test_utils.py

[refactor] 15-15: Too few public methods (1/2)

(R0903)


[refactor] 25-25: Too many public methods (22/20)

(R0904)


[refactor] 396-396: Too few public methods (0/2)

(R0903)

🪛 GitHub Actions: CI with uv
tests/integration/real_api/test_network_resilience.py

[error] 263-293: TestRateLimitHandling.test_rate_limit_status_monitoring failed: GitHub CLI returned exit code 4 indicating missing GH_TOKEN environment variable. Error message: 'gh: To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable. Example: env: GH_TOKEN: ${{ github.token }}'.

🪛 actionlint (1.7.7)
.github/workflows/ci-uv.yml

42-42: the runner of "codecov/codecov-action@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.9)
🔇 Additional comments (9)
tests/unit/formatters/test_color_and_terminal.py (1)

224-226: Nice—one-liner TERM purge

Replacing the verbose if/del dance with pop(..., None) is cleaner and bullet-proof.
Carry on.

src/toady/utils.py (1)

62-63: Stringify exceptions like a pro

Switching to {e!s} tightens the f-strings and avoids double conversion noise.
Looks good and doesn’t touch behaviour.

Also applies to: 76-77, 101-102

tests/unit/formatters/test_json_formatter.py (1)

645-741: Tests hammer the fallback paths – sweet

The extra cases for objects lacking to_dict and for forced failures cover the formatter’s ugly edges nicely. No complaints.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 653-653: Too few public methods (0/2)

(R0903)


[refactor] 672-672: Too few public methods (0/2)

(R0903)


[refactor] 690-690: Too few public methods (0/2)

(R0903)

src/toady/services/resolve_service.py (1)

34-60: Looks good

Type-hint switch and {e!s} formatting are fine; no behavioural change introduced.

Also applies to: 70-75

src/toady/models/models.py (1)

30-36: No issues

Updated error-messages keep prior semantics; nothing further to do.

Also applies to: 192-196

tests/unit/commands/test_schema.py (1)

479-481: Same prefix problem for fetch-side network / file errors

Both assertions should include "Error: " to match real output.
Please verify the message template in schema.py if you believe the prefix is absent.

Also applies to: 491-493

src/toady/formatters/format_interfaces.py (1)

65-67: Why drop int from the public interface?

PrettyFormatter.format_primitive (and existing callers) still accept int.
Unless you intend to ban integers, keep the union aligned:

-def format_primitive(self, value: Union[str, float, bool, None]) -> str:
+def format_primitive(self, value: Union[str, int, float, bool, None]) -> str:
tests/unit/test_format_selection.py (1)

244-261: Monkey-patching __import__ is risky as fuck

Swapping out the built-in importer can grenade parallel tests if they run in the same process. Wrap this in importlib.reload tricks or isolate with pytest.subprocess so you don’t fuck neighbouring suites.

tests/integration/real_api/test_authentication_flows.py (1)

220-231: This “unauthenticated” test does absolutely nothing

You set an invalid GH_TOKEN then… exit the test with zero assertions.
Either invoke a command and assert failure, or delete the filler.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
tests/integration/real_api/test_network_resilience.py (2)

95-101: ⚠️ Potential issue

--limit 1000 still violates the 1-100 contract
Same issue previously flagged; cap at 100 or pull the value from config.


436-438: ⚠️ Potential issue

Repeated contract breach (--limit 1000)

Exact same limit violation as above. Please fix all occurrences.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b68a1e and be0f8fe.

📒 Files selected for processing (4)
  • .github/workflows/ci-uv.yml (1 hunks)
  • .github/workflows/ci.yml (3 hunks)
  • pyproject.toml (4 hunks)
  • tests/integration/real_api/test_network_resilience.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/integration/real_api/test_network_resilience.py (3)
src/toady/cli.py (1)
  • cli (23-89)
tests/integration/conftest.py (9)
  • verify_test_pr_exists (197-244)
  • performance_monitor (342-402)
  • start_timing (352-359)
  • stop_timing (361-373)
  • api_retry_helper (263-296)
  • rate_limit_aware_delay (248-259)
  • skip_if_slow (432-435)
  • assert_performance_threshold (383-400)
  • integration_test_config (23-48)
src/toady/parsers/graphql_queries.py (2)
  • limit (67-82)
  • limit (317-332)
🪛 actionlint (1.7.7)
.github/workflows/ci-uv.yml

42-42: the runner of "codecov/codecov-action@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (1)
.github/workflows/ci.yml (1)

70-82: Secret fallback expression may not work in all runners

The || fallback operator still isn’t universally supported (it requires GHES ≥ 3.8 or Actions runtime ≥ 2023-04-12). Safer pattern:

env:
  GH_TOKEN: ${{ secrets.TOADY_INTEGRATION_TOKEN }}

and rely on repository secret-level defaulting, or add a separate conditional step to export GITHUB_TOKEN when the custom secret is absent.

- Upgraded `codecov-action` in the CI workflow from v3 to v5 for improved coverage reporting.
- Modified error handling in `error_handling.py` to conditionally display error details based on the `TOADY_DEBUG` environment variable.
- Enhanced serialization in `format_interfaces.py` to handle exceptions during `to_dict` calls gracefully.
- Updated cursor validation in `graphql_queries.py` to raise a `ValueError` for empty cursors instead of returning `False`.
- Adjusted test assertions in various test files to improve output handling and error messaging consistency.

These changes aim to modernize the CI setup and improve error reporting across the application.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (6)
tests/integration/real_api/test_end_to_end_workflows.py (1)

214-218: Remove or use the skip_if_slow fixture

skip_if_slow is injected but never referenced, so pytest still resolves it every run with zero benefit. Drop it from the signature or add the logic that actually skips slow runs.

tests/unit/commands/test_schema.py (1)

472-477: Duplicate runner fixtures across modules can shadow each other

This file defines its own runner fixture, and other test modules do the same. If two of them land in the same pytest collection root, the later import silently overrides the first, leading to confusing fixture-loading order. Prefer placing the shared CliRunner fixture in tests/conftest.py and importing it everywhere.

tests/integration/real_api/test_performance_monitoring.py (2)

50-67: Test runtime is unnecessarily inflated by fixed 1-second sleeps

The five-iteration loop already measures performance; the extra time.sleep(1.0) after every call adds 5 s to the wall-clock time of this single test. That slows down local runs and CI without adding meaningful signal.

Consider one of:

-            # Small delay between calls
-            time.sleep(1.0)
+            # Minimal pause just to avoid hammering the API
+            time.sleep(0.1)

or drop the delay entirely if the backend can tolerate the burst.


69-78: print() noise clutters CI logs

The baseline statistics are useful when debugging, but unconditional print() in tests turns routine CI output into scroll-hell. Prefer pytest’s -s option or capsys for ad-hoc debugging, or switch to logging with a marker-controlled verbosity flag so developers opt-in when needed.

tests/integration/real_api/test_network_resilience.py (1)

250-308: Verbose print() statements

As with the performance suite, dozens of print() calls flood logs. Swap to logging.debug guarded by -o log_cli=true or drop them after local tuning.

tests/unit/services/test_github_service.py (1)

747-756: resolve_thread test asserts no behaviour

resolve_thread currently returns raw GraphQL output; this test only re-echoes that behaviour. Either assert expected side-effects (e.g., thread state) or mark as redundant.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be0f8fe and d474dd9.

📒 Files selected for processing (12)
  • .github/workflows/ci-uv.yml (1 hunks)
  • src/toady/error_handling.py (3 hunks)
  • src/toady/formatters/format_interfaces.py (16 hunks)
  • src/toady/parsers/graphql_queries.py (6 hunks)
  • tests/integration/real_api/test_authentication_flows.py (1 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
  • tests/integration/real_api/test_network_resilience.py (1 hunks)
  • tests/integration/real_api/test_performance_monitoring.py (1 hunks)
  • tests/unit/commands/test_schema.py (1 hunks)
  • tests/unit/services/test_github_service.py (3 hunks)
  • tests/unit/test_cli.py (1 hunks)
  • tests/unit/validators/test_schema_validator.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/toady/error_handling.py
  • tests/unit/validators/test_schema_validator.py
  • src/toady/parsers/graphql_queries.py
  • src/toady/formatters/format_interfaces.py
🧰 Additional context used
🧠 Learnings (2)
tests/integration/real_api/test_end_to_end_workflows.py (3)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:53-60
Timestamp: 2025-06-13T15:19:27.384Z
Learning: When reading CLI output in tests, always use
```python
raw_out = getattr(result, "stdout", result.output)
```
before processing, to stay compatible with different Click versions whose `CliRunner.invoke` results may expose either `stdout` or `output`.
tests/integration/real_api/test_authentication_flows.py (1)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_authentication_flows.py:66-73
Timestamp: 2025-06-12T01:25:58.548Z
Learning: Real-API integration tests depend on the GH_TOKEN environment variable; CI workflow now sets `env.GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` in `.github/workflows/ci.yml`.
🧬 Code Graph Analysis (2)
tests/integration/real_api/test_performance_monitoring.py (3)
src/toady/cli.py (1)
  • cli (23-89)
tests/integration/conftest.py (10)
  • integration_cli_runner (129-136)
  • verify_test_pr_exists (197-244)
  • performance_monitor (342-402)
  • start_timing (352-359)
  • stop_timing (361-373)
  • skip_if_slow (432-435)
  • assert_performance_threshold (383-400)
  • temp_cache_dir (140-147)
  • network_simulation (300-338)
  • simulate_slow_connection (316-322)
src/toady/parsers/graphql_queries.py (2)
  • limit (67-82)
  • limit (317-332)
tests/unit/commands/test_schema.py (4)
src/toady/commands/schema.py (7)
  • schema (25-28)
  • _display_query_validation_results (404-459)
  • _display_summary_report (322-401)
  • _has_critical_errors (462-509)
  • check (240-319)
  • fetch (152-224)
  • validate (48-138)
src/toady/exceptions.py (1)
  • ToadyError (71-120)
src/toady/validators/schema_validator.py (5)
  • SchemaValidationError (22-40)
  • fetch_schema (142-192)
  • generate_compatibility_report (557-587)
  • get_schema_version (462-473)
  • validate_query (218-272)
tests/conftest.py (1)
  • runner (22-24)
🪛 Pylint (3.3.7)
tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (26/15)

(R0914)


[refactor] 24-24: Too many statements (68/50)

(R0915)


[refactor] 209-209: Too many arguments (7/5)

(R0913)


[refactor] 209-209: Too many positional arguments (7/5)

(R0917)

tests/integration/real_api/test_performance_monitoring.py

[refactor] 29-29: Too many local variables (17/15)

(R0914)


[refactor] 490-490: Too many local variables (16/15)

(R0914)


[refactor] 557-557: Too many local variables (17/15)

(R0914)

🪛 actionlint (1.7.7)
.github/workflows/ci-uv.yml

44-44: input "file" is not defined in action "codecov/codecov-action@v5". available inputs are "binary", "codecov_yml_path", "commit_parent", "directory", "disable_file_fixes", "disable_safe_directory", "disable_search", "dry_run", "env_vars", "exclude", "fail_ci_if_error", "files", "flags", "gcov_args", "gcov_executable", "gcov_ignore", "gcov_include", "git_service", "handle_no_reports_found", "job_code", "name", "network_filter", "network_prefix", "os", "override_branch", "override_build", "override_build_url", "override_commit", "override_pr", "plugins", "report_code", "report_type", "root_dir", "skip_validation", "slug", "swift_project", "token", "url", "use_legacy_upload_endpoint", "use_oidc", "verbose", "version", "working-directory"

(action)

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: integration-test
🔇 Additional comments (7)
.github/workflows/ci-uv.yml (6)

1-8: CI triggers configuration looks correct
Push and pull_request events target the intended branches (main, develop for push; main for PR).


9-15: Matrix setup is solid
Testing across Python 3.9 through 3.12 ensures compatibility.


16-23: Environment setup is appropriate
Using astral-sh/setup-uv@v4 to install uv before bootstrapping Python is a valid approach.


24-30: Dependency installation step is good
Running uv sync --all-extras covers all extras and dev dependencies neatly.


31-36: Linting commands are comprehensive
Combining Ruff, Black, and Mypy covers style, formatting, and typing checks.


37-40: Test invocation is correct
uv run pytest --cov=src/toady --cov-report=xml properly runs tests and emits coverage.

tests/unit/test_cli.py (1)

90-103: Patch target may drift with refactors

patch("toady.commands.fetch.FetchService") assumes FetchService lives directly in toady.commands.fetch. The implementation recently moved under toady.services.fetch_service (per earlier commits). If that refactor lands, this patch will silently fail and the test will hit the real service. Search for the authoritative import path and patch that instead.

- Updated `TestFetchCLI` to differentiate error output based on the `TOADY_DEBUG` environment variable, ensuring that error details are only shown in debug mode.
- Modified `TestErrorMessageFormatter` to reflect similar changes, verifying that error details are hidden in default mode and displayed in debug mode.
- Adjusted cursor validation in `test_graphql_queries.py` to raise a `ValueError` for empty cursors, improving error handling consistency.

These changes aim to improve error reporting and enhance test reliability across the application.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unit/parsers/test_graphql_queries.py (1)

331-335: Good update, but avoid locking tests to private helpers

Switching the expectation from a boolean return to a ValueError is correct given the new implementation.
However, the test exercises the private helper _validate_cursor. Relying on a leading-underscore function in a public test suite couples the tests to internal details and can hinder future refactors.

Consider driving the same behaviour through the public helpers (create_paginated_query*) and dropping this direct call, or move the test to an “internal” test module that is clearly scoped for white-box checks.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d474dd9 and 5ed89be.

📒 Files selected for processing (3)
  • tests/integration/cli/test_fetch_cli.py (2 hunks)
  • tests/unit/parsers/test_graphql_queries.py (1 hunks)
  • tests/unit/test_error_handling.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/cli/test_fetch_cli.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/unit/test_error_handling.py (1)
src/toady/error_handling.py (2)
  • ErrorMessageFormatter (247-366)
  • format_error (251-323)
tests/unit/parsers/test_graphql_queries.py (1)
src/toady/parsers/graphql_queries.py (1)
  • _validate_cursor (8-43)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: integration-test

- Changed the `file` parameter to `files` in the Codecov action within the CI workflow for improved compatibility.
- Updated `test_authentication_flows.py` to skip a test that cannot properly simulate unauthenticated behavior due to caching issues with the GitHub CLI.
- Modified `test_end_to_end_workflows.py` to use `getattr` for accessing command output, ensuring consistent handling of results.
- Improved assertions in `test_network_resilience.py` to verify performance thresholds and backoff behavior during network resilience tests.
- Refined error handling in `test_error_handling.py` to explicitly clear environment variables during tests.

These changes aim to modernize the CI setup and enhance the reliability of integration tests.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
tests/unit/services/test_github_service.py (1)

644-648: Assertion string too strict – likely to break on minor copy edits

assert "timed out after" in str(exc_info.value) couples the test to an exact wording that the service isn’t obligated to keep. Match a shorter token such as "timed out" or inspect the exception class only.

tests/integration/real_api/test_end_to_end_workflows.py (1)

64-91: Comment cleanup may silently 404

create_result.stdout is treated as a URL, yet gh pr comment normally prints a raw ID unless --json url is used. Deleting via gh api --method DELETE <id> will fail (suppressed) and leave the test artefact behind.

Either request the URL:

- "comment",
+ "comment",
+ "--json",
+ "url",

and pass that field to _cleanup_comment, or build the REST path yourself.

tests/integration/real_api/test_network_resilience.py (1)

44-56: Redundant branch – assert success once then drop fallback

Since you already gate on normal_duration < 30, simply add

assert result.exit_code == 0, result.output

and delete the else: block. The duplicate duration check provides no additional safety.

tests/integration/real_api/test_authentication_flows.py (1)

182-189: Header parsing can bleed into JSON body

-i prints headers, blank line, then JSON. Scanning the whole stdout risks matching the body. Limit the search:

headers, _body = result.stdout.split("\n\n", 1)
for line in headers.splitlines():
    ...

avoids false positives.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed89be and 4786a71.

📒 Files selected for processing (6)
  • .github/workflows/ci-uv.yml (1 hunks)
  • tests/integration/real_api/test_authentication_flows.py (1 hunks)
  • tests/integration/real_api/test_end_to_end_workflows.py (1 hunks)
  • tests/integration/real_api/test_network_resilience.py (1 hunks)
  • tests/unit/services/test_github_service.py (3 hunks)
  • tests/unit/test_error_handling.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/ci-uv.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/test_error_handling.py
🧰 Additional context used
🧠 Learnings (3)
tests/integration/real_api/test_end_to_end_workflows.py (3)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/unit/services/test_fetch_service.py:15-17
Timestamp: 2025-06-12T01:25:15.100Z
Learning: pytest.ini now uses the correct “[pytest]” section header and registers markers `unit`, `service`, `integration`, `model`, `auth`, `resilience`, and `performance`, preventing PytestUnknownMarkWarning in this repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:18-20
Timestamp: 2025-06-12T01:25:37.839Z
Learning: pytest.ini now correctly uses the “[pytest]” section header and registers all markers: unit, service, integration, model, auth, resilience, performance, real_api, and slow, eliminating PytestUnknownMarkWarning across the repository.
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_end_to_end_workflows.py:53-60
Timestamp: 2025-06-13T15:19:27.384Z
Learning: When reading CLI output in tests, always use
```python
raw_out = getattr(result, "stdout", result.output)
```
before processing, to stay compatible with different Click versions whose `CliRunner.invoke` results may expose either `stdout` or `output`.
tests/integration/real_api/test_authentication_flows.py (1)
Learnt from: tonyblank
PR: tonyblank/toady-cli#54
File: tests/integration/real_api/test_authentication_flows.py:66-73
Timestamp: 2025-06-12T01:25:58.548Z
Learning: Real-API integration tests depend on the GH_TOKEN environment variable; CI workflow now sets `env.GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` in `.github/workflows/ci.yml`.
tests/unit/services/test_github_service.py (1)
Learnt from: tonyblank
PR: tonyblank/toady-cli#28
File: src/toady/github_service.py:489-518
Timestamp: 2025-06-09T19:14:20.957Z
Learning: The `_get_review_id_for_comment` method in `src/toady/github_service.py` uses GraphQL to automatically fetch the review ID when replying to node-ID comments, preventing ValueError crashes when review_id is not provided for comment replies.
🪛 Pylint (3.3.7)
tests/integration/real_api/test_end_to_end_workflows.py

[refactor] 24-24: Too many arguments (7/5)

(R0913)


[refactor] 24-24: Too many positional arguments (7/5)

(R0917)


[refactor] 24-24: Too many local variables (26/15)

(R0914)


[refactor] 24-24: Too many statements (69/50)

(R0915)


[refactor] 210-210: Too many arguments (7/5)

(R0913)


[refactor] 210-210: Too many positional arguments (7/5)

(R0917)

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: test (windows-latest, 3.10)
  • GitHub Check: test (windows-latest, 3.12)
  • GitHub Check: test (windows-latest, 3.9)
  • GitHub Check: test (windows-latest, 3.11)
  • GitHub Check: integration-test
🔇 Additional comments (1)
tests/integration/real_api/test_end_to_end_workflows.py (1)

50-59: Missing GH_TOKEN guard

These real-API tests assume an authenticated CLI. Add an early

if not os.getenv("GH_TOKEN") and not os.getenv("GITHUB_TOKEN"):
    pytest.skip("GitHub token not configured")

so local runs without a token don’t hard-fail.

@tonyblank tonyblank merged commit f7e7f96 into main Jun 13, 2025
20 checks passed
@tonyblank tonyblank deleted the tony/bur-33-task-11-develop-unit-and-integration-test-suite branch June 13, 2025 16:27
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.

1 participant