-
Notifications
You must be signed in to change notification settings - Fork 10.3k
[Fixes #1947][Fixes #1978] Fix and identify flaky components E2E Tests #8690
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
Conversation
@@ -41,7 +40,7 @@ public void HasTitle() | |||
[Fact] | |||
public void HasHeading() | |||
{ | |||
Assert.Equal("Hello, world!", Browser.FindElement(By.TagName("h1")).Text); | |||
Browser.Equal("Hello, world!", () => Browser.FindElement(By.CssSelector("h1#index")).Text); |
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 assert is better because it waits for the element to appear, which is good as the issue could come from the page not being navigated from the previous location. Also uses a more specific way to find the element for that reason.
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.
As per other comment, I agree it's right to switch from Assert
to Browser
here, but I disagree that we need to change the CSS selector.
@@ -96,7 +95,7 @@ public void HasFetchDataPage() | |||
{ | |||
// Navigate to "Fetch Data" | |||
Browser.FindElement(By.LinkText("Fetch data")).Click(); | |||
Browser.Equal("Weather forecast", () => Browser.FindElement(By.TagName("h1")).Text); | |||
Browser.Equal("Weather forecast", () => Browser.FindElement(By.CssSelector("h1#fetch-data")).Text); |
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 can happen because we click on the link above and the navigation happens between us finding the current h1 and the one in the page. (Produces a stale reference exception). Use a more specific CSS selector to prevent it.
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.
Use a more specific CSS selector to prevent it.
I don't think this is correct. The behavior of WaitAssertCore
is to keep trying the assertion until it passes (until some timeout). Using a more specific selector won't change this, because it would have kept retrying anyway if the assertion failed. Or am I missing something?
I'm not saying your change is wrong; I'm just saying that there must be some other cause for any flakiness here.
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 issue was a stale element exception.
What likely happened was that the page changed from Index to FetchData while Browser.FindElement was executing, so it would find H1 on index and then that node would become detached from the DOM when accessing text, which would trigger the exception.
By using the more specific selector, the first find would fail until we navigated to the new page and find the h1 we were looking for. In general, based on my experience, it pays off to be more specific here.
That's only my theory of what was happening here.
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 waitassert logic is here: https://github.com/aspnet/AspNetCore/blob/9f1a978230cdd161998815c425bfd2d25e8436b6/src/Shared/E2ETesting/WaitAssert.cs#L55
It does a try
/catch
around the assertion code, so if it throws for any reason, we just keep retrying in case it passes before the eventual timeout. As such I don't see how it would make any difference whether the first find fails or not.
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.
Ok. My bad this is actually a timeout that is hidden by this line:
https://github.com/aspnet/AspNetCore/blob/master/src/Shared/E2ETesting/WaitAssert.cs#L69
There is no way to know the real cause I believe as re-running the assertion is not correct.
Given this is the case, we should modify WaitAssertCore to capture the last exception in a local and rethrow that.
Also, how often does this thing poll?
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.
we should modify WaitAssertCore to capture the last exception in a local and rethrow that.
Isn't that the same as what it already does? It already keeps running the same callback over and over, and if the WebDriverWait
times out, then it runs the same callback one more time but this time lets any exception bubble up the call stack.
Also, how often does this thing poll?
I'm not certain if our code modifies the defaults anywhere, but apparently the default is to poll every 500ms (https://stackoverflow.com/a/44645991).
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.
Isn't that the same as what it already does?
No. It reruns the assertion and that can cause a different exception than the last one.
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.
It's runs the assertion N times in a loop until there's a timeout, then runs it again for the (N+1)th time. For what reason would we prefer to report the Nth exception instead of the (N+1)th exception?
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.
I believe so. If not, I can't think how that test failed.
@@ -133,6 +134,7 @@ public void PreventDefault_DotNotApplyByDefault() | |||
} | |||
|
|||
[Fact] | |||
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/1987")] |
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 flakiness is due to a product issue. Marking it as such until we fix the underlying bug.
@@ -2,7 +2,7 @@ | |||
@page "/fetchdata/{StartDate:datetime}" | |||
@inject WeatherForecastService ForecastService | |||
|
|||
<h1>Weather forecast</h1> | |||
<h1 id="fetch-data">Weather forecast</h1> |
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.
Shouldn't be needed
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.
I've explained my motives above. Is there any specific reason why you think this is an issue? I believe that in principle, being more specific with these tests is better, but I'm all ears.
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.
Let's be sure we understand the real cause of the issue before we know what the principles are :)
|
||
<h1>Hello, world!</h1> | ||
<h1 id="index">Hello, world!</h1> |
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.
Shouldn't be needed
Marks https://github.com/aspnet/AspNetCore-Internal/issues/1987 as flaky, but there's a real product issue behind it #8204