Skip to content

Conversation

@shenxianpeng
Copy link
Contributor

@shenxianpeng shenxianpeng commented Dec 14, 2025

Summary by CodeRabbit

  • Tests

    • Removed several redundant/duplicate test modules and consolidated suites for maintainability.
    • Added broad new and edge-case coverage for config loading (invalid TOML, permission errors, loader fallback), validation engine/validators, main flow, rule building, and utility behaviors.
    • Reorganized tests to improve reliability and reduce overlap.
  • Chores

    • Added a test dependency for TOML parsing to the project configuration.

✏️ Tip: You can customize this high-level summary in your review settings.

@shenxianpeng shenxianpeng requested a review from a team as a code owner December 14, 2025 15:24
@netlify
Copy link

netlify bot commented Dec 14, 2025

Deploy Preview for commit-check ready!

Name Link
🔨 Latest commit 65a259b
🔍 Latest deploy log https://app.netlify.com/projects/commit-check/deploys/693fb478bf089700085dce27
😎 Deploy Preview https://deploy-preview-331--commit-check.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

Consolidates and reorganizes test coverage: three standalone config tests and a comprehensive engine test were removed; their cases were merged into expanded/updated test modules for config, engine, main, rule_builder, and util; tomli was added to test extras in pyproject.toml.

Changes

Cohort / File(s) Summary
Config tests — removed
tests/config_edge_test.py, tests/config_fallback_test.py, tests/config_import_test.py
Deleted three standalone test files covering invalid TOML, file-permission errors, and tomllib→tomli import-fallback scenarios.
Config tests — consolidated
tests/config_test.py
Added multiple test classes (e.g., TestConfigEdgeCases, TestConfigTomllibFallback, TestConfigImportPaths) consolidating invalid-TOML, permission-error, and TOML loader-fallback tests; added import builtins.
Engine tests — removed
tests/engine_comprehensive_test.py
Deleted a comprehensive engine test module that exercised validators and ValidationEngine end-to-end.
Engine tests — expanded
tests/engine_test.py
Added extensive edge-case and comprehensive tests for validators, ValidationEngine mappings, stdin/commit-file/git flows, and many mocked subprocess/git interactions.
Main tests — expanded
tests/main_test.py
Added tests for main flow, _get_message_content, and StdinReader (FileNotFoundError, OSError, whitespace trimming, git-format message validation); added from unittest.mock import patch.
Rule-builder tests — expanded
tests/rule_builder_test.py
Added tests for RuleBuilder and ValidationRule edge cases and to_dict() coverage (non-integer, non-list, empty values, formatting, defaults).
Util tests — expanded
tests/util_test.py
Added tests for _find_check, _print_failure, _find_config_file, _load_toml, validate_config, YAML fallback, and related edge cases.
Project metadata
pyproject.toml
Added tomli to test extra-dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

  • Pay attention to tests that patch sys.modules and builtins.__import__ for proper isolation and cleanup.
  • Review heavy mocking of subprocess/git interactions in tests/engine_test.py for flakiness and global-state leakage.
  • Confirm deleted standalone tests are fully represented in the consolidated tests/config_test.py.

Possibly related PRs

Suggested labels

developer

Poem

🐰 I hopped through files with nimble feet,

Merged tiny tests into one warm suite.
Mocked a toml, chased a flaky git,
Tidied the burrow, then took a bit.
Nose twitch — tests green, my day complete.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Add comprehensive tests' accurately describes the main change: extensive new test coverage across multiple test modules (config_test.py, engine_test.py, main_test.py, rule_builder_test.py, util_test.py) with new test classes and methods, while also reorganizing and consolidating existing edge-case tests.
Docstring Coverage ✅ Passed Docstring coverage is 95.77% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/add-more-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@shenxianpeng shenxianpeng added the tests Add test related changes label Dec 14, 2025
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/engine_test.py (2)

156-159: Remove duplicate assertions.

Lines 157-159 contain identical assertions that should be consolidated into a single assertion.

Apply this diff to fix:

         result = validator.validate(context)
         assert result == ValidationResult.PASS
-        assert result == ValidationResult.PASS
-        assert result == ValidationResult.PASS

245-253: Remove duplicate assertions and comments.

Lines 249-253 duplicate the assertions and comments from lines 245-248.

Apply this diff to fix:

         assert result == ValidationResult.PASS
         # Called once for skip logic ("an"), once for value ("ae")
         assert mock_get_commit_info.call_count == 2
         assert mock_get_commit_info.call_args_list[0][0][0] == "an"
         assert mock_get_commit_info.call_args_list[1][0][0] == "ae"
