Enable test logging for ProjectTemplate tests (#26507)

* Enable test logging for ProjectTemplate tests

* Add logging to templates

* some updates

* nullref
This commit is contained in:
Brennan 2020-10-07 14:37:33 -07:00 committed by GitHub
parent 503ab6de61
commit 5b6362f29a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 361 additions and 461 deletions

View File

@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Xunit; using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "Microsoft.AspNetCore.Components.E2ETests")]
[assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))] [assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: AssemblyFixture(typeof(SauceConnectServer))] [assembly: AssemblyFixture(typeof(SauceConnectServer))]

View File

@ -19,8 +19,6 @@
<OutputPath /> <OutputPath />
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<!-- This project references the shared framework transitively. Prevent restore errors by setting this flag. --> <!-- This project references the shared framework transitively. Prevent restore errors by setting this flag. -->
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks> <GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
</PropertyGroup> </PropertyGroup>

View File

@ -2,11 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers; using Templates.Test.Helpers;
using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "BlazorTemplates.Tests")] [assembly: AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(SeleniumStandaloneServer))]

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<!-- Shared testing infrastructure for running E2E tests using selenium --> <!-- Shared testing infrastructure for running E2E tests using selenium -->
<Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" /> <Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" />
@ -22,7 +22,6 @@
<TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder> <TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder>
<TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath> <TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath>
<TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps> <TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps>
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime> <TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime>
</PropertyGroup> </PropertyGroup>
@ -43,11 +42,6 @@
<Reference Include="Microsoft.NET.Sdk.Razor" ReferenceOutputAssembly="false" SkipGetTargetFrameworkProperties="true" /> <Reference Include="Microsoft.NET.Sdk.Razor" ReferenceOutputAssembly="false" SkipGetTargetFrameworkProperties="true" />
</ItemGroup> </ItemGroup>
<PropertyGroup>
<PreserveExistingLogsInOutput Condition="'$(PreserveExistingLogsInOutput)' == '' AND '$(ContinuousIntegrationBuild)' == 'true'">true</PreserveExistingLogsInOutput>
<PreserveExistingLogsInOutput Condition="'$(PreserveExistingLogsInOutput)' == ''">false</PreserveExistingLogsInOutput>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute"> <AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<_Parameter1>DotNetEfFullPath</_Parameter1> <_Parameter1>DotNetEfFullPath</_Parameter1>
@ -65,11 +59,6 @@
<_Parameter1>ContinuousIntegrationBuild</_Parameter1> <_Parameter1>ContinuousIntegrationBuild</_Parameter1>
<_Parameter2>true</_Parameter2> <_Parameter2>true</_Parameter2>
</AssemblyAttribute> </AssemblyAttribute>
<AssemblyAttribute Include="Microsoft.AspNetCore.Testing.TestFrameworkFileLoggerAttribute">
<_Parameter1>$(PreserveExistingLogsInOutput)</_Parameter1>
<_Parameter2>$(TargetFramework)</_Parameter2>
<_Parameter3></_Parameter3>
</AssemblyAttribute>
</ItemGroup> </ItemGroup>
<Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true"> <Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true">

View File

@ -55,7 +55,7 @@ namespace Templates.Test.Helpers
} }
private static string GetTemplateFolderBasePath(Assembly assembly) => private static string GetTemplateFolderBasePath(Assembly assembly) =>
(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR"))) (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
? assembly.GetCustomAttributes<AssemblyMetadataAttribute>() ? assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.Single(a => a.Key == "TestTemplateCreationFolder") .Single(a => a.Key == "TestTemplateCreationFolder")
.Value .Value

View File

@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;
namespace Templates.Test.Helpers
{
internal class TestOutputLogger : ITestOutputHelper
{
private readonly ILogger _logger;
public TestOutputLogger(ILogger logger)
{
_logger = logger;
}
public void WriteLine(string message)
{
_logger.LogInformation(message);
}
public void WriteLine(string format, params object[] args)
{
_logger.LogInformation(string.Format(format, args));
}
}
}

View File

@ -4,9 +4,6 @@
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers; using Templates.Test.Helpers;
using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "ProjectTemplates.Tests")] [assembly: AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(SeleniumStandaloneServer))]

View File

@ -15,7 +15,7 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class BaselineTest public class BaselineTest : LoggedTest
{ {
private static readonly Regex TemplateNameRegex = new Regex( private static readonly Regex TemplateNameRegex = new Regex(
"new (?<template>[a-zA-Z]+)", "new (?<template>[a-zA-Z]+)",
@ -32,10 +32,9 @@ namespace Templates.Test
RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Singleline, RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Singleline,
TimeSpan.FromSeconds(1)); TimeSpan.FromSeconds(1));
public BaselineTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public BaselineTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; } public Project Project { get; set; }
@ -67,7 +66,18 @@ namespace Templates.Test
} }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[Theory] [Theory]
[MemberData(nameof(TemplateBaselines))] [MemberData(nameof(TemplateBaselines))]

