-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support ordering of listeners #3072
Conversation
WalkthroughThe update enhances TestNG by allowing users to define the order of TestNG listeners using a Changes
Related issues
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
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 as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 7
Configuration used: CodeRabbit UI
Files selected for processing (36)
- CHANGES.txt (1 hunks)
- testng-core/src/main/java/org/testng/CommandLineArgs.java (1 hunks)
- testng-core/src/main/java/org/testng/DataProviderHolder.java (2 hunks)
- testng-core/src/main/java/org/testng/ListenerComparator.java (1 hunks)
- testng-core/src/main/java/org/testng/SuiteRunner.java (9 hunks)
- testng-core/src/main/java/org/testng/TestNG.java (4 hunks)
- testng-core/src/main/java/org/testng/TestRunner.java (7 hunks)
- testng-core/src/main/java/org/testng/internal/Configuration.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/IConfiguration.java (1 hunks)
- testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java (1 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java (4 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/IConfigInvoker.java (2 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java (3 hunks)
- testng-core/src/test/java/org/testng/internal/TestListenerHelperTest.java (1 hunks)
- testng-core/src/test/java/org/testng/internal/invokers/ParameterHandlerTest.java (2 hunks)
- testng-core/src/test/java/test/listeners/ListenersTest.java (3 hunks)
- testng-core/src/test/java/test/listeners/issue2916/AlterSuiteListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/AnnotatedTestCaseSamplesHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/AnnotationBackedListenerComparator.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/ClassListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/ConfigurationListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/DataProviderInterceptorHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/DataProviderListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/DataProviderSampleTestCase.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/ElaborateSampleTestCase.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/ExecutionListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/ExecutionVisualiserHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/InvokedMethodListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/MethodInterceptorHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/NormalSampleTestCase.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/RunOrder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/SimpleConfigTestCase.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/SuiteListenerHolder.java (1 hunks)
- testng-core/src/test/java/test/listeners/issue2916/TestListenerHolder.java (1 hunks)
Additional comments: 39
testng-core/src/test/java/test/listeners/issue2916/RunOrder.java (1)
- 1-12: The
RunOrder
annotation is correctly defined and follows Java annotation best practices. It's a clean and effective way to specify the execution order of listeners in TestNG.testng-core/src/test/java/test/listeners/issue2916/SimpleConfigTestCase.java (1)
- 1-23: The
SimpleConfigTestCase
class is well-structured, using TestNG configuration annotations correctly. The intentional failure inbeforeMethod
serves as a valid test case to verify TestNG's handling of configuration method failures.testng-core/src/test/java/test/listeners/issue2916/DataProviderSampleTestCase.java (1)
- 1-22: The
DataProviderSampleTestCase
class correctly implements data-driven testing patterns in TestNG. The inclusion of a failing data provider is a strategic choice to test the framework's error handling capabilities.testng-core/src/main/java/org/testng/internal/invokers/IConfigInvoker.java (1)
- 21-26: > 📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [5-25]
The addition of the
getConfiguration()
method to theIConfigInvoker
interface is a logical enhancement, allowing for more flexible and informed configuration invocations. The change is correctly implemented and aligns with the interface's responsibilities.testng-core/src/test/java/test/listeners/issue2916/ElaborateSampleTestCase.java (1)
- 1-30: The
ElaborateSampleTestCase
class provides a comprehensive set of test scenarios, including failing, skipping, flaky, and timing-out tests. Each test method is correctly implemented following TestNG conventions, offering valuable test cases for verifying the framework's functionality.testng-core/src/main/java/org/testng/internal/Configuration.java (1)
- 79-94: > 📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [41-90]
The introduction of the
ListenerComparator
field inConfiguration
, along with its setter and getter methods (setListenerComparator
andgetListenerComparator
), is a crucial part of enabling the listener ordering feature. This change allows users to configure the order of listeners programmatically, which is central to the PR's objectives.The implementation of the listener comparator configuration in
Configuration
is correctly done and aligns with the PR's objectives. It's important to ensure that this new configuration option is well-documented and tested to confirm its functionality and impact on listener ordering.testng-core/src/test/java/test/listeners/issue2916/InvokedMethodListenerHolder.java (6)
- 15-88: The array
EXPECTED_LOGS
is well-defined and matches the expected order of listener invocation based on the@RunOrder
annotations. This is crucial for validating the functionality of listener ordering.- 91-95: The definition of
ALL
as a static final list of listeners is appropriate for testing purposes. It correctly includes all defined listener classes.- 97-100: The definition of
SUBSET
as a static final list of a subset of listeners is appropriate and useful for specific test scenarios.- 102-103: The
ALL_STRING
list correctly represents the class names of all listeners. This is useful for assertions or logging purposes.- 105-122: The abstract class
KungFuWarrior
correctly implements theIInvokedMethodListener
interface, providing a template for listener classes. The implementation ofbeforeInvocation
andafterInvocation
methods is correct, appending logs as expected.- 125-131: The use of
@RunOrder
annotations onMasterOogway
andMasterShifu
classes to define execution order is a good practice for testing listener ordering functionality.testng-core/src/main/java/org/testng/CommandLineArgs.java (1)
- 57-63: The addition of the
listenerComparator
command-line argument is correctly implemented and follows the existing code style and structure. The description provided is clear and informative, explaining the purpose of the argument.testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java (2)
- 169-173: The implementation for sorting listeners based on a
ListenerComparator
before invoking@BeforeClass
methods is correctly done. It ensures that listeners are processed in the specified order, which is crucial for the new feature.- 240-244: Similarly, the implementation for sorting listeners before invoking
@AfterClass
methods is correct and follows the same pattern as the@BeforeClass
methods. This consistency is important for the feature's reliability.testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java (1)
- 147-151: The addition of the
configuration
parameter to theDataProviderHolder
constructor call within theprocessMethod
function correctly aligns with the PR's objective to enhance listener ordering functionality. This change ensures that theDataProviderHolder
can utilize the configuration, potentially including the newListenerComparator
, to manage data providers in a way that respects the specified listener order.testng-core/src/main/java/org/testng/SuiteRunner.java (5)
- 44-44: Making the
xmlSuite
,tmpRunnerFactory
,holder
,configuration
,invokedMethodListeners
, andexitCodeListener
fields final in theSuiteRunner
class is a good practice. It enhances the immutability of the class, ensuring that these critical components, which are foundational to the suite's execution, are not inadvertently modified after initialization.Also applies to: 50-51, 60-60, 66-66, 72-72
- 239-243: The modifications to the
invokeListeners
method to sort listeners based on a comparator before invoking them align with the PR's objective to allow ordering of listeners. This change is crucial for ensuring that listeners are executed in the specified order, which can be critical for certain testing scenarios where the order of listener execution affects the outcome.Also applies to: 245-249
- 278-279: The addition of the
configuration
parameter to theProxyTestRunnerFactory
constructor is necessary to pass the configuration, including the new listener ordering feature, to the proxy factory. This ensures that the proxy factory can createTestRunner
instances with the correct configuration, maintaining consistency across the framework.- 608-608: Initializing
DataProviderHolder
with theconfiguration
parameter in theDefaultTestRunnerFactory
'snewTestRunner
method is consistent with the changes made elsewhere in the PR. This ensures that data provider handling within each test runner respects the global configuration, including listener ordering.- 690-690: Similarly, initializing
DataProviderHolder
with theconfiguration
parameter in theProxyTestRunnerFactory
'snewTestRunner
method ensures that the proxy factory's test runners are created with the correct configuration. This change is necessary for consistency and to support the new listener ordering feature throughout the framework.testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java (4)
- 11-11: The addition of the
List
import is appropriate for supporting the changes made in therunConfigurationListeners
method where aList
ofIConfigurationListener
is used.- 25-25: The import of
ListenerComparator
is necessary for the newly introduced sorting functionality of listeners, aligning with the PR's objective to allow ordering of listeners.- 30-30: The import of
org.testng.collections.Lists
is used to leverage theLists.newArrayList
method, which is a part of the changes to create a mutable list from the configuration listeners.- 83-86: The addition of the
getConfiguration
method provides a way to access theIConfiguration
instance from theConfigInvoker
. This method is straightforward and correctly returns them_configuration
field.testng-core/src/test/java/test/listeners/ListenersTest.java (2)
- 59-355: The test methods introduced for validating listener ordering through different approaches (API, XML tag, CLI, and annotations) are well-structured and follow a consistent pattern. Each method clearly describes its purpose and utilizes the
Ensure
class to perform the actual validation. This approach enhances readability and maintainability.However, it's important to ensure that these tests cover all edge cases and potential ordering conflicts among listeners. Additionally, considering the complexity of listener ordering, it might be beneficial to include comments within each test method explaining why certain orderings are expected, especially for tests involving annotations where the ordering might not be immediately obvious.
- 673-736: The
Ensure
class provides static methods to validate the ordering of listeners through different approaches. This class is a key component in the test suite, enabling the concise and clear definition of test cases. The methods within theEnsure
class are well-organized and follow a consistent pattern, which enhances readability and maintainability.A few suggestions for improvement:
- Consider adding comments to explain the logic behind the ordering checks, especially for methods like
orderingViaAnnotation
andorderingViaCli
, where the setup and expectations might not be immediately clear to someone unfamiliar with the context.- Ensure that the
AnnotationBackedListenerComparator
class used in these methods is thoroughly tested elsewhere to guarantee its correct implementation, as it plays a crucial role in determining the listener order.Overall, the
Ensure
class is a well-designed utility for testing listener ordering, but adding more detailed comments could improve its clarity and usefulness for future maintainers.testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java (1)
- 37-37: The import statement for
org.testng.ListenerComparator
is correctly added to support the new functionality of ordering listeners. This is a necessary change to enable the use ofListenerComparator
within theTestInvoker
class.testng-core/src/main/java/org/testng/TestRunner.java (6)
- 174-174: The initialization of
holder
withotherHolder
in the constructor ensures that theDataProviderHolder
instance can be passed externally, allowing for more flexible configuration. This change seems logically sound and correctly implemented.- 197-197: Initializing
holder
with a newDataProviderHolder
instance using theconfiguration
parameter in this constructor variant ensures that theDataProviderHolder
is always properly initialized based on the current configuration. This is a good practice for ensuring consistency and reliability in the TestRunner's behavior.- 220-220: Similar to the previous comment, initializing
holder
with a newDataProviderHolder
instance in this constructor variant ensures consistency and reliability. It's good to see that this pattern is consistently applied across different constructors.- 698-703: Sorting the
visualisers
list using aListenerComparator
if it's not null is a crucial part of implementing the ordered execution of listeners. This approach allows for dynamic ordering based on runtime conditions or configurations. However, it's important to ensure that theListenerComparator
is thoroughly tested to handle all expected and edge cases correctly.Verification successful
To further verify the thoroughness of testing for
ListenerComparator
implementations, including handling of edge cases, we need to examine the relevant test files. Specifically, we should look into tests forAnnotationBackedListenerComparator
and any other tests that directly involve theListenerComparator
interface.
To accurately assess the thoroughness of testing for
ListenerComparator
implementations, including the handling of edge cases, we will now examine the content of bothAnnotationBackedListenerComparator.java
andListenersTest.java
.
The examination of
AnnotationBackedListenerComparator.java
andListenersTest.java
provides valuable insights into the implementation and testing of theListenerComparator
interface within the TestNG framework.
Implementation Details: The
AnnotationBackedListenerComparator
class implements theListenerComparator
interface, providing a custom comparison logic based on annotations present on listener classes. This allows for dynamic ordering of listeners at runtime, aligning with the original review comment's emphasis on the importance of ordered execution.Testing Coverage: The
ListenersTest.java
file contains a comprehensive suite of tests designed to verify the ordering of various types of listeners (e.g., execution listeners, suite listeners, test listeners, etc.) through different mechanisms (API, XML tag, CLI, and annotations). These tests ensure that the ordering logic implemented byAnnotationBackedListenerComparator
works as expected across a wide range of scenarios, including those that might be considered edge cases.Given the detailed implementation of the
AnnotationBackedListenerComparator
and the extensive testing demonstrated inListenersTest.java
, it can be concluded that theListenerComparator
and its implementations are indeed thoroughly tested to handle all expected and edge cases correctly. This confirms the original review comment's assertion about the importance of testing theListenerComparator
to ensure the ordered execution of listeners based on runtime conditions or configurations.* 748-753: Applying the `ListenerComparator` to sort `m_methodInterceptors` is consistent with the approach used for `visualisers`. This ensures that method interceptors are also executed in an ordered manner, which can be critical for tests where the execution order of interceptors affects the outcome. As with the previous comment, thorough testing of the `ListenerComparator` is recommended. * 862-866: Sorting `m_testListeners` using the `ListenerComparator` before firing events is another instance of applying ordered execution logic to listeners. This consistency in handling listener ordering across different types of listeners (test listeners, visualisers, method interceptors) is good to see. Again, ensure that the `ListenerComparator` is robust and well-tested.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Verify the implementation and usage of ListenerComparator across the codebase rg "ListenerComparator" --type javaLength of output: 5220
Script:
#!/bin/bash # Examine tests for ListenerComparator implementations rg "ListenerComparator" --type java --files-with-matches | grep "test/"Length of output: 220
Script:
#!/bin/bash # Inspect the implementation and tests of ListenerComparator cat testng-core/src/test/java/test/listeners/issue2916/AnnotationBackedListenerComparator.java cat testng-core/src/test/java/test/listeners/ListenersTest.javaLength of output: 30028
testng-core/src/main/java/org/testng/TestNG.java (5)
- 276-282: The addition of
setListenerComparator
andgetListenerComparator
methods is correctly implemented. These methods allow setting and retrieving a custom comparator for listeners, which is essential for the new feature of defining the execution order of listeners. The methods are straightforward and follow Java best practices.- 1141-1145: The modification to
runSuiteAlterationListeners
to sort the listeners based on the comparator before invocation is logically sound. This ensures that suite alteration listeners are executed in the order defined by the comparator, enhancing the flexibility of listener execution. However, it's important to ensure that the comparator handles null values gracefully to avoid potentialNullPointerException
s.Verification successful
The implementation of
AnnotationBackedListenerComparator
effectively handles null values by usingOptional.ofNullable
for null safety and providing a default value when necessary. This ensures that the comparator avoidsNullPointerException
s, aligning with the concern raised in the review comment. Therefore, the modification to sort suite alteration listeners based on the comparator is verified to be safe regarding null handling.* 1151-1155: The changes to `runExecutionListeners` to sort execution listeners using the comparator are correctly implemented. This modification aligns with the objective of allowing users to define the execution order of listeners. Similar to the previous comment, ensure that the comparator implementation is robust against null values.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if ListenerComparator implementation handles null values to prevent NullPointerException. grep -R "implements ListenerComparator" | grep -v "TestNG.java"Length of output: 234
Script:
#!/bin/bash # Extract the compare method from AnnotationBackedListenerComparator.java to check for null handling grep -A 20 "public int compare" testng-core/src/test/java/test/listeners/issue2916/AnnotationBackedListenerComparator.javaLength of output: 664
Verification successful
The
AnnotationBackedListenerComparator
class implements a robust approach to handling potentially null annotation values on listener objects, usingOptional.ofNullable
to default toInteger.MAX_VALUE
when annotations are not present. This ensures that listeners without theRunOrder
annotation are ordered towards the end, aligning with the goal of allowing users to define execution order through annotations. However, it's worth noting that there are no explicit null checks on the listener objects (l1
andl2
) themselves before their comparison. This is likely acceptable given the operational context within TestNG, where listener objects passed to this comparator are expected to be non-null. The review comment regarding the robustness against null values in the context of execution listeners is therefore verified with the consideration that the comparator's design is focused on handling null annotation values rather than null listener objects.* 1385-1385: The enhancement to `createSuiteRunner` to initialize `DataProviderHolder` with the configuration is a good addition. It ensures that data provider listeners and interceptors are correctly set up with the suite runner, which is crucial for the new feature's functionality. This change improves the modularity and maintainability of the suite runner creation process. * 1502-1508: The implementation of setting the listener comparator based on command-line arguments is a valuable addition. It allows users to specify a custom comparator class via command-line, enhancing the usability of the new feature. Ensure that the specified class indeed implements `ListenerComparator` and handle potential class loading issues gracefully.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Verify robustness of ListenerComparator against null values in the context of execution listeners. grep -R "implements ListenerComparator" | grep -v "TestNG.java"Length of output: 234
Script:
#!/bin/bash # Inspect the comparison method of AnnotationBackedListenerComparator for null value handling cat testng-core/src/test/java/test/listeners/issue2916/AnnotationBackedListenerComparator.javaLength of output: 865
Verification successful
Given the information from the script output and the context of the review comment, it's clear that the
ListenerComparator
interface is well-integrated within the TestNG framework, and the mechanism for setting a customListenerComparator
via command-line arguments is implemented. However, to fully verify the handling of potential class loading issues and ensure graceful error handling, we would need to examine the error handling or logging mechanisms related to the class loading and instantiation process of theListenerComparator
. Since the script output does not provide this specific detail, further investigation into the source code around the provided snippet is necessary.
The review comment's concerns are partially verified. The implementation indeed allows for specifying a custom
ListenerComparator
class via command-line arguments, enhancing the usability of this feature. The use ofOptional
ensures that only classes implementingListenerComparator
can be set, providing a basic level of error handling by ensuring type safety and null checks. However, the absence of explicit error handling or logging for class loading issues means that while the system may fail gracefully, it might not provide clear feedback to the user about the failure reason. This could be considered an area for improvement rather than an incorrect implementation.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Verify that the specified ListenerComparator class can be loaded and correctly implements the interface. grep -R "ListenerComparator" | grep -v "TestNG.java"Length of output: 4394
Script:
#!/bin/bash # Look for error handling or logging mechanisms around the instantiation of ListenerComparator from command-line arguments rg "setListenerComparator" -A 10 -B 10Length of output: 14588
List<ITestListener> original = m_notifier.getTestListeners(); | ||
ListenerComparator comparator = m_configuration.getListenerComparator(); | ||
if (comparator != null) { | ||
original.sort(comparator::compare); | ||
} | ||
List<ITestListener> listeners = | ||
isFinished | ||
? ListenerOrderDeterminer.reversedOrder(m_notifier.getTestListeners()) | ||
: ListenerOrderDeterminer.order(m_notifier.getTestListeners()); | ||
? ListenerOrderDeterminer.reversedOrder(original) | ||
: ListenerOrderDeterminer.order(original); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic to sort the listeners based on the ListenerComparator
is correctly implemented within the runTestResultListener
method. This ensures that listeners are ordered as per the comparator's logic before being invoked. However, it's important to ensure that the comparator handles nulls gracefully to avoid potential NullPointerExceptions
.
Additionally, consider adding a comment explaining the rationale behind sorting listeners only when comparator
is not null and the impact of listener order on test execution. This will improve code readability and maintainability.
// Sort listeners based on the provided ListenerComparator to ensure the execution order of listeners is as expected.
if (comparator != null) {
original.sort(comparator::compare);
}
List<IConfigurationListener> original = | ||
Lists.newArrayList(m_notifier.getConfigurationListeners()); | ||
ListenerComparator comparator = m_configuration.getListenerComparator(); | ||
if (comparator != null) { | ||
original.sort(comparator::compare); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The modifications in the runConfigurationListeners
method introduce sorting logic for configuration listeners based on the ListenerComparator
. This change is crucial for achieving the PR's objective of allowing users to define the execution order of listeners. However, it's important to ensure that the comparator
is properly tested to handle all edge cases, especially considering the potential complexity of user-defined comparison logic.
Additionally, consider the performance implications of sorting listeners for each configuration method invocation. If the set of listeners or the comparator logic is complex, this could introduce a noticeable overhead. It might be beneficial to cache the sorted list of listeners if the comparator and the set of listeners do not change frequently.
Consider adding performance tests or benchmarks to assess the impact of the sorting logic on the execution time of configuration methods, especially for large sets of listeners or complex comparator logic.
|
||
public class InvokedMethodListenerHolder { | ||
|
||
public static List<String> LOGS = new ArrayList<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of a public static mutable list LOGS
may lead to issues with thread safety and data integrity, especially in a concurrent testing environment.
Consider using thread-safe collections or mechanisms to ensure thread safety, such as Collections.synchronizedList
or CopyOnWriteArrayList
.
* </ol> | ||
*/ | ||
@FunctionalInterface | ||
public interface ListenerComparator { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extends Comparator< ITestNGListener>
List<IDataProviderInterceptor> original = Lists.newArrayList(interceptors); | ||
ListenerComparator comparator = getConfiguration().getListenerComparator(); | ||
if (comparator != null) { | ||
original.sort(comparator::compare); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
original.sort(comparator)
return Collections.unmodifiableCollection(original); | ||
} | ||
|
||
public IConfiguration getConfiguration() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of exposing it in public?
private final IConfiguration configuration; | ||
|
||
public DataProviderHolder(IConfiguration configuration) { | ||
this.configuration = configuration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.configuration = Objects.requireNonNull(configuration);
} | ||
|
||
public Collection<IDataProviderInterceptor> getInterceptors() { | ||
return Collections.unmodifiableCollection(interceptors); | ||
List<IDataProviderInterceptor> original = Lists.newArrayList(interceptors); | ||
ListenerComparator comparator = getConfiguration().getListenerComparator(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid duplication and create a private static method that sorts a list when a comparator is not null and return an unmodifiableCollection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I can create one single method here because:
public Collection<IDataProviderListener> getListeners()
public Collection<IDataProviderInterceptor> getInterceptors()
I cannot create a method that would look like below for e.g.,
private Collection<ITestNGListener> sort(Collection<ITestNGListener> initial)
Java complains that I cannot fit Collection<IDataProviderListener>
into Collection<ITestNGListener> initial
due to type erasure perhaps ? Any suggestions on this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When i build a method that looks like
private Collection<? extends ITestNGListener> sort(Collection<? extends ITestNGListener> initial) {
ListenerComparator comparator = configuration.getListenerComparator();
if (comparator == null) {
return initial;
}
List<? extends ITestNGListener> original = Lists.newArrayList(initial);
original.sort(comparator);
return Collections.unmodifiableCollection(original);
}
then the caller would look like below
public Collection<IDataProviderInterceptor> getInterceptors() {
return (Collection<IDataProviderInterceptor>) sort(interceptors);
}
triggering an Unchecked cast
edit check on this method. I can add a @SuppressWarnings
. Is that fine ?
} | ||
|
||
public Collection<IDataProviderInterceptor> getInterceptors() { | ||
return Collections.unmodifiableCollection(interceptors); | ||
List<IDataProviderInterceptor> original = Lists.newArrayList(interceptors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new list is only mandatory when the comparator is not null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (9)
- testng-core/src/main/java/org/testng/DataProviderHolder.java (2 hunks)
- testng-core/src/main/java/org/testng/ListenerComparator.java (1 hunks)
- testng-core/src/main/java/org/testng/SuiteRunner.java (10 hunks)
- testng-core/src/main/java/org/testng/TestNG.java (5 hunks)
- testng-core/src/main/java/org/testng/TestRunner.java (8 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java (2 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java (4 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java (3 hunks)
Files skipped from review as they are similar to previous changes (9)
- testng-core/src/main/java/org/testng/DataProviderHolder.java
- testng-core/src/main/java/org/testng/ListenerComparator.java
- testng-core/src/main/java/org/testng/SuiteRunner.java
- testng-core/src/main/java/org/testng/TestNG.java
- testng-core/src/main/java/org/testng/TestRunner.java
- testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java
- testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java
- testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java
- testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java
@juherr - Thank you for fixing the comments as well. Can we go ahead and merge this PR now ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files selected for processing (6)
- testng-core/src/main/java/org/testng/SuiteRunner.java (9 hunks)
- testng-core/src/main/java/org/testng/TestNG.java (6 hunks)
- testng-core/src/main/java/org/testng/TestRunner.java (8 hunks)
- testng-core/src/main/java/org/testng/internal/ListenerOrderDeterminer.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java (1 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java (2 hunks)
Files skipped from review as they are similar to previous changes (5)
- testng-core/src/main/java/org/testng/SuiteRunner.java
- testng-core/src/main/java/org/testng/TestNG.java
- testng-core/src/main/java/org/testng/TestRunner.java
- testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java
- testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java
Additional comments: 2
testng-core/src/main/java/org/testng/internal/ListenerOrderDeterminer.java (2)
- 3-3: The import of
ListenerComparator.sort
is correctly added to facilitate sorting functionality within theorder
andreversedOrder
methods. This static import helps in keeping the code concise.- 13-13: The import of
org.testng.ListenerComparator
is necessary for the new functionality, allowing theorder
andreversedOrder
methods to utilize theListenerComparator
for sorting listeners based on the defined criteria.
* @param original - The original collection of listeners | ||
* @return - A re-ordered collection wherein preferential listeners are added at the end | ||
*/ | ||
public static <T> List<T> order(Collection<T> original) { | ||
public static <T extends ITestNGListener> List<T> order( | ||
Collection<T> original, ListenerComparator comparator) { | ||
original = sort(original, comparator); | ||
Pair<List<T>, List<T>> ordered = arrange(original); | ||
List<T> ideListeners = ordered.first(); | ||
List<T> regularListeners = ordered.second(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [50-66]
The method signatures for order
and reversedOrder
have been updated to include a ListenerComparator
parameter. This change is crucial for enabling custom sorting logic based on the comparator provided at runtime. However, there's a potential improvement in how the original
collection is handled within these methods.
Currently, the original
collection is directly modified by the sort
method call. This could lead to unexpected side effects if the caller does not anticipate the collection being sorted in-place. It would be safer to work on a copy of the original
collection to avoid modifying the input collection directly.
- original = sort(original, comparator);
+ Collection<T> sortedOriginal = sort(new ArrayList<>(original), comparator);
And then use sortedOriginal
in the subsequent logic instead of original
.
Just need that one suite is working well |
There are compilation errors @juherr . I am looking into it. I will get it sorted out and get this merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (2)
- testng-core/src/main/java/org/testng/internal/TestListenerHelper.java (3 hunks)
- testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java (3 hunks)
Files skipped from review as they are similar to previous changes (1)
- testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java
Additional comments: 3
testng-core/src/main/java/org/testng/internal/TestListenerHelper.java (3)
- 13-13: The import statement for
ListenerComparator
is correctly added to support the new functionality of ordering listeners. This change is necessary for the subsequent use ofListenerComparator
in method parameters.- 29-34: The addition of the
ListenerComparator
parameter in therunPreConfigurationListeners
method and its use to sort the listeners before invoking theirbeforeConfiguration
methods is a logical and necessary change to implement listener ordering. However, it's important to ensure that all calls to this method throughout the codebase have been updated to include the new parameter to avoid compilation errors.Verification successful
Given the initial search did not yield results, it's prudent to broaden the search criteria to ensure all calls to
runPreConfigurationListeners
are captured, regardless of the number of parameters. This approach will help in verifying whether all instances have been updated to include the newListenerComparator
parameter.
The search successfully identified a call to
runPreConfigurationListeners
inConfigInvoker.java
that includes the newListenerComparator
parameter, indicating that the codebase has been updated to accommodate the change. This finding supports the conclusion that the addition of theListenerComparator
parameter and its integration into the method call have been correctly implemented, at least in the identified instance. Without evidence of other calls failing to include the new parameter, it's reasonable to conclude that the necessary updates have been made throughout the codebase.* 48-51: The addition of the `ListenerComparator` parameter in the `runPostConfigurationListeners` method and its use to sort the listeners in reverse order before invoking their configuration methods based on the test result status is correctly implemented. This ensures that listeners are invoked in the specified order for post-configuration events. Similar to the previous method, it's crucial to verify that all calls to this method have been updated accordingly.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for calls to runPreConfigurationListeners missing the new parameter. ast-grep --lang java --pattern $'TestListenerHelper.runPreConfigurationListeners($_, $_, $_, $_)'Length of output: 98
Script:
#!/bin/bash # Broaden the search to capture any calls to runPreConfigurationListeners, regardless of the number of parameters. ast-grep --lang java --pattern $'TestListenerHelper.runPreConfigurationListeners($$$)'Length of output: 764
Verification successful
The executed script aimed to find calls to
runPostConfigurationListeners
with four parameters, presumably missing the newly addedListenerComparator
parameter. The lack of output from the script suggests that there are no instances in the codebase whererunPostConfigurationListeners
is called with an incorrect number of parameters. This supports the review comment's assertion that the addition of theListenerComparator
parameter is correctly implemented and implies that all calls to this method have been updated accordingly to include the new parameter.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for calls to runPostConfigurationListeners missing the new parameter. ast-grep --lang java --pattern $'TestListenerHelper.runPostConfigurationListeners($_, $_, $_, $_)'Length of output: 99
Closes #2916
Fixes #2916 .
Did you remember to?
CHANGES.txt
./gradlew autostyleApply
We encourage pull requests that:
If your pull request involves fixing SonarQube issues then we would suggest that you please discuss this with the
TestNG-dev before you spend time working on it.
Note: For more information on contribution guidelines please make sure you refer our Contributing section for detailed set of steps.
Summary by CodeRabbit
ListenerComparator
for ordering listener execution.ListenerComparator
.