Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .nuget/Codebelt.Extensions.Xunit.App/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
## About

An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof.
Your ideal companion for .NET 8 and .NET 6.
An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET.

It is, by heart, free, flexible and built to extend and boost your agile codebelt.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
## About

An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof.
Your ideal companion for .NET 8 and .NET 6.
An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET.

It is, by heart, free, flexible and built to extend and boost your agile codebelt.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Availability: .NET 8, .NET 6 and .NET Standard 2.0

# New Features
- ADDED ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService
- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T}
- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor, AddXunitTestOutputHelperAccessor{T} and an overload of AddXunitTestLogging

Version 8.3.2
Availability: .NET 8, .NET 6 and .NET Standard 2.0
Expand Down
3 changes: 1 addition & 2 deletions .nuget/Codebelt.Extensions.Xunit.Hosting/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
## About

An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof.
Your ideal companion for .NET 8, .NET 7, .NET 6, .NET Standard 2 and .NET Framework 4.6.2 and newer.
An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET.

It is, by heart, free, flexible and built to extend and boost your agile codebelt.

Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba
- ITestOutputHelperAccessor interface in the Codebelt.Extensions.Xunit namespace that provides access to the ITestOutputHelper instance
- TestOutputHelperAccessor class in the Codebelt.Extensions.Xunit namespace that provides a default implementation of the ITestOutputHelper interface
- ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService
- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was extended with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T}
- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was extended with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor, AddXunitTestOutputHelperAccessor{T} and an overload of AddXunitTestLogging

### Changed

Expand Down
4 changes: 3 additions & 1 deletion src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using System.Collections;
using System.Linq;
using Cuemon;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;

namespace Codebelt.Extensions.Xunit.Hosting
{
Expand All @@ -12,7 +14,7 @@ namespace Codebelt.Extensions.Xunit.Hosting
public static class LoggerExtensions
{
/// <summary>
/// Returns the associated <see cref="ITestStore{T}"/> that is provided when settings up services from <see cref="ServiceCollectionExtensions.AddXunitTestLogging"/>.
/// Returns the associated <see cref="ITestStore{T}"/> that is provided when settings up services from either <see cref="ServiceCollectionExtensions.AddXunitTestLogging(IServiceCollection,ITestOutputHelper,LogLevel)"/> or <see cref="ServiceCollectionExtensions.AddXunitTestLogging(IServiceCollection,ITestOutputHelperAccessor,LogLevel)"/>.
/// </summary>
/// <param name="logger">The <see cref="ILogger{TCategoryName}"/> from which to retrieve the <see cref="ITestStore{T}"/>.</param>
/// <returns>Returns an implementation of <see cref="ITestStore{T}"/> with all logged entries expressed as <see cref="XunitTestLoggerEntry"/>.</returns>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,38 @@ public static IServiceCollection AddXunitTestLogging(this IServiceCollection ser
});
return services;
}

/// <summary>
/// Adds a unit test optimized implementation of output logging to the <paramref name="services"/> collection.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to extend.</param>
/// <param name="accessor">The <see cref="ITestOutputHelperAccessor"/> that provides access to the output for the logging.</param>
/// <param name="minimumLevel">The <see cref="LogLevel"/> that specifies the minimum level to include for the logging.</param>
/// <returns>A reference to <paramref name="services" /> so that additional configuration calls can be chained.</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> cannot be null -or-
/// <paramref name="accessor"/> cannot be null.
/// </exception>
public static IServiceCollection AddXunitTestLogging(this IServiceCollection services, ITestOutputHelperAccessor accessor, LogLevel minimumLevel = LogLevel.Trace)
{
Validator.ThrowIfNull(services);
Validator.ThrowIfNull(accessor);
services.AddLogging(builder =>
{
builder.SetMinimumLevel(minimumLevel);
builder.AddProvider(new XunitTestLoggerProvider(accessor));
});
return services;
}

/// <summary>
/// Adds a default implementation of <see cref="ITestOutputHelperAccessor"/> to the <paramref name="services"/> collection.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to extend.</param>
/// <returns>A reference to <paramref name="services" /> so that additional configuration calls can be chained.</returns>
public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceCollection services)
public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor(this IServiceCollection services)
{
services.AddXunitTestOutputHelperAccessor<TestOutputHelperAccessor>();
services.AddXunitTestLoggingOutputHelperAccessor<TestOutputHelperAccessor>();
return services;
}

Expand All @@ -54,7 +77,7 @@ public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceC
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> cannot be null.
/// </exception>
public static IServiceCollection AddXunitTestOutputHelperAccessor<T>(this IServiceCollection services) where T : class, ITestOutputHelperAccessor
public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor<T>(this IServiceCollection services) where T : class, ITestOutputHelperAccessor
{
Validator.ThrowIfNull(services);
services.AddSingleton<ITestOutputHelperAccessor, T>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public async Task ShouldHaveResultOfBoolMiddlewareInBody()

Assert.Equal("Hello awesome developers!", context!.Response.Body.ToEncodedString(o => o.LeaveOpen = true));

var logger = _pipeline.ApplicationServices.GetRequiredService<ILogger<AspNetCoreHostTestTest>>();
logger.LogInformation("Hello from {0}", nameof(ShouldHaveResultOfBoolMiddlewareInBody));

await pipeline(context);

Assert.Equal("A:True, B:False, C:True, D:False, E:True, F:False", context.Response.Body.ToEncodedString());
Expand Down Expand Up @@ -68,8 +71,8 @@ public override void ConfigureServices(IServiceCollection services)
o.C = true;
o.E = true;
});
services.AddXunitTestOutputHelperAccessor();
services.AddXunitTestLogging(TestOutput);
services.AddXunitTestLoggingOutputHelperAccessor();
services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput));
Comment on lines +74 to +75
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Update remaining test files to use the new Xunit test logging approach