View File

@ -5,18 +5,30 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class ByteOrderMarkTest public class ByteOrderMarkTest : LoggedTest
{ {
private readonly ITestOutputHelper _output; private ITestOutputHelper _output;
public ITestOutputHelper Output
public ByteOrderMarkTest(ITestOutputHelper output) {
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
public ByteOrderMarkTest()
{ {
_output = output;
} }
[Theory] [Theory]
@ -43,13 +55,13 @@ namespace Templates.Test
// Check for UTF8 BOM 0xEF,0xBB,0xBF // Check for UTF8 BOM 0xEF,0xBB,0xBF
if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
{ {
_output.WriteLine($"File {filePath} has UTF-8 BOM characters."); Output.WriteLine($"File {filePath} has UTF-8 BOM characters.");
filesWithBOMCharactersPresent = true; filesWithBOMCharactersPresent = true;
} }
// Check for UTF16 BOM 0xFF, 0xFE // Check for UTF16 BOM 0xFF, 0xFE
if (bytes[0] == 0xFF && bytes[1] == 0xFE) if (bytes[0] == 0xFF && bytes[1] == 0xFE)
{ {
_output.WriteLine($"File {filePath} has UTF-16 BOM characters."); Output.WriteLine($"File {filePath} has UTF-16 BOM characters.");
filesWithBOMCharactersPresent = true; filesWithBOMCharactersPresent = true;
} }
} }
@ -83,7 +95,7 @@ namespace Templates.Test
var expectedBytes = Encoding.UTF8.GetPreamble(); var expectedBytes = Encoding.UTF8.GetPreamble();
if (bytes[0] != expectedBytes[0] || bytes[1] != expectedBytes[1] || bytes[2] != expectedBytes[2]) if (bytes[0] != expectedBytes[0] || bytes[1] != expectedBytes[1] || bytes[2] != expectedBytes[2])
{ {
_output.WriteLine($"File {filePath} does not have UTF-8 BOM characters."); Output.WriteLine($"File {filePath} does not have UTF-8 BOM characters.");
nonBOMFilesPresent = true; nonBOMFilesPresent = true;
} }
} }

View File

