Skip to content

fix(health): recognize Ruby <stem>_spec.rb test pairing - #1841

Open
sloemo01 wants to merge 1 commit into
repowise-dev:mainfrom
sloemo01:fix/ruby-spec-test-pairing
Open

fix(health): recognize Ruby <stem>_spec.rb test pairing#1841
sloemo01 wants to merge 1 commit into
repowise-dev:mainfrom
sloemo01:fix/ruby-spec-test-pairing

Conversation

@sloemo01

Copy link
Copy Markdown
Contributor

Fixes #1768

Problem

Ruby's standard test layout is <stem>_spec.rb under spec/ (underscore before spec, not a dot). Neither test-pairing heuristic recognized it:

  • _has_paired_test_file in engine.py only had .spec.ts/.spec.js/.spec.mts/.spec.cts (dot form), so every RSpec repo read as has_test_file: false from get_health.
  • The risk tool (via _check_test_gap) delegates to the same shared heuristic, so it also reported test_gap: true.

Fix

Added {stem}_spec{ext} (underscore form) alongside the existing {stem}_test{ext} and dot-form .spec.* candidates. This matches Ruby user_spec.rb and, because Crystal shares the _spec.cr convention, comes along for free.

Note: the %{base}.spec.{ext}% builder previously in the risk tool was already refactored to delegate to the shared _has_paired_test_file, so the single engine.py change covers both get_health and get_risk.

Tests

  • test_paired_test_basenames.py: added test_ruby_and_crystal_underscore_spec_pairing; oracle kept in lockstep.
  • test_risk.py: extended the suffix-convention parametrize with lib/user.rb -> spec/user_spec.rb and src/user.cr -> spec/user_spec.cr.

uv run ruff check passes; the affected tests plus the health/persistence suites pass.

@repowise-bot

repowise-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

✅ Health of changed files: 3.3 → 3.3 (+0.1)

📋 At a glance
3 hotspots touched · 2 files with recent fix history.

Files & modules (2)
  • packages (1 file)
    • .../health/engine.py
  • tests (2 files)
    • .../mcp/test_risk.py
    • .../health/test_paired_test_basenames.py

✅ Health gate: passed

📌 Before you merge

  • Run .../health/test_file_nloc.py, .../health/test_incremental_p80_override.py, .../health/test_module_attribution.py: they import the changed files
🔎 More signals (2)

🗺️ Change map

flowchart LR
  subgraph PR ["Changed in this PR (1 with dependents)"]
    f_packages_core_src_repowise_core_analysis_health_engine_py[".../health/engine.py 🔥"]:::changed
  end
  f_packages_cli_src_repowise_cli_commands_update_cmd_command_py[".../update_cmd/command.py"]
  f_packages_core_src_repowise_core_analysis_health_engine_py --> f_packages_cli_src_repowise_cli_commands_update_cmd_command_py
  f_packages_core_src_repowise_core_analysis_health___init___py[".../health/__init__.py"]
  f_packages_core_src_repowise_core_analysis_health_engine_py --> f_packages_core_src_repowise_core_analysis_health___init___py
  f_packages_core_src_repowise_core_analysis_health_biomarkers_registry_py[".../biomarkers/registry.py"]
  f_packages_core_src_repowise_core_analysis_health_engine_py --> f_packages_core_src_repowise_core_analysis_health_biomarkers_registry_py
  f_packages_core_src_repowise_core_analysis_health_complexity_models_py[".../complexity/models.py"]
  f_packages_core_src_repowise_core_analysis_health_engine_py --> f_packages_core_src_repowise_core_analysis_health_complexity_models_py
  more(["+3 more dependents"])
  PR --> more
  t_tests_unit_health_test_file_nloc_py(["✅ .../health/test_file_nloc.py"]):::guard
  t_tests_unit_health_test_file_nloc_py -.-> f_packages_core_src_repowise_core_analysis_health_engine_py
  classDef changed fill:#dbeafe,stroke:#1d4ed8,color:#1e3a5f
  classDef warn fill:#fef3c7,stroke:#b45309,color:#78350f
  classDef guard fill:#dcfce7,stroke:#15803d,color:#14532d
Loading

Solid arrows: code that imports the changed files (7 direct dependents, from the last indexed snapshot). Dashed: history/tests.

🔥 Hotspots touched (3)

  • .../health/engine.py: 39 commits/90d, 14 dependents · primary owner: Raghav Chamadiya (97%)
  • .../mcp/test_risk.py: 7 commits/90d, 2 dependents · primary owner: Raghav Chamadiya (74%)
  • .../health/test_paired_test_basenames.py: 1 commits/90d, 0 dependents · primary owner: Raghav Chamadiya (100%)

👀 Suggested reviewers @RaghavChamadiya


📊 See the full report for this PR
Your repo map with this PR's blast radius lit up, every caller of the contracts it changes, and health before and after. No sign-in. · ⭐ Star Repowise · 📥 Install bot · Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot · Updated 2026-08-22 12:32 UTC

@Ayush7614 Ayush7614 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verified: packages/core/src/repowise/core/analysis/health/engine.py:289 adds {stem}_spec{ext} candidate alongside dot-form, fixing Ruby _spec.rb (#1768) and Crystal _spec.cr pairing for _has_paired_test_file. Covers both get_health and get_risk via shared helper. Tests in test_paired_test_basenames + test_risk parametrize cover it. LGTM.

@RaghavChamadiya

Copy link
Copy Markdown
Member

Thanks @sloemo01. Reusing test_suffix instead of hardcoding .rb is what makes this land Crystal for free, and testing user_spec.cr alongside user_spec.rb is what proves it rather than assuming it. The negative case (user.spec.rb must not pair, since the dot form is not Ruby's layout) is the one that keeps the two conventions from blurring.

This is half of #1768 though, and I want to flag it because I am the one who left the other half on the thread. The issue has two heuristics missing Ruby, not one. The suffix side is what you fixed. The prefix side is still hardcoded to Python two lines above your change:

candidates = {
    f"test_{stem}.py",
    f"{stem}_test{test_suffix}",
    f"{stem}_spec{test_suffix}",

Ruby minitest names its files test/test_user.rb, and #1750 merged with test_{stem}.py still pinned to .py, so risk lost that layout too. Before #1750 the older extension-blind %test_{base}% match happened to catch it, so this is a regression rather than a gap that was always there. The same test_suffix you are already using closes it:

    f"test_{stem}{test_suffix}",

That also picks up Elixir's test/test_helper-adjacent naming and anything else that puts the marker first, so it is not Ruby-specific work.

Since the PR says Fixes #1768 it will close the issue on merge, which is why I would rather fold both halves in here than merge and reopen. It is one line plus a case in the parametrized list you already extended. Push it and I will merge.

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.

[Bug] Ruby's <stem>_spec.rb is missed by both test-pairing heuristics, so every RSpec repo reads as untested

3 participants