Clean up E2E tests

- Fix incorrect deployment environment variables
 - Utilize xunit logging utility for cleaner, more traceable output
 - Cleanup database creation/deletion
 - Fix name in R# settings file
This commit is contained in:
Nate McMaster 2016-03-03 18:17:34 -08:00
parent 025d8d6a91
commit 944afdc5ea
13 changed files with 301 additions and 107 deletions

View File

@ -35,6 +35,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Facebook", "Facebook", "{B5
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{E839AEB0-7926-4FEE-B22C-11AF7EF5D4BF}"
ProjectSection(SolutionItems) = preProject
shared\MusicStoreConfig.cs = shared\MusicStoreConfig.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{78715843-B625-414E-9074-56908C48EF28}"
ProjectSection(SolutionItems) = preProject

View File

@ -1,9 +1,9 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=EntityFramework/@EntryIndexedValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;Profile name="EntityFramework"&gt;&lt;HtmlReformatCode&gt;True&lt;/HtmlReformatCode&gt;&lt;CSArrangeThisQualifier&gt;True&lt;/CSArrangeThisQualifier&gt;&lt;CSRemoveCodeRedundancies&gt;True&lt;/CSRemoveCodeRedundancies&gt;&lt;CSUseAutoProperty&gt;True&lt;/CSUseAutoProperty&gt;&lt;CSMakeFieldReadonly&gt;True&lt;/CSMakeFieldReadonly&gt;&lt;CSUseVar&gt;&lt;BehavourStyle&gt;CAN_CHANGE_TO_IMPLICIT&lt;/BehavourStyle&gt;&lt;LocalVariableStyle&gt;ALWAYS_IMPLICIT&lt;/LocalVariableStyle&gt;&lt;ForeachVariableStyle&gt;ALWAYS_IMPLICIT&lt;/ForeachVariableStyle&gt;&lt;/CSUseVar&gt;&lt;CSOptimizeUsings&gt;&lt;OptimizeUsings&gt;True&lt;/OptimizeUsings&gt;&lt;EmbraceInRegion&gt;False&lt;/EmbraceInRegion&gt;&lt;RegionName&gt;&lt;/RegionName&gt;&lt;/CSOptimizeUsings&gt;&lt;CSShortenReferences&gt;True&lt;/CSShortenReferences&gt;&lt;CSReformatCode&gt;True&lt;/CSReformatCode&gt;&lt;XMLReformatCode&gt;True&lt;/XMLReformatCode&gt;&lt;CSUpdateFileHeader&gt;True&lt;/CSUpdateFileHeader&gt;&lt;CSharpFormatDocComments&gt;True&lt;/CSharpFormatDocComments&gt;&lt;/Profile&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=MusicStore/@EntryIndexedValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;Profile name="MusicStore"&gt;&lt;HtmlReformatCode&gt;True&lt;/HtmlReformatCode&gt;&lt;CSArrangeThisQualifier&gt;True&lt;/CSArrangeThisQualifier&gt;&lt;CSRemoveCodeRedundancies&gt;True&lt;/CSRemoveCodeRedundancies&gt;&lt;CSUseAutoProperty&gt;True&lt;/CSUseAutoProperty&gt;&lt;CSMakeFieldReadonly&gt;True&lt;/CSMakeFieldReadonly&gt;&lt;CSUseVar&gt;&lt;BehavourStyle&gt;CAN_CHANGE_TO_IMPLICIT&lt;/BehavourStyle&gt;&lt;LocalVariableStyle&gt;ALWAYS_IMPLICIT&lt;/LocalVariableStyle&gt;&lt;ForeachVariableStyle&gt;ALWAYS_IMPLICIT&lt;/ForeachVariableStyle&gt;&lt;/CSUseVar&gt;&lt;CSOptimizeUsings&gt;&lt;OptimizeUsings&gt;True&lt;/OptimizeUsings&gt;&lt;EmbraceInRegion&gt;False&lt;/EmbraceInRegion&gt;&lt;RegionName&gt;&lt;/RegionName&gt;&lt;/CSOptimizeUsings&gt;&lt;CSShortenReferences&gt;True&lt;/CSShortenReferences&gt;&lt;CSReformatCode&gt;True&lt;/CSReformatCode&gt;&lt;XMLReformatCode&gt;True&lt;/XMLReformatCode&gt;&lt;CSUpdateFileHeader&gt;True&lt;/CSUpdateFileHeader&gt;&lt;CSharpFormatDocComments&gt;True&lt;/CSharpFormatDocComments&gt;&lt;/Profile&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">EntityFramework</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">EntityFramework</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">MusicStore</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">MusicStore</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARGUMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">False</s:Boolean>
@ -45,7 +45,8 @@
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue"></s:String>
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) .NET Foundation. All rights reserved.&#xD;
See License.txt in the project root for license information</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Constructor/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Constructor/Options/=XmlDocumentation/@EntryIndexedValue">True</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Equality/@KeyIndexDefined">True</s:Boolean>
@ -63,6 +64,45 @@
<s:Boolean x:Key="/Default/CodeStyle/IntroduceVariableUseVar/UseVarForIntroduceVariableRefactoring/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -0,0 +1,7 @@
namespace MusicStore
{
public class StoreConfig
{
public const string ConnectionStringKey = "Data__DefaultConnection__ConnectionString";
}
}