@ -9,19 +9,27 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class EmptyWebTemplateTest public class EmptyWebTemplateTest : LoggedTest
{ {
public EmptyWebTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public EmptyWebTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[ConditionalFact] [ConditionalFact]
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
@ -38,10 +46,10 @@ namespace Templates.Test
private async Task EmtpyTemplateCore(string languageOverride) private async Task EmtpyTemplateCore(string languageOverride)
{ {
Project = await ProjectFactory.GetOrCreateProject("empty" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output); var project = await ProjectFactory.GetOrCreateProject("empty" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
var createResult = await Project.RunDotNetNewAsync("web", language: languageOverride); var createResult = await project.RunDotNetNewAsync("web", language: languageOverride);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022 // Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022
if (languageOverride != null) if (languageOverride != null)
@ -49,30 +57,30 @@ namespace Templates.Test
return; return;
} }
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("/"); await aspNetProcess.AssertOk("/");
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("/"); await aspNetProcess.AssertOk("/");
} }

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
@ -12,44 +11,47 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class GrpcTemplateTest public class GrpcTemplateTest : LoggedTest
{ {
public GrpcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public GrpcTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[ConditionalFact] [ConditionalFact]
[SkipOnHelix("Not supported queues", Queues = "Windows.7.Amd64;Windows.7.Amd64.Open;Windows.81.Amd64.Open;OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("Not supported queues", Queues = "Windows.7.Amd64;Windows.7.Amd64.Open;Windows.81.Amd64.Open;OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task GrpcTemplate() public async Task GrpcTemplate()
{ {
// Setup AssemblyTestLog var project = await ProjectFactory.GetOrCreateProject("grpc", Output);
var assemblyLog = AssemblyTestLog.Create(Assembly.GetExecutingAssembly(), baseDirectory: Project.ArtifactsLogDir);
using var testLog = assemblyLog.StartTestLog(Output, nameof(GrpcTemplateTest), out var loggerFactory);
var logger = loggerFactory.CreateLogger("TestLogger");
Project = await ProjectFactory.GetOrCreateProject("grpc", Output); var createResult = await project.RunDotNetNewAsync("grpc");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var createResult = await Project.RunDotNetNewAsync("grpc"); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
var publishResult = await Project.RunDotNetPublishAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
var buildResult = await Project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
var isOsx = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); var isOsx = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
var isWindowsOld = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version < new Version(6, 2); var isWindowsOld = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version < new Version(6, 2);
var unsupported = isOsx || isWindowsOld; var unsupported = isOsx || isWindowsOld;
using (var serverProcess = Project.StartBuiltProjectAsync(hasListeningUri: !unsupported, logger: logger)) using (var serverProcess = project.StartBuiltProjectAsync(hasListeningUri: !unsupported, logger: Logger))
{ {
// These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support. // These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support.
// https://github.com/dotnet/aspnetcore/issues/11061 // https://github.com/dotnet/aspnetcore/issues/11061
@ -58,24 +60,24 @@ namespace Templates.Test
serverProcess.Process.WaitForExit(assertSuccess: false); serverProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(serverProcess.Process.HasExited, "built"); Assert.True(serverProcess.Process.HasExited, "built");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.", Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", project, serverProcess.Process));
} }
else if (isWindowsOld) else if (isWindowsOld)
{ {
serverProcess.Process.WaitForExit(assertSuccess: false); serverProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(serverProcess.Process.HasExited, "built"); Assert.True(serverProcess.Process.HasExited, "built");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.", Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", project, serverProcess.Process));
} }
else else
{ {
Assert.False( Assert.False(
serverProcess.Process.HasExited, serverProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", project, serverProcess.Process));
} }
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync(hasListeningUri: !unsupported)) using (var aspNetProcess = project.StartPublishedProjectAsync(hasListeningUri: !unsupported))
{ {
// These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support. // These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support.
// https://github.com/dotnet/aspnetcore/issues/11061 // https://github.com/dotnet/aspnetcore/issues/11061
@ -84,20 +86,20 @@ namespace Templates.Test
aspNetProcess.Process.WaitForExit(assertSuccess: false); aspNetProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(aspNetProcess.Process.HasExited, "published"); Assert.True(aspNetProcess.Process.HasExited, "published");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.", Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on macOS due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", project, aspNetProcess.Process));
} }
else if (isWindowsOld) else if (isWindowsOld)
{ {
aspNetProcess.Process.WaitForExit(assertSuccess: false); aspNetProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(aspNetProcess.Process.HasExited, "published"); Assert.True(aspNetProcess.Process.HasExited, "published");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.", Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on Windows 7 due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", project, aspNetProcess.Process));
} }
else else
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", project, aspNetProcess.Process));
} }
} }
} }

View File

