-
Notifications
You must be signed in to change notification settings - Fork 6
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
OSOE-353: Add duplicate SQL query detector in Lombiq.UITestingToolbox #216
base: dev
Are you sure you want to change the base?
Conversation
This pull request has merge conflicts. Please resolve those before requesting a review. |
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.
Impressive!
|
||
namespace Lombiq.Tests.UI.Services; | ||
|
||
public class PhaseCounterConfiguration |
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.
Mention this feature in the root Readme.
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 still needs to be done.
/// <summary> | ||
/// Gets the currently running <see cref="CounterDataCollector"/> instance. | ||
/// </summary> | ||
public CounterDataCollector CounterDataCollector { get; init; } |
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 needs to be possible to be completely disabled too.
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 still needs to be done. The page change dumps should also only be written when duplicate SQL query detection is enabled.
{ | ||
} | ||
|
||
private static string FormatMessage( |
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.
Generate exception messages that are easier to understand than:
DbExecuteCounterKey
SELECT [Document].* FROM [Document] WHERE [Document].[Type] = @type LIMIT 1
[0]Type = OrchardCore.Settings.SiteSettings, OrchardCore.SettingsIntegerCounterValue value: 26
Counter value is greater then DbCommandExecutionRepetitionThreshold, threshold: 22
I as an ordinary developer who didn't set up these counter thresholds but just wanted to change something unrelated but accidentally implemented a SELECT
N+1 issue, should be able to understand what I did wrong.
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.
While the current message is better, it's still cryptic when you first see it.
SessionProbe, [GET]https://localhost:9341/Admin
Database reader read counter
Query: SELECT [Document].* FROM [Document] WHERE [Document].[Type] = @type LIMIT 1
Parameters: [0]Type = OrchardCore.AdminMenu.Models.AdminMenuList, OrchardCore.AdminMenu
Count: 2
Counter value is greater then SessionThreshold.DbReaderReadThreshold, threshold: 0.
Start the exception with a message that explains, in plain English, what happened.
Lombiq.Tests.UI/Services/OrchardCoreHosting/OrchardApplicationFactory.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
Addressing "This needs to be possible to be completely disabled too." Addressing ""human-readable" everywhere." Addressing counting on page load not just navigation request Addressing counting command text with and without parameters Addressing "Keep the order of private fields and ctor assignments the same as the ctor parameters." Addressing "Comment why this is necessary." Addressing "After a page change, write all counters' values to the TestOutput for debugging."
Lombiq.Tests.UI/Services/Counters/Configuration/CounterThresholdConfiguration.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
@coderabbitai review I'm testing the AI code review tool CodeRabbit here. Please bear with me. And if it comments some useful feedback, please address it. |
WalkthroughWalkthroughThe changes implement a detection system for duplicated SQL queries and excessive row fetching during page loads, aiming to enhance testing efficiency and application performance. The system allows setting thresholds for query duplication and integrates with the UI Testing Toolbox. It introduces new classes and extensions for data collection, counter management, and performance probing, as well as modifications to existing services to support the new functionality. Changes
Assessment against linked issues
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 (
|
@Piedone, I'm ready to review the pull request as requested. Please provide any specific files or code snippets you would like me to focus on, or I will proceed with a general review of the changes. Action performedReview triggered. |
@coderabbitai review Sorry about that. |
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: 3
Configuration used: CodeRabbit UI
Files selected for processing (47)
- Lombiq.Tests.UI.Samples/Readme.md (1 hunks)
- Lombiq.Tests.UI.Samples/Tests/BasicOrchardFeaturesTests.cs (1 hunks)
- Lombiq.Tests.UI.Samples/Tests/DuplicatedSqlQueryDetectorTests.cs (1 hunks)
- Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs (1 hunks)
- Lombiq.Tests.UI/Exceptions/CounterThresholdException.cs (1 hunks)
- Lombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.cs (2 hunks)
- Lombiq.Tests.UI/Services/CounterDataCollector.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/CounterConfiguration.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/CounterConfigurations.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/CounterThresholdConfiguration.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/PhaseCounterConfiguration.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/RelativeUrlConfigurationKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Configuration/RunningPhaseCounterConfiguration.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/CounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/CounterProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/CounterProbeBase.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/DbCommandCounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/DbCommandExecuteCounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/DbCommandTextExecuteCounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/DbReaderReadCounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/ProbedDbCommand.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/ProbedDbConnection.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/ProbedDbDataReader.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Data/ProbedSqliteConnection.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Extensions/CounterDataCollectorExtensions.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Extensions/RelativeUrlConfigurationKeyExtensions.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Extensions/RunningPhaseCounterConfigurationExtensions.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/ICounterConfigurationKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/ICounterDataCollector.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/ICounterKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/ICounterProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/ICounterValue.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/IOutOfTestContextCounterProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/IRelativeUrlConfigurationKey.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Middlewares/PageLoadProbeMiddleware.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/NavigationProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/PageLoadProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/SessionProbe.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Value/CounterValue.cs (1 hunks)
- Lombiq.Tests.UI/Services/Counters/Value/IntegerCounterValue.cs (1 hunks)
- Lombiq.Tests.UI/Services/OrchardCoreHosting/OrchardApplicationFactory.cs (5 hunks)
- Lombiq.Tests.UI/Services/OrchardCoreInstance.cs (3 hunks)
- Lombiq.Tests.UI/Services/OrchardCoreUITestExecutorConfiguration.cs (2 hunks)
- Lombiq.Tests.UI/Services/ProbedConnectionFactory.cs (1 hunks)
- Lombiq.Tests.UI/Services/UITestContext.cs (2 hunks)
- Lombiq.Tests.UI/Services/UITestExecutionSession.cs (7 hunks)
- Lombiq.Tests.UI/Services/UITestExecutor.cs (5 hunks)
Files skipped from review due to trivial changes (1)
- Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs
Additional comments: 69
Lombiq.Tests.UI/Services/Counters/ICounterConfigurationKey.cs (1)
- 1-10: The interface
ICounterConfigurationKey
is well-defined as a marker interface for type safety and comparison in configurations.Lombiq.Tests.UI/Services/Counters/IOutOfTestContextCounterProbe.cs (1)
- 1-9: The interface
IOutOfTestContextCounterProbe
correctly extendsICounterProbe
to specialize for probes operating outside of the test context.Lombiq.Tests.UI/Services/Counters/Value/IntegerCounterValue.cs (1)
- 1-14: The
IntegerCounterValue
class provides a concrete implementation for integer counter values with an appropriate string representation.Lombiq.Tests.UI/Services/Counters/Value/CounterValue.cs (1)
- 1-15: The
CounterValue<TValue>
class is well-designed as a generic base for counter values, with a default display name and a mechanism to dump the value.Lombiq.Tests.UI/Services/Counters/Configuration/PhaseCounterConfiguration.cs (1)
- 1-14: The
PhaseCounterConfiguration
class is correctly set up with default threshold values for different application phases.Lombiq.Tests.UI/Services/Counters/IRelativeUrlConfigurationKey.cs (1)
- 1-19: The
IRelativeUrlConfigurationKey
interface extendsICounterConfigurationKey
with additional properties for URL-based configuration keys.Lombiq.Tests.UI/Services/Counters/ICounterValue.cs (1)
- 1-20: The
ICounterValue
interface defines a clear contract for counter values with aDisplayName
property and aDump
method.Lombiq.Tests.UI/Services/Counters/ICounterKey.cs (1)
- 1-21: The
ICounterKey
interface is well-defined, providing a clear contract for implementing counter keys with aDisplayName
property and aDump
method.Lombiq.Tests.UI/Services/Counters/Configuration/RelativeUrlConfigurationKey.cs (1)
- 1-22: The
RelativeUrlConfigurationKey
class correctly implementsIRelativeUrlConfigurationKey
with proper equality comparison and hash code generation.Lombiq.Tests.UI/Services/Counters/CounterKey.cs (1)
- 1-16: The
CounterKey
abstract class provides a solid base for counter keys with necessary abstract members for concrete implementations.Lombiq.Tests.UI/Services/Counters/Data/DbReaderReadCounterKey.cs (1)
- 1-22: The
DbReaderReadCounterKey
class is well-defined, providing a specific counter key for database reader read operations.Lombiq.Tests.UI/Services/Counters/Middlewares/PageLoadProbeMiddleware.cs (1)
- 1-24: The
PageLoadProbeMiddleware
class is correctly defined, integrating thePageLoadProbe
into the request pipeline.Lombiq.Tests.UI/Services/Counters/Data/DbCommandExecuteCounterKey.cs (1)
- 1-22: The
DbCommandExecuteCounterKey
class is well-defined, providing a specific counter key for database command executions with parameters.Lombiq.Tests.UI/Services/Counters/Extensions/RelativeUrlConfigurationKeyExtensions.cs (1)
- 1-20: The
RelativeUrlConfigurationKeyExtensions
class provides a clear and correct implementation for comparing relative URL configuration keys.Lombiq.Tests.UI/Services/Counters/NavigationProbe.cs (1)
- 1-24: The
NavigationProbe
class is correctly implemented, providing a concrete implementation for navigation probes with URL configuration.Lombiq.Tests.UI/Services/Counters/Data/DbCommandTextExecuteCounterKey.cs (1)
- 1-28: The
DbCommandTextExecuteCounterKey
class is well-defined, providing a specific counter key for database command executions based on command text.Lombiq.Tests.UI/Services/Counters/PageLoadProbe.cs (1)
- 1-28: The
PageLoadProbe
class is correctly implemented, providing a concrete implementation for page load probes with URL configuration.Lombiq.Tests.UI/Services/ProbedConnectionFactory.cs (1)
- 1-33: The
ProbedConnectionFactory
class is well-designed, providing a mechanism to create probed connections for performance tracking.Lombiq.Tests.UI/Services/Counters/ICounterDataCollector.cs (1)
- 1-36: The
ICounterDataCollector
interface provides a comprehensive contract for a counter data collector with methods for managing probes and asserting data.Lombiq.Tests.UI/Services/Counters/Data/ProbedSqliteConnection.cs (1)
- 1-36: The
ProbedSqliteConnection
class is correctly implemented, providing a probed connection specifically for Sqlite with the necessary overrides for performance tracking.Lombiq.Tests.UI/Services/Counters/ICounterProbe.cs (1)
- 1-45: The
ICounterProbe
interface defines a clear contract for implementing probes in the counter infrastructure with properties and methods for managing and dumping counter data.Lombiq.Tests.UI/Services/Counters/Configuration/CounterThresholdConfiguration.cs (1)
- 1-32: The
CounterThresholdConfiguration
class provides a clear configuration structure for setting thresholds in the counter infrastructure.Lombiq.Tests.UI.Samples/Tests/BasicOrchardFeaturesTests.cs (1)
- 25-38: The configuration lambda in
BasicOrchardFeaturesShouldWork
correctly sets theDbCommandExecutionThreshold
. Ensure that the threshold value of 26 is based on known requirements or empirical data to avoid false positives or negatives in tests.Lombiq.Tests.UI/Exceptions/CounterThresholdException.cs (1)
- 8-64: The constructors of
CounterThresholdException
are well-structured, providing multiple overloads for different use cases. TheFormatMessage
method is also well-implemented, ensuring that all relevant information is included in the exception message.Lombiq.Tests.UI/Services/Counters/Data/DbCommandCounterKey.cs (1)
- 8-56: The
DbCommandCounterKey
class correctly encapsulates the command text and parameters, providing a robustEquals
method for comparison. TheDump
method is also well-implemented, providing detailed information for debugging purposes.Lombiq.Tests.UI/Services/Counters/Configuration/RunningPhaseCounterConfiguration.cs (1)
- 8-43: The
RunningPhaseCounterConfiguration
class correctly implements theIDictionary
interface, providing thread-safe access to counter configurations. The use ofConcurrentDictionary
is appropriate for concurrent access scenarios.Lombiq.Tests.UI/Services/Counters/Extensions/RunningPhaseCounterConfigurationExtensions.cs (1)
- 11-60: The extension methods in
RunningPhaseCounterConfigurationExtensions
are well-designed, providing a fluent interface for configuring counter thresholds. The use ofGetMaybeByKey
to avoid key not found exceptions is a good practice.Lombiq.Tests.UI/Services/CounterDataCollector.cs (1)
- 10-73: The
CounterDataCollector
class is well-implemented, with clear responsibilities and proper encapsulation of its members. TheAssertCounter
method correctly handles postponed exceptions, ensuring they are not lost.Lombiq.Tests.UI.Samples/Readme.md (1)
- 27-30: The addition of "Duplicated SQL query detector" to the Readme.md file is clear and follows the existing format of the document. This update should help users find information about the new feature.
Lombiq.Tests.UI/Services/Counters/CounterProbeBase.cs (1)
- 9-77: The
CounterProbeBase
class provides a solid foundation for counter probes with a clear and concise implementation. TheDumpSummary
method is particularly well-done, providing a summary of the counters in a readable format.Lombiq.Tests.UI.Samples/Tests/DuplicatedSqlQueryDetectorTests.cs (1)
- 13-58: The test methods in
DuplicatedSqlQueryDetectorTests
are well-structured, and the configuration methodConfigureAsync
is correctly setting up the counter thresholds. Ensure that the threshold values are based on the expected behavior of the application to avoid false positives.Lombiq.Tests.UI/Services/Counters/Extensions/CounterDataCollectorExtensions.cs (1)
- 9-64: The extension methods in
CounterDataCollectorExtensions
correctly increment the appropriate counters before executing the database commands. This ensures that all database interactions are tracked, which is essential for detecting duplicated SQL queries.Lombiq.Tests.UI/Services/Counters/SessionProbe.cs (4)
12-12: The
SessionProbe
class correctly implementsISession
andIRelativeUrlConfigurationKey
interfaces, which is consistent with the PR objectives to enhance performance monitoring.20-26: The constructor of
SessionProbe
properly initializes its properties and the underlying session object. It's good practice to validate the non-nullness of thesession
parameter since it's a critical dependency.55-61: The asynchronous disposal pattern in
DisposeAsync
is correctly implemented, ensuring that the session is disposed of and then the base disposal logic is called. This is important for proper resource management.63-68: The implementation of
IRelativeUrlConfigurationKey
inSessionProbe
is consistent and provides the necessary properties and method for URL configuration. This aligns with the PR's goal of enhancing performance monitoring.Lombiq.Tests.UI/Services/Counters/Data/ProbedDbConnection.cs (3)
13-13: The
ProbedDbConnection
class is designed to wrap aDbConnection
and collect performance data, which aligns with the PR's objectives to monitor database interactions.37-42: The constructor of
ProbedDbConnection
correctly initializes the connection and the counter data collector, including a null check and event subscription for state changes. This is crucial for the reliability of the performance tracking feature.80-90: The disposal pattern in
ProbedDbConnection
is correctly implemented, ensuring that the wrapped connection is disposed of and the event handler is unsubscribed, which is important to prevent memory leaks.Lombiq.Tests.UI/Services/Counters/Configuration/CounterConfiguration.cs (2)
8-8: The
CounterConfiguration
class provides a central place to manage various threshold configurations and exclude filters, which is essential for the new feature's configurability as described in the PR objectives.10-15: The SQL query constant within
CounterConfiguration
is used in the default exclude list, which suggests it's a known query that should not trigger performance warnings. This is a good practice to prevent false positives in performance monitoring.Lombiq.Tests.UI/Services/Counters/Configuration/CounterConfigurations.cs (3)
11-11: The
CounterConfigurations
class holds different counter configurations for various phases of the web application, which is in line with the PR's objectives to provide detailed performance monitoring.23-73: The
DefaultAssertCounterData
method inCounterConfigurations
contains complex logic to assert counter data. Ensure that this logic is thoroughly tested to prevent any issues during runtime.75-95: The
AssertIntegerCounterValue
method correctly throws aCounterThresholdException
when a counter value exceeds the threshold. This is a key part of the feature to detect performance issues.Lombiq.Tests.UI/Services/Counters/Data/ProbedDbCommand.cs (3)
13-13: The
ProbedDbCommand
class is designed to wrap aDbCommand
and collect performance data, which aligns with the PR's objectives to monitor database command executions.71-81: The constructor of
ProbedDbCommand
correctly initializes the command and the counter data collector, including a null check. This is crucial for the reliability of the performance tracking feature.122-131: The disposal pattern in
ProbedDbCommand
is correctly implemented, ensuring that the wrapped command is disposed of, which is important to prevent resource leaks.Lombiq.Tests.UI/Services/Counters/Data/ProbedDbDataReader.cs (4)
12-12: The
ProbedDbDataReader
class is designed to wrap aDbDataReader
and collect performance data, which aligns with the PR's objectives to monitor database interactions.39-55: The constructor of
ProbedDbDataReader
correctly initializes the reader, command, and counter data collector, including a null check and the initialization of the counter key. This is crucial for accurate performance tracking.119-133: The
Read
andReadAsync
methods inProbedDbDataReader
correctly increment the performance counter when a row is read, which is essential for tracking the number of rows fetched by a query.139-143: The disposal pattern in
ProbedDbDataReader
is correctly implemented, ensuring that the wrapped reader is disposed of, which is important to prevent resource leaks.Lombiq.Tests.UI/Services/UITestExecutor.cs (1)
- 15-18: The introduction of a
SemaphoreSlim
for limiting concurrent tests is a good practice for resource management. Ensure that all usages of_numberOfTestsLimit
properly handle the semaphore's release, even in the case of exceptions.Lombiq.Tests.UI/Services/OrchardCoreHosting/OrchardApplicationFactory.cs (2)
30-34: The use of
ConcurrentBag
for_createdStores
is appropriate for thread-safe operations. Ensure that all interactions with_createdStores
are thread-safe and consider the implications of unordered access inherent toConcurrentBag
.152-172: The
AddSessionProbe
method correctly replaces theISession
service withSessionProbe
. Verify that theSessionProbe
implementation is compatible with all expected usages ofISession
throughout the application.Lombiq.Tests.UI/Services/OrchardCoreUITestExecutorConfiguration.cs (1)
- 175-178: The addition of the
CounterConfiguration
property aligns with the PR's objective to introduce performance monitoring. Ensure that theCounterConfigurations
type is correctly defined and used throughout the application.Lombiq.Tests.UI/Services/OrchardCoreInstance.cs (1)
- 60-75: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [54-72]
The integration of
CounterDataCollector
intoOrchardCoreInstance
is consistent with the PR's objectives. Ensure that theCounterDataCollector
is properly utilized within theOrchardCoreInstance
and that its lifecycle is managed correctly.Lombiq.Tests.UI/Services/UITestContext.cs (2)
102-105: The addition of the
CounterDataCollector
property toUITestContext
introduces a new dependency that will be used for performance tracking. Ensure that all necessary null checks and exception handling are in place where this new property is utilized.99-117: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [113-124]
The constructor now initializes the
CounterDataCollector
property. Ensure that all instantiations ofUITestContext
throughout the codebase are updated to provide this new parameter.Verification successful
The output from the shell script indicates that there is an instantiation of
UITestContext
in the fileUITestExecutionSession.cs
that includes the newCounterDataCollector
parameter. This suggests that at least one place in the codebase has been updated to accommodate the new constructor signature.However, this does not guarantee that all instances have been updated accordingly. To ensure that all instantiations of
UITestContext
have been updated, we would need to check for any other occurrences that do not include the new parameter.Given the information at hand, the review comment is partially verified, as we have found at least one instance where the
UITestContext
is correctly instantiated with the new parameter. To fully verify the comment, we would need to check for all instances ofUITestContext
instantiation.
The output from the shell script indicates that the only instantiation of
UITestContext
found in the codebase is the one inUITestExecutionSession.cs
, which correctly includes the newCounterDataCollector
parameter. This suggests that the necessary update to theUITestContext
constructor has been made at least in this instance.Since no other instantiations were found by the script, it appears that either there are no other instantiations in the codebase or they have already been updated to include the new parameter. Therefore, based on the information provided by the script, the review comment concerning the update of
UITestContext
instantiations has been verified.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for instantiations of UITestContext without the new parameter. ast-grep --lang csharp --pattern $'new UITestContext($_, $_, $_, $_, $_, $_, $_)'Length of output: 840
Script:
#!/bin/bash # Search for all instantiations of UITestContext to ensure they include the new parameter. ast-grep --lang csharp --pattern $'new UITestContext($$$)'Length of output: 817
Lombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.cs (2)
- 6-6: The import statement for
Lombiq.Tests.UI.Services.Counters
has been added to support the newNavigationProbe
functionality. Verify that this namespace is used elsewhere in the file to avoid unnecessary imports.Verification successful
The search for the usage of the namespace
Lombiq.Tests.UI.Services.Counters
in the fileLombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.cs
only returned the import statement itself. This suggests that the namespace is not used elsewhere in the file, which could mean that the import is unnecessary. However, since the AI-generated summary mentioned that aNavigationProbe
object is being used within ausing
block, it's possible that theNavigationProbe
class is part of this namespace and the search result is incomplete due to the scope of the search command.To verify the actual usage of the
NavigationProbe
within the file, a more detailed search is needed to check for instances ofNavigationProbe
being instantiated or used.
The search confirmed that the
NavigationProbe
class is indeed used within theLombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.cs
file. This validates the necessity of the import statement for theLombiq.Tests.UI.Services.Counters
namespace, as it contains theNavigationProbe
class which is utilized in ausing
block.Based on this information, the import statement is correctly placed and is required for the new functionality introduced in the pull request.
* 49-52: The `context.Driver.Navigate().GoToUrl(absoluteUri)` call is now wrapped in a `using` block with a `NavigationProbe`. This is a good use of the `using` statement for resource management, ensuring that the probe is disposed of correctly after navigation. Confirm that the `NavigationProbe` correctly implements `IDisposable`.Scripts Executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for usage of Lombiq.Tests.UI.Services.Counters in the file. rg --type cs 'Lombiq.Tests.UI.Services.Counters' Lombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.csLength of output: 153
Script:
#!/bin/bash # Search for instances of NavigationProbe being used in the file. rg --type cs 'NavigationProbe' Lombiq.Tests.UI/Extensions/NavigationUITestContextExtensions.csLength of output: 181
Lombiq.Tests.UI/Services/UITestExecutionSession.cs (9)
9-9: The addition of the
CounterDataCollector
configuration namespace is noted and seems appropriate for the new functionality being introduced.109-109: Resetting the
CounterDataCollector
at the beginning of the test execution ensures that the counters start from a clean state for each test run.110-112: Setting the phase to
Running
and asserting counter data based on the running configuration is a good practice to ensure that the test is aware of the current phase and can validate the counters accordingly.120-121: Dumping and asserting the counter data at the end of the test execution is crucial for identifying any duplicated SQL queries or excessive row fetching. This should help in catching performance issues early.
483-486: Configuring the
CounterDataCollector
during the setup phase with the appropriate phase and assertion data is consistent with the changes in the previous hunk and aligns with the objectives of the PR.495-496: The operations to dump and assert counter data after the setup operation are consistent with the intent to monitor performance issues during all phases of test execution.
515-515: Catching
CounterThresholdException
explicitly allows the test to fail fast if performance thresholds are exceeded during setup, which is a critical part of performance testing.619-625: Instantiating a new
CounterDataCollector
and passing it to theOrchardCoreInstance
constructor ensures that counter data is collected throughout the application lifecycle.660-661: Passing the
CounterDataCollector
to theUITestContext
constructor ensures that the test context has access to the counter data, which is necessary for the new performance monitoring features.
private static async Task PrepareTestLimitAsync(OrchardCoreUITestExecutorConfiguration configuration) | ||
{ | ||
await _numberOfTestsLimitLock.WaitAsync(); | ||
|
||
if (_numberOfTestsLimit == null && configuration.MaxParallelTests > 0) | ||
{ | ||
_numberOfTestsLimit = new SemaphoreSlim(configuration.MaxParallelTests); | ||
} | ||
|
||
_numberOfTestsLimitLock.Release(); | ||
} |
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 PrepareTestLimitAsync
method correctly initializes the _numberOfTestsLimit
semaphore within a lock to ensure thread safety. However, the lock release should be in a finally
block to guarantee it's released even if an exception occurs.
- _numberOfTestsLimitLock.Release();
+ finally
+ {
+ _numberOfTestsLimitLock.Release();
+ }
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.
private static async Task PrepareTestLimitAsync(OrchardCoreUITestExecutorConfiguration configuration) | |
{ | |
await _numberOfTestsLimitLock.WaitAsync(); | |
if (_numberOfTestsLimit == null && configuration.MaxParallelTests > 0) | |
{ | |
_numberOfTestsLimit = new SemaphoreSlim(configuration.MaxParallelTests); | |
} | |
_numberOfTestsLimitLock.Release(); | |
} | |
private static async Task PrepareTestLimitAsync(OrchardCoreUITestExecutorConfiguration configuration) | |
{ | |
await _numberOfTestsLimitLock.WaitAsync(); | |
try | |
{ | |
if (_numberOfTestsLimit == null && configuration.MaxParallelTests > 0) | |
{ | |
_numberOfTestsLimit = new SemaphoreSlim(configuration.MaxParallelTests); | |
} | |
} | |
finally | |
{ | |
_numberOfTestsLimitLock.Release(); | |
} | |
} |
public abstract class CounterProbe : CounterProbeBase, IDisposable | ||
{ | ||
private bool _disposed; | ||
|
||
public override bool IsAttached => !_disposed; | ||
public ICounterDataCollector CounterDataCollector { get; init; } | ||
|
||
public override IEnumerable<string> Dump() | ||
{ | ||
var lines = new List<string> | ||
{ | ||
DumpHeadline(), | ||
}; | ||
|
||
lines.AddRange( | ||
Counters.SelectMany(entry => | ||
entry.Key.Dump() | ||
.Concat(entry.Value.Dump().Select(line => $"\t{line}"))) | ||
.Concat(DumpSummary()) | ||
.Select(line => $"\t{line}")); | ||
|
||
return lines; | ||
} | ||
|
||
protected CounterProbe(ICounterDataCollector counterDataCollector) | ||
{ | ||
CounterDataCollector = counterDataCollector; | ||
CounterDataCollector.AttachProbe(this); | ||
} | ||
|
||
protected virtual void OnAssertData() => | ||
CounterDataCollector.AssertCounter(this); | ||
|
||
protected virtual void OnDisposing() | ||
{ | ||
} | ||
|
||
protected virtual void OnDisposed() | ||
{ | ||
} | ||
|
||
protected virtual void Dispose(bool disposing) | ||
{ | ||
if (!_disposed) | ||
{ | ||
OnDisposing(); | ||
try { OnAssertData(); } | ||
finally | ||
{ | ||
if (disposing) | ||
{ | ||
OnDisposed(); | ||
} | ||
|
||
_disposed = true; | ||
OnCaptureCompleted(); | ||
} | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(disposing: true); | ||
GC.SuppressFinalize(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.
The implementation of IDisposable
in CounterProbe
is correct, following the standard dispose pattern. However, the empty virtual methods OnDisposing
and OnDisposed
could be removed if they are not overridden in derived classes to reduce unnecessary code.
@Piedone, no worries at all! I'm here to assist you. If you have any specific areas or files in the pull request that you would like me to review, please let me know. Otherwise, I will proceed with a general review of the changes. Action performedReview triggered. |
These comments seem useful, please check them out. You can also chat with the bot, see the tips under #216 (comment). |
/// <summary> | ||
/// Gets or sets a value indicating whether the current threshold configuration and checking is disabled. | ||
/// </summary> | ||
public bool Disable { get; set; } = true; |
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 property Disable
should be renamed to IsEnabled
and its logic inverted for consistency with common API naming conventions. This change also addresses a previous review comment.
- public bool Disable { get; set; } = true;
+ public bool IsEnabled { get; set; } = false;
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.
/// <summary> | |
/// Gets or sets a value indicating whether the current threshold configuration and checking is disabled. | |
/// </summary> | |
public bool Disable { get; set; } = true; | |
/// <summary> | |
/// Gets or sets a value indicating whether the current threshold configuration and checking is disabled. | |
/// </summary> | |
public bool IsEnabled { get; set; } = false; |
}), | ||
}; | ||
|
||
public static bool DefaultExcludeFilter(ICounterKey key) => DefaultExcludeList.Contains(key); |
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.
Consider optimizing the DefaultExcludeFilter
method if the default exclude list grows large. Using a more efficient lookup method, such as a hash set, could improve performance.
- public static bool DefaultExcludeFilter(ICounterKey key) => DefaultExcludeList.Contains(key);
+ public static bool DefaultExcludeFilter(ICounterKey key) => DefaultExcludeListHashSet.Contains(key);
+ private static HashSet<ICounterKey> DefaultExcludeListHashSet = new HashSet<ICounterKey>(DefaultExcludeList);
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.
public static bool DefaultExcludeFilter(ICounterKey key) => DefaultExcludeList.Contains(key); | |
public static bool DefaultExcludeFilter(ICounterKey key) => DefaultExcludeListHashSet.Contains(key); | |
private static HashSet<ICounterKey> DefaultExcludeListHashSet = new HashSet<ICounterKey>(DefaultExcludeList); |
public CounterThresholdConfiguration NavigationThreshold { get; set; } = new CounterThresholdConfiguration | ||
{ | ||
DbCommandIncludingParametersExecutionCountThreshold = 11, | ||
DbCommandExcludingParametersExecutionThreshold = 22, | ||
DbReaderReadThreshold = 11, | ||
}; | ||
|
||
/// <summary> | ||
/// Gets or sets threshold configuration used per <see cref="YesSql.ISession"/> lifetime. See: | ||
/// <see cref="SessionProbe"/>. | ||
/// </summary> | ||
public CounterThresholdConfiguration SessionThreshold { get; set; } = new CounterThresholdConfiguration | ||
{ | ||
DbCommandIncludingParametersExecutionCountThreshold = 22, | ||
DbCommandExcludingParametersExecutionThreshold = 44, | ||
DbReaderReadThreshold = 11, | ||
}; | ||
|
||
/// <summary> | ||
/// Gets or sets threshold configuration used per page load. See: <see cref="PageLoadProbe"/>. | ||
/// </summary> | ||
public CounterThresholdConfiguration PageLoadThreshold { get; set; } = new CounterThresholdConfiguration | ||
{ | ||
DbCommandIncludingParametersExecutionCountThreshold = 22, | ||
DbCommandExcludingParametersExecutionThreshold = 44, | ||
DbReaderReadThreshold = 11, | ||
}; |
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.
Please add a piece of docs contrasting these three configs: when would you want to use each?
… instead of KeyValuePair<> Setting default configuration more generic Moving OSOCE default configuration to OrchardCoreUITestExecutorConfiguration
Fine-tuning thresholds in tests
…re exactly matching with the counter values captured during navigation.
…re` -> `RequestProbeMiddleware`
Adding more sample tests
OSOE-353
Fixes #93
Summary by CodeRabbit
New Features
Enhancements
Documentation
Bug Fixes
Refactor
Tests
Chores