Skip to content

Conversation

@volodya-lombrozo
Copy link
Member

@volodya-lombrozo volodya-lombrozo commented Jan 29, 2026

This PR introduces the LogProgress extension to enhance logging for parameterized tests in eo-parser, addressing test execution issues during mvn clean install.

Fixes #4833

Summary by CodeRabbit

  • Tests
    • Added a JUnit 5 test extension to log test progress and report completion of parameterized tests.
    • Enabled INFO-level logging for the affected test suite so progress messages are shown during runs.
    • No changes to production behavior or public APIs; improves visibility into test execution in CI and local runs.

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

Copilot AI review requested due to automatic review settings January 29, 2026 10:38
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 29, 2026

📝 Walkthrough

Walkthrough

Adds a JUnit 5 test extension LogProgress, applies it to EoSyntaxTest via @ExtendWith, and enables INFO logging for that test class via test log4j.properties.

Changes

Cohort / File(s) Summary
Test Class Update
eo-parser/src/test/java/org/eolang/parser/EoSyntaxTest.java
Added import org.junit.jupiter.api.extension.ExtendWith and annotated class with @ExtendWith(LogProgress.class) to enable the logging extension.
New JUnit Extension
eo-parser/src/test/java/org/eolang/parser/LogProgress.java
New package-private final class implementing AfterEachCallback; on each test completion detects @ParameterizedTest and logs a completion message (uses org.jcabi.log.Logger).
Test Logging Configuration
eo-parser/src/test/resources/log4j.properties
Added logger entry to set org.eolang.parser.EoSyntaxTest logging level to INFO for test runs.

Sequence Diagram(s)

sequenceDiagram
    participant JUnit as JUnit 5
    participant Test as Test Method
    participant Extension as LogProgress
    participant Logger as org.jcabi.log.Logger

    JUnit->>Test: execute()
    Test->>JUnit: completes
    JUnit->>Extension: afterEach(context)
    Extension->>Extension: inspect test method metadata
    alt method annotated with `@ParameterizedTest`
        Extension->>Logger: log "parameterized test completed" (INFO)
    end
    Extension->>JUnit: callback finished
Loading

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 I hopped into tests with a cheerful nod,
A tiny extension pacing the sod,
Parameter runs now call out their name,
Logged in the files, a quiet little fame,
Hooray — the test garden's less odd.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding logging for progress of parameterized tests in EoSyntaxTest, which aligns with the changes made.
Linked Issues check ✅ Passed The PR implements logging for EoSyntaxTest parameterized tests via LogProgress extension to provide visibility during test execution, addressing the issue #4833 requirement to prevent test halting.
Out of Scope Changes check ✅ Passed All changes are within scope: LogProgress JUnit extension, EoSyntaxTest annotation, and log4j configuration for the test class are directly related to adding logging for parameterized test progress.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a JUnit extension to log the progress of parameterized tests in EoSyntaxTest, addressing test execution issues where tests appear to hang during mvn clean install. The extension logs completion messages for each parameterized test iteration to help diagnose test progress.

Changes:

  • Added LogProgress extension class to log parameterized test completion
  • Applied the LogProgress extension to EoSyntaxTest class

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
eo-parser/src/test/java/org/eolang/parser/LogProgress.java New JUnit extension that logs completion of parameterized test executions to help diagnose test hanging issues
eo-parser/src/test/java/org/eolang/parser/EoSyntaxTest.java Applied the LogProgress extension to enable progress logging for parameterized tests

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 28 to 35
if (LogProgress.parameterized(context)) {
Logger.info(
clazz,
"Parameterized test %s done",
context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
);
}
logger.setLevel(before);
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The logger level is modified on line 27 and restored on line 35, but if an exception occurs during the logging operation (lines 28-34), the logger level will not be restored. Consider using a try-finally block to ensure the logger level is always restored, regardless of exceptions.