@ -12,19 +12,27 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class IdentityUIPackageTest public class IdentityUIPackageTest : LoggedTest
{ {
public IdentityUIPackageTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public IdentityUIPackageTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; set; } public ProjectFactoryFixture ProjectFactory { get; set; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
public static string[] Bootstrap4ContentFiles { get; } = new string[] public static string[] Bootstrap4ContentFiles { get; } = new string[]
{ {
@ -71,35 +79,35 @@ namespace Templates.Test
public async Task IdentityUIPackage_WorksWithDifferentOptions() public async Task IdentityUIPackage_WorksWithDifferentOptions()
{ {
var packageOptions = new Dictionary<string, string>(); var packageOptions = new Dictionary<string, string>();
Project = await ProjectFactory.GetOrCreateProject("identityuipackage" + string.Concat(packageOptions.Values), Output); var project = await ProjectFactory.GetOrCreateProject("identityuipackage" + string.Concat(packageOptions.Values), Output);
var useLocalDB = false; var useLocalDB = false;
var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions); var createResult = await project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); var projectFileContents = ReadFile(project.TemplateOutputDir, $"{project.ProjectName}.csproj");
Assert.Contains(".db", projectFileContents); Assert.Contains(".db", projectFileContents);
var publishResult = await Project.RunDotNetPublishAsync(packageOptions: packageOptions); var publishResult = await project.RunDotNetPublishAsync(packageOptions: packageOptions);
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(packageOptions: packageOptions); var buildResult = await project.RunDotNetBuildAsync(packageOptions: packageOptions);
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages"); var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
Project.AssertEmptyMigration("razorpages"); project.AssertEmptyMigration("razorpages");
var versionValidator = "Bootstrap v4.3.1"; var versionValidator = "Bootstrap v4.3.1";
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css"); var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css");
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -107,11 +115,11 @@ namespace Templates.Test
await ValidatePublishedFiles(aspNetProcess, Bootstrap4ContentFiles); await ValidatePublishedFiles(aspNetProcess, Bootstrap4ContentFiles);
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css"); var response = await aspNetProcess.SendRequest("/Identity/lib/bootstrap/dist/css/bootstrap.css");
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);

View File

@ -10,21 +10,31 @@ using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers; using Templates.Test.Helpers;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Templates.Test namespace Templates.Test
{ {
public class MvcTemplateTest public class MvcTemplateTest : LoggedTest
{ {
public MvcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public MvcTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; }
private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[Fact] [Fact]
public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#"); public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#");
@ -35,13 +45,13 @@ namespace Templates.Test
private async Task MvcTemplateCore(string languageOverride) private async Task MvcTemplateCore(string languageOverride)
{ {
Project = await ProjectFactory.GetOrCreateProject("mvcnoauth" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output); var project = await ProjectFactory.GetOrCreateProject("mvcnoauth" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
var createResult = await Project.RunDotNetNewAsync("mvc", language: languageOverride); var createResult = await project.RunDotNetNewAsync("mvc", language: languageOverride);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var projectExtension = languageOverride == "F#" ? "fsproj" : "csproj"; var projectExtension = languageOverride == "F#" ? "fsproj" : "csproj";
var projectFileContents = Project.ReadFile($"{Project.ProjectName}.{projectExtension}"); var projectFileContents = project.ReadFile($"{project.ProjectName}.{projectExtension}");
Assert.DoesNotContain(".db", projectFileContents); Assert.DoesNotContain(".db", projectFileContents);
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents); Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
@ -54,15 +64,15 @@ namespace Templates.Test
return; return;
} }
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
IEnumerable<string> menuLinks = new List<string> { IEnumerable<string> menuLinks = new List<string> {
PageUrls.HomeUrl, PageUrls.HomeUrl,
@ -86,20 +96,20 @@ namespace Templates.Test
} }
}; };
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
@ -111,30 +121,30 @@ namespace Templates.Test
[SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task MvcTemplate_IndividualAuth(bool useLocalDB) public async Task MvcTemplate_IndividualAuth(bool useLocalDB)
{ {
Project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output); var project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output);
var createResult = await Project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: useLocalDB); var createResult = await project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: useLocalDB);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var projectFileContents = Project.ReadFile($"{Project.ProjectName}.csproj"); var projectFileContents = project.ReadFile($"{project.ProjectName}.csproj");
if (!useLocalDB) if (!useLocalDB)
{ {
Assert.Contains(".db", projectFileContents); Assert.Contains(".db", projectFileContents);
} }
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("mvc"); var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("mvc");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
Project.AssertEmptyMigration("mvc"); project.AssertEmptyMigration("mvc");
var pages = new List<Page> { var pages = new List<Page> {
new Page new Page
@ -204,20 +214,20 @@ namespace Templates.Test
} }
}; };
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
@ -243,14 +253,14 @@ namespace Templates.Test
return; return;
} }
Project = await ProjectFactory.GetOrCreateProject("mvcsinglefileexe", Output); var project = await ProjectFactory.GetOrCreateProject("mvcsinglefileexe", Output);
Project.RuntimeIdentifier = runtimeIdentifer; project.RuntimeIdentifier = runtimeIdentifer;
var createResult = await Project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: true); var createResult = await project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: true);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync(additionalArgs: $"/p:PublishSingleFile=true -r {runtimeIdentifer}", noRestore: false); var publishResult = await project.RunDotNetPublishAsync(additionalArgs: $"/p:PublishSingleFile=true -r {runtimeIdentifer}", noRestore: false);
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
var pages = new[] var pages = new[]
{ {
@ -286,10 +296,10 @@ namespace Templates.Test
}, },
}; };
using var aspNetProcess = Project.StartPublishedProjectAsync(usePublishedAppHost: true); using var aspNetProcess = project.StartPublishedProjectAsync(usePublishedAppHost: true);
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
@ -298,9 +308,9 @@ namespace Templates.Test
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23993")] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23993")]
public async Task MvcTemplate_RazorRuntimeCompilation_BuildsAndPublishes() public async Task MvcTemplate_RazorRuntimeCompilation_BuildsAndPublishes()
{ {
await MvcTemplateBuildsAndPublishes(auth: null, args: new[] { "--razor-runtime-compilation" }); var project = await MvcTemplateBuildsAndPublishes(auth: null, args: new[] { "--razor-runtime-compilation" });
Assert.False(Directory.Exists(Path.Combine(Project.TemplatePublishDir, "refs")), "The refs directory should not be published."); Assert.False(Directory.Exists(Path.Combine(project.TemplatePublishDir, "refs")), "The refs directory should not be published.");
} }
[Theory] [Theory]
@ -311,20 +321,22 @@ namespace Templates.Test
[InlineData("SingleOrg", new string[] { "--calls-graph" })] [InlineData("SingleOrg", new string[] { "--calls-graph" })]
public Task MvcTemplate_IdentityWeb_BuildsAndPublishes(string auth, string[] args) => MvcTemplateBuildsAndPublishes(auth: auth, args: args); public Task MvcTemplate_IdentityWeb_BuildsAndPublishes(string auth, string[] args) => MvcTemplateBuildsAndPublishes(auth: auth, args: args);
private async Task MvcTemplateBuildsAndPublishes(string auth, string[] args) private async Task<Project> MvcTemplateBuildsAndPublishes(string auth, string[] args)
{ {
Project = await ProjectFactory.GetOrCreateProject("mvc" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); var project = await ProjectFactory.GetOrCreateProject("mvc" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output);
var createResult = await Project.RunDotNetNewAsync("mvc", auth: auth, args: args); var createResult = await project.RunDotNetNewAsync("mvc", auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Verify building in debug works // Verify building in debug works
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
// Publish builds in "release" configuration. Running publish should ensure we can compile in release and that we can publish without issues. // Publish builds in "release" configuration. Running publish should ensure we can compile in release and that we can publish without issues.
buildResult = await Project.RunDotNetPublishAsync(); buildResult = await project.RunDotNetPublishAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, buildResult));
return project;
} }
} }
} }

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<!-- Shared testing infrastructure for running E2E tests using selenium --> <!-- Shared testing infrastructure for running E2E tests using selenium -->
<Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" /> <Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" />
@ -21,7 +21,6 @@
<TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder> <TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder>
<TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath> <TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath>
<TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps> <TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps>
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime> <TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime>
</PropertyGroup> </PropertyGroup>
@ -79,11 +78,6 @@
<_Parameter1>ContinuousIntegrationBuild</_Parameter1> <_Parameter1>ContinuousIntegrationBuild</_Parameter1>
<_Parameter2>true</_Parameter2> <_Parameter2>true</_Parameter2>
</AssemblyAttribute> </AssemblyAttribute>
<AssemblyAttribute Include="Microsoft.AspNetCore.Testing.TestFrameworkFileLoggerAttribute">
<_Parameter1>$(PreserveExistingLogsInOutput)</_Parameter1>
<_Parameter2>$(TargetFramework)</_Parameter2>
<_Parameter3></_Parameter3>
</AssemblyAttribute>
</ItemGroup> </ItemGroup>
<Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true"> <Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true">

View File

@ -9,55 +9,63 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class RazorClassLibraryTemplateTest public class RazorClassLibraryTemplateTest : LoggedTest
{ {
public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[Fact] [Fact]
public async Task RazorClassLibraryTemplate_WithViews_Async() public async Task RazorClassLibraryTemplate_WithViews_Async()
{ {
Project = await ProjectFactory.GetOrCreateProject("razorclasslibwithviews", Output); var project = await ProjectFactory.GetOrCreateProject("razorclasslibwithviews", Output);
var createResult = await Project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" }); var createResult = await project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
} }
[Fact] [Fact]
public async Task RazorClassLibraryTemplateAsync() public async Task RazorClassLibraryTemplateAsync()
{ {
Project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output); var project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output);
var createResult = await Project.RunDotNetNewAsync("razorclasslib"); var createResult = await project.RunDotNetNewAsync("razorclasslib");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
} }
} }
} }

View File

@ -12,45 +12,53 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class RazorPagesTemplateTest public class RazorPagesTemplateTest : LoggedTest
{ {
public RazorPagesTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public RazorPagesTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; set; } public ProjectFactoryFixture ProjectFactory { get; set; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[ConditionalFact] [ConditionalFact]
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task RazorPagesTemplate_NoAuth() public async Task RazorPagesTemplate_NoAuth()
{ {
Project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output); var project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output);
var createResult = await Project.RunDotNetNewAsync("razor"); var createResult = await project.RunDotNetNewAsync("razor");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("razor", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("razor", project, createResult));
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); var projectFileContents = ReadFile(project.TemplateOutputDir, $"{project.ProjectName}.csproj");
Assert.DoesNotContain(".db", projectFileContents); Assert.DoesNotContain(".db", projectFileContents);
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents); Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents); Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents); Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, createResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, createResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, createResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, createResult));
var pages = new List<Page> var pages = new List<Page>
{ {
@ -76,20 +84,20 @@ namespace Templates.Test
} }
}; };
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
@ -102,30 +110,30 @@ namespace Templates.Test
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/19716")] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/19716")]
public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB)
{ {
Project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output); var project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output);
var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB); var createResult = await project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj"); var projectFileContents = ReadFile(project.TemplateOutputDir, $"{project.ProjectName}.csproj");
if (!useLocalDB) if (!useLocalDB)
{ {
Assert.Contains(".db", projectFileContents); Assert.Contains(".db", projectFileContents);
} }
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages"); var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult)); Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
Project.AssertEmptyMigration("razorpages"); project.AssertEmptyMigration("razorpages");
var pages = new List<Page> { var pages = new List<Page> {
new Page new Page
@ -195,20 +203,20 @@ namespace Templates.Test
} }
}; };
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages); await aspNetProcess.AssertPagesOk(pages);
} }
@ -217,12 +225,12 @@ namespace Templates.Test
[Fact] [Fact]
public async Task RazorPagesTemplate_RazorRuntimeCompilation_BuildsAndPublishes() public async Task RazorPagesTemplate_RazorRuntimeCompilation_BuildsAndPublishes()
{ {
await BuildAndPublishRazorPagesTemplate(auth: null, new[] { "--razor-runtime-compilation" }); var project = await BuildAndPublishRazorPagesTemplate(auth: null, new[] { "--razor-runtime-compilation" });
Assert.False(Directory.Exists(Path.Combine(Project.TemplatePublishDir, "refs")), "The refs directory should not be published."); Assert.False(Directory.Exists(Path.Combine(project.TemplatePublishDir, "refs")), "The refs directory should not be published.");
// Verify ref assemblies isn't published // Verify ref assemblies isn't published
var refsDirectory = Path.Combine(Project.TemplatePublishDir, "refs"); var refsDirectory = Path.Combine(project.TemplatePublishDir, "refs");
Assert.False(Directory.Exists(refsDirectory), $"{refsDirectory} should not be in the publish output."); Assert.False(Directory.Exists(refsDirectory), $"{refsDirectory} should not be in the publish output.");
} }
@ -234,20 +242,22 @@ namespace Templates.Test
[InlineData("SingleOrg", new string[] { "--calls-graph" })] [InlineData("SingleOrg", new string[] { "--calls-graph" })]
public Task RazorPagesTemplate_IdentityWeb_BuildsAndPublishes(string auth, string[] args) => BuildAndPublishRazorPagesTemplate(auth: auth, args: args); public Task RazorPagesTemplate_IdentityWeb_BuildsAndPublishes(string auth, string[] args) => BuildAndPublishRazorPagesTemplate(auth: auth, args: args);
private async Task BuildAndPublishRazorPagesTemplate(string auth, string[] args) private async Task<Project> BuildAndPublishRazorPagesTemplate(string auth, string[] args)
{ {
Project = await ProjectFactory.GetOrCreateProject("razorpages" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); var project = await ProjectFactory.GetOrCreateProject("razorpages" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output);
var createResult = await Project.RunDotNetNewAsync("razor", auth: auth, args: args); var createResult = await project.RunDotNetNewAsync("razor", auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Verify building in debug works // Verify building in debug works
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
// Publish builds in "release" configuration. Running publish should ensure we can compile in release and that we can publish without issues. // Publish builds in "release" configuration. Running publish should ensure we can compile in release and that we can publish without issues.
buildResult = await Project.RunDotNetPublishAsync(); buildResult = await project.RunDotNetPublishAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, buildResult));
return project;
} }

View File

@ -10,19 +10,27 @@ using Xunit.Abstractions;
namespace Templates.Test namespace Templates.Test
{ {
public class WebApiTemplateTest public class WebApiTemplateTest : LoggedTest
{ {
public WebApiTemplateTest(ProjectFactoryFixture factoryFixture, ITestOutputHelper output) public WebApiTemplateTest(ProjectFactoryFixture factoryFixture)
{ {
FactoryFixture = factoryFixture; FactoryFixture = factoryFixture;
Output = output;
} }
public ProjectFactoryFixture FactoryFixture { get; } public ProjectFactoryFixture FactoryFixture { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
public Project Project { get; set; } {
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[Theory] [Theory]
[InlineData("IndividualB2C", null)] [InlineData("IndividualB2C", null)]
@ -43,49 +51,51 @@ namespace Templates.Test
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task WebApiTemplateCSharp_WithoutOpenAPI() public async Task WebApiTemplateCSharp_WithoutOpenAPI()
{ {
Project = await FactoryFixture.GetOrCreateProject("webapinoopenapi", Output); var project = await FactoryFixture.GetOrCreateProject("webapinoopenapi", Output);
var createResult = await Project.RunDotNetNewAsync("webapi", args: new[] { "--no-openapi" }); var createResult = await project.RunDotNetNewAsync("webapi", args: new[] { "--no-openapi" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
using var aspNetProcess = Project.StartBuiltProjectAsync(); using var aspNetProcess = project.StartBuiltProjectAsync();
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertNotFound("swagger"); await aspNetProcess.AssertNotFound("swagger");
} }
private async Task PublishAndBuildWebApiTemplate(string languageOverride, string auth, string[] args) private async Task<Project> PublishAndBuildWebApiTemplate(string languageOverride, string auth, string[] args)
{ {
Project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp") + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); var project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp") + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output);
var createResult = await Project.RunDotNetNewAsync("webapi", language: languageOverride, auth: auth, args: args); var createResult = await project.RunDotNetNewAsync("webapi", language: languageOverride, auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022 // Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022
if (languageOverride != null) if (languageOverride != null)
{ {
return; return project;
} }
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
return project;
} }
private async Task WebApiTemplateCore(string languageOverride) private async Task WebApiTemplateCore(string languageOverride)
{ {
await PublishAndBuildWebApiTemplate(languageOverride, null, null); var project = await PublishAndBuildWebApiTemplate(languageOverride, null, null);
// Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022 // Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022
if (languageOverride != null) if (languageOverride != null)
@ -93,22 +103,22 @@ namespace Templates.Test
return; return;
} }
using (var aspNetProcess = Project.StartBuiltProjectAsync()) using (var aspNetProcess = project.StartBuiltProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("weatherforecast"); await aspNetProcess.AssertOk("weatherforecast");
await aspNetProcess.AssertOk("swagger"); await aspNetProcess.AssertOk("swagger");
await aspNetProcess.AssertNotFound("/"); await aspNetProcess.AssertNotFound("/");
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync()) using (var aspNetProcess = project.StartPublishedProjectAsync())
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("weatherforecast"); await aspNetProcess.AssertOk("weatherforecast");

View File

@ -9,17 +9,26 @@ using Microsoft.AspNetCore.Testing;
namespace Templates.Test namespace Templates.Test
{ {
public class WorkerTemplateTest public class WorkerTemplateTest : LoggedTest
{ {
public WorkerTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output) public WorkerTemplateTest(ProjectFactoryFixture projectFactory)
{ {
ProjectFactory = projectFactory; ProjectFactory = projectFactory;
Output = output;
} }
public Project Project { get; set; }
public ProjectFactoryFixture ProjectFactory { get; } public ProjectFactoryFixture ProjectFactory { get; }
public ITestOutputHelper Output { get; } private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux, SkipReason = "https://github.com/dotnet/sdk/issues/12831")] [OSSkipCondition(OperatingSystems.Linux, SkipReason = "https://github.com/dotnet/sdk/issues/12831")]
@ -27,35 +36,35 @@ namespace Templates.Test
[InlineData("F#")] [InlineData("F#")]
public async Task WorkerTemplateAsync(string language) public async Task WorkerTemplateAsync(string language)
{ {
Project = await ProjectFactory.GetOrCreateProject( var project = await ProjectFactory.GetOrCreateProject(
$"worker-{ language.ToLowerInvariant()[0] }sharp", $"worker-{ language.ToLowerInvariant()[0] }sharp",
Output); Output);
var createResult = await Project.RunDotNetNewAsync("worker", language: language); var createResult = await project.RunDotNetNewAsync("worker", language: language);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync(); var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
// The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
// later, while the opposite is not true. // later, while the opposite is not true.
var buildResult = await Project.RunDotNetBuildAsync(); var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
using (var aspNetProcess = Project.StartBuiltProjectAsync(hasListeningUri: false)) using (var aspNetProcess = project.StartBuiltProjectAsync(hasListeningUri: false))
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
} }
using (var aspNetProcess = Project.StartPublishedProjectAsync(hasListeningUri: false)) using (var aspNetProcess = project.StartPublishedProjectAsync(hasListeningUri: false))
{ {
Assert.False( Assert.False(
aspNetProcess.Process.HasExited, aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process)); ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
} }
} }
} }

View File

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNetCore.E2ETesting
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class AssemblyFixtureAttribute : Attribute
{
public AssemblyFixtureAttribute(Type fixtureType)
{
FixtureType = fixtureType;
}
public Type FixtureType { get; private set; }
}
}

View File

@ -1,48 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.E2ETesting
{
public class XunitTestCollectionRunnerWithAssemblyFixture : XunitTestCollectionRunner
{
private readonly IDictionary<Type, object> _assemblyFixtureMappings;
private readonly IMessageSink _diagnosticMessageSink;
public XunitTestCollectionRunnerWithAssemblyFixture(Dictionary<Type, object> assemblyFixtureMappings,
ITestCollection testCollection,
IEnumerable<IXunitTestCase> testCases,
IMessageSink diagnosticMessageSink,
IMessageBus messageBus,
ITestCaseOrderer testCaseOrderer,
ExceptionAggregator aggregator,
CancellationTokenSource cancellationTokenSource)
: base(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource)
{
_assemblyFixtureMappings = assemblyFixtureMappings;
_diagnosticMessageSink = diagnosticMessageSink;
}
protected override Task<RunSummary> RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable<IXunitTestCase> testCases)
{
var runner = new XunitTestClassRunner(
testClass,
@class,
testCases,
_diagnosticMessageSink,
MessageBus,
TestCaseOrderer,
new ExceptionAggregator(Aggregator),
CancellationTokenSource,
_assemblyFixtureMappings);
return runner.RunAsync();
}
}
}

View File

@ -1,82 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.E2ETesting
{
public class XunitTestAssemblyRunnerWithAssemblyFixture : XunitTestAssemblyRunner
{
private readonly Dictionary<Type, object> _assemblyFixtureMappings = new Dictionary<Type, object>();
public XunitTestAssemblyRunnerWithAssemblyFixture(ITestAssembly testAssembly,
IEnumerable<IXunitTestCase> testCases,
IMessageSink diagnosticMessageSink,
IMessageSink executionMessageSink,
ITestFrameworkExecutionOptions executionOptions)
: base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions)
{
}
protected override async Task AfterTestAssemblyStartingAsync()
{
await base.AfterTestAssemblyStartingAsync();
// Find all the AssemblyFixtureAttributes on the test assembly
Aggregator.Run(() =>
{
var fixturesAttributes = ((IReflectionAssemblyInfo)TestAssembly.Assembly)
.Assembly
.GetCustomAttributes(typeof(AssemblyFixtureAttribute), false)
.Cast<AssemblyFixtureAttribute>()
.ToList();
// Instantiate all the fixtures
foreach (var fixtureAttribute in fixturesAttributes)
{
var ctorWithDiagnostics = fixtureAttribute.FixtureType.GetConstructor(new[] { typeof(IMessageSink) });
if (ctorWithDiagnostics != null)
{
_assemblyFixtureMappings[fixtureAttribute.FixtureType] = Activator.CreateInstance(fixtureAttribute.FixtureType, DiagnosticMessageSink);
}
else
{
_assemblyFixtureMappings[fixtureAttribute.FixtureType] = Activator.CreateInstance(fixtureAttribute.FixtureType);
}
}
});
}
protected override Task BeforeTestAssemblyFinishedAsync()
{
// Dispose fixtures
foreach (var disposable in _assemblyFixtureMappings.Values.OfType<IDisposable>())
{
Aggregator.Run(disposable.Dispose);
}
return base.BeforeTestAssemblyFinishedAsync();
}
protected override Task<RunSummary> RunTestCollectionAsync(
IMessageBus messageBus,
ITestCollection testCollection,
IEnumerable<IXunitTestCase> testCases,
CancellationTokenSource cancellationTokenSource)
=> new XunitTestCollectionRunnerWithAssemblyFixture(
_assemblyFixtureMappings,
testCollection,
testCases,
DiagnosticMessageSink,
messageBus,
TestCaseOrderer,
new ExceptionAggregator(Aggregator),
cancellationTokenSource).RunAsync();
}
}

View File

@ -1,26 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reflection;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.E2ETesting
{
public class XunitTestFrameworkExecutorWithAssemblyFixture : XunitTestFrameworkExecutor
{
public XunitTestFrameworkExecutorWithAssemblyFixture(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink)
: base(assemblyName, sourceInformationProvider, diagnosticMessageSink)
{
}
protected override async void RunTestCases(IEnumerable<IXunitTestCase> testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions)
{
using (var assemblyRunner = new XunitTestAssemblyRunnerWithAssemblyFixture(TestAssembly, testCases, DiagnosticMessageSink, executionMessageSink, executionOptions))
{
await assemblyRunner.RunAsync();
}
}
}
}

View File

@ -1,20 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.E2ETesting
{
public class XunitTestFrameworkWithAssemblyFixture : XunitTestFramework
{
public XunitTestFrameworkWithAssemblyFixture(IMessageSink messageSink)
: base(messageSink)
{
}
protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
=> new XunitTestFrameworkExecutorWithAssemblyFixture(assemblyName, SourceInformationProvider, DiagnosticMessageSink);
}
}