View File

@ -52,7 +52,7 @@ namespace MusicStore
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MusicStoreContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
options.UseSqlServer(Configuration[StoreConfig.ConnectionStringKey.Replace("__",":")]));
}
// Add Identity services to the services container

View File

@ -8,7 +8,7 @@
"DefaultConnection": {
// Use a shared (and running) LocalDB database when executing in IIS e.g.
// "Server=(localdb)\\.\\IIS_DB;Database=MusicStore;Trusted_Connection=False;MultipleActiveResultSets=true;User ID=iis_login;Password=********"
"Connectionstring": "Server=(localdb)\\MSSQLLocalDB;Database=MusicStore;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;"
"ConnectionString": "Server=(localdb)\\MSSQLLocalDB;Database=MusicStore;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;"
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Data.SqlClient;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;
namespace E2ETests
@ -9,14 +10,28 @@ namespace E2ETests
/// </summary>
public class DbUtils
{
public const string CONNECTION_STRING_FORMAT = "Server=(localdb)\\MSSQLLocalDB;Database={0};Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;";
private const string BaseConnString = @"Server=(localdb)\MSSQLLocalDB;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;";
public static string CreateConnectionString(string dbName)
=> new SqlConnectionStringBuilder(BaseConnString)
{
InitialCatalog = dbName
}.ToString();
public static string GetUniqueName()
=> "MusicStore_Test_" + Guid.NewGuid().ToString().Replace("-", string.Empty);
public static void DropDatabase(string databaseName, ILogger logger)
{
if (Helpers.RunningOnMono
|| !TestPlatformHelper.IsWindows)
{
return;
}
try
{
logger.LogInformation("Trying to drop database '{0}'", databaseName);
using (var conn = new SqlConnection(string.Format(CONNECTION_STRING_FORMAT, "master")))
using (var conn = new SqlConnection(CreateConnectionString("master")))
{
conn.Open();

View File

@ -0,0 +1,59 @@
// Copyright (c) .NET Foundation. All rights reserved.
// See License.txt in the project root for license information
using System;
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;
using System.Linq;
namespace E2ETests.Common
{
public class XunitLogger : ILogger, IDisposable
{
private readonly LogLevel _minLogLevel;
private readonly ITestOutputHelper _output;
private bool _disposed;
public XunitLogger(ITestOutputHelper output, LogLevel minLogLevel)
{
_minLogLevel = minLogLevel;
_output = output;
}
public void Log<TState>(
LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
var firstLinePrefix = "| " + logLevel + ": ";
var lines = formatter(state, exception).Split('\n');
_output.WriteLine(firstLinePrefix + lines.First());
var additionalLinePrefix = "|" + new string(' ', firstLinePrefix.Length - 1);
foreach (var line in lines.Skip(1))
{
_output.WriteLine(additionalLinePrefix + line.Trim('\r'));
}
}
public bool IsEnabled(LogLevel logLevel)
=> logLevel >= _minLogLevel && !_disposed;
public IDisposable BeginScopeImpl(object state)
=> new NullScope();
private class NullScope : IDisposable
{
public void Dispose()
{
}
}
public void Dispose()
{
_disposed = true;
}
}
}

View File

@ -37,7 +37,7 @@ namespace E2ETests
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Home page content : {0}", responseContent);
_logger.LogInformation("Home page content : {0}", responseContent);
}
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -177,6 +177,7 @@ namespace E2ETests
var content = new FormUrlEncodedContent(formParameters.ToArray());
response = await _httpClient.PostAsync("Account/Register", content);
await ThrowIfResponseStatusNotOk(response);
responseContent = await response.Content.ReadAsStringAsync();
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNetCore.Microsoft.AspNetCore.Identity.Application"));
Assert.Contains("<div class=\"text-danger validation-summary-errors\" data-valmsg-summary=\"true\"><ul><li>The password and confirmation password do not match.</li>", responseContent, StringComparison.OrdinalIgnoreCase);
@ -492,7 +493,11 @@ namespace E2ETests
{
if (response.StatusCode != HttpStatusCode.OK)
{
_logger.LogError(await response.Content.ReadAsStringAsync());
_logger.LogError(
"Headers: {0}",
string.Join("\n", response.Headers.Select(h => h.Key + "=" + string.Join(",", h.Value))));
var content = await response.Content.ReadAsStringAsync();
_logger.LogError("Content: Length={0}\n{1}", content.Length, content);
throw new Exception(string.Format("Received the above response with status code : {0}", response.StatusCode));
}
}

View File

@ -3,30 +3,34 @@ using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using E2ETests.Common;
using Microsoft.AspNetCore.Server.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
namespace E2ETests
{
// Uses ports ranging 5050 - 5060.
public class NtlmAuthenticationTests
public class NtlmAuthenticationTests : IDisposable
{
private readonly XunitLogger _logger;
public NtlmAuthenticationTests(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5050/")]
public async Task NtlmAuthenticationTest(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
{
var logger = new LoggerFactory()
.AddConsole(LogLevel.Information)
.CreateLogger(string.Format("Ntlm:{0}:{1}:{2}", serverType, runtimeFlavor, architecture));
using (logger.BeginScope("NtlmAuthenticationTest"))
using (_logger.BeginScope("NtlmAuthenticationTest"))
{
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
var musicStoreDbName = DbUtils.GetUniqueName();
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
{
@ -38,21 +42,17 @@ namespace E2ETests
SiteName = "MusicStoreNtlmAuthentication", //This is configured in the NtlmAuthentication.config
UserAdditionalCleanup = parameters =>
{
if (!Helpers.RunningOnMono)
{
// Mono uses InMemoryStore
DbUtils.DropDatabase(musicStoreDbName, logger);
}
DbUtils.DropDatabase(musicStoreDbName, _logger);
}
};
// Override the connection strings using environment based configuration
deploymentParameters.EnvironmentVariables
.Add(new KeyValuePair<string, string>(
"SQLAZURECONNSTR_DefaultConnection",
string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName)));
MusicStore.StoreConfig.ConnectionStringKey,
DbUtils.CreateConnectionString(musicStoreDbName)));
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
{
var deploymentResult = deployer.Deploy();
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true, AllowAutoRedirect = false };
@ -62,20 +62,25 @@ namespace E2ETests
var response = await RetryHelper.RetryRequest(async () =>
{
return await httpClient.GetAsync(string.Empty);
}, logger: logger, cancellationToken: deploymentResult.HostShutdownToken);
}, logger: _logger, cancellationToken: deploymentResult.HostShutdownToken);
Assert.False(response == null, "Response object is null because the client could not " +
"connect to the server after multiple retries");
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
var validator = new Validator(httpClient, httpClientHandler, _logger, deploymentResult);
await validator.VerifyNtlmHomePage(response);
//Should be able to access the store as the Startup adds necessary permissions for the current user
await validator.AccessStoreWithPermissions();
logger.LogInformation("Variation completed successfully.");
_logger.LogInformation("Variation completed successfully.");
}
}
}
public void Dispose()
{
_logger.Dispose();
}
}
}