Suggested change
if (LogProgress.parameterized(context)) {
Logger.info(
clazz,
"Parameterized test %s done",
context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
);
}
logger.setLevel(before);
try {
if (LogProgress.parameterized(context)) {
Logger.info(
clazz,
"Parameterized test %s done",
context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
);
}
} finally {
logger.setLevel(before);
}

Copilot uses AI. Check for mistakes.
Comment on lines 24 to 26
final var clazz = context.getTestClass().orElse(LogProgress.class);
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(clazz);
final var before = logger.getLevel();
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The use of 'var' for type inference deviates from the codebase convention. Throughout the codebase, explicit types are used for variable declarations. For consistency, declare these variables with explicit types: 'final Class<?> clazz' and 'final Level before'.

Copilot uses AI. Check for mistakes.
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

🤖 Fix all issues with AI agents
In `@eo-parser/src/test/java/org/eolang/parser/LogProgress.java`:
- Around line 24-26: The code uses Java's local-variable type inference (`var`)
which isn't supported by the project's Java target; replace `var` with explicit
types for the variables in the LogProgress test setup: change the declaration of
`clazz` to `Class<?> clazz = context.getTestClass().orElse(LogProgress.class);`
and change `before` to the explicit type returned by `logger.getLevel()` (e.g.,
`org.apache.log4j.Level before = logger.getLevel();`), keeping the existing
logger declaration `org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger(clazz);` and usages unchanged.
- Around line 26-35: logger.getLevel() can be null and calling
logger.setLevel(null) will clear inherited behavior; modify the LogProgress code
so you capture the effective level instead and always restore it in a finally
block: use logger.getEffectiveLevel() (or fall back to a non-null Level) to set
the temporary Level.INFO, and wrap the logging and setLevel calls in try { ... }
finally { logger.setLevel(originalEffectiveLevel); } referencing the logger
variable and the LogProgress class/method where getLevel()/setLevel() are used.
🧹 Nitpick comments (1)
eo-parser/src/test/java/org/eolang/parser/EoSyntaxTest.java (1)

56-76: Consider consolidating log level management.

The test class now has two mechanisms managing log levels:

  1. The new LogProgress extension (for the test class logger)
  2. The existing setUp/tearDown methods (lines 66-76, for EoSyntax.class logger)

This is fine since they target different loggers, but consider whether the existing @BeforeEach/@AfterEach logic could be moved into LogProgress or a similar extension for consistency, especially if other test classes need the same pattern.

Comment on lines 26 to 35
final var before = logger.getLevel();
logger.setLevel(Level.INFO);
if (LogProgress.parameterized(context)) {
Logger.info(
clazz,
"Parameterized test %s done",
context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
);
}
logger.setLevel(before);
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

Handle potential null value from getLevel().

logger.getLevel() returns null when no level is explicitly configured on the logger (it inherits from parent). Passing null to setLevel() on line 35 will clear the level, which may differ from the original inherited behavior.

