Skip to content
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-530: Fixing that FeatureCodeGeneration UI test can be flaky with StaleElementReferenceException #109

Merged
merged 3 commits into from
Jan 11, 2023

Conversation

Piedone
Copy link
Member

@Piedone Piedone commented Jan 9, 2023

OSOE-530
Fixes #108.

@github-actions github-actions bot changed the title Fixing that FeatureCodeGeneration UI test can be flaky with StaleElementReferenceException OSOE-530: Fixing that FeatureCodeGeneration UI test can be flaky with StaleElementReferenceException Jan 9, 2023
// so we need to retry for these random issues.
var succeeded = false;
const int maxTries = 3;
for (var i = 1; !succeeded && i <= maxTries; i++)
Copy link
Member

Choose a reason for hiding this comment

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

var i = 1 please use more meaningful variable name.

Copy link
Member

Choose a reason for hiding this comment

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

Can't we use ReliabilityUITestContextExtensions.RetryIfStaleOrFailAsync instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

i is the index variable, like in every for loop ever. Why would we use a different name?

I'll check out RetryIfStaleOrFailAsync.

Copy link
Member

Copy link
Member Author

Choose a reason for hiding this comment

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

I see, let's use currentTry.

I checked out RetryIfStaleOrFailAsync and due to us having maxTries it won't help.

Copy link
Member

Choose a reason for hiding this comment

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

Could we create a reusable extension like RetryIfStaleOrFailAsync? With maxRetry instead of timeouts.

Copy link
Member Author

Choose a reason for hiding this comment

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

Now that you say it, actually, we shouldn't use tries here but timeouts. For UI tests, it's more meaningful to say "try this for 10s" than to "try this 10 times" (which can take any amount of time, but for test execution we care about the runtime).

Comment on lines +112 to +135
await context.RetryIfStaleOrFailAsync(async () =>
{
try
{
await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code"));

context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue().ShouldBe(GeneratedMigrationCodes.Page);

// Making sure that the collapsible area is open.
context.Get(By.CssSelector("#generated-migration-code-container.collapse.show"));

// Checking the first line of the CodeMirror editor.
context.Get(By.CssSelector(".CodeMirror-line .cm-variable")).Text.ShouldBe("_contentDefinitionManager");
context.Get(By.CssSelector(".CodeMirror-line .cm-property")).Text.ShouldBe("AlterTypeDefinition");
context.Get(By.CssSelector(".CodeMirror-line .cm-string")).Text.ShouldBe("\"Page\"");

return true;
}
catch (StaleElementReferenceException)
{
context.Refresh();
throw;
}
});
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest since the StaleElementReferenceException is handled by RetryIfStaleOrFailAsync.
My opinion is the place for context.Refresh after context.ClickReliablyOnAsync would be better since DOM changes can occur after that call.

Suggested change
await context.RetryIfStaleOrFailAsync(async () =>
{
try
{
await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code"));
context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue().ShouldBe(GeneratedMigrationCodes.Page);
// Making sure that the collapsible area is open.
context.Get(By.CssSelector("#generated-migration-code-container.collapse.show"));
// Checking the first line of the CodeMirror editor.
context.Get(By.CssSelector(".CodeMirror-line .cm-variable")).Text.ShouldBe("_contentDefinitionManager");
context.Get(By.CssSelector(".CodeMirror-line .cm-property")).Text.ShouldBe("AlterTypeDefinition");
context.Get(By.CssSelector(".CodeMirror-line .cm-string")).Text.ShouldBe("\"Page\"");
return true;
}
catch (StaleElementReferenceException)
{
context.Refresh();
throw;
}
});
await context.RetryIfStaleOrFailAsync(async () =>
{
await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code"));
context.Refresh();
context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue().ShouldBe(GeneratedMigrationCodes.Page);
// Making sure that the collapsible area is open.
context.Get(By.CssSelector("#generated-migration-code-container.collapse.show"));
// Checking the first line of the CodeMirror editor.
context.Get(By.CssSelector(".CodeMirror-line .cm-variable")).Text.ShouldBe("_contentDefinitionManager");
context.Get(By.CssSelector(".CodeMirror-line .cm-property")).Text.ShouldBe("AlterTypeDefinition");
context.Get(By.CssSelector(".CodeMirror-line .cm-string")).Text.ShouldBe("\"Page\"");
return true;
});

Copy link
Member Author

Choose a reason for hiding this comment

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

Opening the code block doesn't retain its state between page loads (I don't see why it would need to), so a refresh in between won't work.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, sorry, I mixed it with an other context.Refresh

Comment on lines +112 to +135
await context.RetryIfStaleOrFailAsync(async () =>
{
try
{
await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code"));

context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue().ShouldBe(GeneratedMigrationCodes.Page);

// Making sure that the collapsible area is open.
context.Get(By.CssSelector("#generated-migration-code-container.collapse.show"));

// Checking the first line of the CodeMirror editor.
context.Get(By.CssSelector(".CodeMirror-line .cm-variable")).Text.ShouldBe("_contentDefinitionManager");
context.Get(By.CssSelector(".CodeMirror-line .cm-property")).Text.ShouldBe("AlterTypeDefinition");
context.Get(By.CssSelector(".CodeMirror-line .cm-string")).Text.ShouldBe("\"Page\"");

return true;
}
catch (StaleElementReferenceException)
{
context.Refresh();
throw;
}
});
Copy link
Member

Choose a reason for hiding this comment

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

BTW This approach does not seem good, since the click on the button toggles the generated-migration-code-container visibility. So If the first try any element gets stale, then in the next cycle, the button gets clicked again which possibly removes the show css class and the generated-migration-code-container get hidden, after this the context. Get will throw a not found exception and the test fail.

Copy link
Member

Choose a reason for hiding this comment

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

A possible solution is to move out await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code")); of the cycle, then it will be called only once while the other checks retried in case of error.

Copy link
Member Author

Choose a reason for hiding this comment

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

The click needs to be done every time to open the code area, see my comment above #109 (comment). So it needs to be repeated after a refresh. The refresh in turn is needed so if anything is stale (what it really shouldn't), it gets resolved.

This works in a loop, I checked.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, sorry, I mixed it with an other context.Refresh

@dministro dministro merged commit 51cde8d into dev Jan 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FeatureCodeGeneration UI test can be flaky with StaleElementReferenceException (OSOE-530)
2 participants