I have written 4 or 5 tests in one test class which are getting execute parallelly. If those are getting executed sequentially no issue occurs, but any how I want to execute those parallelly.
This is very random issue.
Failed tests showing following issue.
TearDown : System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
--TearDown
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at Microsoft.Playwright.NUnit.BrowserTest.BrowserTearDown() in /_/src/Playwright.NUnit/BrowserTest.cs:line 55
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunSetUpOrTearDownMethod(TestExecutionContext context, IMethodInfo method)
at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunTearDown(TestExecutionContext context)
Microsoft.Playwright.TargetClosedException : Target page, context or browser has been closed
at Microsoft.Playwright.Transport.Connection.InnerSendMessageToServerAsync[T](ChannelOwner object, String method, Dictionary`2 dictionary, Boolean keepNulls) in /_/src/Playwright/Transport/Connection.cs:line 206
at Microsoft.Playwright.Transport.Connection.WrapApiCallAsync[T](Func`1 action, Boolean isInternal) in /_/src/Playwright/Transport/Connection.cs:line 532
at Microsoft.Playwright.Core.Page.ScreenshotAsync(PageScreenshotOptions options) in /_/src/Playwright/Core/Page.cs:line 675
at MyTests.Utilities.Traces.AllureScreenshot.TakeAllureScreenshot(IPage page, String stepDetail, Status status) in C:\Users\kedarg\Documents\Project\AutomationTool\MGB-Member-Portal-Automation\MyTests\Utilities\Traces\AllureScreenshot.cs:line 19
at MyTests.Tests.Sections.LoginTests.LoginTest.LogInInfo(Login login) in C:\Users\kedarg\Documents\Project\AutomationTool\MGB-Member-Portal-Automation\MyTests\Tests\Sections\LoginTests\LoginTest.cs:line 170
at Allure.Net.Commons.Steps.AllureAbstractStepAspect.WrapAsync(Func`2 target, Object[] args, MethodBase metadata, String stepName, List`1 stepParameters)
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
at NUnit.Framework.Internal.Commands.DelegatingTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
My code is as below:
namespace MyTests.Tests.Sections.LoginTests
{
[Parallelizable(ParallelScope.All)]
[TestFixture]
[AllureNUnit]
public class LoginTest : BaseTestSetup
{
[OneTimeSetUp]
public void OneTimeSetup()
{
_baseUrl = JsonDataManager.Instance.GetApplicationUrl();
}
[Test]
[AllureStep]
//[Parallelizable(ParallelScope.Self)]
public async Task UserNameEditable()
{
var page = Browser
.NewContextAsync(new CustomBrowserNewContextOptions().Create())
.Result.NewPageAsync()
.Result;
try
{
//* Arrange
//var newPage = await Browser.NewContextAsync(new CustomBrowserNewContextOptions().Create()).Result.NewPageAsync();
LoginPage loginPage = new LoginPage(page);
//* Act
await loginPage.VisitPage(_baseUrl);
var userNameField = loginPage.GetUserNameLocator();
//* Assert
await Assertions.Expect(userNameField).ToBeEditableAsync();
await AllureScreenshot.TakeAllureScreenshot(
page,
"Username field is editable",
Status.passed
);
await page.CloseAsync();
}
catch (Exception ex)
{
await AllureScreenshot.TakeAllureScreenshot(
page,
"Username editable test failed",
Status.failed
);
await page.CloseAsync();
Assert.Fail($"Username field on login page is not editable : {ex.Message}");
}
}
[Test]
[AllureStep]
//[Parallelizable(ParallelScope.Self)]
public async Task PasswordEditable()
{
var page = Browser
.NewContextAsync(new CustomBrowserNewContextOptions().Create())
.Result.NewPageAsync()
.Result;
try
{
//* Arrange
//var newPage = await Browser.NewContextAsync(new CustomBrowserNewContextOptions().Create()).Result.NewPageAsync();
LoginPage loginPage = new LoginPage(page);
//* Act
await loginPage.VisitPage(_baseUrl);
var passwordField = loginPage.GetPasswordLocator();
//* Assert
await Assertions.Expect(passwordField).ToBeEditableAsync();
await AllureScreenshot.TakeAllureScreenshot(
page,
"Password field is editable",
Status.passed
);
await page.CloseAsync();
}
catch (Exception ex)
{
await AllureScreenshot.TakeAllureScreenshot(
page,
"Password editable test failed",
Status.failed
);
await page.CloseAsync();
Assert.Fail($"Password field on login page is not editable : {ex.Message}");
}
}
[Test]
[AllureStep]
//[Parallelizable(ParallelScope.Self)]
public async Task SignInClickable()
{
var page = Browser
.NewContextAsync(new CustomBrowserNewContextOptions().Create())
.Result.NewPageAsync()
.Result;
try
{
//* Arrange
LoginPage loginPage = new LoginPage(page);
//* Act
await loginPage.VisitPage(_baseUrl);
var signInBtn = loginPage.GetSignInLocator();
//* Assert
await Assertions.Expect(signInBtn).ToBeEnabledAsync();
await AllureScreenshot.TakeAllureScreenshot(
page,
"Sign in button is clickable",
Status.passed
);
await page.CloseAsync();
}
catch (Exception ex)
{
await AllureScreenshot.TakeAllureScreenshot(
page,
"Sign in button is not clickable",
Status.failed
);
await page.CloseAsync();
Assert.Fail($"Sign In button on login page is not clickable : {ex.Message}");
}
}
[Test]
[AllureStep]
[TestCaseSource(typeof(TestDataProvider), nameof(TestDataProvider.GetLogins))]
public async Task LogInInfo(Login login)
{
var page = Browser
.NewContextAsync(new CustomBrowserNewContextOptions().Create())
.Result.NewPageAsync()
.Result;
try
{
//* Arrange
LoginPage loginPage = new LoginPage(page);
string password = AesOperation.DecryptString(null, login.password);
//* Act
var loginLocator = await loginPage.LogInInfo(
url: _baseUrl,
user: login.username,
pass: password
);
//* Assert
await Assertions
.Expect(loginLocator.WelcomeMenu)
.ToHaveTextAsync(new Regex("PERSON NAME"));
await AllureScreenshot.TakeAllureScreenshot(
page,
"Login Performed Successfully",
Status.passed
);
await page.CloseAsync();
}
catch (Exception ex)
{
await AllureScreenshot.TakeAllureScreenshot(page, "Login Failed", Status.failed);
await page.CloseAsync();
Assert.Fail($"Failed to log in with user '{login.username}': {ex.Message}");
}
}
}
As per the Microsoft team, method level parallel execution is not possible till version 1.45.1