Skip to content

test(coverage): quick wins for CLIPipeline/mainwindow/MaterialEditorQML - #266

Merged
fernandotonon merged 2 commits into
masterfrom
codex/coverage-quickwins
Apr 9, 2026
Merged

test(coverage): quick wins for CLIPipeline/mainwindow/MaterialEditorQML#266
fernandotonon merged 2 commits into
masterfrom
codex/coverage-quickwins

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Apr 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • add parser/error-path tests in CLIPipeline_test.cpp that increase non-Ogre branch coverage:
    • cmdFix existing-invalid-file with --all
    • cmdAnim rename/merge modes without explicit output path
    • cmdLod --info --json nonexistent-file path and invalid --count parsing
  • add no-Ogre coverage tests in MaterialEditorQML_test.cpp:
    • deterministic directory filtering (dirs + image files only)
    • getFileSizeString() KB/MB branches
    • AI/SD precondition paths (generateMaterialFromPrompt, generateTextureFromPrompt, stop methods)
  • add mainwindow_test.cpp coverage tests for:
    • keyReleaseEvent
    • stale recent-file cleanup path in openRecentFile
  • update CI coverage exclusions for non-CI-testable AI/SD paths:
    • exclude AIChatManager.cpp/.h
    • exclude SDManager.h and SDWorker.h

Coverage config updates

  • .github/workflows/deploy.yml (gcovr excludes)
  • sonar-project.properties (sonar.coverage.exclusions)

Validation

  • cmake --build . --target UnitTests -j6
  • QT_QPA_PLATFORM=offscreen ./bin/UnitTests --gtest_filter='CLIPipelineCmdFixError.ExistingInvalidFileWithAllFlagReturnsError:CLIPipelineCmdAnimError.RenameModeWithoutOutputUsesDefaultOutputPath:CLIPipelineCmdAnimError.MergeModeWithoutOutputUsesDefaultOutputPath:CLIPipelineCmdLodError.NonexistentFileWithInfoAndJsonMode:CLIPipelineCmdLodError.InvalidCountValueReportsModeError:MaterialEditorQMLTest.FileSystem_ListDirectoryFiltersOnlyImagesAndDirectories:MaterialEditorQMLTest.FileSystem_GetFileSizeStringCoversKbAndMbBranches:MaterialEditorQMLTest.GenerateMaterialFromPrompt_EmptyPromptEmitsError:MaterialEditorQMLTest.GenerateMaterialFromPrompt_NoModelLoadedEmitsError:MaterialEditorQMLTest.GenerateTextureFromPrompt_EmptyPromptEmitsError:MaterialEditorQMLTest.GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel:MaterialEditorQMLTest.StopGenerationMethodsWithoutActiveJobsDoNotCrash:MainWindowTest.KeyReleaseEventDoesNotCrash:MainWindowTest.OpenRecentFileRemovesMissingPathFromSettings'
  • QT_QPA_PLATFORM=offscreen ./bin/UnitTests --gtest_filter='CLIPipelineCmdFixError.*:CLIPipelineCmdAnimError.*:CLIPipelineCmdLodError.*:MaterialEditorQMLTest.Generate*:*FileSystem_GetFileSizeStringCoversKbAndMbBranches:*FileSystem_ListDirectoryFiltersOnlyImagesAndDirectories:MainWindowTest.KeyReleaseEventDoesNotCrash:MainWindowTest.OpenRecentFileRemovesMissingPathFromSettings'

Notes

  • Local environment cannot construct MainWindow (X11/Ogre parentWindowHandle issue), so the two new MainWindowTest cases are compiled and discovered but skipped locally. They are intended for CI environments where MainWindowTest currently runs.

Summary by CodeRabbit

  • Tests

    • Enhanced error-path test coverage for command-line pipeline commands.
    • Added comprehensive tests for file system operations, LLM/texture generation error scenarios, and robustness checks.
    • Added tests for keyboard event handling and recent file cleanup.
  • Chores

    • Updated CI coverage exclusions and SonarQube configuration to include additional AI and graphics-related components.

