Skip to content

Commit

Permalink
feature: logic for ef core smoke testing (#1557)
Browse files Browse the repository at this point in the history
* smoke test import

* more prep on efcore smoke tests

* clean up smoke test wrapper
  • Loading branch information
dpvreony authored Dec 8, 2023
1 parent 057dfbe commit 8022bac
Show file tree
Hide file tree
Showing 8 changed files with 387 additions and 2 deletions.
22 changes: 20 additions & 2 deletions src/Whipstaff.Core/Logging/EventIdFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,30 @@ public static class EventIdFactory
/// Gets the Event Id for the Middleware Exception event.
/// </summary>
/// <returns>Event Id.</returns>
public static EventId MiddlewareException() => new(7, "Middleware Exception");
public static EventId MiddlewareException() => new(8, "Middleware Exception");

/// <summary>
/// Gets the Event Id for the Middleware Finished event.
/// </summary>
/// <returns>Event Id.</returns>
public static EventId MiddlewareFinished() => new(7, "Middleware Finished");
public static EventId MiddlewareFinished() => new(9, "Middleware Finished");

/// <summary>
/// Gets the Event Id for the "Starting Test Of DbSet" event which is used in the EF Core smoke test process.
/// </summary>
/// <returns>Event Id.</returns>
public static EventId TestOfDbSetStarting() => new(10, "Starting Test Of DbSet");

/// <summary>
/// Gets the Event Id for the "Test Of DbSet Failed" event which is used in the EF Core smoke test process.
/// </summary>
/// <returns>Event Id.</returns>
public static EventId TestOfDbSetFailed() => new(11, "Test Of DbSet Failed");

/// <summary>
/// Gets the Event Id for the "Completed Test Of DbSet" event which is used in the EF Core smoke test process.
/// </summary>
/// <returns>Event Id.</returns>
public static EventId TestOfDbSetCompleted() => new(11, "Test Of DbSet Completed");
}
}
59 changes: 59 additions & 0 deletions src/Whipstaff.EntityFramework/SmokeTest/AbstractDbSetChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2022 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Whipstaff.EntityFramework.SmokeTest
{
/// <summary>
/// Abstract class for checking DBSets.
/// </summary>
/// <typeparam name="TDbContext">The type of the DbContext being tested.</typeparam>
public abstract class AbstractDbSetChecker<TDbContext>
where TDbContext : DbContext
{
private readonly DbSetCheckerLogMessageActionsWrapper<TDbContext> _logMessageActionsWrapper;

/// <summary>
/// Initializes a new instance of the <see cref="AbstractDbSetChecker{TDbContext}"/> class.
/// </summary>
/// <param name="logMessageActionsWrapper">Log Message Wrapper instance.</param>
protected AbstractDbSetChecker(DbSetCheckerLogMessageActionsWrapper<TDbContext> logMessageActionsWrapper)
{
ArgumentNullException.ThrowIfNull(logMessageActionsWrapper);
_logMessageActionsWrapper = logMessageActionsWrapper;
}

/// <summary>
/// Carries out the testing of DB Sets.
/// </summary>
/// <param name="dbContext">Instance of the DbContext to test.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public abstract Task CheckDbSets(TDbContext dbContext);

/// <summary>
/// Carries out the test of an individual Db Set.
/// </summary>
/// <typeparam name="TEntity">The type of the entity being tested.</typeparam>
/// <param name="dbSet">The Db Set to test.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
protected async Task CheckDbSet<TEntity>(DbSet<TEntity> dbSet)
where TEntity : class
{
try
{
_logMessageActionsWrapper.StartingTestOfDbSet(typeof(TEntity));
var result = await dbSet.FirstOrDefaultAsync().ConfigureAwait(false);
}
#pragma warning disable CA1031
catch (Exception ex)
#pragma warning restore CA1031
{
_logMessageActionsWrapper.FailedToTestDbSet(ex, typeof(TEntity));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2022 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Whipstaff.Core.Logging;

namespace Whipstaff.EntityFramework.SmokeTest
{
/// <summary>
/// Log Message Actions for DBSet checks.
/// </summary>
/// <typeparam name="TDbContext">The type for the DBContext being tested.</typeparam>
public sealed class DbSetCheckerLogMessageActions<TDbContext> : ILogMessageActions<AbstractDbSetChecker<TDbContext>>
where TDbContext : DbContext
{
private readonly Action<ILogger, Type, Exception?> _startingTestOfDbSet;
private readonly Action<ILogger, Type, Exception?> _testOfDbSetFailed;

/// <summary>
/// Initializes a new instance of the <see cref="DbSetCheckerLogMessageActions{TDbContext}"/> class.
/// </summary>
public DbSetCheckerLogMessageActions()
{
_startingTestOfDbSet = LoggerMessage.Define<Type>(
Microsoft.Extensions.Logging.LogLevel.Information,
EventIdFactory.TestOfDbSetStarting(),
"Starting Test of DBSet for {EntityType}");

_testOfDbSetFailed = LoggerMessage.Define<Type>(
Microsoft.Extensions.Logging.LogLevel.Error,
EventIdFactory.TestOfDbSetFailed(),
"Failed during test of DBSet for {EntityType}");
}

/// <summary>
/// Logs the start of a test of a DBSet.
/// </summary>
/// <param name="logger">Logging framework instance.</param>
/// <param name="type">The type of the db set being tested.</param>
public void StartingTestOfDbSet(ILogger logger, Type type)
{
_startingTestOfDbSet(logger, type, null);
}

/// <summary>
/// Logs a failure during a test of a DBSet.
/// </summary>
/// <param name="logger">Logging framework instance.</param>
/// <param name="type">The type of the db set being tested.</param>
/// <param name="exception">The exception that occurred.</param>
public void TestOfDbSetFailed(ILogger logger, Type type, Exception exception)
{
_testOfDbSetFailed(logger, type, exception);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2022 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Whipstaff.Core.Logging;

namespace Whipstaff.EntityFramework.SmokeTest
{
/// <summary>
/// Log Message Actions for DBSet checks.
/// </summary>
/// <typeparam name="TDbContext">The type for the DbContext.</typeparam>
public sealed class DbSetCheckerLogMessageActionsWrapper<TDbContext> : AbstractLogMessageActionsWrapper<AbstractDbSetChecker<TDbContext>, DbSetCheckerLogMessageActions<TDbContext>>
where TDbContext : DbContext
{
/// <summary>
/// Initializes a new instance of the <see cref="DbSetCheckerLogMessageActionsWrapper{TDbContext}"/> class.
/// </summary>
/// <param name="logMessageActions">Log Message Actions instance.</param>
/// <param name="logger">Logging framework instance.</param>
public DbSetCheckerLogMessageActionsWrapper(
DbSetCheckerLogMessageActions<TDbContext> logMessageActions,
ILogger<AbstractDbSetChecker<TDbContext>> logger)
: base(logMessageActions, logger)
{
}

/// <summary>
/// Logs the start of a test of a DBSet.
/// </summary>
/// <param name="type">The type of the DbSet being tested.</param>
public void StartingTestOfDbSet(Type type)
{
LogMessageActions.StartingTestOfDbSet(Logger, type);
}

/// <summary>
/// Logs a failure during a test of a DBSet.
/// </summary>
/// <param name="exception">The exception that occurred.</param>
/// <param name="type">The type of the DbSet being tested.</param>
public void FailedToTestDbSet(Exception exception, Type type)
{
LogMessageActions.TestOfDbSetFailed(Logger, type, exception);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2022 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;

namespace Whipstaff.EntityFramework.SmokeTest
{
/// <summary>
/// Background Worker for running smoke tests on a DBContext.
/// </summary>
/// <typeparam name="TDbContext">The type for the DbContext.</typeparam>
/// <typeparam name="TDbSetChecker">The type for the DbSet checker.</typeparam>
public sealed class SmokeTestBackgroundWorker<TDbContext, TDbSetChecker> : BackgroundService
where TDbContext : DbContext
where TDbSetChecker : AbstractDbSetChecker<TDbContext>
{
private readonly IDbContextFactory<TDbContext> _dbContextFactory;
private readonly TDbSetChecker _dbSetChecker;
private readonly SmokeTestBackgroundWorkerLogMessageActionsWrapper<TDbContext, TDbSetChecker> _logMessageActionsWrappper;

/// <summary>
/// Initializes a new instance of the <see cref="SmokeTestBackgroundWorker{TDbContext, TDbSetChecker}"/> class.
/// </summary>
/// <param name="dbContextFactory">DBContext factory for connecting to the database to test.</param>
/// <param name="dbSetChecker">The logic for running the test of Db Sets.</param>
/// <param name="logMessageActionsWrappper">Log Message Actions Wrapper instance.</param>
public SmokeTestBackgroundWorker(
IDbContextFactory<TDbContext> dbContextFactory,
TDbSetChecker dbSetChecker,
SmokeTestBackgroundWorkerLogMessageActionsWrapper<TDbContext, TDbSetChecker> logMessageActionsWrappper)
{
ArgumentNullException.ThrowIfNull(dbContextFactory);
ArgumentNullException.ThrowIfNull(dbSetChecker);
ArgumentNullException.ThrowIfNull(logMessageActionsWrappper);

_dbContextFactory = dbContextFactory;
_dbSetChecker = dbSetChecker;
_logMessageActionsWrappper = logMessageActionsWrappper;
}

/// <inheritdoc/>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var dbContext = await _dbContextFactory.CreateDbContextAsync(stoppingToken).ConfigureAwait(false))
{
try
{
_logMessageActionsWrappper.StartingDbSetChecker();
var dbSets = _dbSetChecker.CheckDbSets(dbContext);
_logMessageActionsWrappper.CompletedDbSetChecker();
}
#pragma warning disable CA1031
catch (Exception ex)
#pragma warning restore CA1031
{
_logMessageActionsWrappper.FailureOfDbSetChecker(ex);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2022 DHGMS Solutions and Contributors. All rights reserved.
// This file is licensed to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Whipstaff.Core.Logging;

namespace Whipstaff.EntityFramework.SmokeTest
{
/// <summary>
/// Log Message Actions for <see cref="SmokeTestBackgroundWorker{TDbContext,TDbSetChecker}"/>.
/// </summary>
/// <typeparam name="TDbContext">The type for the DbContext.</typeparam>
/// <typeparam name="TDbSetChecker">The type for the DbSet checker.</typeparam>
public sealed class SmokeTestBackgroundWorkerLogMessageActions<TDbContext, TDbSetChecker> : ILogMessageActions<SmokeTestBackgroundWorker<TDbContext, TDbSetChecker>>
where TDbContext : DbContext
where TDbSetChecker : AbstractDbSetChecker<TDbContext>
{
private readonly Action<ILogger, Exception?> _startingTestOfDbSet;
private readonly Action<ILogger, Exception?> _completedTestOfDbSet;
private readonly Action<ILogger, Exception?> _testOfDbSetFailed;

/// <summary>
/// Initializes a new instance of the <see cref="SmokeTestBackgroundWorkerLogMessageActions{TDbContext, TDbSetChecker}"/> class.
/// </summary>
public SmokeTestBackgroundWorkerLogMessageActions()
{
_startingTestOfDbSet = LoggerMessage.Define(
LogLevel.Information,
EventIdFactory.TestOfDbSetStarting(),
"Starting test of DBSet");

_completedTestOfDbSet = LoggerMessage.Define(
LogLevel.Information,
EventIdFactory.TestOfDbSetCompleted(),
"Completed test of DBSet");

_testOfDbSetFailed = LoggerMessage.Define(
LogLevel.Information,
EventIdFactory.TestOfDbSetFailed(),
"Starting test of DBSet");
}

/// <summary>
/// Logging event for when the test of DB Sets is starting.
/// </summary>
/// <param name="logger">Logging framework instance.</param>
public void StartingTestOfDbSet(ILogger<SmokeTestBackgroundWorker<TDbContext, TDbSetChecker>> logger)
{
_startingTestOfDbSet(logger, null);
}

/// <summary>
/// Logging event for when the test of DB Sets has completed.
/// </summary>
/// <param name="logger">Logging framework instance.</param>
public void CompletedTestOfDbSet(ILogger<SmokeTestBackgroundWorker<TDbContext, TDbSetChecker>> logger)
{
_completedTestOfDbSet(logger, null);
}

/// <summary>
/// Logging event for when the test of DB Sets has failed.
/// </summary>
/// <param name="logger">Logging framework instance.</param>
/// <param name="exception">The exception that occurred.</param>
public void TestOfDbSetFailed(ILogger<SmokeTestBackgroundWorker<TDbContext, TDbSetChecker>> logger, Exception exception)
{
_testOfDbSetFailed(logger, exception);
}
}
}
Loading

0 comments on commit 8022bac

Please sign in to comment.