Skip to content

Commit

Permalink
feat: create version 1.0.5
Browse files Browse the repository at this point in the history
Generate xml docs and move test case classes to internal
  • Loading branch information
draekien committed Jul 23, 2021
1 parent 7570b56 commit 8387768
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@

namespace Fluent.ConstructorAssertions.Contexts
{
public sealed class ConstructorArgumentContext<T> where T : class
/// <summary>
/// The context that handles creation of test cases based on the provided constructor arguments and the expected
/// test results.
/// </summary>
/// <typeparam name="TClass">The class with the constructor to test.</typeparam>
public sealed class ConstructorArgumentContext<TClass> where TClass : class
{
internal ExceptionContext<T>? ExceptionContext { get; }
internal SuccessContext<T>? SuccessContext { get; }
internal ExceptionContext<TClass>? ExceptionContext { get; }
internal SuccessContext<TClass>? SuccessContext { get; }

internal ConstructorArgumentContext(ExpectedResultContext<T> expectedResultContext, params object?[] args)
internal ConstructorArgumentContext(ExpectedResultContext<TClass> expectedResultContext, params object?[] args)
{
switch (expectedResultContext)
{
case ExceptionContext<T> exceptionContext:
case ExceptionContext<TClass> exceptionContext:
{
ExceptionContext = exceptionContext;

TestCase<T> testCase = new FailTestCase<T>(
TestCase<TClass> testCase = new FailTestCase<TClass>(
exceptionContext.TestContext.Constructor,
exceptionContext.Because,
exceptionContext.ExceptionType,
Expand All @@ -28,11 +33,11 @@ internal ConstructorArgumentContext(ExpectedResultContext<T> expectedResultConte
break;
}

case SuccessContext<T> successContext:
case SuccessContext<TClass> successContext:
{
SuccessContext = successContext;

TestCase<T> testCase = new SuccessTestCase<T>(
TestCase<TClass> testCase = new SuccessTestCase<TClass>(
successContext.TestContext.Constructor,
successContext.Because,
args
Expand All @@ -44,8 +49,16 @@ internal ConstructorArgumentContext(ExpectedResultContext<T> expectedResultConte
}
}

public TestContext<T> And => (ExceptionContext?.TestContext ?? SuccessContext?.TestContext) ?? throw new InvalidOperationException();
/// <summary>
/// The chaining API call to add additional scenarios to the Test Context.
/// </summary>
/// <exception cref="InvalidOperationException">No test context exists.</exception>
public TestContext<TClass> And => (ExceptionContext?.TestContext ?? SuccessContext?.TestContext)
?? throw new InvalidOperationException("No valid test context.");

public TestRunner<T> Should => new(this);
/// <summary>
/// The chaining API call to start the test runner.
/// </summary>
public TestRunner<TClass> Should => new(this);
}
}
6 changes: 4 additions & 2 deletions src/Fluent.ConstructorAssertions/Contexts/ExceptionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace Fluent.ConstructorAssertions.Contexts
{
public sealed class ExceptionContext<T> : ExpectedResultContext<T> where T : class
/// <inheritdoc />
public sealed class ExceptionContext<TClass> : ExpectedResultContext<TClass> where TClass : class
{
internal string? Because { get; }
internal Type ExceptionType { get; }

internal ExceptionContext(TestContext<T> testContext, Type exceptionType, string? because) : base(testContext)
internal ExceptionContext(TestContext<TClass> testContext, Type exceptionType, string? because)
: base(testContext)
{
ExceptionType = exceptionType;
Because = because;
Expand Down
26 changes: 20 additions & 6 deletions src/Fluent.ConstructorAssertions/Contexts/ExpectedResultContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,34 @@

namespace Fluent.ConstructorAssertions.Contexts
{
public abstract class ExpectedResultContext<T> where T : class
/// <summary>
/// The context responsible for telling the test runner which outcome is expected and which assertion should be executed.
/// </summary>
/// <typeparam name="TClass">The class with the constructor to test.</typeparam>
public abstract class ExpectedResultContext<TClass> where TClass : class
{
internal TestContext<T> TestContext { get; }
internal TestContext<TClass> TestContext { get; }

protected ExpectedResultContext(TestContext<T> testContext)
/// <summary>
/// Instantiates a new <see cref="ExpectedResultContext{TClass}"/>
/// </summary>
/// <param name="testContext">The current <see cref="TestContext"/></param>
protected ExpectedResultContext(TestContext<TClass> testContext)
{
TestContext = testContext;
}

public ConstructorArgumentContext<T> ForArgs(params object?[] args)
/// <summary>
/// Creates the <see cref="ConstructorArgumentContext{TClass}"/> for TClass with the provided argument parameters.
/// </summary>
/// <param name="args">The arguments to instantiate TClass with.</param>
/// <remarks>Not passing through any params will instantiate TClass with all arguments set to null.</remarks>
/// <returns>The constructor argument context for TClass.</returns>
public ConstructorArgumentContext<TClass> ForArgs(params object?[] args)
{
return !args.Any()
? new ConstructorArgumentContext<T>(this, new object?[TestContext.NumberOfConstructorArguments])
: new ConstructorArgumentContext<T>(this, args);
? new ConstructorArgumentContext<TClass>(this, new object?[TestContext.NumberOfConstructorArguments])
: new ConstructorArgumentContext<TClass>(this, args);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Fluent.ConstructorAssertions.Contexts
{
/// <inheritdoc />
public sealed class SuccessContext<T> : ExpectedResultContext<T> where T : class
{
internal string? Because { get; }
Expand Down
23 changes: 19 additions & 4 deletions src/Fluent.ConstructorAssertions/Contexts/TestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,39 @@

namespace Fluent.ConstructorAssertions.Contexts
{
public sealed class TestContext<T> where T : class
/// <summary>
/// The test context is responsible for storing the constructor and the test cases defined by the chaining methods.
/// </summary>
/// <typeparam name="TClass">The class with the constructor to test.</typeparam>
public sealed class TestContext<TClass> where TClass : class
{
internal ConstructorInfo Constructor { get; }
internal int NumberOfConstructorArguments { get; }
internal IList<TestCase<T>> TestCases { get; } = new List<TestCase<T>>();
internal IList<TestCase<TClass>> TestCases { get; } = new List<TestCase<TClass>>();

internal TestContext(ConstructorInfo constructor, int numberOfConstructorArguments)
{
Constructor = constructor;
NumberOfConstructorArguments = numberOfConstructorArguments;
}

public ExceptionContext<T> Throws<TException>(string? because = default)
/// <summary>
/// Begins construction of a test case that asserts an exception of type TException will be thrown.
/// </summary>
/// <param name="because">The reason the exception should be thrown.</param>
/// <typeparam name="TException">The exception type.</typeparam>
/// <returns>A new <see cref="ExceptionContext{TClass}"/> for TClass.</returns>
public ExceptionContext<TClass> Throws<TException>(string? because = default)
{
return new(this, typeof(TException), because);
}

public SuccessContext<T> Succeeds(string? because = default)
/// <summary>
/// Begins construction of a test case which asserts that no errors are thrown when instantiation TClass.
/// </summary>
/// <param name="because">The reason the test should pass.</param>
/// <returns>A new <see cref="SuccessContext{TClass}"/> for TClass.</returns>
public SuccessContext<TClass> Succeeds(string? because = default)
{
return new(this, because);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageVersion>1.0.4</PackageVersion>
<PackageVersion>1.0.5</PackageVersion>
</PropertyGroup>

<PropertyGroup>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>

<ItemGroup>
Expand Down
17 changes: 13 additions & 4 deletions src/Fluent.ConstructorAssertions/ForConstructorOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@

namespace Fluent.ConstructorAssertions
{
/// <summary>
/// Declares a new constructor test statement.
/// </summary>
/// <typeparam name="TClass">The class with the constructor to test.</typeparam>
[PublicAPI]
public sealed class ForConstructorOf<T> where T : class
public sealed class ForConstructorOf<TClass> where TClass : class
{
public static TestContext<T> WithArgTypes(params Type[] argTypes)
/// <summary>
/// Defines the argument types expected by the constructor of TClass.
/// </summary>
/// <param name="argTypes">The argument types.</param>
/// <returns>A new <see cref="TestContext{TClass}"/> for the constructor of TClass.</returns>
public static TestContext<TClass> WithArgTypes(params Type[] argTypes)
{
ConstructorInfo? constructor = typeof(T).GetConstructor(argTypes);
ConstructorInfo? constructor = typeof(TClass).GetConstructor(argTypes);

constructor.Should()
.NotBeNull("A constructor must exist for the provided class type.");

return new TestContext<T>(constructor!, argTypes.Length);
return new TestContext<TClass>(constructor!, argTypes.Length);
}
}
}
17 changes: 12 additions & 5 deletions src/Fluent.ConstructorAssertions/Runners/TestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@

namespace Fluent.ConstructorAssertions.Runners
{
public sealed class TestRunner<T> where T : class
/// <summary>
/// The class responsible for running the tests.
/// </summary>
/// <typeparam name="TClass">The class with the constructor to test.</typeparam>
public sealed class TestRunner<TClass> where TClass : class
{
private readonly List<TestCase<T>> _testCases = new List<TestCase<T>>();
private readonly List<TestCase<TClass>> _testCases = new();

internal TestRunner(ConstructorArgumentContext<T> context)
internal TestRunner(ConstructorArgumentContext<TClass> context)
{
if (context.ExceptionContext != null)
_testCases.AddRange(context.ExceptionContext.TestContext.TestCases);
Expand All @@ -18,6 +22,9 @@ internal TestRunner(ConstructorArgumentContext<T> context)
_testCases.AddRange(context.SuccessContext.TestContext.TestCases);
}

/// <summary>
/// Executes the registered test cases from the context and asserts that all scenarios are true.
/// </summary>
public void BeTrue()
{
List<string> errorContext = new();
Expand All @@ -27,13 +34,13 @@ public void BeTrue()

private void ExecuteTestCases(ICollection<string> errors)
{
foreach (TestCase<T> testCase in _testCases)
foreach (TestCase<TClass> testCase in _testCases)
{
ExecuteTestCase(errors, testCase);
}
}

private static void ExecuteTestCase(ICollection<string> errorContext, TestCase<T> testCase)
private static void ExecuteTestCase(ICollection<string> errorContext, TestCase<TClass> testCase)
{
string error = testCase.Execute();

Expand Down
2 changes: 1 addition & 1 deletion src/Fluent.ConstructorAssertions/TestCases/FailTestCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Fluent.ConstructorAssertions.TestCases
{
public class FailTestCase<T> : TestCase<T> where T : class
internal class FailTestCase<T> : TestCase<T> where T : class
{
private readonly Type _exceptionType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Fluent.ConstructorAssertions.TestCases
{
public class SuccessTestCase<T> : TestCase<T> where T : class
internal class SuccessTestCase<T> : TestCase<T> where T : class
{
/// <inheritdoc />
internal SuccessTestCase(ConstructorInfo constructor, string? because, object?[] args)
Expand Down
2 changes: 1 addition & 1 deletion src/Fluent.ConstructorAssertions/TestCases/TestCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Fluent.ConstructorAssertions.TestCases
{
public abstract class TestCase<T> where T : class
internal abstract class TestCase<T> where T : class
{
private readonly object?[] _arguments;
private readonly string? _because;
Expand Down

0 comments on commit 8387768

Please sign in to comment.