-        assert result == ValidationResult.PASS
-        # Called once for skip logic ("an"), once for value ("ae")
-        assert mock_get_commit_info.call_count == 2
-        assert mock_get_commit_info.call_args_list[0][0][0] == "an"
-        assert mock_get_commit_info.call_args_list[1][0][0] == "ae"
🧹 Nitpick comments (6)
tests/engine_test.py (3)

867-1004: Add missing test markers and consolidate duplicate tests.

Several issues in this section:

  1. Tests at lines 871, 888, 900, 916, 932, 948, 965, 981, and 993 are missing the @pytest.mark.benchmark decorator used consistently throughout the file.

  2. TestCommitMessageValidatorEdgeCases.test_validate_with_valid_conventional_commit (lines 871-882) duplicates the test at lines 62-72.

  3. Consider consolidating these edge case tests into the existing test classes rather than creating separate edge case classes, as the distinction between "edge cases" and regular tests is unclear.

Apply this diff to add missing decorators:

 class TestCommitMessageValidatorEdgeCases:
     """Test edge cases for CommitMessageValidator."""
 
+    @pytest.mark.benchmark
     def test_validate_with_valid_conventional_commit(self):

 class TestSubjectCapitalizationEdgeCases:
     """Test additional subject capitalization validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_validate_merge_commit_passes(self):
         """Test that merge commits pass capitalization check."""

+    @pytest.mark.benchmark
     def test_validate_conventional_commit_capitalized(self):

 class TestSubjectImperativeEdgeCases:
     """Test additional imperative validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_validate_non_match_fallback(self):

 class TestSubjectLengthEdgeCases:
     """Test additional subject length validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_validate_unknown_check_type(self):

 class TestAuthorValidatorEdgeCases:
     """Test additional author validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_validate_regex_first_then_ignored(self):

 class TestMergeBaseEdgeCases:
     """Test additional merge base validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_find_target_branch_cleans_remote_prefix(self):

 class TestCommitTypeEdgeCases:
     """Test additional commit type validator edge cases."""
 
+    @pytest.mark.benchmark
     def test_validate_merge_commit_when_not_allowed(self):

+    @pytest.mark.benchmark
     def test_validate_unknown_check_type(self):

1006-1301: Consolidate duplicate test coverage.

This section duplicates significant test coverage from earlier in the file:

  • TestValidationResultComprehensive (lines 1007-1012) duplicates TestValidationResult (lines 26-31)
  • TestValidationContextComprehensive (lines 1015-1027) duplicates TestValidationContext (lines 34-49)
  • TestCommitMessageValidatorComprehensive overlaps heavily with TestCommitMessageValidator (lines 60-140)
  • Similar patterns for other validators

Consider consolidating these tests into the existing test classes rather than creating separate "comprehensive" test classes. The current organization makes it difficult to understand which tests provide unique coverage versus duplicates. If these tests were meant to replace earlier tests, the old tests should be removed.


1-1301: Overall assessment: Good coverage with organizational improvements needed.

The test file provides comprehensive coverage of the engine module and follows the coding guideline to ensure tests run via pytest and cover commit, branch, author, and CLI behaviors. However, the file would benefit from:

  1. Better organization: Having three separate test class hierarchies (base tests, edge case tests, and comprehensive tests) for the same validators creates confusion about which tests provide unique coverage.

  2. Reduced duplication: Many tests in the "edge cases" and "comprehensive" sections duplicate existing test coverage. Consider consolidating into single, well-organized test classes per validator.

  3. Consistent test markers: Ensure all tests have the @pytest.mark.benchmark decorator for consistency.

The tests themselves are well-written with appropriate mocking and assertions, but the file structure makes maintenance more difficult than necessary.

Based on learnings, ensuring tests run via pytest -v and cover commit, branch, author, and CLI behaviors.

tests/util_test.py (1)

373-393: Consider using mocks instead of manipulating function attributes.

Directly setting print_error_header.has_been_called (lines 375, 386) couples tests to implementation details and may be brittle.

Consider using mocker.patch or tracking calls through capsys output instead:

-    def test_print_failure_first_call_prints_header(self, capsys):
+    def test_print_failure_first_call_prints_header(self, capsys, mocker):
         """Test that header is printed on first failure."""
-        print_error_header.has_been_called = False
+        mocker.patch("commit_check.util.print_error_header")
         check = {"check": "message", "error": "Invalid format", "suggest": "Use feat:"}
         _print_failure(check, "^feat:.*", "wrong message")
tests/config_test.py (2)

230-234: Optional: Consider simplifying the mock error message.

Line 232 raises a PermissionError with a detailed message. While this works, Ruff suggests keeping exception messages concise (TRY003).

             if "no_perms.toml" in str(args[0]):
-                raise PermissionError("Permission denied")
+                raise PermissionError()

The test verifies the exception type, so the message content may not be critical.


362-365: Optional: Simplify mock exception message.

Similar to line 232, line 364 has a detailed error message that triggers Ruff TRY003.

                 if name == "tomllib":
-                    raise ModuleNotFoundError("No module named 'tomllib'")
+                    raise ModuleNotFoundError()
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c792143 and dc97f29.

📒 Files selected for processing (9)
  • tests/config_edge_test.py (0 hunks)
  • tests/config_fallback_test.py (0 hunks)
  • tests/config_import_test.py (0 hunks)
  • tests/config_test.py (2 hunks)
  • tests/engine_comprehensive_test.py (0 hunks)
  • tests/engine_test.py (1 hunks)
  • tests/main_test.py (2 hunks)
  • tests/rule_builder_test.py (1 hunks)
  • tests/util_test.py (2 hunks)
💤 Files with no reviewable changes (4)
  • tests/config_fallback_test.py
  • tests/engine_comprehensive_test.py
  • tests/config_edge_test.py
  • tests/config_import_test.py
🧰 Additional context used
📓 Path-based instructions (1)
tests/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Files:

  • tests/util_test.py
  • tests/main_test.py
  • tests/engine_test.py
  • tests/config_test.py
  • tests/rule_builder_test.py
🧠 Learnings (4)
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to tests/** : Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Applied to files:

  • tests/util_test.py
  • tests/main_test.py
  • tests/engine_test.py
  • tests/config_test.py
  • tests/rule_builder_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to commit_check/main.py : Expose CLI flags: --message, --branch, --help, --version, --config, --dry-run; support combining checks

Applied to files:

  • tests/util_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to commit_check/commit.py : Support the set of commit types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test

Applied to files:

  • tests/util_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to .commit-check.yml : Maintain default validation rules for the tool in .commit-check.yml

Applied to files:

  • tests/util_test.py
  • tests/engine_test.py
🧬 Code graph analysis (3)
tests/main_test.py (1)
commit_check/main.py (4)
  • StdinReader (14-26)
  • main (127-225)
  • _get_message_content (92-124)
  • read_piped_input (18-26)
tests/engine_test.py (2)
commit_check/rule_builder.py (1)
  • ValidationRule (14-40)
commit_check/engine.py (24)
  • CommitMessageValidator (97-131)
  • ValidationContext (27-32)
  • validate (42-44)
  • validate (100-114)
  • validate (137-145)
  • validate (241-250)
  • validate (287-303)
  • validate (309-329)
  • validate (356-370)
  • validate (393-418)
  • validate (441-456)
  • ValidationResult (19-23)
  • SubjectCapitalizationValidator (167-189)
  • SubjectImperativeValidator (192-213)
  • SubjectLengthValidator (216-235)
  • AuthorValidator (238-281)
  • MergeBaseValidator (306-350)
  • _find_target_branch (331-350)
  • CommitTypeValidator (438-516)
  • ValidationEngine (519-563)
  • BranchValidator (284-303)
  • SignoffValidator (353-387)
  • BodyValidator (390-435)
  • validate_all (545-563)
tests/config_test.py (1)
commit_check/config.py (1)
  • load_config (21-37)
🪛 Ruff (0.14.8)
tests/engine_test.py

1065-1065: Unused method argument: mock_get_commit_info

(ARG002)

tests/config_test.py

219-219: Do not assert blind exception: Exception

(B017)


232-232: Avoid specifying long messages outside the exception class

(TRY003)


279-279: Unused noqa directive (non-enabled: F401)

Remove unused noqa directive

(RUF100)


364-364: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run benchmarks
🔇 Additional comments (5)
tests/util_test.py (2)

11-15: LGTM! Good coverage of internal utilities.

Testing internal/private functions is appropriate for comprehensive test coverage.


408-514: Excellent comprehensive edge case coverage!

These tests thoroughly cover TOML loading errors, config file discovery, and YAML fallback scenarios. The use of tmp_path fixtures and proper error path testing aligns well with the PR objectives.

Based on coding guidelines, confirming tests follow pytest patterns and cover the intended behaviors.

tests/main_test.py (1)

323-380: LGTM! Solid edge case coverage for main flow.

These additional tests provide good coverage of:

  • Git format fallback behavior
  • FileNotFoundError handling
  • OSError handling in file operations
  • Stdin whitespace trimming

The mocking patterns are appropriate and tests follow pytest conventions.

Based on coding guidelines, tests cover CLI behaviors and use pytest -v compatible patterns.

tests/rule_builder_test.py (1)

160-273: Excellent validation of edge cases and defensive coding!

These tests thoroughly verify:

  • Proper handling of invalid config types (non-integer, non-list, non-string)
  • Empty value handling
  • Complete and minimal field serialization in to_dict()

The assertions correctly verify that invalid configurations don't create rules, which is good defensive behavior.

tests/config_test.py (1)

282-435: Excellent comprehensive coverage of import fallback paths!

These tests thoroughly exercise the tomllib→tomli fallback mechanism and properly handle module state restoration. The systematic approach to testing different import scenarios is well-structured.

Based on coding guidelines, tests use pytest patterns and provide comprehensive coverage.

Comment on lines 214 to 220
def test_load_config_invalid_toml(self, tmp_path):
"""Test loading config with invalid TOML syntax."""
invalid_config = tmp_path / "invalid.toml"
invalid_config.write_text("invalid toml [[[")

with pytest.raises(Exception): # Could be TOMLDecodeError or similar
load_config(str(invalid_config))
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Specify the expected exception type.

The broad Exception catch on line 219 makes the test less precise. Consider catching the specific TOML parsing exception.

Apply this diff to be more specific:

     def test_load_config_invalid_toml(self, tmp_path):
         """Test loading config with invalid TOML syntax."""
         invalid_config = tmp_path / "invalid.toml"
         invalid_config.write_text("invalid toml [[[")
 
-        with pytest.raises(Exception):  # Could be TOMLDecodeError or similar
+        with pytest.raises((Exception,)):  # TOMLDecodeError varies by library
             load_config(str(invalid_config))

Or better yet, import and use the specific exception from your TOML library.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.8)

219-219: Do not assert blind exception: Exception

(B017)

🤖 Prompt for AI Agents
In tests/config_test.py around lines 214 to 220, the test uses a broad
pytest.raises(Exception) which is too general; replace it with the specific TOML
parsing exception (e.g., TOMLDecodeError or tomli.TOMLDecodeError depending on
which TOML library the project uses) and add the corresponding import at the top
of the test module so the test asserts the precise parsing error is raised when
loading invalid TOML.

# Force reimport of config module to restore original state
if "commit_check.config" in sys.modules:
del sys.modules["commit_check.config"]
import commit_check.config # noqa: F401
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused noqa directive.

The noqa: F401 directive on line 279 is not needed.

-            import commit_check.config  # noqa: F401
+            import commit_check.config
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import commit_check.config # noqa: F401
import commit_check.config
🧰 Tools
🪛 Ruff (0.14.8)

279-279: Unused noqa directive (non-enabled: F401)

Remove unused noqa directive

(RUF100)

🤖 Prompt for AI Agents
In tests/config_test.py around line 279, the import line currently includes an
unnecessary " # noqa: F401" directive; remove the " # noqa: F401" suffix so the
line is just "import commit_check.config" (keeping the import intact) and run
linters/tests to confirm the unused noqa has been removed.

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 14, 2025

CodSpeed Performance Report

Merging #331 will degrade performances by 40.01%

Comparing feat/add-more-tests (65a259b) with main (c792143)1

Summary

❌ 2 regressions
✅ 135 untouched
🆕 17 new
⏩ 108 skipped2

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
test_commit_message_validator_valid_conventional_commit 507.1 µs 568.3 µs -10.76%
🆕 test_commit_message_validator_skip_validation N/A 909 µs N/A
🆕 test_commit_message_validator_failure N/A 2 ms N/A
🆕 test_commit_message_validator_with_stdin N/A 874.7 µs N/A
🆕 test_commit_message_validator_creation N/A 116.6 µs N/A
test_main_with_message_empty_string_no_stdin_with_git 4.7 ms 7.8 ms -40.01%
🆕 test_subject_capitalization_pass N/A 515.1 µs N/A
🆕 test_subject_capitalization_fail N/A 1.1 ms N/A
🆕 test_subject_imperative_fail N/A 1.1 ms N/A
🆕 test_subject_length_fail N/A 1.1 ms N/A
🆕 test_subject_length_pass N/A 504.4 µs N/A
🆕 test_validation_engine_creation N/A 118.1 µs N/A
🆕 test_validation_context_creation N/A 116.9 µs N/A
🆕 test_validation_engine_validator_map N/A 119.4 µs N/A
🆕 test_validation_engine_unknown_validator N/A 127.1 µs N/A
🆕 test_subject_imperative_pass N/A 516.9 µs N/A
🆕 test_validation_engine_validate_all_pass N/A 868.2 µs N/A
🆕 test_validation_result_values N/A 103 µs N/A
🆕 test_validation_engine_validate_all_fail N/A 915.7 µs N/A

Footnotes

  1. No successful run was found on main (5674ddd) during the generation of this report, so c792143 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 108 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@codecov
Copy link

codecov bot commented Dec 14, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.29%. Comparing base (5674ddd) to head (65a259b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #331      +/-   ##
==========================================
+ Coverage   87.17%   93.29%   +6.12%     
==========================================
  Files           8        8              
  Lines         686      686              
==========================================
+ Hits          598      640      +42     
+ Misses         88       46      -42     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

♻️ Duplicate comments (2)
tests/engine_test.py (1)

1061-1066: Fix @patch decorator / test signature mismatch (currently breaks pytest).
You have 2 patches but only 1 injected mock parameter, matching the CI failure (“takes 2 positional arguments but 3 were given”). Also aligns with the prior review note: the get_commit_info patch isn’t used here, so drop it.

-    @patch("commit_check.engine.get_commit_info")
     @patch("commit_check.engine.has_commits")
     @pytest.mark.benchmark
-    def test_commit_message_validator_failure(self, mock_has_commits):
+    def test_commit_message_validator_failure(self, mock_has_commits):
         """Test CommitMessageValidator failure case."""
         mock_has_commits.return_value = True
tests/config_test.py (1)

214-221: Avoid pytest.raises(Exception); assert the TOML decode error specifically.
This is the same issue raised previously, and Ruff flags it (B017). Prefer TOMLDecodeError via tomllib/tomli fallback.

 import builtins
 import pytest
@@
 from unittest.mock import patch
 from commit_check.config import load_config, DEFAULT_CONFIG_PATHS
+
+try:
+    from tomllib import TOMLDecodeError
+except ImportError:  # pragma: no cover
+    from tomli import TOMLDecodeError
@@
 class TestConfigEdgeCases:
@@
     def test_load_config_invalid_toml(self, tmp_path):
         """Test loading config with invalid TOML syntax."""
         invalid_config = tmp_path / "invalid.toml"
         invalid_config.write_text("invalid toml [[[")

-        with pytest.raises(Exception):  # TOMLDecodeError varies by library
+        with pytest.raises(TOMLDecodeError):
             load_config(str(invalid_config))
🧹 Nitpick comments (1)
tests/engine_test.py (1)

865-1004: Consider deduplicating the new “EdgeCases” tests vs earlier ones to keep the suite lean.
Several of these overlap existing tests in the same module (e.g., commit message / capitalization / imperative basics). Not a blocker, but it’ll reduce maintenance and run time.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5cd6d6 and 7759d0a.

📒 Files selected for processing (2)
  • tests/config_test.py (2 hunks)
  • tests/engine_test.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Files:

  • tests/config_test.py
  • tests/engine_test.py
🧠 Learnings (2)
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to tests/** : Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Applied to files:

  • tests/config_test.py
  • tests/engine_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to .commit-check.yml : Maintain default validation rules for the tool in .commit-check.yml

Applied to files:

  • tests/engine_test.py
🧬 Code graph analysis (2)
tests/config_test.py (1)
commit_check/config.py (1)
  • load_config (21-37)
tests/engine_test.py (2)
commit_check/rule_builder.py (1)
  • ValidationRule (14-40)
commit_check/engine.py (24)
  • CommitMessageValidator (97-131)
  • ValidationContext (27-32)
  • validate (42-44)
  • validate (100-114)
  • validate (137-145)
  • validate (241-250)
  • validate (287-303)
  • validate (309-329)
  • validate (356-370)
  • validate (393-418)
  • validate (441-456)
  • ValidationResult (19-23)
  • SubjectCapitalizationValidator (167-189)
  • SubjectImperativeValidator (192-213)
  • SubjectLengthValidator (216-235)
  • AuthorValidator (238-281)
  • MergeBaseValidator (306-350)
  • _find_target_branch (331-350)
  • CommitTypeValidator (438-516)
  • ValidationEngine (519-563)
  • BranchValidator (284-303)
  • SignoffValidator (353-387)
  • BodyValidator (390-435)
  • validate_all (545-563)
🪛 GitHub Actions: main
tests/engine_test.py

[error] 1-200: TestCommitMessageValidatorComprehensive.test_commit_message_validator_failure() takes 2 positional arguments but 3 were given. TypeError occurred within test suite during pytest execution.

🪛 Ruff (0.14.8)
tests/config_test.py

219-219: Do not assert blind exception: Exception

(B017)


232-232: Avoid specifying long messages outside the exception class

(TRY003)


363-363: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run benchmarks
🔇 Additional comments (1)
tests/config_test.py (1)

3-3: import builtins usage looks appropriate for the permission/import fallback tests.

@shenxianpeng
Copy link
Contributor Author

@copilot fix ci failure

Copy link
Contributor

Copilot AI commented Dec 15, 2025

@shenxianpeng I've opened a new pull request, #332, to work on those changes. Once the pull request is ready, I'll request review from you.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/engine_test.py (2)

157-159: Remove duplicate assertions.

Lines 157-159 repeat the same assertion three times. This appears to be a copy-paste error.

Apply this diff to fix:

         result = validator.validate(context)
         assert result == ValidationResult.PASS
-        assert result == ValidationResult.PASS
-        assert result == ValidationResult.PASS

249-253: Remove duplicate assertions.

Lines 249-253 duplicate the assertions from lines 246-248.

Apply this diff to fix:

         assert result == ValidationResult.PASS
         # Called once for skip logic ("an"), once for value ("ae")
         assert mock_get_commit_info.call_count == 2
         assert mock_get_commit_info.call_args_list[0][0][0] == "an"
         assert mock_get_commit_info.call_args_list[1][0][0] == "ae"
-        assert result == ValidationResult.PASS
-        # Called once for skip logic ("an"), once for value ("ae")
-        assert mock_get_commit_info.call_count == 2
-        assert mock_get_commit_info.call_args_list[0][0][0] == "an"
-        assert mock_get_commit_info.call_args_list[1][0][0] == "ae"
♻️ Duplicate comments (1)
tests/engine_test.py (1)

1061-1083: Remove unused mock parameter (previously flagged).

The mock_get_commit_info parameter is decorated but never used in the test body since the test provides stdin_text directly. This issue was previously identified but still appears in the code.

Apply this diff to fix:

-    @patch("commit_check.engine.get_commit_info")
     @patch("commit_check.engine.has_commits")
     @pytest.mark.benchmark
     def test_commit_message_validator_failure(
-        self, mock_has_commits, mock_get_commit_info
+        self, mock_has_commits
     ):
🧹 Nitpick comments (3)
tests/engine_test.py (3)

871-882: Add missing benchmark decorator and consider consolidation.

This test is missing the @pytest.mark.benchmark decorator that is consistently used throughout the file. Additionally, this test duplicates test_commit_message_validator_valid_conventional_commit at lines 62-72.

Apply this diff to add the decorator:

+    @pytest.mark.benchmark
     def test_validate_with_valid_conventional_commit(self):

Consider whether this test class adds unique value or if it can be consolidated with the existing TestCommitMessageValidator class.


1007-1028: Remove duplicate test classes.

TestValidationResultComprehensive and TestValidationContextComprehensive duplicate tests already covered by TestValidationResult (lines 26-31) and TestValidationContext (lines 34-49) respectively. These duplicates don't add new coverage.

Consider removing these duplicate test classes to reduce maintenance burden:

-# Tests from engine_comprehensive_test.py
-class TestValidationResultComprehensive:
-    @pytest.mark.benchmark
-    def test_validation_result_values(self):
-        """Test ValidationResult enum values."""
-        assert ValidationResult.PASS == 0
-        assert ValidationResult.FAIL == 1
-
-
-class TestValidationContextComprehensive:
-    @pytest.mark.benchmark
-    def test_validation_context_creation(self):
-        """Test ValidationContext creation."""
-        context = ValidationContext()
-        assert context.stdin_text is None
-        assert context.commit_file is None
-
-        context_with_data = ValidationContext(
-            stdin_text="test commit", commit_file="commit.txt"
-        )
-        assert context_with_data.stdin_text == "test commit"
-        assert context_with_data.commit_file == "commit.txt"

1030-1101: Consider consolidating duplicate validator tests.

TestCommitMessageValidatorComprehensive duplicates much of the coverage already provided by TestCommitMessageValidator (lines 60-140). While comprehensive testing is valuable, consolidating these into a single well-organized test class would improve maintainability and reduce duplication.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7759d0a and 9ed393c.

📒 Files selected for processing (1)
  • tests/engine_test.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Files:

  • tests/engine_test.py
🧠 Learnings (2)
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to tests/** : Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Applied to files:

  • tests/engine_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to .commit-check.yml : Maintain default validation rules for the tool in .commit-check.yml

Applied to files:

  • tests/engine_test.py
🪛 Ruff (0.14.8)
tests/engine_test.py

1065-1065: Unused method argument: mock_get_commit_info

(ARG002)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run benchmarks
🔇 Additional comments (2)
tests/engine_test.py (2)

888-898: Verify merge commit format matches real-world usage.

The test uses "merge: something" which doesn't match typical git merge commit formats like "Merge branch 'feature'". Confirm whether this lowercase format is intentionally tested or if the test should use a realistic merge commit message.


1223-1248: LGTM - excellent comprehensive coverage.

This test validates all expected validator mappings in the VALIDATOR_MAP, ensuring completeness and correctness of the validator registration system. This is a valuable test for catching configuration errors.

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

♻️ Duplicate comments (1)
tests/config_test.py (1)

214-220: Specify the expected exception type.

The broad Exception catch on line 219 makes the test less precise. The specific TOML parsing exception should be caught instead.

This issue was already flagged in a previous review.

🧹 Nitpick comments (2)
tests/config_test.py (1)

337-434: Consider consolidating duplicate import fallback tests.

The import fallback mechanism is tested multiple times across different test classes (lines 141-207, 240-274, 341-388, 389-434). While comprehensive coverage is valuable, consider consolidating these into a single, well-organized test class to reduce maintenance burden and improve clarity.

tests/main_test.py (1)

329-338: Consider using pytest-mock fixture for cleaner test setup.

The deeply nested with patch() statements (4 levels) make the test harder to read and maintain. Consider using the mocker fixture (already used elsewhere in the file) for a cleaner approach:

def test_main_message_validation_git_format_used(self, mocker):
    """Test message validation uses git format B."""
    mocker.patch("sys.argv", ["commit-check", "--message"])
    mocker.patch.object(StdinReader, "read_piped_input", return_value=None)
    mocker.patch("commit_check.util.get_commit_info", return_value="feat: test")
    mocker.patch("commit_check.util.has_commits", return_value=True)
    
    result = main()
    assert result == 0
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ed393c and 65a259b.

📒 Files selected for processing (10)
  • pyproject.toml (1 hunks)
  • tests/config_edge_test.py (0 hunks)
  • tests/config_fallback_test.py (0 hunks)
  • tests/config_import_test.py (0 hunks)
  • tests/config_test.py (2 hunks)
  • tests/engine_comprehensive_test.py (0 hunks)
  • tests/engine_test.py (1 hunks)
  • tests/main_test.py (2 hunks)
  • tests/rule_builder_test.py (1 hunks)
  • tests/util_test.py (2 hunks)
💤 Files with no reviewable changes (4)
  • tests/config_edge_test.py
  • tests/config_import_test.py
  • tests/config_fallback_test.py
  • tests/engine_comprehensive_test.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🧰 Additional context used
📓 Path-based instructions (1)
tests/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Files:

  • tests/engine_test.py
  • tests/config_test.py
  • tests/main_test.py
  • tests/util_test.py
  • tests/rule_builder_test.py
🧠 Learnings (4)
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to tests/** : Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors

Applied to files:

  • tests/engine_test.py
  • tests/config_test.py
  • tests/main_test.py
  • tests/util_test.py
  • tests/rule_builder_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to .commit-check.yml : Maintain default validation rules for the tool in .commit-check.yml

Applied to files:

  • tests/engine_test.py
  • tests/util_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to commit_check/main.py : Expose CLI flags: --message, --branch, --help, --version, --config, --dry-run; support combining checks

Applied to files:

  • tests/util_test.py
📚 Learning: 2025-10-03T10:28:06.793Z
Learnt from: CR
Repo: commit-check/commit-check PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-03T10:28:06.793Z
Learning: Applies to commit_check/commit.py : Support the set of commit types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test

Applied to files:

  • tests/util_test.py
🧬 Code graph analysis (4)
tests/engine_test.py (2)
commit_check/rule_builder.py (1)
  • ValidationRule (14-40)
commit_check/engine.py (24)
  • CommitMessageValidator (97-131)
  • ValidationContext (27-32)
  • validate (42-44)
  • validate (100-114)
  • validate (137-145)
  • validate (241-250)
  • validate (287-303)
  • validate (309-329)
  • validate (356-370)
  • validate (393-418)
  • validate (441-456)
  • ValidationResult (19-23)
  • SubjectCapitalizationValidator (167-189)
  • SubjectImperativeValidator (192-213)
  • SubjectLengthValidator (216-235)
  • AuthorValidator (238-281)
  • MergeBaseValidator (306-350)
  • _find_target_branch (331-350)
  • CommitTypeValidator (438-516)
  • ValidationEngine (519-563)
  • BranchValidator (284-303)
  • SignoffValidator (353-387)
  • BodyValidator (390-435)
  • validate_all (545-563)
tests/config_test.py (1)
commit_check/config.py (1)
  • load_config (21-37)
tests/main_test.py (1)
commit_check/main.py (4)
  • StdinReader (14-26)
  • main (127-225)
  • _get_message_content (92-124)
  • read_piped_input (18-26)
tests/util_test.py (1)
commit_check/util.py (7)
  • _find_check (27-32)
  • _print_failure (35-41)
  • _find_config_file (164-181)
  • _load_toml (151-161)
  • validate_config (184-207)
  • print_error_header (220-236)
  • print_suggestion (257-269)
🪛 Ruff (0.14.8)
tests/engine_test.py

1065-1065: Unused method argument: mock_get_commit_info

(ARG002)

tests/config_test.py

219-219: Do not assert blind exception: Exception

(B017)


232-232: Avoid specifying long messages outside the exception class

(TRY003)


363-363: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: install (3.13, ubuntu-24.04)
  • GitHub Check: install (3.14, ubuntu-24.04)
  • GitHub Check: install (3.11, macos-latest)
  • GitHub Check: install (3.9, ubuntu-24.04)
  • GitHub Check: install (3.12, ubuntu-24.04)
  • GitHub Check: install (3.9, windows-latest)
  • GitHub Check: install (3.13, macos-latest)
  • GitHub Check: install (3.13, windows-latest)
  • GitHub Check: install (3.12, windows-latest)
  • GitHub Check: install (3.14, macos-latest)
  • GitHub Check: install (3.10, windows-latest)
  • GitHub Check: install (3.9, macos-latest)
  • GitHub Check: install (3.10, macos-latest)
  • GitHub Check: install (3.14, windows-latest)
  • GitHub Check: install (3.11, windows-latest)
  • GitHub Check: install (3.11, ubuntu-24.04)
  • GitHub Check: install (3.10, ubuntu-24.04)
  • GitHub Check: Run benchmarks
🔇 Additional comments (5)
tests/config_test.py (1)

281-335: LGTM!

The tomlib fallback test correctly verifies the import fallback mechanism by blocking tomllib and ensuring tomli is used. The cleanup in the finally block is appropriate.

tests/engine_test.py (1)

868-1301: LGTM!

The comprehensive test classes added provide excellent coverage of edge cases and various validator behaviors. The tests are well-structured with:

  • Appropriate use of mocking and patching
  • Clear test names and docstrings
  • Proper assertions
  • Good coverage of pass/fail scenarios

Based on coding guidelines: Ensure tests run via pytest -v and cover commit, branch, author, and CLI behaviors.

tests/util_test.py (1)

350-514: LGTM!

The additional test coverage for utility functions is comprehensive and well-structured:

  • Proper use of tmp_path fixture for file operations
  • Good edge case coverage (nonexistent files, invalid TOML, permission errors)
  • Clear test names and assertions

The tests properly exercise the utility functions' error handling paths.

tests/main_test.py (1)

363-380: LGTM!

The additional test coverage for _get_message_content and StdinReader properly exercises edge cases like OSError handling and whitespace stripping.

tests/rule_builder_test.py (1)

160-273: LGTM!

The additional test coverage for RuleBuilder and ValidationRule is comprehensive:

  • Edge case handling for invalid config values (non-integer, non-list, non-string, empty values)
  • Verification that invalid configs are gracefully handled by returning empty rule lists
  • Complete coverage of to_dict() serialization with all fields and minimal fields

The tests follow good practices with clear names and appropriate assertions.

@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Add test related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants