-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Templating] Fix templating infrastructure and add additional tests for new scenarios #8275
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
5aeb375 to
3e4fe46
Compare
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.
My only serious concern is the FetchData thing, the rest are just opinions and suggestions.
| Output = output; | ||
| } | ||
|
|
||
| public Project Project { get; set; } |
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.
You may as well get rid of this it you're not generating the project in the constructor.
| } | ||
|
|
||
| public Project Project { get; } | ||
| public Project Project { get; set; } |
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.
Again, no point in this if its only use is in the test that created 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.
This will be used when I break the test into multiple stages.
src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs
Outdated
Show resolved
Hide resolved
src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs
Outdated
Show resolved
Hide resolved
47fb4c4 to
5f663d8
Compare
6e38440 to
ae0f6be
Compare
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.
Like the consistent updates to the test classes but didn't review that part or the fixture in depth. Defer to @SteveSandersonMS there.
|
|
||
| using (var aspNetProcess = Project.StartBuiltProjectAsync()) | ||
| { | ||
| Assert.False(aspNetProcess.Process.HasExited, ErrorMessages.GetErrorMessage("Run built project", Project, aspNetProcess.Process); |
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.
Considering all the places we're copying this let's just put it inside AssertOk.
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.
Nope, the asserts are better of at the test method level so that:
- You see a very specific error message about what test failed and why.
- You get the exact line of code where the test blew up instead of having to dig through the call stack.
DRY is good for product code, not for tests.
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.
Hitting these endpoints is unlikely to have anything to do with why the process has stopped, and if that's what we're testing for oughtn't these checks run after we actually do something?
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 is checking that the process didn't exit early. Like when you do dotnet run and there is a framework mismatch or similar.
src/Components/test/E2ETest/ServerExecutionTests/ServerSideAppTest.cs
Outdated
Show resolved
Hide resolved
|
|
||
| // Verify we're now on the counter page, with that nav link (only) highlighted | ||
| WaitAssert.Equal("Counter", () => Browser.FindElement(mainHeaderSelector).Text); | ||
| Browser.Equal("Counter", () => Browser.FindElement(mainHeaderSelector).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.
What's the reason for changing these?
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.
They were relying on an async local and I wanted to avoid that as much as possible. I considered either passing the browser explicitly or making them extension methods, and I did the second because it felt more "idiomatic".
I didn't think a lot of one way or the other. Just wanted the async local usage limited to the minimum.
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.
But isn't this a big change in functionality? If these needed waitassert in the past, why is this safe to remove?
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 didn't remove anything. I transformed the method.
This used to be WaitAssert.Equal(string expected, Func func) and internally used BrowserTestBase.Browser (an async local).
I converted it into WaitAssert.Equal(IWebDriver browser, string expected, Func func) and to make it more similar to what it was I made WaitAssert.Equal and related methods extension methods on IWebDriver, so WaitAssert.Equal(this IWebDriver browser, string expected, Func<string> func).
Functionality wise they are equivalent. The use of an async local was unnecessary, when we can just pass the browser parameter explicitly.
ae38d93 to
cab3c28
Compare
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.
for the components changes
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 exclude-based approach looks kind of risky, as in the future we might add more files and not realise they also have to be included in the exclude list. Two possibilities:
- Do we already have tests that assert the template output doesn't include any extra unexpected files? If so we're probably fine already.
- If not, maybe we should establish a naming convention like
internal.setupTests.jsand then have an exclude pattern like**\internal.*so someone who's just copying/pasting existing patterns would automatically have their new files exclued.
Not a massively big deal - just wanted to get your thoughts on 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.
Oh it looks like we do have baseline tests.
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.
Should this new line be here? It doesn't seem necessary for the test.
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 is, when we are doing auth the test becomes async and fails if not. (Throws indicating that the component has been unmounted). Technically a promise resolve method passed to ReactDOM.Render as third parameter should work, but empirically it doesn't. The timeout makes it reliable.
I could have queued this only for the auth case, but I think this way is a much better starting point, as this test will fail the moment you add a single http request to your app and it's not easy to figure out.
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.
Nit: Missing semicolons at the ends of all these lines.
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'm wondering why the linter doesn't complain
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.
Semicolon
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.
Semicolon
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 seems strange. We're importing a .props file into a .targets project. Should this line be in Directory.Build.props.in instead?
I know it might work either way but it could be confusing for props-like things to be imported at an unexpected time in the build process.
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 needs to be here so that the settings on the project don't override them. This is meant to override the project settings with all the stuff from our build.
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.
Wow, this is super sophisticated. Glad to see you've modernised a lot of it and cleared away many of the older obsolete workarounds!
Looking forwards to a world of more reliable E2E tests.
* Improved selenium start and tear down
* Selenium is set up and torn down in an assembly fixture.
* Selenium is initialized lazily and in a non-blocking way.
* Selenium processes are tracked as part of the build and their pids
written to a file on disk for cleanup in the event of unexpected
termination of the test process.
* Browser fixture retries with linear backoff to create a remote
driver. Under heavy load (like when we are doing a simultaneous NPM
restore) the selenium server can become unresponsive so we retry
three times, with a longer comand timeout allowance each time up to
a max of 3 minutes.
* Moved test project setup to build time instead of runtime.
* Added target PrepareForTest to create the required files for testing
* The template creation folder.
* The template props file to use our built packages.
* The folder for the custom hive.
* Added assembly metadata attributes to find all the data we need to
run the tests.
* Path to the artifacts shipping packages folder.
* Path to the artifacts non-shipping packages folder.
* Path to the test templates creation folder.
* Path to use for the custom templating hive used in tests.
* Proper cleanup as part of the build
* Remove the test templates creation folder.
* Remove the test packages restore path.
* Recreate the test templates creation folder.
* Recreate the test packages restore path.
* Generated Directory.Build.Props and Directory.Build.Targets in the
test templates creation folder.
* Cleaned up potentially stale templatetestsprops.
* Improved test flows
* Initialization is done lazily and asynchronously.
* Selenium
* Browser fixture
* Template initialization.
* Flattened test flows to avoid assertions inside deep callstacks.
* All assertions happen at the test level with improved error messages.
* With the exception of the migrations assertions.
* Assertions contain information about which step failed, for what
project and what failure details.
* Broke down tests to perform individual steps instead of mixing build
and publish.
* Publish project.
* Build project. (Debug)
* Run built project.
* Run published project.
* Concentrated build logic into the Project class.
* Context between the different steps of a test is maintained in
this class.
* All operations that require coordination are performed within this
class.
* There is a lock for dotnet and a lock for nodejs. When building
SPAs we acquire the nodejs lock to correctly prevent multiple
runs of nodejs in parallel.
[ApiAuthorization template cleanups]
* Fix preview3 issues with breaking changes on Entity framework by
manually configuring the model in ApiAuthorizationDbContext.
* Add app.db to the project file when using local db.
* Fix linting errors on angular template.
* Fix react tests
* Add tests to cover new auth options in the SPA templates.
020c640 to
e854ee9
Compare
written to a file on disk for cleanup in the event of unexpected
termination of the test process.
driver. Under heavy load (like when we are doing a simultaneous NPM
restore) the selenium server can become unresponsive so we retry
three times, with a longer comand timeout allowance each time up to
a max of 3 minutes.
run the tests.
test templates creation folder.
project and what failure details.
and publish.
this class.
class.
SPAs we acquire the nodejs lock to correctly prevent multiple
runs of nodejs in parallel.
[ApiAuthorization template cleanups]
manually configuring the model in ApiAuthorizationDbContext.
This is an example of what a failing test looks like now.
See that all the details are on the first line, what part of the test exactly failed and what template + arguments failed.
Project new react --auth Individual failed to publish.