Updates to Aspire.Hosting.Testing#4444
Conversation
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
| { | ||
| foreach (var line in logEvent) | ||
| { | ||
| var logLevel = line.IsErrorMessage ? LogLevel.Error : LogLevel.Information; |
There was a problem hiding this comment.
Should we make the log level the resource LogLines are logged at an option?
There was a problem hiding this comment.
I was on the fence, but then I thought we might want to tune things so we only get errors/warnings to help with memory consumption in the test case (for longer running tests).
There was a problem hiding this comment.
That could be done already by filtering the logs to error or higher in the test setup I think. But it might be desirable to be able to change the level the non-errors are logged at? Not sure, might not be worth the complexity.
- Add ResourceNotificationService.WaitForResource
6caf78c to
75a6baf
Compare
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
Outdated
Show resolved
Hide resolved
|
|
||
| Assert.True(res.ExitCode != 0, $"Expected the tests project build to fail"); | ||
| Assert.Matches("System.ArgumentException.*Resource 'webfrontend' not found.", res.Output); | ||
| Assert.Matches("System.InvalidOperationException.*Sequence contains no matching element", res.Output); |
There was a problem hiding this comment.
- (In the existing code) @radical - Why are we expecting the tests to fail?
- For the updated code, isn't the original exception better? Seems like we are making this worse.
There was a problem hiding this comment.
- (In the existing code) @radical - Why are we expecting the tests to fail?
The test creates an aspire project, then a aspire-xunit project, uncomments the code in the generated test file, and runs that. And that causes the test to fail because the test is expecting a webfrontend to exist. So, this what the user would see.
We could add a webfrontend to the solution, and patch that up so it gets used in this test. Do we want to do that?
There was a problem hiding this comment.
We could move the CreateHttpClient call to before the WaitForResourceAsync call to retain the original exception message and not bother with finding the resource in the DistributedApplicationModel.
There was a problem hiding this comment.
I went ahead and adjusted the order of lines in the test templates so that the original exception is thrown. @radical I do think it would be better to update these tests to add a resource though so the tests actually pass. Perhaps we could just base it on the starter template instead (without the tests project option) in order to get the web project by default?
There was a problem hiding this comment.
I was under the understanding we were validating the scenario @radical describes above. What is the experience when a dev adds the test project, and just runs it. Do they get an understandable error?
There was a problem hiding this comment.
If you just add the test project and run it you don't get an error. The test here actually uncomments the sample code and then runs the test, which fails because the sample code assumes there's a resource to test against (which the comments say).
eerhardt
left a comment
There was a problem hiding this comment.
LGTM.
Might want to wait to see if @davidfowl doesn't approve of the ResourceLoggerService change.
| /// <param name="builder">The resource builder instance.</param> | ||
| /// <param name="options">Options for configuring the Dapr sidecar, if any.</param> | ||
| /// <returns>The resource builder instance.</returns> | ||
| [System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:API with optional parameter(s) should have the most parameters amongst its public overloads", Justification = "<Pending>")] |
There was a problem hiding this comment.
Hmm not sure. Possibly I got a "suppression not required" diagnostic and acted on it? Will have to check
|
@DamianEdwards Wonder if the logger race is similar to #4606 Although on second thoughts, if it's the same issue I'd expect logs to be lost rather than duplicated. |
mitchdenny
left a comment
There was a problem hiding this comment.
Looking forward to this going in. I think I've got an immediate use case for it in some tests I'm writing!
|
You can merge |
|
@davidfowl @ReubenBond @eerhardt @mitchdenny I've reimplemented the UPDATE: OK I updated this again so that the backlog is always returned immediately and is synchronized with the |
|
Green!! |
|
Since #4500 has merged, this PR should merge |
|
kicking build again because it failed because of a code coverage upload issue. |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
|
||
| flushBacklogSync.Wait(cancellationToken); | ||
| // We need to ensure we don't write this log to the channel if it was already in the backlog | ||
| if (backlogSnapshot?.Contains(log) == false) |
There was a problem hiding this comment.
Can backlogSnapshot ever be null here? flushBacklogSync.Set(); is called after backlogSnapshot is set. So if we are waiting for it to be set, backlogSnapshot should always be non-null.
There was a problem hiding this comment.
Correct. I had this throwing when null previously but that seemed extreme. Are you suggesting this is a case we should just bang the nullability warning away?
There was a problem hiding this comment.
I guess I personally would just do:
Debug.Assert(backlogSnapshot is not null, "backlogSnapshot is always set before flushBacklogSync is set");
if (!backlogSnapshot.Contains(log))(Note that this is really just a nit on the readability of the method. Not critical to change.)
There was a problem hiding this comment.
Yeah I personally like the Debug.Assert approach too but this seems like another example of where we're not super consistent in the repo.

This change enables capturing resource logs and forwarding them to
ILoggerduring testing when usingAspire.Hosting.Testing, along with an update toResourceNotificationServiceto enable waiting for a resource to transition to a given state text.ILoggerinAspire.Hosting.TestingResourceNotificationService.WaitForResourceAsyncKnownResourceStatesResourceNotificationService.WaitForResourceAsyncILoggertoITestOutputHelperSome open questions:
ILoggeror not inAspire.Hosting.Testing?ResourceNotificationServiceto cancelWatchAsyncstreams whenIHostApplicationLifetime.ApplicationStoppingis triggered?Fixes #4445
Fixes #2790
File -> New -> Aspire Starter App with xUnit.net test project with these changes:

File -> New -> Aspire Starter app with MSTest test project:

File -> New -> Aspire Starter app with NUnit test project:
