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.
using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "Microsoft.AspNetCore.Components.E2ETests")]
[assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: AssemblyFixture(typeof(SauceConnectServer))]

View File

@ -19,8 +19,6 @@
<OutputPath />
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<!-- This project references the shared framework transitively. Prevent restore errors by setting this flag. -->
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
</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.
using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers;
using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "BlazorTemplates.Tests")]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: 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 -->
<Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" />
@ -22,7 +22,6 @@
<TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder>
<TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath>
<TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps>
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime>
</PropertyGroup>
@ -43,11 +42,6 @@
<Reference Include="Microsoft.NET.Sdk.Razor" ReferenceOutputAssembly="false" SkipGetTargetFrameworkProperties="true" />
</ItemGroup>
<PropertyGroup>
<PreserveExistingLogsInOutput Condition="'$(PreserveExistingLogsInOutput)' == '' AND '$(ContinuousIntegrationBuild)' == 'true'">true</PreserveExistingLogsInOutput>
<PreserveExistingLogsInOutput Condition="'$(PreserveExistingLogsInOutput)' == ''">false</PreserveExistingLogsInOutput>
</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<_Parameter1>DotNetEfFullPath</_Parameter1>
@ -65,11 +59,6 @@
<_Parameter1>ContinuousIntegrationBuild</_Parameter1>
<_Parameter2>true</_Parameter2>
</AssemblyAttribute>
<AssemblyAttribute Include="Microsoft.AspNetCore.Testing.TestFrameworkFileLoggerAttribute">
<_Parameter1>$(PreserveExistingLogsInOutput)</_Parameter1>
<_Parameter2>$(TargetFramework)</_Parameter2>
<_Parameter3></_Parameter3>
</AssemblyAttribute>
</ItemGroup>
<Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true">

View File

@ -55,7 +55,7 @@ namespace Templates.Test.Helpers
}
private static string GetTemplateFolderBasePath(Assembly assembly) =>
(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
? assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.Single(a => a.Key == "TestTemplateCreationFolder")
.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.Testing;
using Templates.Test.Helpers;
using Xunit;
[assembly: TestFramework("Microsoft.AspNetCore.E2ETesting.XunitTestFrameworkWithAssemblyFixture", "ProjectTemplates.Tests")]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: Microsoft.AspNetCore.E2ETesting.AssemblyFixture(typeof(SeleniumStandaloneServer))]
[assembly: AssemblyFixture(typeof(ProjectFactoryFixture))]
[assembly: AssemblyFixture(typeof(SeleniumStandaloneServer))]

View File

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

View File

@ -5,18 +5,30 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers;
using Xunit;
using Xunit.Abstractions;
namespace Templates.Test
{
public class ByteOrderMarkTest
public class ByteOrderMarkTest : LoggedTest
{
private readonly ITestOutputHelper _output;
public ByteOrderMarkTest(ITestOutputHelper output)
private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
public ByteOrderMarkTest()
{
_output = output;
}
[Theory]
@ -43,13 +55,13 @@ namespace Templates.Test
// Check for UTF8 BOM 0xEF,0xBB,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;
}
// Check for UTF16 BOM 0xFF, 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;
}
}
@ -83,7 +95,7 @@ namespace Templates.Test
var expectedBytes = Encoding.UTF8.GetPreamble();
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;
}
}

View File

@ -9,19 +9,27 @@ using Xunit.Abstractions;
namespace Templates.Test
{
public class EmptyWebTemplateTest
public class EmptyWebTemplateTest : LoggedTest
{
public EmptyWebTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public EmptyWebTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { get; set; }
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]
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
@ -38,10 +46,10 @@ namespace Templates.Test
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("web", language: languageOverride);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022
if (languageOverride != null)
@ -49,30 +57,30 @@ namespace Templates.Test
return;
}
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("/");
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
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.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing;
@ -12,44 +11,47 @@ using Xunit.Abstractions;
namespace Templates.Test
{
public class GrpcTemplateTest
public class GrpcTemplateTest : LoggedTest
{
public GrpcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public GrpcTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { get; set; }
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]
[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()
{
// Setup AssemblyTestLog
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");
var project = await ProjectFactory.GetOrCreateProject("grpc", Output);
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");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var publishResult = await project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var buildResult = await Project.RunDotNetBuildAsync();
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 isWindowsOld = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version < new Version(6, 2);
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.
// https://github.com/dotnet/aspnetcore/issues/11061
@ -58,24 +60,24 @@ namespace Templates.Test
serverProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(serverProcess.Process.HasExited, "built");
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)
{
serverProcess.Process.WaitForExit(assertSuccess: false);
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.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", project, serverProcess.Process));
}
else
{
Assert.False(
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.
// https://github.com/dotnet/aspnetcore/issues/11061
@ -84,20 +86,20 @@ namespace Templates.Test
aspNetProcess.Process.WaitForExit(assertSuccess: false);
Assert.True(aspNetProcess.Process.HasExited, "published");
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)
{
aspNetProcess.Process.WaitForExit(assertSuccess: false);
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.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", project, aspNetProcess.Process));
}
else
{
Assert.False(
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
{
public class IdentityUIPackageTest
public class IdentityUIPackageTest : LoggedTest
{
public IdentityUIPackageTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public IdentityUIPackageTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { 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[]
{
@ -71,35 +79,35 @@ namespace Templates.Test
public async Task IdentityUIPackage_WorksWithDifferentOptions()
{
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 createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB, environmentVariables: packageOptions);
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);
var publishResult = await Project.RunDotNetPublishAsync(packageOptions: packageOptions);
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync(packageOptions: packageOptions);
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync(packageOptions: packageOptions);
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
var buildResult = await project.RunDotNetBuildAsync(packageOptions: packageOptions);
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
var migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
Project.AssertEmptyMigration("razorpages");
var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
project.AssertEmptyMigration("razorpages");
var versionValidator = "Bootstrap v4.3.1";
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
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");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -107,11 +115,11 @@ namespace Templates.Test
await ValidatePublishedFiles(aspNetProcess, Bootstrap4ContentFiles);
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
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");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);

View File

@ -10,21 +10,31 @@ using Microsoft.AspNetCore.Testing;
using Templates.Test.Helpers;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Templates.Test
{
public class MvcTemplateTest
public class MvcTemplateTest : LoggedTest
{
public MvcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public MvcTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { get; set; }
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]
public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#");
@ -35,13 +45,13 @@ namespace Templates.Test
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("mvc", language: languageOverride);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
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("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
@ -54,15 +64,15 @@ namespace Templates.Test
return;
}
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
IEnumerable<string> menuLinks = new List<string> {
PageUrls.HomeUrl,
@ -86,20 +96,20 @@ namespace Templates.Test
}
};
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
@ -111,30 +121,30 @@ namespace Templates.Test
[SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: useLocalDB);
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)
{
Assert.Contains(".db", projectFileContents);
}
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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 migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("mvc");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
Project.AssertEmptyMigration("mvc");
var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("mvc");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
project.AssertEmptyMigration("mvc");
var pages = new List<Page> {
new Page
@ -204,20 +214,20 @@ namespace Templates.Test
}
};
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
@ -243,14 +253,14 @@ namespace Templates.Test
return;
}
Project = await ProjectFactory.GetOrCreateProject("mvcsinglefileexe", Output);
Project.RuntimeIdentifier = runtimeIdentifer;
var project = await ProjectFactory.GetOrCreateProject("mvcsinglefileexe", Output);
project.RuntimeIdentifier = runtimeIdentifer;
var createResult = await Project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: true);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: true);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync(additionalArgs: $"/p:PublishSingleFile=true -r {runtimeIdentifer}", noRestore: false);
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync(additionalArgs: $"/p:PublishSingleFile=true -r {runtimeIdentifer}", noRestore: false);
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
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(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
@ -298,9 +308,9 @@ namespace Templates.Test
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23993")]
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]
@ -311,20 +321,22 @@ namespace Templates.Test
[InlineData("SingleOrg", new string[] { "--calls-graph" })]
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("mvc", auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Verify building in debug works
var buildResult = await Project.RunDotNetBuildAsync();
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));
// 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();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, buildResult));
buildResult = await project.RunDotNetPublishAsync();
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 -->
<Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" />
@ -21,7 +21,6 @@
<TestTemplateCreationFolder>TestTemplates\</TestTemplateCreationFolder>
<TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath>
<TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps>
<GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes>
<TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime>
</PropertyGroup>
@ -79,11 +78,6 @@
<_Parameter1>ContinuousIntegrationBuild</_Parameter1>
<_Parameter2>true</_Parameter2>
</AssemblyAttribute>
<AssemblyAttribute Include="Microsoft.AspNetCore.Testing.TestFrameworkFileLoggerAttribute">
<_Parameter1>$(PreserveExistingLogsInOutput)</_Parameter1>
<_Parameter2>$(TargetFramework)</_Parameter2>
<_Parameter3></_Parameter3>
</AssemblyAttribute>
</ItemGroup>
<Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true">

View File

@ -9,55 +9,63 @@ using Xunit.Abstractions;
namespace Templates.Test
{
public class RazorClassLibraryTemplateTest
public class RazorClassLibraryTemplateTest : LoggedTest
{
public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { get; set; }
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]
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" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
}
[Fact]
public async Task RazorClassLibraryTemplateAsync()
{
Project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output);
var project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output);
var createResult = await Project.RunDotNetNewAsync("razorclasslib");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razorclasslib");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
}
}
}

View File

@ -12,45 +12,53 @@ using Xunit.Abstractions;
namespace Templates.Test
{
public class RazorPagesTemplateTest
public class RazorPagesTemplateTest : LoggedTest
{
public RazorPagesTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public RazorPagesTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { 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]
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
public async Task RazorPagesTemplate_NoAuth()
{
Project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output);
var project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output);
var createResult = await Project.RunDotNetNewAsync("razor");
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("razor", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razor");
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("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, createResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, createResult));
var buildResult = await project.RunDotNetBuildAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, createResult));
var pages = new List<Page>
{
@ -76,20 +84,20 @@ namespace Templates.Test
}
};
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
@ -102,30 +110,30 @@ namespace Templates.Test
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/19716")]
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB);
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)
{
Assert.Contains(".db", projectFileContents);
}
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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 migrationsResult = await Project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
Project.AssertEmptyMigration("razorpages");
var migrationsResult = await project.RunDotNetEfCreateMigrationAsync("razorpages");
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult));
project.AssertEmptyMigration("razorpages");
var pages = new List<Page> {
new Page
@ -195,20 +203,20 @@ namespace Templates.Test
}
};
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
await aspNetProcess.AssertPagesOk(pages);
}
@ -217,12 +225,12 @@ namespace Templates.Test
[Fact]
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
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.");
}
@ -234,20 +242,22 @@ namespace Templates.Test
[InlineData("SingleOrg", new string[] { "--calls-graph" })]
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("razor", auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Verify building in debug works
var buildResult = await Project.RunDotNetBuildAsync();
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));
// 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();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, buildResult));
buildResult = await project.RunDotNetPublishAsync();
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, buildResult));
return project;
}

View File

@ -10,19 +10,27 @@ using Xunit.Abstractions;
namespace Templates.Test
{
public class WebApiTemplateTest
public class WebApiTemplateTest : LoggedTest
{
public WebApiTemplateTest(ProjectFactoryFixture factoryFixture, ITestOutputHelper output)
public WebApiTemplateTest(ProjectFactoryFixture factoryFixture)
{
FactoryFixture = factoryFixture;
Output = output;
}
public ProjectFactoryFixture FactoryFixture { get; }
public ITestOutputHelper Output { get; }
public Project Project { get; set; }
private ITestOutputHelper _output;
public ITestOutputHelper Output
{
get
{
if (_output == null)
{
_output = new TestOutputLogger(Logger);
}
return _output;
}
}
[Theory]
[InlineData("IndividualB2C", null)]
@ -43,49 +51,51 @@ namespace Templates.Test
[SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")]
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" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("webapi", args: new[] { "--no-openapi" });
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var buildResult = await Project.RunDotNetBuildAsync();
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));
using var aspNetProcess = Project.StartBuiltProjectAsync();
using var aspNetProcess = project.StartBuiltProjectAsync();
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
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);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("webapi", language: languageOverride, auth: auth, args: args);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
// Avoid the F# compiler. See https://github.com/dotnet/aspnetcore/issues/14022
if (languageOverride != null)
{
return;
return project;
}
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
return project;
}
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
if (languageOverride != null)
@ -93,22 +103,22 @@ namespace Templates.Test
return;
}
using (var aspNetProcess = Project.StartBuiltProjectAsync())
using (var aspNetProcess = project.StartBuiltProjectAsync())
{
Assert.False(
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("swagger");
await aspNetProcess.AssertNotFound("/");
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
using (var aspNetProcess = project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", project, aspNetProcess.Process));
await aspNetProcess.AssertOk("weatherforecast");

View File

@ -9,17 +9,26 @@ using Microsoft.AspNetCore.Testing;
namespace Templates.Test
{
public class WorkerTemplateTest
public class WorkerTemplateTest : LoggedTest
{
public WorkerTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
public WorkerTemplateTest(ProjectFactoryFixture projectFactory)
{
ProjectFactory = projectFactory;
Output = output;
}
public Project Project { get; set; }
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]
[OSSkipCondition(OperatingSystems.Linux, SkipReason = "https://github.com/dotnet/sdk/issues/12831")]
@ -27,35 +36,35 @@ namespace Templates.Test
[InlineData("F#")]
public async Task WorkerTemplateAsync(string language)
{
Project = await ProjectFactory.GetOrCreateProject(
var project = await ProjectFactory.GetOrCreateProject(
$"worker-{ language.ToLowerInvariant()[0] }sharp",
Output);
var createResult = await Project.RunDotNetNewAsync("worker", language: language);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
var createResult = await project.RunDotNetNewAsync("worker", language: language);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
var publishResult = await Project.RunDotNetPublishAsync();
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
var publishResult = await project.RunDotNetPublishAsync();
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
// 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.
var buildResult = await Project.RunDotNetBuildAsync();
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));
using (var aspNetProcess = Project.StartBuiltProjectAsync(hasListeningUri: false))
using (var aspNetProcess = project.StartBuiltProjectAsync(hasListeningUri: false))
{
Assert.False(
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(
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);
}
}