View File

@ -2,17 +2,26 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using E2ETests.Common;
using Microsoft.AspNetCore.Server.Testing;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
namespace E2ETests
{
// Uses ports ranging 5040 - 5049.
public class OpenIdConnectTests
public class OpenIdConnectTests : IDisposable
{
private readonly XunitLogger _logger;
public OpenIdConnectTests(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory(Skip = "Temporarily skipped the test to fix potential product issue"), Trait("E2Etests", "E2Etests")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
@ -47,14 +56,9 @@ namespace E2ETests
private async Task OpenIdConnectTestSuite(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
{
var logger = new LoggerFactory()
.AddConsole(LogLevel.Information)
.CreateLogger(string.Format("OpenId:{0}:{1}:{2}", serverType, runtimeFlavor, architecture));
using (logger.BeginScope("OpenIdConnectTestSuite"))
using (_logger.BeginScope("OpenIdConnectTestSuite"))
{
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
var musicStoreDbName = DbUtils.GetUniqueName();
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
{
@ -64,22 +68,17 @@ namespace E2ETests
EnvironmentName = "OpenIdConnectTesting",
UserAdditionalCleanup = parameters =>
{
if (!Helpers.RunningOnMono
&& TestPlatformHelper.IsWindows)
{
// Mono uses InMemoryStore
DbUtils.DropDatabase(musicStoreDbName, logger);
}
DbUtils.DropDatabase(musicStoreDbName, _logger);
}
};
// Override the connection strings using environment based configuration
deploymentParameters.EnvironmentVariables
.Add(new KeyValuePair<string, string>(
"SQLAZURECONNSTR_DefaultConnection",
string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName)));
MusicStore.StoreConfig.ConnectionStringKey,
DbUtils.CreateConnectionString(musicStoreDbName)));
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
{
var deploymentResult = deployer.Deploy();
var httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
@ -89,20 +88,25 @@ namespace E2ETests
var response = await RetryHelper.RetryRequest(async () =>
{
return await httpClient.GetAsync(string.Empty);
}, logger: logger, cancellationToken: deploymentResult.HostShutdownToken);
}, logger: _logger, cancellationToken: deploymentResult.HostShutdownToken);
Assert.False(response == null, "Response object is null because the client could not " +
"connect to the server after multiple retries");
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
var validator = new Validator(httpClient, httpClientHandler, _logger, deploymentResult);
await validator.VerifyHomePage(response);
// OpenIdConnect login.
await validator.LoginWithOpenIdConnect();
logger.LogInformation("Variation completed successfully.");
_logger.LogInformation("Variation completed successfully.");
}
}
}
public void Dispose()
{
_logger.Dispose();
}
}
}

