From dc7dd83203d76a36a9735334fd655be7b5951978 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Karel=20Frajt=C3=A1k?=
<1510452+kfrajtak@users.noreply.github.com>
Date: Mon, 16 Jun 2025 13:55:57 +0200
Subject: [PATCH] using Xunit test output helper for logging
---
.../WorkflowCore.Testing.csproj | 6 ++
src/WorkflowCore.Testing/WorkflowTest.cs | 10 +-
src/WorkflowCore.Testing/XUnitLogger.cs | 91 +++++++++++++++++++
.../Scenarios/DelayScenario.cs | 5 +-
.../Scenarios/MongoDelayScenario.cs | 3 +-
.../Scenarios/MysqlDelayScenario.cs | 5 +
.../Scenarios/OracleDelayScenario.cs | 7 +-
.../Scenarios/PostgresDelayScenario.cs | 7 +-
.../Scenarios/SqlServerDelayScenario.cs | 7 +-
.../Scenarios/SqliteDelayScenario.cs | 26 ++++++
10 files changed, 159 insertions(+), 8 deletions(-)
create mode 100644 src/WorkflowCore.Testing/XUnitLogger.cs
create mode 100644 test/WorkflowCore.Tests.Sqlite/Scenarios/SqliteDelayScenario.cs
diff --git a/src/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/src/WorkflowCore.Testing/WorkflowCore.Testing.csproj
index 6102c9892..2f52d6592 100644
--- a/src/WorkflowCore.Testing/WorkflowCore.Testing.csproj
+++ b/src/WorkflowCore.Testing/WorkflowCore.Testing.csproj
@@ -19,4 +19,10 @@
+
+
+ ..\..\..\..\..\.nuget\packages\xunit.abstractions\2.0.3\lib\netstandard2.0\xunit.abstractions.dll
+
+
+
diff --git a/src/WorkflowCore.Testing/WorkflowTest.cs b/src/WorkflowCore.Testing/WorkflowTest.cs
index bf0eb97ab..7b0746d31 100644
--- a/src/WorkflowCore.Testing/WorkflowTest.cs
+++ b/src/WorkflowCore.Testing/WorkflowTest.cs
@@ -7,6 +7,7 @@
using Microsoft.Extensions.Logging;
using WorkflowCore.Interface;
using WorkflowCore.Models;
+using Xunit.Abstractions;
namespace WorkflowCore.Testing
{
@@ -18,11 +19,16 @@ public abstract class WorkflowTest : IDisposable
protected IPersistenceProvider PersistenceProvider;
protected List UnhandledStepErrors = new List();
- protected virtual void Setup()
+ protected virtual void Setup(ITestOutputHelper testOutputHelper = null)
{
//setup dependency injection
IServiceCollection services = new ServiceCollection();
- services.AddLogging();
+ services.AddLogging(l => l.SetMinimumLevel(LogLevel.Trace));
+ services.AddSingleton(p => new XUnitLoggerProvider(testOutputHelper));
+ services.Add(ServiceDescriptor.Singleton());
+ services.Add(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(XUnitLogger<>)));
+ services.AddSingleton(sp => testOutputHelper);
+
ConfigureServices(services);
var serviceProvider = services.BuildServiceProvider();
diff --git a/src/WorkflowCore.Testing/XUnitLogger.cs b/src/WorkflowCore.Testing/XUnitLogger.cs
new file mode 100644
index 000000000..d160a0c55
--- /dev/null
+++ b/src/WorkflowCore.Testing/XUnitLogger.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Text;
+using Microsoft.Extensions.Logging;
+using Xunit.Abstractions;
+
+namespace WorkflowCore.Testing
+{
+ internal class XUnitLogger : ILogger
+ {
+ private readonly ITestOutputHelper _testOutputHelper;
+ private readonly string _categoryName;
+ private readonly LoggerExternalScopeProvider _scopeProvider;
+
+ public static ILogger CreateLogger(ITestOutputHelper testOutputHelper) =>
+ new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider(), "");
+
+ public static ILogger CreateLogger(ITestOutputHelper testOutputHelper) =>
+ new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider());
+
+ public XUnitLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider,
+ string categoryName)
+ {
+ _testOutputHelper = testOutputHelper;
+ _scopeProvider = scopeProvider;
+ _categoryName = categoryName;
+ }
+
+ public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
+
+ public IDisposable BeginScope(TState state) => _scopeProvider.Push(state);
+
+ public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception,
+ Func formatter)
+ {
+ if (_testOutputHelper == null) return;
+ var sb = new StringBuilder();
+ sb.Append(DateTime.Now.ToString("HH:mm:ss.fff"))
+ .Append(" ")
+ .Append(GetLogLevelString(logLevel))
+ .Append(" [").Append(_categoryName).Append("] ")
+ .Append(formatter(state, exception));
+
+ if (exception != null)
+ {
+ sb.Append('\n').Append(exception);
+ }
+
+ // Append scopes
+ _scopeProvider.ForEachScope((scope, s) =>
+ {
+ s.Append("\n => ");
+ s.Append(scope);
+ }, sb);
+
+ _testOutputHelper.WriteLine(sb.ToString());
+ }
+
+ private static string GetLogLevelString(LogLevel logLevel)
+ {
+ return logLevel.ToString().ToUpper();
+ }
+ }
+
+ internal sealed class XUnitLogger : XUnitLogger, ILogger
+ {
+ public XUnitLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider)
+ : base(testOutputHelper, scopeProvider, typeof(T).FullName)
+ {
+ }
+ }
+
+ internal sealed class XUnitLoggerProvider : ILoggerProvider
+ {
+ private readonly ITestOutputHelper _testOutputHelper;
+ private readonly LoggerExternalScopeProvider _scopeProvider = new LoggerExternalScopeProvider();
+
+ public XUnitLoggerProvider(ITestOutputHelper testOutputHelper)
+ {
+ _testOutputHelper = testOutputHelper;
+ }
+
+ public ILogger CreateLogger(string categoryName)
+ {
+ return new XUnitLogger(_testOutputHelper, _scopeProvider, categoryName);
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs
index 704b27d79..e5402be0c 100644
--- a/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs
+++ b/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs
@@ -4,6 +4,7 @@
using Xunit;
using FluentAssertions;
using WorkflowCore.Testing;
+using Xunit.Abstractions;
namespace WorkflowCore.IntegrationTests.Scenarios
{
@@ -31,9 +32,9 @@ public class MyDataClass
public class DelayScenario : WorkflowTest
{
- public DelayScenario()
+ public DelayScenario(ITestOutputHelper testOutputHelper)
{
- Setup();
+ Setup(testOutputHelper);
}
[Fact]
diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs
index 45aca549f..b5a1d572b 100644
--- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs
+++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs
@@ -3,13 +3,14 @@
using MongoDB.Bson.Serialization;
using WorkflowCore.IntegrationTests.Scenarios;
using Xunit;
+using Xunit.Abstractions;
namespace WorkflowCore.Tests.MongoDB.Scenarios
{
[Collection("Mongo collection")]
public class MongoDelayScenario : DelayScenario
{
- public MongoDelayScenario() : base()
+ public MongoDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
BsonClassMap.RegisterClassMap(map => map.AutoMap());
}
diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs
index deed80f2b..68c247cf6 100644
--- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs
+++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs
@@ -2,12 +2,17 @@
using System;
using WorkflowCore.IntegrationTests.Scenarios;
using Xunit;
+using Xunit.Abstractions;
namespace WorkflowCore.Tests.MySQL.Scenarios
{
[Collection("Mysql collection")]
public class MysqlDelayScenario : DelayScenario
{
+ public MysqlDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
+ {
+ }
+
protected override void ConfigureServices(IServiceCollection services)
{
services.AddWorkflow(cfg =>
diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs
index 55062f0c3..325106eb6 100644
--- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs
+++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs
@@ -5,12 +5,17 @@
using WorkflowCore.Tests.Oracle;
using Xunit;
+using Xunit.Abstractions;
namespace WorkflowCore.Tests.Oracle.Scenarios
{
[Collection("Oracle collection")]
public class OracleDelayScenario : DelayScenario
- {
+ {
+ public OracleDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
+ {
+ }
+
protected override void ConfigureServices(IServiceCollection services)
{
services.AddWorkflow(cfg =>
diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs
index 649632ac5..2d2814d07 100644
--- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs
+++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs
@@ -2,12 +2,17 @@
using Microsoft.Extensions.DependencyInjection;
using WorkflowCore.IntegrationTests.Scenarios;
using Xunit;
+using Xunit.Abstractions;
namespace WorkflowCore.Tests.PostgreSQL.Scenarios
{
[Collection("Postgres collection")]
public class PostgresDelayScenario : DelayScenario
- {
+ {
+ public PostgresDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
+ {
+ }
+
protected override void ConfigureServices(IServiceCollection services)
{
services.AddWorkflow(cfg =>
diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs
index 5e623c1db..52b17fc6a 100644
--- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs
+++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs
@@ -2,12 +2,17 @@
using Microsoft.Extensions.DependencyInjection;
using WorkflowCore.IntegrationTests.Scenarios;
using Xunit;
+using Xunit.Abstractions;
namespace WorkflowCore.Tests.SqlServer.Scenarios
{
[Collection("SqlServer collection")]
public class SqlServerDelayScenario : DelayScenario
- {
+ {
+ public SqlServerDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
+ {
+ }
+
protected override void ConfigureServices(IServiceCollection services)
{
services.AddWorkflow(cfg =>
diff --git a/test/WorkflowCore.Tests.Sqlite/Scenarios/SqliteDelayScenario.cs b/test/WorkflowCore.Tests.Sqlite/Scenarios/SqliteDelayScenario.cs
new file mode 100644
index 000000000..f79dbd202
--- /dev/null
+++ b/test/WorkflowCore.Tests.Sqlite/Scenarios/SqliteDelayScenario.cs
@@ -0,0 +1,26 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using WorkflowCore.IntegrationTests.Scenarios;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace WorkflowCore.Tests.Sqlite.Scenarios
+{
+ [Collection("Sqlite collection")]
+ public class SqliteDelayScenario : DelayScenario
+ {
+ public SqliteDelayScenario(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
+ {
+ }
+
+ protected override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddWorkflow(cfg =>
+ {
+ cfg.UseSqlite($"Data Source=wfc-tests-{DateTime.Now.Ticks}.db;", true);
+ cfg.UsePollInterval(TimeSpan.FromSeconds(2));
+ });
+ }
+ }
+}
+