@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR extends test coverage across CLI pipelines and Qt UI components while refining CI/coverage configuration. Updates cover exclusion patterns in deployment workflows and Sonar analysis, adds negative-path test cases for CLI commands (cmdFix, cmdAnim, cmdLod), and introduces Qt file-system, AI/SD generation error-handling, and UI event tests with temporary file fixtures.

Changes

Cohort / File(s) Summary
CI/Coverage Configuration
.github/workflows/deploy.yml, sonar-project.properties
Updated gcovr and Sonar coverage exclusions to broaden AI/SD-related file filtering: replaced single-pattern exclusion with explicit list covering AIChatManager.cpp, AIChatManager.h, SDManager.h, and SDWorker.h.
CLI Pipeline Tests
src/CLIPipeline_test.cpp
Added error-path unit tests: cmdFix with invalid existing file and --all; cmdAnim with --rename/--merge missing output path scenarios; cmdLod with nonexistent --info --json and invalid non-numeric --count value. Each creates/cleans temporary test files.
Qt Material Editor Tests
src/MaterialEditorQML_test.cpp
Extended test coverage for file-system operations (listDirectory() filtering, getFileSizeString() formatting) and AI/SD error handling: empty/missing prompt validation, model-not-loaded errors, disabled SD checks. Added robustness assertions for stopAIGeneration() and stopTextureGeneration() with no active jobs. Added QFile and QTemporaryDir includes.
Qt Mainwindow Tests
src/mainwindow_test.cpp
Added KeyReleaseEventDoesNotCrash test for key event handling; added OpenRecentFileRemovesMissingPathFromSettings test using QTimer to auto-accept QMessageBox and verify missing path removal from settings/in-memory list. Added <QMessageBox> and <QTimer> includes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 Hop, hop! Tests now leap so high,
Coverage files weed out the rye,
Error paths caught, no surprises to spy—
Quality blooms as the details comply! 🌱

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main focus of the PR: adding test coverage for CLIPipeline, mainwindow, and MaterialEditorQML.
Description check ✅ Passed The description comprehensively covers the changes with clear summaries, technical details, and validation steps, though it deviates from the template structure by embedding content into a single Summary section rather than separating Features and Bugfixes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/coverage-quickwins

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0004ed959f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


editor->generateTextureFromPrompt("brushed steel", 512, 512);