View File

@ -3,17 +3,26 @@ using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using E2ETests.Common;
using Microsoft.AspNetCore.Server.Testing;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
namespace E2ETests
{
// Uses ports ranging 5025 - 5039.
public class PublishAndRunTests_OnX64
public class PublishAndRunTests_OnX64 : IDisposable
{
private readonly XunitLogger _logger;
public PublishAndRunTests_OnX64(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "PublishAndRun")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
@ -28,7 +37,7 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource)
{
var testRunner = new PublishAndRunTests();
var testRunner = new PublishAndRunTests(_logger);
await testRunner.Publish_And_Run_Tests(
serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
}
@ -43,16 +52,28 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource)
{
var testRunner = new PublishAndRunTests();
var testRunner = new PublishAndRunTests(_logger);
await testRunner.Publish_And_Run_Tests(
serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
}
public void Dispose()
{
_logger.Dispose();
}
}
// TODO: temporarily disabling x86 tests as dotnet xunit test runner currently does not support 32-bit
// public
class PublishAndRunTests_OnX86
class PublishAndRunTests_OnX86 : IDisposable
{
private readonly XunitLogger _logger;
public PublishAndRunTests_OnX86(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "PublishAndRun")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
@ -67,7 +88,7 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource)
{
var testRunner = new PublishAndRunTests();
var testRunner = new PublishAndRunTests(_logger);
await testRunner.Publish_And_Run_Tests(
serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
}
@ -82,14 +103,26 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource)
{
var testRunner = new PublishAndRunTests();
var testRunner = new PublishAndRunTests(_logger);
await testRunner.Publish_And_Run_Tests(
serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
}
public void Dispose()
{
_logger.Dispose();
}
}
public class PublishAndRunTests
{
private ILogger _logger;
public PublishAndRunTests(ILogger logger)
{
_logger = logger;
}
public async Task Publish_And_Run_Tests(
ServerType serverType,
RuntimeFlavor runtimeFlavor,
@ -97,14 +130,9 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource)
{
var logger = new LoggerFactory()
.AddConsole(LogLevel.Information)
.CreateLogger($"Publish:{serverType}:{runtimeFlavor}:{architecture}:{noSource}");
using (logger.BeginScope("Publish_And_Run_Tests"))
using (_logger.BeginScope("Publish_And_Run_Tests"))
{
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
var musicStoreDbName = DbUtils.GetUniqueName();
var deploymentParameters = new DeploymentParameters(
Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
@ -114,22 +142,17 @@ namespace E2ETests
PublishTargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "dnx451" : "netstandardapp1.5",
UserAdditionalCleanup = parameters =>
{
if (!Helpers.RunningOnMono
&& TestPlatformHelper.IsWindows)
{
// Mono uses InMemoryStore
DbUtils.DropDatabase(musicStoreDbName, logger);
}
DbUtils.DropDatabase(musicStoreDbName, _logger);
}
};
// Override the connection strings using environment based configuration
deploymentParameters.EnvironmentVariables
.Add(new KeyValuePair<string, string>(
"SQLAZURECONNSTR_DefaultConnection",
string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName)));
MusicStore.StoreConfig.ConnectionStringKey,
DbUtils.CreateConnectionString(musicStoreDbName)));
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
{
var deploymentResult = deployer.Deploy();
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true, AllowAutoRedirect = false };
@ -139,15 +162,12 @@ namespace E2ETests
// Request to base address and check if various parts of the body are rendered &
// measure the cold startup time.
// Add retry logic since tests are flaky on mono due to connection issues
var response = await RetryHelper.RetryRequest(async () =>
{
return await httpClient.GetAsync(string.Empty);
}, logger: logger, cancellationToken: deploymentResult.HostShutdownToken);
var response = await RetryHelper.RetryRequest(async () => await httpClient.GetAsync(string.Empty), logger: _logger, cancellationToken: deploymentResult.HostShutdownToken);
Assert.False(response == null, "Response object is null because the client could not " +
"connect to the server after multiple retries");
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
var validator = new Validator(httpClient, httpClientHandler, _logger, deploymentResult);
await validator.VerifyHomePage(response);
// Static files are served?
@ -162,7 +182,7 @@ namespace E2ETests
}
}
logger.LogInformation("Variation completed successfully.");
_logger.LogInformation("Variation completed successfully.");
}
}
}

