diff --git a/src/GalaxyCheck.Xunit.Tests/GlobalConfigurationTests/AboutLocatingGlobalConfiguration.cs b/src/GalaxyCheck.Xunit.Tests/GlobalConfigurationTests/AboutLocatingGlobalConfiguration.cs new file mode 100644 index 00000000..42e1c6c0 --- /dev/null +++ b/src/GalaxyCheck.Xunit.Tests/GlobalConfigurationTests/AboutLocatingGlobalConfiguration.cs @@ -0,0 +1,26 @@ +using FluentAssertions; +using GalaxyCheck.Configuration; +using GalaxyCheck.Internal; +using Xunit; + +namespace Tests.GlobalConfigurationTests +{ + public class AboutLocatingGlobalConfiguration + { + [Fact] + public void ItWorks() + { + var instance = GlobalConfiguration.Instance; + + instance.DefaultIterations.Should().Be(420); + } + } + + public class MyConfigureGlobal : IConfigureGlobal + { + public void Configure(IGlobalConfiguration instance) + { + instance.DefaultIterations = 420; + } + } +} diff --git a/src/GalaxyCheck.Xunit.Tests/IntegrationSample/ConfigureGalaxyCheck.cs b/src/GalaxyCheck.Xunit.Tests/IntegrationSample/ConfigureGalaxyCheck.cs new file mode 100644 index 00000000..31dc7221 --- /dev/null +++ b/src/GalaxyCheck.Xunit.Tests/IntegrationSample/ConfigureGalaxyCheck.cs @@ -0,0 +1,12 @@ +using GalaxyCheck.Configuration; + +namespace IntegrationSample +{ + internal class ConfigureGalaxyCheck : IConfigureGlobal + { + public void Configure(IGlobalConfiguration instance) + { + instance.DefaultIterations = 100; + } + } +} diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutFactory.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutFactory.cs index 4d64ef26..2595d851 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutFactory.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutFactory.cs @@ -1,6 +1,6 @@ using GalaxyCheck; using GalaxyCheck.Gens; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using Moq; using System; using System.Collections.Generic; @@ -20,7 +20,12 @@ public void WhenClassNorMethodHasFactoryConfig_ItPassesThroughNull(string testMe var testClassType = typeof(PropertiesWithoutFactoryConfig); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + mockPropertyFactory.Object, + new GlobalConfiguration()); VerifyFactoryNotPassedThrough(mockPropertyFactory); } @@ -34,7 +39,12 @@ public void ItPassesThroughTheFactoryFromTheMethod(string testMethodName) var testClassType = typeof(PropertiesWithoutFactoryConfig); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + mockPropertyFactory.Object, + new GlobalConfiguration()); VerifyFactoryPassedThrough(mockPropertyFactory, typeof(GenFactory1)); } @@ -48,7 +58,12 @@ public void ItPassesThroughTheFactoryFromTheClass(string testMethodName) var testClassType = typeof(PropertiesWithFactoryConfig); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + mockPropertyFactory.Object, + new GlobalConfiguration()); VerifyFactoryPassedThrough(mockPropertyFactory, typeof(GenFactory2)); } @@ -62,7 +77,12 @@ public void AMethodLevelFactoryIsPreferredOverAClassLevelFactory(string testMeth var testClassType = typeof(PropertiesWithFactoryConfig); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + mockPropertyFactory.Object, + new GlobalConfiguration()); VerifyFactoryPassedThrough(mockPropertyFactory, typeof(GenFactory1)); } diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutIterations.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutIterations.cs index 186f3cb9..f0c01c18 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutIterations.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutIterations.cs @@ -1,6 +1,6 @@ using FluentAssertions; using GalaxyCheck; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using System.Reflection; using Xunit; @@ -35,20 +35,42 @@ public void SampleWith10Iterations() } [Theory] - [InlineData(nameof(Properties.PropertyWithDefaultIterations), 100)] [InlineData(nameof(Properties.PropertyWith10Iterations), 10)] - [InlineData(nameof(Properties.SampleWithDefaultIterations), 100)] [InlineData(nameof(Properties.SampleWith10Iterations), 10)] public void ItPassesThroughIterations(string testMethodName, int expectedIterations) { var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration { DefaultIterations = 999 }); result.Parameters.Iterations.Should().Be(expectedIterations); } + [Theory] + [InlineData(nameof(Properties.PropertyWithDefaultIterations))] + [InlineData(nameof(Properties.SampleWithDefaultIterations))] + public void ItPassesThroughTheDefaultIterationsIfNotExplicitlySet(string testMethodName) + { + var defaultIterations = 1000; + var testClassType = typeof(Properties); + var testMethodInfo = GetMethod(testMethodName); + + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration { DefaultIterations = defaultIterations }); + + result.Parameters.Iterations.Should().Be(defaultIterations); + } + private static MethodInfo GetMethod(string name) { var methodInfo = typeof(Properties).GetMethod(name, BindingFlags.Public | BindingFlags.Instance); diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutMemberGenAttribute.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutMemberGenAttribute.cs index de2c9434..e445e20f 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutMemberGenAttribute.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutMemberGenAttribute.cs @@ -1,7 +1,7 @@ using FluentAssertions; using GalaxyCheck; using GalaxyCheck.Gens; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using Moq; using System; using System.Collections.Generic; @@ -87,7 +87,12 @@ public void ItErrorsWhenReferencePropertyIsNotAGen(string testMethodName) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - Action test = () => PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + Action test = () => PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); test.Should() .Throw() @@ -108,7 +113,12 @@ public void ItPassesThroughGen(string testMethodName) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + mockPropertyFactory.Object, + new GlobalConfiguration()); VerifyGenPassedThrough(mockPropertyFactory, Gen, 0); } @@ -122,7 +132,7 @@ public void ItPassesThroughGenKeyedToCorrectIndex(string testMethodName, int exp var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object); + PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, mockPropertyFactory.Object, new GlobalConfiguration()); VerifyGenPassedThrough(mockPropertyFactory, Gen, expectedIndex); } diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutReplay.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutReplay.cs index 41ca6c53..bb40b819 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutReplay.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutReplay.cs @@ -1,6 +1,6 @@ using FluentAssertions; using GalaxyCheck; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using System.Reflection; using Xunit; @@ -46,7 +46,12 @@ public void ItPassesThroughReplay(string testMethodName, string? expectedReplay) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); result.Parameters.Replay.Should().Be(expectedReplay); } diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSeed.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSeed.cs index f3f51f0a..19c22858 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSeed.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSeed.cs @@ -1,6 +1,6 @@ using FluentAssertions; using GalaxyCheck; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using System.Reflection; using Xunit; @@ -66,7 +66,12 @@ public void ItPassesThroughSeed(string testMethodName, int expectedSeed) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); result.Parameters.Seed.Should().Be(expectedSeed); } @@ -81,7 +86,12 @@ public void ItDoesNotPassThroughSeed(string testMethodName) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); result.Parameters.Seed.Should().Be(null); } diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutShrinkLimit.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutShrinkLimit.cs index d80c3617..53e382fc 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutShrinkLimit.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutShrinkLimit.cs @@ -1,6 +1,6 @@ using FluentAssertions; using GalaxyCheck; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using System.Reflection; using Xunit; @@ -35,20 +35,42 @@ public void SampleWith10ShrinkLimit() } [Theory] - [InlineData(nameof(Properties.PropertyWithDefaultShrinkLimit), 500)] [InlineData(nameof(Properties.PropertyWith10ShrinkLimit), 10)] - [InlineData(nameof(Properties.SampleWithDefaultShrinkLimit), 500)] [InlineData(nameof(Properties.SampleWith10ShrinkLimit), 10)] public void ItPassesThroughShrinkLimit(string testMethodName, int expectedShrinkLimit) { var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration() { DefaultShrinkLimit = 999 }); result.Parameters.ShrinkLimit.Should().Be(expectedShrinkLimit); } + [Theory] + [InlineData(nameof(Properties.PropertyWithDefaultShrinkLimit))] + [InlineData(nameof(Properties.SampleWithDefaultShrinkLimit))] + public void ItPassesThroughTheDefaultShrinkLimitIfNotExplicitlySet(string testMethodName) + { + var defaultShrinkLimit = 1000; + var testClassType = typeof(Properties); + var testMethodInfo = GetMethod(testMethodName); + + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration { DefaultShrinkLimit = defaultShrinkLimit }); + + result.Parameters.ShrinkLimit.Should().Be(defaultShrinkLimit); + } + private static MethodInfo GetMethod(string name) { var methodInfo = typeof(Properties).GetMethod(name, BindingFlags.Instance | BindingFlags.Public); diff --git a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSize.cs b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSize.cs index c4a6aade..b126113d 100644 --- a/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSize.cs +++ b/src/GalaxyCheck.Xunit.Tests/PropertyInitializerTests/AboutSize.cs @@ -1,6 +1,6 @@ using FluentAssertions; using GalaxyCheck; -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using System.Reflection; using Xunit; @@ -66,7 +66,12 @@ public void ItPassesThroughSize(string testMethodName, int expectedSize) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); result.Parameters.Size.Should().Be(expectedSize); } @@ -81,7 +86,12 @@ public void ItDoesNotPassThroughSize(string testMethodName) var testClassType = typeof(Properties); var testMethodInfo = GetMethod(testMethodName); - var result = PropertyInitializer.Initialize(testClassType, testMethodInfo, new object[] { }, new DefaultPropertyFactory()); + var result = PropertyInitializer.Initialize( + testClassType, + testMethodInfo, + new object[] { }, + new DefaultPropertyFactory(), + new GlobalConfiguration()); result.Parameters.Size.Should().Be(null); } diff --git a/src/GalaxyCheck.Xunit/Configuration/ActivateConfigureGlobalException.cs b/src/GalaxyCheck.Xunit/Configuration/ActivateConfigureGlobalException.cs new file mode 100644 index 00000000..ce9dea6d --- /dev/null +++ b/src/GalaxyCheck.Xunit/Configuration/ActivateConfigureGlobalException.cs @@ -0,0 +1,19 @@ +using System; + +namespace GalaxyCheck.Configuration +{ + public class ActivateConfigureGlobalException : Exception + { + public ActivateConfigureGlobalException(Type type, Exception ex) + : base(BuildMessage(type, ex), ex) + { + } + + private static string BuildMessage(Type type, Exception ex) + { + return @$"Failed to create instance of type '{type}' during global GalaxyCheck configuration. + +Exception: {ex}"; + } + } +} diff --git a/src/GalaxyCheck.Xunit/Configuration/IConfigureGlobal.cs b/src/GalaxyCheck.Xunit/Configuration/IConfigureGlobal.cs new file mode 100644 index 00000000..b1b299f7 --- /dev/null +++ b/src/GalaxyCheck.Xunit/Configuration/IConfigureGlobal.cs @@ -0,0 +1,7 @@ +namespace GalaxyCheck.Configuration +{ + public interface IConfigureGlobal + { + void Configure(IGlobalConfiguration instance); + } +} diff --git a/src/GalaxyCheck.Xunit/Configuration/IGlobalConfiguration.cs b/src/GalaxyCheck.Xunit/Configuration/IGlobalConfiguration.cs new file mode 100644 index 00000000..c845bec5 --- /dev/null +++ b/src/GalaxyCheck.Xunit/Configuration/IGlobalConfiguration.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalaxyCheck.Configuration +{ + public interface IGlobalConfiguration + { + int DefaultIterations { get; set; } + + int DefaultShrinkLimit { get; set; } + } +} diff --git a/src/GalaxyCheck.Xunit/GalaxyCheck.Xunit.csproj b/src/GalaxyCheck.Xunit/GalaxyCheck.Xunit.csproj index a782acc9..909f0c48 100644 --- a/src/GalaxyCheck.Xunit/GalaxyCheck.Xunit.csproj +++ b/src/GalaxyCheck.Xunit/GalaxyCheck.Xunit.csproj @@ -4,6 +4,7 @@ net6.0 9.0 enable + GalaxyCheck true GalaxyCheck.Xunit.nuspec PackageVersion=$(PackageVersion) diff --git a/src/GalaxyCheck.Xunit/Internal/DefaultPropertyFactory.cs b/src/GalaxyCheck.Xunit/Internal/DefaultPropertyFactory.cs index 86a3d3e4..7238fe3a 100644 --- a/src/GalaxyCheck.Xunit/Internal/DefaultPropertyFactory.cs +++ b/src/GalaxyCheck.Xunit/Internal/DefaultPropertyFactory.cs @@ -1,8 +1,9 @@ using GalaxyCheck.Gens; +using GalaxyCheck.Internal; using System.Collections.Generic; using System.Reflection; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal class DefaultPropertyFactory : IPropertyFactory { diff --git a/src/GalaxyCheck.Xunit/Internal/GlobalConfiguration.cs b/src/GalaxyCheck.Xunit/Internal/GlobalConfiguration.cs new file mode 100644 index 00000000..ab624979 --- /dev/null +++ b/src/GalaxyCheck.Xunit/Internal/GlobalConfiguration.cs @@ -0,0 +1,64 @@ +using GalaxyCheck; +using GalaxyCheck.Configuration; +using System; +using System.Linq; + +namespace GalaxyCheck.Internal +{ + internal class GlobalConfiguration : IGlobalConfiguration + { + public int DefaultIterations { get; set; } = 100; + + public int DefaultShrinkLimit { get; set; } = 100; + + private static object _instanceLock = new(); + private static GlobalConfiguration? _instance = null; + + public static GlobalConfiguration Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + { + _instance = CreateInstance(); + } + } + } + + return _instance; + } + } + + private static GlobalConfiguration CreateInstance() + { + var instance = new GlobalConfiguration(); + + var configureGlobalTypes = + from assembly in AppDomain.CurrentDomain.GetAssemblies() + from type in assembly.GetTypes() + where type.GetInterfaces().Contains(typeof(IConfigureGlobal)) + select type; + + foreach (var configureGlobalType in configureGlobalTypes) + { + IConfigureGlobal configureGlobal; + try + { + configureGlobal = (IConfigureGlobal)Activator.CreateInstance(configureGlobalType)!; + } + catch (Exception ex) + { + throw new ActivateConfigureGlobalException(configureGlobalType, ex); + } + + configureGlobal.Configure(instance); + } + + return instance; + } + } +} diff --git a/src/GalaxyCheck.Xunit/Internal/IPropertyFactory.cs b/src/GalaxyCheck.Xunit/Internal/IPropertyFactory.cs index 5dc865c5..6637b7cf 100644 --- a/src/GalaxyCheck.Xunit/Internal/IPropertyFactory.cs +++ b/src/GalaxyCheck.Xunit/Internal/IPropertyFactory.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Reflection; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { public interface IPropertyFactory { diff --git a/src/GalaxyCheck.Xunit/Internal/IPropertyRunner.cs b/src/GalaxyCheck.Xunit/Internal/IPropertyRunner.cs index dd60b204..522cd38c 100644 --- a/src/GalaxyCheck.Xunit/Internal/IPropertyRunner.cs +++ b/src/GalaxyCheck.Xunit/Internal/IPropertyRunner.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Xunit.Abstractions; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal record PropertyRunParameters( AsyncProperty Property, diff --git a/src/GalaxyCheck.Xunit/Internal/PropertyAssertRunner.cs b/src/GalaxyCheck.Xunit/Internal/PropertyAssertRunner.cs index 4148b60f..fe276673 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertyAssertRunner.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertyAssertRunner.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Xunit.Abstractions; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal class PropertyAssertRunner : IPropertyRunner { diff --git a/src/GalaxyCheck.Xunit/Internal/PropertyConfigurationException.cs b/src/GalaxyCheck.Xunit/Internal/PropertyConfigurationException.cs index 56048b69..4cb5c0a9 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertyConfigurationException.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertyConfigurationException.cs @@ -1,6 +1,6 @@ using System; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal class PropertyConfigurationException : Exception { diff --git a/src/GalaxyCheck.Xunit/Internal/PropertyDiscoverer.cs b/src/GalaxyCheck.Xunit/Internal/PropertyDiscoverer.cs index b1e0d92a..7a3b24f0 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertyDiscoverer.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertyDiscoverer.cs @@ -2,7 +2,7 @@ using Xunit.Abstractions; using Xunit.Sdk; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { public class PropertyDiscoverer : IXunitTestCaseDiscoverer { diff --git a/src/GalaxyCheck.Xunit/Internal/PropertyInitializer.cs b/src/GalaxyCheck.Xunit/Internal/PropertyInitializer.cs index dae47b68..1a65ea68 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertyInitializer.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertyInitializer.cs @@ -1,10 +1,11 @@ -using GalaxyCheck.Gens; +using GalaxyCheck.Configuration; +using GalaxyCheck.Gens; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal record PropertyInitializationResult( IPropertyRunner Runner, @@ -20,7 +21,8 @@ public static PropertyInitializationResult Initialize( Type testClassType, MethodInfo testMethodInfo, object[] constructorArguments, - IPropertyFactory propertyFactory) + IPropertyFactory propertyFactory, + IGlobalConfiguration globalConfig) { var testClassInstance = Activator.CreateInstance(testClassType, constructorArguments)!; var propertyAttribute = testMethodInfo.GetCustomAttributes(inherit: true).Single(); @@ -32,8 +34,8 @@ public static PropertyInitializationResult Initialize( var propertyRunParameters = new PropertyRunParameters( Property: property, - Iterations: propertyAttribute.Iterations, - ShrinkLimit: propertyAttribute.ShrinkLimit, + Iterations: propertyAttribute.NullableIterations ?? globalConfig.DefaultIterations, + ShrinkLimit: propertyAttribute.NullableShrinkLimit ?? globalConfig.DefaultShrinkLimit, Replay: replay, Seed: replay == null ? propertyAttribute.NullableSeed : null, Size: replay == null ? propertyAttribute.NullableSize : null); diff --git a/src/GalaxyCheck.Xunit/Internal/PropertySampleRunner.cs b/src/GalaxyCheck.Xunit/Internal/PropertySampleRunner.cs index 0bd7eb83..8b407b1f 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertySampleRunner.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertySampleRunner.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Xunit.Abstractions; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { internal class PropertySampleRunner : IPropertyRunner { diff --git a/src/GalaxyCheck.Xunit/Internal/PropertyTestCase.cs b/src/GalaxyCheck.Xunit/Internal/PropertyTestCase.cs index 91ddabcc..e15d6a10 100644 --- a/src/GalaxyCheck.Xunit/Internal/PropertyTestCase.cs +++ b/src/GalaxyCheck.Xunit/Internal/PropertyTestCase.cs @@ -7,7 +7,7 @@ using Xunit.Abstractions; using Xunit.Sdk; -namespace GalaxyCheck.Xunit.Internal +namespace GalaxyCheck.Internal { public class PropertyTestCase : XunitTestCase { @@ -72,7 +72,8 @@ RunSummary Skip(string reason) TestMethod.TestClass.Class.ToRuntimeType(), TestMethod.Method.ToRuntimeMethod(), constructorArguments, - new DefaultPropertyFactory()); + new DefaultPropertyFactory(), + GlobalConfiguration.Instance); } catch (Exception exception) { diff --git a/src/GalaxyCheck.Xunit/PropertyAttribute.cs b/src/GalaxyCheck.Xunit/PropertyAttribute.cs index b27ab3ac..d05e40a0 100644 --- a/src/GalaxyCheck.Xunit/PropertyAttribute.cs +++ b/src/GalaxyCheck.Xunit/PropertyAttribute.cs @@ -1,4 +1,4 @@ -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using Xunit; using Xunit.Sdk; @@ -6,12 +6,46 @@ namespace GalaxyCheck { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - [XunitTestCaseDiscoverer("GalaxyCheck.Xunit.Internal.PropertyDiscoverer", "GalaxyCheck.Xunit")] + [XunitTestCaseDiscoverer("GalaxyCheck.Internal.PropertyDiscoverer", "GalaxyCheck.Xunit")] public class PropertyAttribute : FactAttribute { - public int ShrinkLimit { get; set; } = 500; + public int Iterations + { + get + { + if (NullableIterations == null) + { + throw new InvalidOperationException($"{nameof(Iterations)} was not set, and does not have a default value"); + } + + throw new InvalidOperationException(""); + } + set + { + NullableIterations = value; + } + } + + internal int? NullableIterations { get; private set; } + + public int ShrinkLimit + { + get + { + if (NullableShrinkLimit == null) + { + throw new InvalidOperationException($"{nameof(ShrinkLimit)} was not set, and does not have a default value"); + } + + throw new InvalidOperationException(""); + } + set + { + NullableShrinkLimit = value; + } + } - public int Iterations { get; set; } = 100; + internal int? NullableShrinkLimit { get; private set; } public int Seed { diff --git a/src/GalaxyCheck.Xunit/SampleAttribute.cs b/src/GalaxyCheck.Xunit/SampleAttribute.cs index 08277e4a..76149f03 100644 --- a/src/GalaxyCheck.Xunit/SampleAttribute.cs +++ b/src/GalaxyCheck.Xunit/SampleAttribute.cs @@ -1,11 +1,11 @@ -using GalaxyCheck.Xunit.Internal; +using GalaxyCheck.Internal; using System; using Xunit.Sdk; namespace GalaxyCheck { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - [XunitTestCaseDiscoverer("GalaxyCheck.Xunit.Internal.PropertyDiscoverer", "GalaxyCheck.Xunit")] + [XunitTestCaseDiscoverer("GalaxyCheck.Internal.PropertyDiscoverer", "GalaxyCheck.Xunit")] public class SampleAttribute : PropertyAttribute { internal override IPropertyRunner Runner => new PropertySampleRunner(); diff --git a/src/GalaxyCheck/Runners/Assert.cs b/src/GalaxyCheck/Runners/Assert.cs index 5801014a..28aceac5 100644 --- a/src/GalaxyCheck/Runners/Assert.cs +++ b/src/GalaxyCheck/Runners/Assert.cs @@ -21,7 +21,7 @@ public static void Assert( Func? formatMessage = null) { var checkResult = property.Check(iterations: iterations, seed: seed, size: size, shrinkLimit: shrinkLimit, replay: replay, deepCheck: deepCheck); - ThrowIfFalsified(checkResult); + ThrowIfFalsified(checkResult, formatReproduction, formatMessage); } public static async Task AssertAsync( @@ -36,13 +36,13 @@ public static async Task AssertAsync( Func? formatMessage = null) { var checkResult = await property.CheckAsync(iterations: iterations, seed: seed, size: size, shrinkLimit: shrinkLimit, replay: replay, deepCheck: deepCheck); - ThrowIfFalsified(checkResult); + ThrowIfFalsified(checkResult, formatReproduction, formatMessage); } private static void ThrowIfFalsified( CheckResult checkResult, - Func? formatReproduction = null, - Func? formatMessage = null) + Func? formatReproduction, + Func? formatMessage) { if (checkResult.Falsified) {