The new Xunit test logging approach is not consistently applied across all test files. Two files still use the old approach:

  • test/Codebelt.Extensions.Xunit.Hosting.Tests/ServiceCollectionExtensions.cs
  • test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs

Please update these files to use the new approach, following the pattern in AspNetCoreHostTestTest.cs:

services.AddXunitTestLoggingOutputHelperAccessor();
services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput));

Additionally, perform a manual review of other test files to ensure complete migration to the new approach, as there might be files that weren't caught by our search.

Analysis chain

Verify the consistency of the new Xunit test logging approach.

The changes in the service configuration for adding Xunit test logging look good. The new approach using AddXunitTestLoggingOutputHelperAccessor and AddXunitTestLogging with a TestOutputHelperAccessor instance seems to be an improvement in integrating with the Xunit logging framework.

To ensure consistency, please verify that this new approach is applied consistently throughout the test project. You can use the following script to search for other test files and check if they need to be updated:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistency of the new Xunit test logging approach in other test files.

# Test: Search for other test files. Expect: Occurrences of test files that may need to be updated.
fd --type file --extension cs --exclude Program.cs --exec rg --type cs $'services\.AddXunitTestOutputHelperAccessor\(\);|services\.AddXunitTestLogging\(TestOutput\);'

Length of output: 284


Script:

#!/bin/bash
# Description: Identify files with old and new Xunit test logging approaches and provide context.

# Search for files with the old approach
echo "Files with old approach:"
rg --type cs -n "services\.AddXunitTestLogging\(TestOutput\);" -C 2

echo "\nFiles with new approach:"
rg --type cs -n "services\.AddXunitTestLoggingOutputHelperAccessor\(\);" -C 2

echo "\nFiles with TestOutputHelperAccessor:"
rg --type cs -n "new TestOutputHelperAccessor\(TestOutput\)" -C 2

Length of output: 2894

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Cuemon.AspNetCore" Version="8.3.2" />
<PackageReference Include="Cuemon.Extensions.AspNetCore" Version="8.3.2" />
<PackageReference Include="Cuemon.Extensions.IO" Version="8.3.2" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Cuemon.AspNetCore.Diagnostics;
using Cuemon.Extensions.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
using Xunit.Abstractions;

Expand All @@ -12,13 +20,13 @@ public WebHostTestFactoryTest(ITestOutputHelper output) : base(output)
}

[Fact]
public void CreateMiddlewareTest_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest()
public void Create_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest()
{
Type sut1 = GetType();
string sut2 = null;
var middleware = WebHostTestFactory.Create(Assert.NotNull, Assert.NotNull, host =>
{
host.ConfigureAppConfiguration((context, configuration) =>
host.ConfigureAppConfiguration((context, _) =>
{
sut2 = context.HostingEnvironment.ApplicationName;
});
Expand All @@ -29,11 +37,11 @@ public void CreateMiddlewareTest_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTe
}

[Fact]
public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly()
public Task RunAsync_ShouldHaveApplicationNameEqualToThisAssembly()
{
return WebHostTestFactory.RunAsync(Assert.NotNull, Assert.NotNull, host =>
{
host.ConfigureAppConfiguration((context, configuration) =>
host.ConfigureAppConfiguration((context, _) =>
{
TestOutput.WriteLine(context.HostingEnvironment.ApplicationName);
Assert.Equal(GetType().Assembly.GetName().Name, context.HostingEnvironment.ApplicationName);
Expand All @@ -42,7 +50,7 @@ public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly()
}

[Fact]
public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext()
public Task RunWithHostBuilderContextAsync_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext()
{
return WebHostTestFactory.RunWithHostBuilderContextAsync((context, app) =>
{
Expand All @@ -69,5 +77,38 @@ public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly_WithH
});
});
}

[Fact]
public async Task RunAsync_ShouldWorkWithXunitTestLogging()
{
using var response = await WebHostTestFactory.RunAsync(
services =>
{
services.AddXunitTestLogging(TestOutput);
services.AddServerTiming(o => o.SuppressHeaderPredicate = _ => false);
}
, app =>
{
app.UseServerTiming();
app.Use(async (context, next) =>
{
var sw = Stopwatch.StartNew();
context.Response.OnStarting(() =>
{
sw.Stop();
context.RequestServices.GetRequiredService<IServerTiming>().AddServerTiming("use-middleware", sw.Elapsed);
return Task.CompletedTask;
});
await next(context).ConfigureAwait(false);
});
app.Run(context =>
{
Thread.Sleep(400);
return context.Response.WriteAsync("Hello World!");
});
}).ConfigureAwait(false);

Assert.StartsWith("use-middleware;dur=", response.Headers.Single(kvp => kvp.Key == ServerTiming.HeaderName).Value.FirstOrDefault());
}
}
}