[tests] Extract support for building tests outside the repo into re-usable props+targets#4923
Conversation
… for more common use
…evant properties, and remove old custom tasks
.. `Aspire.Testing.Repo.{props,targets}`.
From the comments:
```
This provides support for running tests outside of the repo, for example on a helix agent.
- For this you need the source of the tests, and any dependencies.
- Instead of direct `ProjectReferences` to the various Aspire hosting, and component projects use
`@(ComponentReferenceForTests)`, and @(NonComponentReferenceForTests)`.
- These are converted to `ProjectReference` when `$(TestsRunningOutsideOfRepo) != true`.
- But converted to `PackageReference` when `$(TestsRunningOutsideOfRepo) == true`.
- To allow building such test projects, the build is isolated and patched to build outside the
repo by adding appropriate `Directory.Build.{props,targets}`, and `Directory.Packages.props`
- and using a custom `nuget.config` which resolves the Aspire packages from the locally built packages
- and a `Directory.Packages.Versions.props` is generated with PackageVersions taken from the repo
- This also adds properties named in `@(PropertyForHelixRun)` from the repo, like `$(NetCurrent)`
```
.. which were there essentially to import Hosting.props/targets .
Instead, now the `Aspire.Testing.Repo.{props,targets}` are imported by
default, which decide how to get the hosting targets.
- `TestsRunningOutsideOfRepo` now means that the whole project builds
from source outside the repo.
- But for `EndToEnd` tests only supporting test project is built in
that mode.
- So, update the property and the corresponding `#define` to reflect
that
- And track changes from adding the new props/targets
.. as it is only used by that.
8616c15 to
1fe6b17
Compare
| <TestsSharedDir>$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), 'tests', 'Shared'))</TestsSharedDir> | ||
| <TestsSharedRepoTestingDir>$([MSBuild]::NormalizeDirectory($(TestsSharedDir), 'RepoTesting'))</TestsSharedRepoTestingDir> |
There was a problem hiding this comment.
(nit) can/should these go into tests/Directory.Build.props?
There was a problem hiding this comment.
I had to put these here to be accessible from playground apps, which would get similar changes to remove the hosting targets import.
| <!-- Used for running one helix job per test class --> | ||
| <Target Name="_ExtractTestClassNames" |
There was a problem hiding this comment.
Why do we want one helix job per test class? That seems extreme, isn't it?
There was a problem hiding this comment.
This is used for workload tests, where the tests are expensive. I'm just making it available for other projects.
|
|
||
| <ItemGroup Condition="'$(_BuildForTestsRunningOutsideOfRepo)' == 'true'"> | ||
| <None Include="..\testproject\**\*" Link="testassets\testproject\%(RecursiveDir)%(FileName)%(Extension)" CopyToOutputDirectory="PreserveNewest" /> | ||
| <None Include="..\.editorconfig" Link="testassets\%(FileName)%(Extension)" CopyToOutputDirectory="PreserveNewest" /> |
There was a problem hiding this comment.
Should copying the tests.editorconfig be part of the "infra"?
There was a problem hiding this comment.
This exists in main. IIRC, this was become some test seemed to indirectly depend on this file being available. So, we are copying it here as part of preparing the output dir to be usable for out-of-repo builds.
There was a problem hiding this comment.
And I didn't hit a need for this other projects that use out-of-repo (like future playground, and hosting.testing tests).
| @@ -1,8 +1,7 @@ | |||
| <Project> | |||
| <PropertyGroup> | |||
| <IsAspireHost>true</IsAspireHost> | |||
There was a problem hiding this comment.
Is there a way to make it so this stays defined in the .csproj?
There was a problem hiding this comment.
We can keep it there also! It is needed basically for this in tests/Shared/RepoTesting/Aspire.Testing.Repo.props which gets imported early - before the project file itself:
<!-- IsAspireHost property might not be available here, so allow infering that from the project name -->
<ImportGroup Condition="'$(RepoRoot)' != 'null' and '$(TestsRunningOutsideOfRepo)' != 'true' and ($(MSBuildProjectName.EndsWith('AppHost')) or '$(IsAspireHost)' == 'true')">
<Import Project="$(RepoRoot)src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.props" Condition="Exists('$(RepoRoot)src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.props')" />
</ImportGroup>We are using ($(MSBuildProjectName.EndsWith('AppHost')) or '$(IsAspireHost)' == 'true') to determine whether it is an aspire host or not. And in this case the name does not help. Open to any suggestions of course.
| </ItemGroup> | ||
|
|
||
| <ItemGroup Label="For tests"> | ||
| <PackageVersion Include="xunit" Version="$(XunitVersion)" /> |
There was a problem hiding this comment.
Why are the xunit packages needed to be defined here, but not any other external packages?
There was a problem hiding this comment.
When a test project is built in the repo, Arcade adds these references automatically. But when we are building outside the repo, the Arcade targets are not used, thus we need to explicitly add these.
Any other external packages needed by a project would be added by those projects themselves. We add PackageVersion for them in ./tests/Shared/RepoTesting/Directory.Packages.Helix.props. Hm this should be added in a common README.md too.
| <PackageReference Include="Aspire.Hosting.SqlServer" /> | ||
| <PackageReference Include="Aspire.Hosting.Valkey" /> | ||
| <ItemGroup> | ||
| <NonComponentReferenceForTests Include="Aspire.Hosting.Azure" IsAspireProjectResource="false" /> |
There was a problem hiding this comment.
Why is this named NonComponentReferenceForTests? What does "Component" matter?
There was a problem hiding this comment.
Lack of a better name! Please suggest one :)
There was a problem hiding this comment.
Maybe drop Component and just have ReferenceForTests. Or OutsideOfRepoReference?
AbstractReference
There was a problem hiding this comment.
After some offline discussion with @eerhardt I was able to combine the two into a single item AspireProjectOrPackageReference. Feel free to suggest a different name though :)
Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
…gets # Conflicts: # tests/testproject/TestProject.AppHost/TestProject.AppHost.csproj
…gets # Conflicts: # tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj
… into AspireProjectOrPackageReference
| <_BuildForTestsRunningOutsideOfRepo Condition="'$(TestsRunningOutsideOfRepo)' == 'true' or '$(ContinuousIntegrationBuild)' == 'true'">true</_BuildForTestsRunningOutsideOfRepo> | ||
| <DeployOutsideOfRepoSupportFiles>$(_BuildForTestsRunningOutsideOfRepo)</DeployOutsideOfRepoSupportFiles> |
There was a problem hiding this comment.
| <_BuildForTestsRunningOutsideOfRepo Condition="'$(TestsRunningOutsideOfRepo)' == 'true' or '$(ContinuousIntegrationBuild)' == 'true'">true</_BuildForTestsRunningOutsideOfRepo> | |
| <DeployOutsideOfRepoSupportFiles>$(_BuildForTestsRunningOutsideOfRepo)</DeployOutsideOfRepoSupportFiles> | |
| <DeployOutsideOfRepoSupportFilesCondition="'$(TestsRunningOutsideOfRepo)' == 'true' or '$(ContinuousIntegrationBuild)' == 'true'">true</DeployOutsideOfRepoSupportFiles> |
Why do we need 2 separate properties for the same thing?
There was a problem hiding this comment.
The condition is needed in multiple places, and it clarifies that this project is being built for running tests out-of-repo vs project itself being prepared to run out of repo.
There was a problem hiding this comment.
Merging the PR, but if we decide for a change here then I can do it in the follow up.
| <clear /> | ||
| <add key="built-local" value="%BUILT_NUGETS_PATH%" /> | ||
| <add key="dotnet-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json" /> | ||
| <add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" /> |
There was a problem hiding this comment.
I don't recall why I had to add that one :( I will remove this in the follow up PR, and see what fails.
Also, with using a single nuget.org for sources this will coming from the root nuget.config .
| <ItemGroup> | ||
| <Compile Include="$(MSBuildThisFileDirectory)*.cs" Link="WorkloadTestingCommon" /> | ||
|
|
||
| <_DataFile Include="$(MSBuildThisFileDirectory)data\**\*" Link="testassets\%(RecursiveDir)%(FileName)%(Extension)" CopyToOutputDirectory="PreserveNewest" /> |
There was a problem hiding this comment.
Can we call this something other than data? That doesn't seem like a great name.
TestSupportFiles maybe? I see we call it TestAssets elsewhere. Maybe that would be a good name for the folder in the repo as well?
| @@ -0,0 +1,31 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
There was a problem hiding this comment.
This is the 3rd time we have a nuget.config copied in the repo. Is there a way to use the root and just tweak it in places we need it to be special?
There was a problem hiding this comment.
Yeah, we had a task doing that earlier because we needed to put in the path to the built nugets. But now we use %BUILT_NUGETS_PATH% as the source in the nuget.config for tests, so it always resolves it from the environment variable.
I'll bring the task back to get the sources from the root nuget.config, add the source for built-nugets, and add the package source mapping as needed.
Added this as follow up work - #4946 .
What
Extract bits required for running tests outside of repo into
Aspire.RepoTesting.{props,targets}. And consolidate the various support bits (tasks/targets) spread around the repo. When running tests outside the repo they need some extra msbuild bits to allow building with aspire nugets instead of directProjectReferences to source projects.Why
There is a need to have some other projects run out-of-repo too, for example,
Aspire.Hosting.Testing.Tests, and upcomingAspire.Playground.Tests.Details
This provides support for running tests outside of the repo, for example on a helix agent.
For this you need the source of the tests, and any dependencies.
Instead of direct
ProjectReferencesto the various Aspire hosting, and component projects use@(AspireProjectOrPackageReference).ProjectReferencewhen$(TestsRunningOutsideOfRepo) != true.PackageReferencewhen$(TestsRunningOutsideOfRepo) == true.To allow building such test projects, the build is isolated and patched to build outside the
repo by adding appropriate
Directory.Build.{props,targets}, andDirectory.Packages.propsnuget.configwhich resolves the Aspire packages from the locally built packagesDirectory.Packages.Versions.propsis generated with PackageVersions taken from the repo@(PropertyForHelixRun)from the repo, like$(NetCurrent)Also:
Microsoft Reviewers: Open in CodeFlow