diff --git a/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs b/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs index 8bfc90d..d40ea4c 100644 --- a/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs +++ b/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -17,6 +16,8 @@ public class DbContextBuilder where T : DbContext private ILoggerFactory? _loggerFactory; private string _sqliteConnectionString = "Data Source=:memory:"; + + private string _databaseName = "TestDatabase"; public DbContextBuilder WithLoggerProvider(ILoggerProvider loggerProvider) { @@ -36,12 +37,30 @@ public DbContextBuilder WithService(Action conf return this; } + public DbContextBuilder WithLoggerFactory(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + return this; + } + public DbContextBuilder WithOptions(Action> configureOptions) { _configuredOptions = configureOptions as Action; return this; } + public DbContextBuilder WithDatabaseName(string databaseName) + { + _databaseName = databaseName; + return this; + } + + public DbContextBuilder WithRandomDatabaseName() + { + _databaseName = Guid.NewGuid().ToString(); + return this; + } + public T Build() { _serviceCollection.AddDbContext(OptionsAction); diff --git a/Frank.Testing.Logging/LoggingBuilderExtensions.cs b/Frank.Testing.Logging/LoggingBuilderExtensions.cs index 736375d..52f0c24 100644 --- a/Frank.Testing.Logging/LoggingBuilderExtensions.cs +++ b/Frank.Testing.Logging/LoggingBuilderExtensions.cs @@ -19,7 +19,6 @@ public static class LoggingBuilderExtensions /// The modified ILoggingBuilder with the test logging added. public static ILoggingBuilder AddPulseFlowTestLoggingProvider(this ILoggingBuilder builder, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) { - builder.ClearProviders(); builder.AddPulseFlow(); builder.Services.AddSingleton(outputHelper); builder.Services.Configure(options => @@ -29,4 +28,21 @@ public static ILoggingBuilder AddPulseFlowTestLoggingProvider(this ILoggingBuild builder.Services.AddPulseFlow(flowBuilder => flowBuilder.AddFlow()); return builder; } -} \ No newline at end of file + + public static ILoggingBuilder AddSimpleTestLoggingProvider(this ILoggingBuilder builder, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) + { + builder.Services.AddSingleton(outputHelper); + builder.Services.Configure(options => + { + options.MinLevel = logLevel; + }); + builder.AddProvider(); + return builder; + } + + public static ILoggingBuilder AddProvider(this ILoggingBuilder builder) where T : class, ILoggerProvider + { + builder.Services.AddSingleton(); + return builder; + } +} diff --git a/Frank.Testing.Logging/ServiceCollectionExtensions.cs b/Frank.Testing.Logging/ServiceCollectionExtensions.cs index 9ef25e3..e04386f 100644 --- a/Frank.Testing.Logging/ServiceCollectionExtensions.cs +++ b/Frank.Testing.Logging/ServiceCollectionExtensions.cs @@ -23,4 +23,21 @@ public static IServiceCollection AddTestLogging(this IServiceCollection services services.AddLogging(builder => builder.AddPulseFlowTestLoggingProvider(outputHelper, logLevel)); return services; } + + /// + /// Adds simple test logging to the IServiceCollection. + /// + /// The IServiceCollection to add the test logging to. + /// The ITestOutputHelper to redirect the logging output to. + /// The log level to use for the test logging. Default is LogLevel.Debug. + /// The modified IServiceCollection with the test logging added. + public static IServiceCollection AddSimpleTestLogging(this IServiceCollection services, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) + { + services.Configure(options => + { + options.MinLevel = logLevel; + }); + services.AddLogging(builder => builder.AddSimpleTestLoggingProvider(outputHelper, logLevel)); + return services; + } } \ No newline at end of file diff --git a/Frank.Testing.Logging/SimpleTestLogger.cs b/Frank.Testing.Logging/SimpleTestLogger.cs index 1119b31..fa185fe 100644 --- a/Frank.Testing.Logging/SimpleTestLogger.cs +++ b/Frank.Testing.Logging/SimpleTestLogger.cs @@ -11,8 +11,6 @@ public class SimpleTestLogger(ITestOutputHelper outputHelper, LogLevel logLev public class SimpleTestLogger(ITestOutputHelper outputHelper, LogLevel level, string categoryName) : ILogger { - private string _categoryName = categoryName; - public IDisposable? BeginScope(TState state) where TState : notnull => new PulseFlowLoggerScope(state); @@ -23,6 +21,6 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except if (logLevel < level) return; - outputHelper.WriteLine(new LogPulse(logLevel, eventId, exception, _categoryName, formatter.Invoke(state, exception), state as IReadOnlyList>).ToString()); + outputHelper.WriteLine(new LogPulse(logLevel, eventId, exception, categoryName, formatter.Invoke(state, exception), state as IReadOnlyList>).ToString()); } } \ No newline at end of file diff --git a/Frank.Testing.Logging/SimpleTestLoggerProvider.cs b/Frank.Testing.Logging/SimpleTestLoggerProvider.cs new file mode 100644 index 0000000..3e5b0bb --- /dev/null +++ b/Frank.Testing.Logging/SimpleTestLoggerProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Concurrent; + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +using Xunit.Abstractions; + +namespace Frank.Testing.Logging; + +public class SimpleTestLoggerProvider(ITestOutputHelper outputHelper, IOptionsMonitor options) : ILoggerProvider +{ + private readonly ConcurrentDictionary _loggers = new(); + + /// + public void Dispose() + { + _loggers.Clear(); + } + + /// + public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, new SimpleTestLogger(outputHelper, options.CurrentValue.MinLevel, categoryName)); +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj b/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj new file mode 100644 index 0000000..76ed464 --- /dev/null +++ b/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/Frank.Testing.TestBases/HostApplicationTestBase.cs b/Frank.Testing.TestBases/HostApplicationTestBase.cs new file mode 100644 index 0000000..a9bb85f --- /dev/null +++ b/Frank.Testing.TestBases/HostApplicationTestBase.cs @@ -0,0 +1,43 @@ +using Frank.Testing.Logging; + +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit; +using Xunit.Abstractions; + +namespace Frank.Testing.TestBases; + +public abstract class HostApplicationTestBase : IAsyncLifetime +{ + private readonly HostApplicationBuilder _hostApplicationBuilder; + private IHost? _host; + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private bool _initialized = false; + + protected HostApplicationTestBase(ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Information) + { + _hostApplicationBuilder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings()); + _hostApplicationBuilder.Logging.AddSimpleTestLoggingProvider(outputHelper, logLevel); + } + + public IServiceProvider Services => (_initialized ? _host?.Services : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + + protected virtual async Task SetupAsync(HostApplicationBuilder builder) => await Task.CompletedTask; + + public async Task InitializeAsync() + { + await SetupAsync(_hostApplicationBuilder); + _host = _hostApplicationBuilder.Build(); + await _host.StartAsync(_cancellationTokenSource.Token); + _initialized = true; + } + + public async Task DisposeAsync() + { + await _cancellationTokenSource.CancelAsync(); + await _host?.StopAsync()!; + await _host.WaitForShutdownAsync(); + _host.Dispose(); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/WebHostApplicationTestBase.cs b/Frank.Testing.TestBases/WebHostApplicationTestBase.cs new file mode 100644 index 0000000..926d1d7 --- /dev/null +++ b/Frank.Testing.TestBases/WebHostApplicationTestBase.cs @@ -0,0 +1,46 @@ +using Frank.Testing.Logging; + +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit; +using Xunit.Abstractions; + +namespace Frank.Testing.TestBases; + +public abstract class WebHostApplicationTestBase : IAsyncLifetime +{ + private readonly IWebHostBuilder _hostApplicationBuilder; + private IWebHost? _host; + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private bool _initialized = false; + + protected WebHostApplicationTestBase(ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Information) + { + _hostApplicationBuilder = WebHost.CreateDefaultBuilder(); + _hostApplicationBuilder.ConfigureLogging(logging => logging.AddSimpleTestLoggingProvider(outputHelper, logLevel)); + } + + public IServiceProvider Services => (_initialized ? _host?.Services : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + + protected virtual async Task SetupAsync(IWebHostBuilder builder) => await Task.CompletedTask; + + protected HttpClient TestClient => (_initialized ? _host?.CreateTestClient() : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + protected IEnumerable GetServerEndpoints() => (_initialized ? _host?.GetServerEndpoints() : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + public async Task InitializeAsync() + { + await SetupAsync(_hostApplicationBuilder); + _host = _hostApplicationBuilder.Build(); + await _host.StartAsync(_cancellationTokenSource.Token); + _initialized = true; + } + + public async Task DisposeAsync() + { + await _cancellationTokenSource.CancelAsync(); + await _host?.StopAsync()!; + await _host.WaitForShutdownAsync(); + _host.Dispose(); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/WebHostExtensions.cs b/Frank.Testing.TestBases/WebHostExtensions.cs new file mode 100644 index 0000000..80ae8f6 --- /dev/null +++ b/Frank.Testing.TestBases/WebHostExtensions.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Frank.Testing.TestBases; + +public static class WebHostExtensions +{ + public static HttpClient CreateTestClient(this IWebHost host) + { + var baseAddress = host.ServerFeatures.Get()?.Addresses.First(); + + return new HttpClient + { + BaseAddress = new Uri(baseAddress ?? throw new InvalidOperationException("The host has not been initialized yet."), UriKind.Absolute) + }; + } + + public static IEnumerable GetServerEndpoints(this IWebHost host) + { + return host.Services.GetServices().SelectMany(x => x.Endpoints).Select(x => x.DisplayName); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs index 5e83731..bb29e2c 100644 --- a/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs +++ b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs @@ -63,11 +63,4 @@ public static void WriteCSharp(this ITestOutputHelper outputHelper, IEnumerab SortDirection = ListSortDirection.Ascending, MaxDepth = 64, }; -} - -public enum CSharpDumpType -{ - Variable, - Class, - IEnumerable } \ No newline at end of file diff --git a/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs index 19c05b5..38c290f 100644 --- a/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs +++ b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs @@ -13,7 +13,7 @@ public static void WriteXml(this ITestOutputHelper outputHelper, T source, Xm using var textWriter = new StringWriter(); using var xmlWriter = XmlWriter.Create(textWriter, settings); var xmlSerializer = new XmlSerializerFactory().CreateSerializer(typeof(T)); - xmlSerializer.Serialize(xmlWriter, source); + xmlSerializer.Serialize(xmlWriter, source, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })); outputHelper.WriteLine(textWriter.ToString()); } @@ -24,6 +24,6 @@ public static void WriteXml(this ITestOutputHelper outputHelper, T source, Xm NewLineChars = "\n", NewLineHandling = NewLineHandling.Replace, OmitXmlDeclaration = false, - Encoding = new UTF8Encoding(false), + Encoding = new UTF8Encoding(false) }; } \ No newline at end of file diff --git a/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs b/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs index 5904d46..73bc729 100644 --- a/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs +++ b/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs @@ -1,6 +1,4 @@ -using Frank.PulseFlow; -using Frank.PulseFlow.Logging; -using Frank.Testing.EntityFrameworkCore; +using Frank.Testing.EntityFrameworkCore; using Frank.Testing.Logging; using Frank.Testing.Tests.TestingInfrastructure; @@ -10,6 +8,8 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using NSubstitute; + using Xunit.Abstractions; namespace Frank.Testing.Tests.EntityFramworkCoreTests; @@ -19,7 +19,10 @@ public class DbContextBuilderTests(ITestOutputHelper outputHelper) [Fact] public void Build_WithLoggerProvider_UsesLoggerProvider() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .Build(); dbContext.Database.EnsureCreated(); dbContext.Database.ExecuteSqlRaw("SELECT 1"); @@ -29,7 +32,10 @@ public void Build_WithLoggerProvider_UsesLoggerProvider() [Fact] public void Build_WithService_UsesService() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithService(services => services.AddSingleton()) .Build(); Assert.NotNull(dbContext.GetService()); @@ -38,7 +44,10 @@ public void Build_WithService_UsesService() [Fact] public void Build_WithOptions_UsesOptions() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithOptions(options => options.UseSqlite("Data Source=:memory:")) .Build(); dbContext.Database.EnsureCreated(); @@ -49,8 +58,10 @@ public void Build_WithOptions_UsesOptions() [Fact] public void Build_WithLoggerProviderAndService_UsesLoggerProviderAndService() { - var conduit = new TestConduit(); + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithSqliteConnectionString("Data Source=MyTestDatabase.db") .WithService(services => services.AddSingleton()) .Build(); @@ -60,24 +71,13 @@ public void Build_WithLoggerProviderAndService_UsesLoggerProviderAndService() dbContext.Dispose(); } - public class TestService : ITestService - { - public async Task DoSomethingAsync() - { - await Task.CompletedTask; - } - } - - public interface ITestService - { - Task DoSomethingAsync(); - } - [Fact] public void Build_WithLoggerProviderAndOptions_UsesLoggerProviderAndOptions() { - var conduit = new TestConduit(); + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithSqliteConnectionString("Data Source=MyTestDatabase.db") .Build(); dbContext.Database.EnsureCreated(); @@ -86,17 +86,20 @@ public void Build_WithLoggerProviderAndOptions_UsesLoggerProviderAndOptions() dbContext.Database.ExecuteSqlRaw("SELECT 1"); dbContext.Dispose(); - outputHelper.WriteJson(conduit.Logs); } - public class TestConduit : IConduit + + + public class TestService : ITestService { - public async Task SendAsync(IPulse message) + public async Task DoSomethingAsync() { await Task.CompletedTask; - Logs.Add(message as LogPulse ?? throw new InvalidOperationException()); } - - public List Logs { get; } = new(); + } + + public interface ITestService + { + Task DoSomethingAsync(); } } diff --git a/Frank.Testing.Tests/Frank.Testing.Tests.csproj b/Frank.Testing.Tests/Frank.Testing.Tests.csproj index 0d61dde..9e82f46 100644 --- a/Frank.Testing.Tests/Frank.Testing.Tests.csproj +++ b/Frank.Testing.Tests/Frank.Testing.Tests.csproj @@ -30,6 +30,8 @@ + + diff --git a/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs b/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs new file mode 100644 index 0000000..08431a3 --- /dev/null +++ b/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs @@ -0,0 +1,54 @@ +using FluentAssertions; + +using Frank.Testing.TestBases; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests.TestBases; + +public class HostApplicationTestBaseTests(ITestOutputHelper outputHelper) : HostApplicationTestBase(outputHelper) +{ + protected override Task SetupAsync(HostApplicationBuilder builder) + { + builder.Services.AddHostedService(); + builder.Services.AddSingleton(); + return Task.CompletedTask; + } + + [Fact] + public async Task Test() + { + await Task.Delay(2500); + } + + [Fact] + public void Test2() + { + var service = Services.GetService(); + service.Should().NotBeNull(); + } + + public class TestService2 + { + public TestService2(ILogger logger) + { + logger.LogInformation("Foo"); + } + } + + public class TestService(ILogger logger) : BackgroundService + { + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(1000, stoppingToken); + logger.LogInformation("Hello, world!"); + } + } + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs b/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs new file mode 100644 index 0000000..07aa9a1 --- /dev/null +++ b/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs @@ -0,0 +1,74 @@ +using System.Net; + +using FluentAssertions; + +using Frank.Testing.TestBases; + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests.TestBases; + +public class WebHostApplicationTestBaseTests(ITestOutputHelper outputHelper) : WebHostApplicationTestBase(outputHelper) +{ + protected override Task SetupAsync(IWebHostBuilder builder) + { + builder.ConfigureServices((context, services) => + { + services.AddControllersWithViews(); + }); + builder.Configure((context, app) => + { + app.UseRouting(); + app.UseEndpoints(endpoints => + { + // endpoints.MapHealthChecks("/health"); + endpoints.MapControllers(); + endpoints.MapGet("/test1", async httpContext => + { + await httpContext.Response.WriteAsync("Test1 endpoint"); + }); + + }); + }); + return Task.CompletedTask; + } + + [Fact] + public async Task Test() + { + var response = await TestClient.GetAsync("/test1"); + var content = await response.Content.ReadAsStringAsync(); + content.Should().Be("Test1 endpoint"); + } + + [Fact] + public async Task Test2() + { + var response = await TestClient.GetAsync("/test2"); + var content = await response.Content.ReadAsStringAsync(); + content.Should().Be("Test2 endpoint"); + } + + [Fact] + public void Test3() + { + var endpoints = GetServerEndpoints(); + // endpoints = Enumerable.Empty(); + outputHelper.WriteLine(string.Join(Environment.NewLine, endpoints)); + } +} + +public class MyController : ControllerBase +{ + [HttpGet("/test2")] + public IActionResult Test2() + { + return Ok("Test2 endpoint"); + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs b/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs index 63a668b..ae94b03 100644 --- a/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs +++ b/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs @@ -24,7 +24,10 @@ private IHostBuilder CreateHostBuilder() return Host.CreateDefaultBuilder() .ConfigureLogging(logging => { - logging.AddPulseFlowTestLoggingProvider(outputHelper, LogLevel.Information); + logging + .AddPulseFlowTestLoggingProvider(outputHelper, LogLevel.Information) + // .AddSimpleTestLoggingProvider(outputHelper, LogLevel.Information) + ; }) .ConfigureServices((context, services) => { @@ -37,9 +40,10 @@ private class MyService(ILogger logger) : BackgroundService protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var scope = logger.BeginScope("Titans are {Description}", "awesome"); + var counter = 0; while (!stoppingToken.IsCancellationRequested) { - logger.LogInformation("Hello from MyService"); + logger.LogInformation("Hello from MyService {Counter}", counter++); await Task.Delay(100, stoppingToken); } } diff --git a/Frank.Testing.sln b/Frank.Testing.sln index 58df3c9..e7e2343 100644 --- a/Frank.Testing.sln +++ b/Frank.Testing.sln @@ -26,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.EntityFramewo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.Testcontainers", "Frank.Testing.Testcontainers\Frank.Testing.Testcontainers.csproj", "{13E7B32B-CBA5-4BA3-854B-697B835796F7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.TestBases", "Frank.Testing.TestBases\Frank.Testing.TestBases.csproj", "{33258CFE-D91E-42A4-80CB-A47CB954A53A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -59,5 +61,9 @@ Global {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Release|Any CPU.Build.0 = Release|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/README.md b/README.md index d7eeef0..8602eff 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ A set of nugets to allow for easier testing of dotnet code using xUnit ___ [![GitHub License](https://img.shields.io/github/license/frankhaugen/Frank.Testing)](LICENSE) -[![NuGet](https://img.shields.io/nuget/v/Frank.Testing.svg)](https://www.nuget.org/packages/Frank.Testing) -[![NuGet](https://img.shields.io/nuget/dt/Frank.Testing.svg)](https://www.nuget.org/packages/Frank.Testing) +[![NuGet](https://img.shields.io/nuget/v/Frank.Testing.Logging.svg)](https://www.nuget.org/packages/Frank.Testing.Logging) +[![NuGet](https://img.shields.io/nuget/dt/Frank.Testing.Logging.svg)](https://www.nuget.org/packages/Frank.Testing.Logging) ![GitHub contributors](https://img.shields.io/github/contributors/frankhaugen/Frank.Testing) ![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/frankhaugen/Frank.Testing)