ASSERT_GE(errorSpy.count(), 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard SD error-path test when a model is already loaded

generateTextureFromPrompt("brushed steel", ...) only emits sdGenerationError synchronously when SD is disabled or no SD model is loaded; when ENABLE_STABLE_DIFFUSION is on and a model has already been auto-loaded, the call takes the generation path and this assertion fails immediately even though nothing is wrong. This makes the test environment-dependent/flaky (similar to the LLM test right above, which already skips when a model is loaded), so the check should be conditioned on sdModelLoaded() or otherwise handle the loaded-model path explicitly.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/mainwindow_test.cpp (1)

148-151: Update the adjacent outdated comment about keyReleaseEvent coverage.

This new test now exercises keyReleaseEvent directly, so the nearby note saying it is only tested implicitly is stale and should be revised/removed for clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mainwindow_test.cpp` around lines 148 - 151, Update the outdated comment
near the KeyReleaseEvent tests to reflect that keyReleaseEvent is now covered
directly by the new test KeyReleaseEventDoesNotCrash; locate the comment
adjacent to the TEST_F(MainWindowTest, KeyReleaseEventDoesNotCrash) block and
either remove or rewrite it to state that keyReleaseEvent is explicitly
exercised by this test (reference keyReleaseEvent and the test name to find the
spot).
src/CLIPipeline_test.cpp (1)

1036-1045: Prefer QDir::tempPath() over hardcoded /tmp in new tests.

Using Qt temp-path APIs makes these cases more portable across non-Linux CI/dev environments.

Also applies to: 1656-1662

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/CLIPipeline_test.cpp` around lines 1036 - 1045, Replace hardcoded "/tmp"
paths in the tests (e.g., the TestArgv usages in TEST(CLIPipelineCmdAnimError,
MergeModeWithoutOutputUsesDefaultOutputPath) and the earlier rename test) with
Qt's QDir::tempPath() so the tests use a platform-appropriate temporary
directory; update the TestArgv constructions and any string concatenation that
builds filenames (references: TestArgv, CLIPipeline::cmdAnim, tests named
CLIPipelineCmdAnimError and MergeModeWithoutOutputUsesDefaultOutputPath) to call
QDir::tempPath() + "/" + "<unique_filename>" (and apply the same change to the
other occurrences mentioned around lines 1656-1662).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/MaterialEditorQML_test.cpp`:
- Around line 1979-1994: The test
GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel should be made
deterministic by skipping the "SD unavailable" assertions when Stable Diffusion
is present: check editor->stableDiffusionEnabled() at the start of the test and
call GTEST_SKIP() (or otherwise short-circuit the test) with an explanatory
message if true, otherwise keep the existing errorSpy assertions that expect
sdGenerationError after calling editor->generateTextureFromPrompt; this uses the
MaterialEditorQMLTest test, editor->generateTextureFromPrompt,
editor->stableDiffusionEnabled(), and the sdGenerationError signal to locate
where to add the guard.

---

Nitpick comments:
In `@src/CLIPipeline_test.cpp`:
- Around line 1036-1045: Replace hardcoded "/tmp" paths in the tests (e.g., the
TestArgv usages in TEST(CLIPipelineCmdAnimError,
MergeModeWithoutOutputUsesDefaultOutputPath) and the earlier rename test) with
Qt's QDir::tempPath() so the tests use a platform-appropriate temporary
directory; update the TestArgv constructions and any string concatenation that
builds filenames (references: TestArgv, CLIPipeline::cmdAnim, tests named
CLIPipelineCmdAnimError and MergeModeWithoutOutputUsesDefaultOutputPath) to call
QDir::tempPath() + "/" + "<unique_filename>" (and apply the same change to the
other occurrences mentioned around lines 1656-1662).

In `@src/mainwindow_test.cpp`:
- Around line 148-151: Update the outdated comment near the KeyReleaseEvent
tests to reflect that keyReleaseEvent is now covered directly by the new test
KeyReleaseEventDoesNotCrash; locate the comment adjacent to the
TEST_F(MainWindowTest, KeyReleaseEventDoesNotCrash) block and either remove or
rewrite it to state that keyReleaseEvent is explicitly exercised by this test
(reference keyReleaseEvent and the test name to find the spot).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89276af9-2ee9-4fa6-a0a9-d59de833b04f

📥 Commits

Reviewing files that changed from the base of the PR and between e32c511 and 0004ed9.

📒 Files selected for processing (5)
  • .github/workflows/deploy.yml
  • sonar-project.properties
  • src/CLIPipeline_test.cpp
  • src/MaterialEditorQML_test.cpp
  • src/mainwindow_test.cpp

Comment on lines +1979 to +1994
TEST_F(MaterialEditorQMLTest, GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel) {
QSignalSpy errorSpy(editor.get(), &MaterialEditorQML::sdGenerationError);

editor->generateTextureFromPrompt("brushed steel", 512, 512);

ASSERT_GE(errorSpy.count(), 1);
const QList<QVariant> args = errorSpy.takeFirst();
ASSERT_EQ(args.size(), 1);
const QString message = args.at(0).toString();

if (editor->stableDiffusionEnabled()) {
EXPECT_TRUE(message.contains("No SD model loaded") || message.contains("AI Settings"));
} else {
EXPECT_TRUE(message.contains("Stable Diffusion support is not enabled"));
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Make the SD unavailable-path assertion deterministic across environments.

This test hard-requires an error signal, but in environments where SD is fully available/configured, generateTextureFromPrompt(...) may not emit sdGenerationError, causing a false failure.

Proposed test hardening
 TEST_F(MaterialEditorQMLTest, GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel) {
     QSignalSpy errorSpy(editor.get(), &MaterialEditorQML::sdGenerationError);

     editor->generateTextureFromPrompt("brushed steel", 512, 512);

-    ASSERT_GE(errorSpy.count(), 1);
+    if (errorSpy.count() == 0 && !errorSpy.wait(300)) {
+        GTEST_SKIP() << "Stable Diffusion backend appears available/configured; unavailable-path assertion not applicable";
+    }
+    ASSERT_GE(errorSpy.count(), 1);
     const QList<QVariant> args = errorSpy.takeFirst();
     ASSERT_EQ(args.size(), 1);
     const QString message = args.at(0).toString();

     if (editor->stableDiffusionEnabled()) {
         EXPECT_TRUE(message.contains("No SD model loaded") || message.contains("AI Settings"));
     } else {
         EXPECT_TRUE(message.contains("Stable Diffusion support is not enabled"));
     }
 }

As per coding guidelines: "Features depending on optional components (e.g., local LLM / llama.cpp) may not be available in the test environment — guard with #ifdef ENABLE_LOCAL_LLM or skip gracefully".

📝 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
TEST_F(MaterialEditorQMLTest, GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel) {
QSignalSpy errorSpy(editor.get(), &MaterialEditorQML::sdGenerationError);
editor->generateTextureFromPrompt("brushed steel", 512, 512);
ASSERT_GE(errorSpy.count(), 1);
const QList<QVariant> args = errorSpy.takeFirst();
ASSERT_EQ(args.size(), 1);
const QString message = args.at(0).toString();
if (editor->stableDiffusionEnabled()) {
EXPECT_TRUE(message.contains("No SD model loaded") || message.contains("AI Settings"));
} else {
EXPECT_TRUE(message.contains("Stable Diffusion support is not enabled"));
}
}
TEST_F(MaterialEditorQMLTest, GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel) {
QSignalSpy errorSpy(editor.get(), &MaterialEditorQML::sdGenerationError);
editor->generateTextureFromPrompt("brushed steel", 512, 512);
if (errorSpy.count() == 0 && !errorSpy.wait(300)) {
GTEST_SKIP() << "Stable Diffusion backend appears available/configured; unavailable-path assertion not applicable";
}
ASSERT_GE(errorSpy.count(), 1);
const QList<QVariant> args = errorSpy.takeFirst();
ASSERT_EQ(args.size(), 1);
const QString message = args.at(0).toString();
if (editor->stableDiffusionEnabled()) {
EXPECT_TRUE(message.contains("No SD model loaded") || message.contains("AI Settings"));
} else {
EXPECT_TRUE(message.contains("Stable Diffusion support is not enabled"));
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MaterialEditorQML_test.cpp` around lines 1979 - 1994, The test
GenerateTextureFromPrompt_ReportsUnavailableBackendOrModel should be made
deterministic by skipping the "SD unavailable" assertions when Stable Diffusion
is present: check editor->stableDiffusionEnabled() at the start of the test and
call GTEST_SKIP() (or otherwise short-circuit the test) with an explanatory
message if true, otherwise keep the existing errorSpy assertions that expect
sdGenerationError after calling editor->generateTextureFromPrompt; this uses the
MaterialEditorQMLTest test, editor->generateTextureFromPrompt,
editor->stableDiffusionEnabled(), and the sdGenerationError signal to locate
where to add the guard.

@sonarqubecloud

sonarqubecloud Bot commented Apr 8, 2026

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit 9e77e56 into master Apr 9, 2026
4 checks passed
@fernandotonon
fernandotonon deleted the codex/coverage-quickwins branch April 9, 2026 00:09
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