feat: Add opt-in scenario-level parallelism (ParallelizationScope.Scenario)#1093
Open
sourrinn wants to merge 1 commit into
Open
feat: Add opt-in scenario-level parallelism (ParallelizationScope.Scenario)#1093sourrinn wants to merge 1 commit into
sourrinn wants to merge 1 commit into
Conversation
a3072c0 to
a219982
Compare
…nario) Introduces scenario-level parallel execution as a non-breaking, opt-in feature. When enabled via reqnroll.json, scenarios within the same feature can run concurrently across threads. Key changes: - New ParallelizationScope enum (Feature/Scenario) with JSON config support - FeatureLifecycleManager: ref-counted BeforeFeature/AfterFeature hook execution - ReadOnlyFeatureContextProxy: copy-on-write context isolation per scenario - TestExecutionEngine: branches on parallelization scope - TestRunnerManager: work-stealing pool without feature affinity in scenario mode - Generator: skips class-level fixture setup/teardown in scenario mode - All 5 framework providers adapted (NUnit, xUnit2, xUnit3, MSTest, TUnit) - 9 stress tests validating thread-safety under concurrent load Closes reqnroll#114
a219982 to
4acde9a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds scenario-level parallel execution as a non-breaking, opt-in configuration. When
"parallelizationScope": "Scenario"is set inreqnroll.json, scenarios within the same feature run concurrently on independent threads.Motivation
Closes #114. Feature-level parallelism leaves threads idle when one feature has many more scenarios than others. Scenario-level parallelism achieves linear speedup proportional to total scenario count, not feature count.
Design
Runtime
ParallelizationScopeenum (Featuredefault,Scenarioopt-in) with full JSON schema supportBeforeFeature/AfterFeaturehooks — fire exactly once per feature usingInterlocked.CompareExchange+SemaphoreSlimfor async-safe mutual exclusionConcurrentDictionary, shared context remains read-only afterBeforeFeaturecompletesParallelizationScopeinOnFeatureStartAsync/OnFeatureEndAsync; delegates lifecycle toFeatureLifecycleManagerin scenario modeEndFeatureForAvailableTestRunnersAsyncis a no-op since lifecycle is per-scenarioGenerator
OnFeatureEndAsyncbefore releasing the runnerParallelizationScopestored inCustomDatafor providers to inspectFramework Plugins
[Parallelizable(ParallelScope.Self)], skips[OneTimeSetUp]/[OneTimeTearDown]IClassFixture/FixtureDatapatternIClassFixture/IAsyncLifetimefixture[ClassInitialize]/[ClassCleanup][Before(Class)]/[After(Class)](already supports method-level parallelism)Configuration
{ "runtime": { "parallelizationScope": "Scenario" } }Default remains
Feature— zero behavior change for existing users.Thread-Safety Guarantees
Interlocked.CompareExchangeCASReadOnlyFeatureContextProxywithConcurrentDictionaryoverlaySemaphoreSlim(async-compatible), no nested lock acquisitionExceptionDispatchInforelays BeforeFeature failures to all concurrent scenariosDisableSingletonInstance()throws onFeatureContext.Currentin parallel modeTesting
Breaking Changes
None. The default
ParallelizationScope.Featurepreserves all existing behavior. The constructor parameter is optional with a default value.