Skip to content

Commit 8f99635

Browse files
committed
Improved test configuration performance (#135 #168)
1 parent e915ced commit 8f99635

File tree

7 files changed

+96
-76
lines changed

7 files changed

+96
-76
lines changed

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/Application/TestApplication.cs

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ public static class TestApplication
4848
private static bool initialiazed;
4949

5050
private static string testAssemblyName;
51-
private static TestConfiguration testConfiguration;
51+
private static IConfigurationBuilder configurationBuilder;
52+
private static TestConfiguration configuration;
5253

5354
private static IHostingEnvironment environment;
5455

@@ -72,8 +73,7 @@ static TestApplication()
7273
#if NET451
7374
FindTestAssembly();
7475
#endif
75-
76-
PrepareTestConfiguration();
76+
7777
FindTestAssemblyName();
7878
}
7979

@@ -115,7 +115,7 @@ internal static Type StartupType
115115

116116
set
117117
{
118-
if (startupType != null && TestConfiguration.General.AsynchronousTests)
118+
if (startupType != null && Configuration().General().AsynchronousTests())
119119
{
120120
throw new InvalidOperationException("Multiple Startup types per test project while running asynchronous tests is not supported. Either set 'General.AsynchronousTests' in the 'testconfig.json' file to 'false' or separate your tests into different test projects. The latter is recommended. If you choose the first option, you may need to disable asynchronous testing in your preferred test runner too.");
121121
}
@@ -163,31 +163,38 @@ internal static IHostingEnvironment Environment
163163
}
164164
}
165165

166-
public static TestConfiguration TestConfiguration
166+
internal static string ApplicationName =>
167+
Configuration().General().ApplicationName()
168+
?? TestAssembly?.GetName().Name
169+
?? StartupAssemblyName
170+
?? PlatformServices.Default.Application.ApplicationName;
171+
172+
public static TestConfiguration Configuration()
167173
{
168-
get
174+
if (configuration == null || AdditionalConfiguration != null)
169175
{
170-
if (testConfiguration == null || AdditionalConfiguration != null)
176+
if (configurationBuilder == null)
171177
{
172-
testConfiguration = TestConfiguration.With(PrepareTestConfiguration());
173-
PrepareLicensing();
178+
configurationBuilder = new ConfigurationBuilder()
179+
.AddJsonFile("testconfig.json", optional: true);
174180
}
175181

176-
return testConfiguration;
182+
AdditionalConfiguration?.Invoke(configurationBuilder);
183+
AdditionalConfiguration = null;
184+
185+
configuration = TestConfiguration.With(configurationBuilder.Build());
186+
187+
PrepareLicensing();
177188
}
178-
}
179189

180-
internal static string ApplicationName =>
181-
TestConfiguration.General.ApplicationName
182-
?? TestAssembly?.GetName().Name
183-
?? StartupAssemblyName
184-
?? PlatformServices.Default.Application.ApplicationName;
190+
return configuration;
191+
}
185192

186193
public static void TryInitialize()
187194
{
188195
lock (Sync)
189196
{
190-
if (!initialiazed && TestConfiguration.General.AutomaticStartup)
197+
if (!initialiazed && Configuration().General().AutomaticStartup())
191198
{
192199
var defaultStartupType = TryFindDefaultStartupType();
193200

@@ -267,7 +274,7 @@ internal static Type TryFindDefaultStartupType()
267274
{
268275
var applicationAssembly = TestAssembly ?? Assembly.Load(new AssemblyName(testAssemblyName));
269276

270-
var defaultStartupType = TestConfiguration.General.StartupType ?? $"{Environment.EnvironmentName}Startup";
277+
var defaultStartupType = Configuration().General().StartupType() ?? $"{Environment.EnvironmentName}Startup";
271278

272279
// check root of the test project
273280
var startup =
@@ -292,21 +299,10 @@ private static void Initialize()
292299

293300
initialiazed = true;
294301
}
295-
296-
private static IConfiguration PrepareTestConfiguration()
297-
{
298-
var configurationBuilder = new ConfigurationBuilder()
299-
.AddJsonFile("testconfig.json", optional: true);
300-
301-
AdditionalConfiguration?.Invoke(configurationBuilder);
302-
AdditionalConfiguration = null;
303-
304-
return configurationBuilder.Build();
305-
}
306-
302+
307303
private static void FindTestAssemblyName()
308304
{
309-
testAssemblyName = TestConfiguration.General.TestAssemblyName
305+
testAssemblyName = Configuration().General().TestAssemblyName()
310306
?? TestAssembly?.GetName().Name
311307
?? DependencyContext
312308
.Default
@@ -318,7 +314,7 @@ private static void FindTestAssemblyName()
318314
private static void PrepareLicensing()
319315
{
320316
TestCounter.SetLicenseData(
321-
TestConfiguration.Licenses,
317+
Configuration().Licenses(),
322318
DateTime.ParseExact(ReleaseDate, "yyyy-MM-dd", CultureInfo.InvariantCulture),
323319
TestAssembly?.GetName().Name ?? StartupAssemblyName);
324320
}
@@ -328,7 +324,7 @@ private static IHostingEnvironment PrepareEnvironment()
328324
return new HostingEnvironment
329325
{
330326
ApplicationName = ApplicationName,
331-
EnvironmentName = TestConfiguration.General.EnvironmentName,
327+
EnvironmentName = Configuration().General().EnvironmentName(),
332328
ContentRootPath = PlatformServices.Default.Application.ApplicationBasePath
333329
};
334330
}
@@ -515,6 +511,8 @@ private static void TryLockedInitialization()
515511
private static void Reset()
516512
{
517513
initialiazed = false;
514+
configurationBuilder = null;
515+
configuration = null;
518516
environment = null;
519517
startupType = null;
520518
serviceProvider = null;
@@ -531,29 +529,29 @@ private static void Reset()
531529
RoutingServiceRegistrationPlugins.Clear();
532530
InitializationPlugins.Clear();
533531
LicenseValidator.ClearLicenseDetails();
534-
}
532+
}
535533

536534
#if NET451
537-
private static void FindTestAssembly()
538-
{
539-
var executingAssembly = Assembly.GetExecutingAssembly();
540-
541-
var stackTrace = new StackTrace(false);
542-
543-
foreach (var frame in stackTrace.GetFrames())
535+
private static void FindTestAssembly()
544536
{
545-
var method = frame.GetMethod();
546-
var methodAssembly = method?.DeclaringType?.Assembly;
537+
var executingAssembly = Assembly.GetExecutingAssembly();
538+
539+
var stackTrace = new StackTrace(false);
547540

548-
if (methodAssembly != null
549-
&& methodAssembly != executingAssembly
550-
&& !methodAssembly.FullName.StartsWith(TestFrameworkName))
541+
foreach (var frame in stackTrace.GetFrames())
551542
{
552-
TestAssembly = methodAssembly;
553-
return;
543+
var method = frame.GetMethod();
544+
var methodAssembly = method?.DeclaringType?.Assembly;
545+
546+
if (methodAssembly != null
547+
&& methodAssembly != executingAssembly
548+
&& !methodAssembly.FullName.StartsWith(TestFrameworkName))
549+
{
550+
TestAssembly = methodAssembly;
551+
return;
552+
}
554553
}
555554
}
556-
}
557555
#endif
558-
}
556+
}
559557
}

src/MyTested.AspNetCore.Mvc.Configuration/Internal/Configuration/BaseConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public BaseConfiguration(IConfiguration configuration)
1212
this.Configuration = configuration;
1313
}
1414

15-
protected IConfiguration Configuration
15+
public IConfiguration Configuration
1616
{
1717
get
1818
{

src/MyTested.AspNetCore.Mvc.Configuration/Internal/Configuration/GeneralTestConfiguration.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ public GeneralTestConfiguration(IConfiguration configuration)
1818
this.Prefix = "General";
1919
}
2020

21-
public bool AsynchronousTests => this.GetValue(AsynchronousTestsConfigKey, true);
21+
public bool AsynchronousTests() => this.GetValue(AsynchronousTestsConfigKey, true);
2222

23-
public string WebAssemblyName => this.GetValue(WebAssemblyNameConfigKey);
23+
public string WebAssemblyName() => this.GetValue(WebAssemblyNameConfigKey);
2424

25-
public string TestAssemblyName => this.GetValue(TestAssemblyNameConfigKey);
25+
public string TestAssemblyName() => this.GetValue(TestAssemblyNameConfigKey);
2626

27-
public bool AutomaticStartup => this.GetValue(AutomaticStartupConfigKey, true);
27+
public bool AutomaticStartup() => this.GetValue(AutomaticStartupConfigKey, true);
2828

29-
public string StartupType => this.GetValue(StartupTypeConfigKey);
29+
public string StartupType() => this.GetValue(StartupTypeConfigKey);
3030

31-
public string ApplicationName => this.GetValue(ApplicationNameConfigKey);
31+
public string ApplicationName() => this.GetValue(ApplicationNameConfigKey);
3232

33-
public string EnvironmentName => this.GetValue(EnvironmentNameConfigKey, "Test");
33+
public string EnvironmentName() => this.GetValue(EnvironmentNameConfigKey, "Test");
3434
}
3535
}

src/MyTested.AspNetCore.Mvc.Configuration/Internal/Configuration/TestConfiguration.cs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,48 @@
11
namespace MyTested.AspNetCore.Mvc.Internal.Configuration
22
{
3+
using System;
34
using System.Collections.Generic;
45
using Microsoft.Extensions.Configuration;
56

67
public class TestConfiguration : BaseConfiguration
78
{
89
private const string LicenseConfigKey = "License";
910
private const string LicensesConfigKey = "Licenses";
10-
11+
12+
private readonly IDictionary<Type, BaseConfiguration> configurationTypes;
13+
1114
private TestConfiguration(IConfiguration configuration)
1215
: base(configuration)
1316
{
14-
this.General = new GeneralTestConfiguration(this.Configuration);
15-
this.Controllers = new ControllersTestConfiguration(this.Configuration);
17+
this.configurationTypes = new Dictionary<Type, BaseConfiguration>();
1618
}
19+
20+
public GeneralTestConfiguration General()
21+
=> this.GetConfiguration(() => new GeneralTestConfiguration(this.Configuration));
1722

18-
public GeneralTestConfiguration General { get; private set; }
23+
public IEnumerable<string> Licenses()
24+
{
25+
var license = this.Configuration[LicenseConfigKey];
26+
if (license != null)
27+
{
28+
return new[] { license };
29+
}
1930

20-
public ControllersTestConfiguration Controllers { get; private set; }
31+
var licenses = new List<string>();
32+
this.Configuration.GetSection(LicensesConfigKey).Bind(licenses);
33+
return licenses;
34+
}
2135

22-
public IEnumerable<string> Licenses
36+
public TConfiguration GetConfiguration<TConfiguration>(Func<TConfiguration> configurationFactory)
37+
where TConfiguration : BaseConfiguration
2338
{
24-
get
39+
var typeOfConfiguration = typeof(TConfiguration);
40+
if (!this.configurationTypes.ContainsKey(typeOfConfiguration))
2541
{
26-
var license = this.Configuration[LicenseConfigKey];
27-
if (license != null)
28-
{
29-
return new[] { license };
30-
}
31-
32-
var licenses = new List<string>();
33-
this.Configuration.GetSection(LicensesConfigKey).Bind(licenses);
34-
return licenses;
42+
this.configurationTypes[typeOfConfiguration] = configurationFactory();
3543
}
44+
45+
return (TConfiguration)this.configurationTypes[typeOfConfiguration];
3646
}
3747

3848
public static TestConfiguration With(IConfiguration configuration)

src/MyTested.AspNetCore.Mvc.Controllers/Builders/Controllers/ControllerBuilder.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Components;
44
using Contracts.Controllers;
55
using Internal.Application;
6+
using Internal.Configuration;
67
using Internal.Contracts;
78
using Internal.TestContexts;
89
using Microsoft.AspNetCore.Mvc.Controllers;
@@ -24,7 +25,10 @@ public partial class ControllerBuilder<TController> : BaseComponentBuilder<TCont
2425
public ControllerBuilder(ControllerTestContext testContext)
2526
: base(testContext)
2627
{
27-
this.EnabledModelStateValidation = TestApplication.TestConfiguration.Controllers.ModelStateValidation;
28+
this.EnabledModelStateValidation = TestApplication
29+
.Configuration()
30+
.Controllers()
31+
.ModelStateValidation();
2832
}
2933

3034
public bool EnabledModelStateValidation { get; set; }
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ public ControllersTestConfiguration(IConfiguration configuration)
1212
this.Prefix = "Controllers";
1313
}
1414

15-
public bool ModelStateValidation => this.GetValue(ModelStateValidationConfigKey, true);
15+
public bool ModelStateValidation() => this.GetValue(ModelStateValidationConfigKey, true);
1616
}
1717
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace MyTested.AspNetCore.Mvc.Internal.Configuration
2+
{
3+
public static class TestConfigurationControllersExtensions
4+
{
5+
public static ControllersTestConfiguration Controllers(this TestConfiguration testConfiguration)
6+
=> testConfiguration.GetConfiguration(() => new ControllersTestConfiguration(testConfiguration.Configuration));
7+
}
8+
}

0 commit comments

Comments
 (0)