🛡️ Proposed fix to handle null level
     public void afterEach(final ExtensionContext context) {
-        final var clazz = context.getTestClass().orElse(LogProgress.class);
+        final Class<?> clazz = context.getTestClass().orElse(LogProgress.class);
         final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(clazz);
-        final var before = logger.getLevel();
-        logger.setLevel(Level.INFO);
-        if (LogProgress.parameterized(context)) {
-            Logger.info(
-                clazz,
-                "Parameterized test %s done",
-                context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
-            );
+        final Level before = logger.getEffectiveLevel();
+        try {
+            logger.setLevel(Level.INFO);
+            if (LogProgress.parameterized(context)) {
+                Logger.info(
+                    clazz,
+                    "Parameterized test %s done",
+                    context.getDisplayName().lines().findFirst().orElse(context.getUniqueId())
+                );
+            }
+        } finally {
+            logger.setLevel(before);
         }
-        logger.setLevel(before);
     }

Using getEffectiveLevel() returns the inherited level if none is set. Wrapping in try-finally ensures level is restored even if logging throws.

🤖 Prompt for AI Agents
In `@eo-parser/src/test/java/org/eolang/parser/LogProgress.java` around lines 26 -
35, logger.getLevel() can be null and calling logger.setLevel(null) will clear
inherited behavior; modify the LogProgress code so you capture the effective
level instead and always restore it in a finally block: use
logger.getEffectiveLevel() (or fall back to a non-null Level) to set the
temporary Level.INFO, and wrap the logging and setLevel calls in try { ... }
finally { logger.setLevel(originalEffectiveLevel); } referencing the logger
variable and the LogProgress class/method where getLevel()/setLevel() are used.

@volodya-lombrozo
Copy link
Member Author

Now in tests I might perfectly see the following output:

13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [189] #\t\u9DD7          CJK_UNIFIED_IDEOGRAPHS (U+9DD7) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [190] #\t\u0152           LATIN SMALL LIGATURE OE (U+0153)  done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [191] #\t\u00E9           LATIN SMALL LETTER E WITH ACUTE (U+00E9) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [192] #\t\uFF22           FULLWIDTH LATIN CAPITAL LETTER B (U+FF22) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [193] #\t\u900D          CJK_UNIFIED_IDEOGRAPHS (U+900D) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [194] #\t\u00DC           LATIN SMALL LETTER U WITH DIAERESIS (U+00FC) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [195] #\t\u00DF           LATIN SMALL LETTER SHARP S (U+00DF) done
13:40:51 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [196] #\t\u00AA           FEMININE ORDINAL INDICATOR (U+00AA) done
13:40:52 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [197] #\t\u0105           LATIN SMALL LETTER A WITH OGONEK (U+0105) done
13:40:52 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [198] #\t\u00F1           LATIN SMALL LETTER N WITH TILDE (U+00F1) done
13:40:52 [INFO] org.eolang.parser.EoSyntaxTest: Parameterized test [199] #\t\u4E02          CJK_UNIFIED_IDEOGRAPHS (U+4E02) done

Instead of silence.

@volodya-lombrozo volodya-lombrozo force-pushed the 4833-eo-parser-test-halt branch from 9748995 to e5bd471 Compare January 29, 2026 10:43
@github-actions
Copy link
Contributor

github-actions bot commented Jan 29, 2026

🚀 Performance Analysis

All benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information.

Click to see the detailed report
Test Base Score PR Score Change % Change Unit Mode
benchmarks.XmirBench.xmirToEO 199.705 171.783 -27.922 -13.98% ms/op Average Time

✅ Performance gain: benchmarks.XmirBench.xmirToEO is faster by 27.922 ms/op (13.98%)

@volodya-lombrozo
Copy link
Member Author

@yegor256 could you have a look, please? I'm not sure if it's a perfect solution, but now I can see some progress in logs

final Class<?> clazz = context.getTestClass().orElse(LogProgress.class);
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(clazz);
final Level before = logger.getLevel();
logger.setLevel(Level.INFO);
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo this indeed is dirty. Can't you just set this log level in the src/test/resources/log4j.properties? The effect should be the same.

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 agree. Fixed. Could you take a look one more time, please?

@yegor256 yegor256 merged commit a7bd26d into objectionary:master Jan 30, 2026
27 checks passed
@0crat
Copy link

0crat commented Jan 30, 2026

@volodya-lombrozo Great work on your contribution! 🎯 You've earned +16 points and your total score now stands at +208. Keep up the momentum with quality contributions, and don't forget to monitor your progress through your Zerocracy account.

@0crat
Copy link

0crat commented Jan 30, 2026

@yegor256 Hey! Nice work on that review 👍 You snagged +7 points this time: started with the standard +12 base points, but got dinged -5 for having just 1 comment (our policy encourages at least 12 comments to avoid penalties). Your running total is now +140 - keep those detailed reviews coming to maximize your bonuses! Don't forget to peek at your Zerocracy account when you get a chance.

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.

eo-parser Tests Halt During mvn clean install Execution

3 participants