View File

@ -2,19 +2,27 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using E2ETests.Common;
using Microsoft.AspNetCore.Server.Testing;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
namespace E2ETests
{
// Uses ports ranging 5001 - 5025.
// TODO: temporarily disabling these tests as dotnet xunit runner does not support 32-bit yet.
// public
class SmokeTests_X86
class SmokeTests_X86 : IDisposable
{
private readonly XunitLogger _logger;
public SmokeTests_X86(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "Smoke")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
@ -28,7 +36,7 @@ namespace E2ETests
RuntimeArchitecture architecture,
string applicationBaseUrl)
{
var smokeTestRunner = new SmokeTests();
var smokeTestRunner = new SmokeTests(_logger);
await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
}
@ -41,13 +49,25 @@ namespace E2ETests
RuntimeArchitecture architecture,
string applicationBaseUrl)
{
var smokeTestRunner = new SmokeTests();
var smokeTestRunner = new SmokeTests(_logger);
await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
}
public void Dispose()
{
_logger.Dispose();
}
}
public class SmokeTests_X64
public class SmokeTests_X64 : IDisposable
{
private readonly XunitLogger _logger;
public SmokeTests_X64(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "Smoke")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
@ -61,7 +81,7 @@ namespace E2ETests
RuntimeArchitecture architecture,
string applicationBaseUrl)
{
var smokeTestRunner = new SmokeTests();
var smokeTestRunner = new SmokeTests(_logger);
await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
}
@ -74,13 +94,24 @@ namespace E2ETests
RuntimeArchitecture architecture,
string applicationBaseUrl)
{
var smokeTestRunner = new SmokeTests();
var smokeTestRunner = new SmokeTests(_logger);
await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
}
public void Dispose()
{
_logger.Dispose();
}
}
class SmokeTests_OnIIS
class SmokeTests_OnIIS : IDisposable
{
private readonly XunitLogger _logger;
public SmokeTests_OnIIS(ITestOutputHelper output)
{
_logger = new XunitLogger(output, LogLevel.Information);
}
[ConditionalTheory, Trait("E2Etests", "Smoke")]
[OSSkipCondition(OperatingSystems.MacOSX)]
[OSSkipCondition(OperatingSystems.Linux)]
@ -94,14 +125,26 @@ namespace E2ETests
RuntimeArchitecture architecture,
string applicationBaseUrl)
{
var smokeTestRunner = new SmokeTests();
var smokeTestRunner = new SmokeTests(_logger);
await smokeTestRunner.SmokeTestSuite(
serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource: true);
}
public void Dispose()
{
_logger.Dispose();
}
}
public class SmokeTests
{
private ILogger _logger;
public SmokeTests(ILogger logger)
{
_logger = logger;
}
public async Task SmokeTestSuite(
ServerType serverType,
RuntimeFlavor donetFlavor,
@ -109,13 +152,9 @@ namespace E2ETests
string applicationBaseUrl,
bool noSource = false)
{
var logger = new LoggerFactory()
.AddConsole(LogLevel.Information)
.CreateLogger($"Smoke:{serverType}:{donetFlavor}:{architecture}");
using (logger.BeginScope("SmokeTestSuite"))
using (_logger.BeginScope("SmokeTestSuite"))
{
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
var musicStoreDbName = DbUtils.GetUniqueName();
var deploymentParameters = new DeploymentParameters(
Helpers.GetApplicationPath(), serverType, donetFlavor, architecture)
@ -126,26 +165,20 @@ namespace E2ETests
PublishTargetFramework = donetFlavor == RuntimeFlavor.Clr ? "dnx451" : "netstandardapp1.5",
UserAdditionalCleanup = parameters =>
{
if (!Helpers.RunningOnMono
&& TestPlatformHelper.IsWindows
&& parameters.ServerType != ServerType.IIS)
{
// Mono uses InMemoryStore
DbUtils.DropDatabase(musicStoreDbName, logger);
}
DbUtils.DropDatabase(musicStoreDbName, _logger);
}
};
// Override the connection strings using environment based configuration
deploymentParameters.EnvironmentVariables
.Add(new KeyValuePair<string, string>(
"SQLAZURECONNSTR_DefaultConnection",
string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName)));
MusicStore.StoreConfig.ConnectionStringKey,
DbUtils.CreateConnectionString(musicStoreDbName)));
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
{
var deploymentResult = deployer.Deploy();
Helpers.SetInMemoryStoreForIIS(deploymentParameters, logger);
Helpers.SetInMemoryStoreForIIS(deploymentParameters, _logger);
var httpClientHandler = new HttpClientHandler()
{
@ -163,12 +196,12 @@ namespace E2ETests
var response = await RetryHelper.RetryRequest(async () =>
{
return await httpClient.GetAsync(string.Empty);
}, logger: logger, cancellationToken: deploymentResult.HostShutdownToken);
}, logger: _logger, cancellationToken: deploymentResult.HostShutdownToken);
Assert.False(response == null, "Response object is null because the client could not " +
"connect to the server after multiple retries");
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
var validator = new Validator(httpClient, httpClientHandler, _logger, deploymentResult);
await validator.VerifyHomePage(response);
@ -255,7 +288,7 @@ namespace E2ETests
// MicrosoftAccountLogin
await validator.LoginWithMicrosoftAccount();
logger.LogInformation("Variation completed successfully.");
_logger.LogInformation("Variation completed successfully.");
}
}
}

View File

@ -1,4 +1,7 @@
using System;
// Copyright (c) .NET Foundation. All rights reserved.
// See License.txt in the project root for license information
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MusicStore.Models;