Skip to content

Commit

Permalink
Small improvements on specs/tests (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Jan 21, 2024
1 parent d6b3f20 commit 566d7c7
Show file tree
Hide file tree
Showing 57 changed files with 445 additions and 448 deletions.
8 changes: 4 additions & 4 deletions props/common.props
Expand Up @@ -51,13 +51,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PolySharp" Version="1.*" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="PolySharp" Version="1.*" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Label="Analyzers">
<PackageReference Include="AsyncFixer" Version="*" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="DotNetProjectFile.Analyzers" Version="*" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="*" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="AsyncFixer" Version="*" PrivateAssets="all" />
<PackageReference Include="DotNetProjectFile.Analyzers" Version="*" Condition="'$(TargetFramework)'=='net8.0'" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="*" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Label="Additional files">
Expand Down
2 changes: 2 additions & 0 deletions specs/.editorconfig
Expand Up @@ -3,6 +3,8 @@
[*]
dotnet_diagnostic.CA1861.severity = none # Prefer 'static readonly' fields over constant array arguments

dotnet_diagnostic.S1133.severity = none # Deprecated code should be removed
dotnet_diagnostic.S3900.severity = none # Arguments of public methods should be validated against null

dotnet_diagnostic.SYSLIB1045.severity = none # Convert to 'GeneratedRegexAttribute'.

6 changes: 6 additions & 0 deletions specs/Qowaiv.Benchmarks/IbanBenchmark.Reference.cs
Expand Up @@ -25,6 +25,8 @@ public static class RegexBased
{
var str = buffer.ToString();

#pragma warning disable S1067 // Expressions should not be too complex
// This code is here just for reference purposes.
if (Country.TryParse(str[..2], out var country)
&& !country.IsEmptyOrUnknown()
&& (LocalizedPatterns.TryGetValue(country, out var localizedPattern)
Expand All @@ -38,6 +40,7 @@ public static class RegexBased
{
return null;
}
#pragma warning restore S1067 // Expressions should not be too complex

}
else if (Qowaiv.Unknown.IsUnknown(buffer))
Expand All @@ -54,6 +57,8 @@ public static class RegexBased
{
return null;
}
#pragma warning disable S1067 // Expressions should not be too complex
// here for reference only.
else if (Qowaiv.Unknown.IsUnknown(str))
{
return "ZZ";
Expand All @@ -65,6 +70,7 @@ public static class RegexBased
{
return str;
}
#pragma warning restore S1067 // Expressions should not be too complex
return null;
}

Expand Down
3 changes: 3 additions & 0 deletions specs/Qowaiv.Benchmarks/Properties/GlobalUsings.cs
Expand Up @@ -4,9 +4,12 @@
global using Qowaiv.Financial;
global using Qowaiv.Globalization;
global using Qowaiv.Text;
global using System;
global using System.Collections;
global using System.Collections.Generic;
global using System.Diagnostics.CodeAnalysis;
global using System.Diagnostics.Contracts;
global using System.Globalization;
global using System.Linq;
global using System.Text;
global using System.Text.RegularExpressions;
11 changes: 9 additions & 2 deletions specs/Qowaiv.Benchmarks/Qowaiv.Benchmarks.csproj
@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\props\nopackage.props" />

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>Benchmarks</RootNamespace>
</PropertyGroup>

Expand All @@ -21,8 +22,14 @@
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
</ItemGroup>

<ItemGroup Label="Analyzers">
<PackageReference Include="FluentAssertions.Analyzers" Version="*" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="*" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Qowaiv\Qowaiv.csproj" />
<ProjectReference Include="..\..\src\Qowaiv.TestTools\Qowaiv.TestTools.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions specs/Qowaiv.Benchmarks/UuidBenchmark.cs
@@ -1,10 +1,12 @@
using Qowaiv;
using Qowaiv.Identifiers;
using Qowaiv.TestTools;

namespace Benchmarks;

public partial class UuidBenchmark
{
[EmptyTestClass]
public sealed class ForUuid : UuidBehavior { }

internal const int Iterations = 1000;
Expand Down
1 change: 0 additions & 1 deletion specs/Qowaiv.Specs/Clock_specs.cs
@@ -1,5 +1,4 @@
using System.Threading;
using System.Threading.Tasks;

namespace Clock_specs;

Expand Down
15 changes: 15 additions & 0 deletions specs/Qowaiv.Specs/Date_span_specs.cs
Expand Up @@ -265,3 +265,18 @@ public void two_date_onlys_based_on_settings(int months, int days, Date d1, Date
}
#endif
}

public class Throws_when
{
[Test]
public void Mutatation_overflows()
=> 1.Invoking(DateSpan.MaxValue.AddDays)
.Should().Throw<OverflowException>()
.WithMessage("DateSpan overflowed because the resulting duration is too long.");

[Test]
public void Ctor_arguments_are_out_of_range()
=> int.MaxValue.Invoking(n => new DateSpan(n, n))
.Should().Throw<ArgumentOutOfRangeException>()
.WithMessage("The specified years, months and days results in an un-representable DateSpan.");
}
4 changes: 1 addition & 3 deletions specs/Qowaiv.Specs/Debug_specs.cs
@@ -1,6 +1,4 @@
using Qowaiv.OpenApi;

namespace Debug_specs;
namespace Debug_specs;

public class Type_is
{
Expand Down
5 changes: 3 additions & 2 deletions specs/Qowaiv.Specs/Email_address_specs.cs
Expand Up @@ -169,8 +169,9 @@ public void from_valid_input_only_otherwise_throws_on_Parse()
{
using (TestCultures.en_GB.Scoped())
{
var exception = Assert.Throws<FormatException>(() => EmailAddress.Parse("invalid input"));
exception.Message.Should().Be("Not a valid email address");
"invalid input".Invoking(EmailAddress.Parse)
.Should().Throw<FormatException>()
.WithMessage("Not a valid email address");
}
}

Expand Down
13 changes: 13 additions & 0 deletions specs/Qowaiv.Specs/Financial/Currency_specs.cs
Expand Up @@ -117,3 +117,16 @@ public void throws_for_invalid_json(object json, Type exceptionType)
.Should().Throw<Exception>()
.And.Should().BeOfType(exceptionType);
}

public class Is_equal_by_value
{
[TestCase("", 0)]
[TestCase("EUR", -943833935)]
public void hash_code_is_value_based(Currency svo, int hash)
{
using (Hash.WithoutRandomizer())
{
svo.GetHashCode().Should().Be(hash);
}
}
}
25 changes: 25 additions & 0 deletions specs/Qowaiv.Specs/Financial/Money_specs.cs
Expand Up @@ -106,3 +106,28 @@ public void to_divide_money_by_money_with_different_currencies_is_not_supported(
division.Should().Throw<CurrencyMismatchException>();
}
}

public class Throws_when
{
[Test]
public void adding_multiple_currencies()
{
var euros = 16 + Currency.EUR;
var dollars = 666 + Currency.USD;
var operation = () => euros + dollars;

operation.Should().Throw<CurrencyMismatchException>()
.WithMessage("The addition operation could not be applied. There is a mismatch between EUR and USD.");
}

[Test]
public void subtracting_multiple_currencies()
{
var euros = 16 + Currency.EUR;
var dollars = 666 + Currency.USD;
var operation = () => euros - dollars;

operation.Should().Throw<CurrencyMismatchException>()
.WithMessage("The subtraction operation could not be applied. There is a mismatch between EUR and USD.");
}
}
21 changes: 21 additions & 0 deletions specs/Qowaiv.Specs/Formatting/Formatting_arguments_specs.cs
@@ -1,5 +1,26 @@
namespace Formatting_arguments_specs;

public class Is_equal_by_value
{
[Test]
public void hash_code_is_value_based_for_none()
{
using (Hash.WithoutRandomizer())
{
FormattingArguments.None.GetHashCode().Should().Be(0);
}
}

[Test]
public void hash_code_is_value_based_for_value()
{
using (Hash.WithoutRandomizer())
{
new FormattingArguments("f", null).GetHashCode().Should().Be(-362413457);
}
}
}

public class ToString
{
[Test]
Expand Down
2 changes: 1 addition & 1 deletion specs/Qowaiv.Specs/Globalization/Countries_specs.cs
Expand Up @@ -2,7 +2,7 @@

public class All
{
private static readonly Country[] all = Country.All.ToArray();
private static readonly Country[] all = [.. Country.All];

[TestCaseSource(nameof(all))]
public void Has_constant(Country country)
Expand Down
22 changes: 22 additions & 0 deletions specs/Qowaiv.Specs/Globalization/Country_specs.cs
Expand Up @@ -11,6 +11,14 @@ public class With_domain_logic
[TestCase(false, "?")]
[TestCase(false, "")]
public void IsKnown_is(bool result, Country svo) => svo.IsKnown.Should().Be(result);

/// <remarks>
/// As the regions available depend on the environment running, we can't
/// predict the outcome.
/// </remarks>
[TestCaseSource(typeof(Country), nameof(Country.All))]
public void RegionInfo_exists_indicates_counterpart_exists(Country country)
=> country.Invoking(c => c.RegionInfoExists).Should().NotThrow();
}

public class Display_name
Expand Down Expand Up @@ -210,6 +218,19 @@ public void storing_value_in_SerializationInfo()
}
#endif

public class Is_equal_by_value
{
[TestCase("", 0)]
[TestCase("NL", -1174190069)]
public void hash_code_is_value_based(Country svo, int hash)
{
using (Hash.WithoutRandomizer())
{
svo.GetHashCode().Should().Be(hash);
}
}
}

public class Can_parse
{
[Test]
Expand All @@ -220,3 +241,4 @@ public void prefering_existing_over_former_countries()
public void former_countries_via_ISO_3166_3()
=> Country.Parse("BQAQ").Should().Be(Country.BQAQ);
}

93 changes: 93 additions & 0 deletions specs/Qowaiv.Specs/Identifiers/ID_Cast_specs.cs
@@ -0,0 +1,93 @@
namespace Identifiers.Id_specs;

public class Create
{
[Test]
public void string_from_null_is_empty()
=> StringId.Create(null).Should().Be(StringId.Empty);

[Test]
public void Guid_from_null_is_empty()
=> CustomGuid.Create(null).Should().Be(CustomGuid.Empty);
[Test]
public void long_from_null_is_empty()
=> Int64Id.Create(null).Should().Be(Int64Id.Empty);
}

public class Casts_from
{
[Test]
public void GUID_to_GUID_based_id()
{
var guid = Guid.Parse("AD38ECD4-020F-475C-9318-DFF2067DA1D4");
var casted = (CustomGuid)guid;
casted.Should().Be(CustomGuid.Parse("AD38ECD4-020F-475C-9318-DFF2067DA1D4"));
}

[Test]
public void GUID_to_string_based_id()
{
var guid = Guid.Parse("ad38ecd4-020f-475c-9318-dff2067da1d4");
var casted = (StringId)guid;
casted.Should().Be(StringId.Parse("ad38ecd4-020f-475c-9318-dff2067da1d4"));
}

[Test]
public void long_to_long_based_id()
{
var id = 12345L;
var casted = (Int64Id)id;
casted.Should().Be(Int64Id.Create(12345L));
}

[Test]
public void long_to_string_based_id()
{
var id = 12345L;
var casted = (StringId)id;
casted.Should().Be(StringId.Parse("12345"));
}

[Test]
public void string_to_long_based_id()
{
var id = "12345";
var casted = (Int64Id)id;
casted.Should().Be(Int64Id.Create(12345L));
}
}

public class Can_not_cast_from
{
[Test]
public void invalid_string_for_long()
=> "NaN".Invoking(Int64Id.Create)
.Should().Throw<InvalidCastException>()
.WithMessage("Cast from string to Qowaiv.Identifiers.Id<Qowaiv.TestTools.ForInt64> is not valid.");

[Test]
public void non_numeric_string_to_long()
=> "ABC".Invoking(id => (Int64Id)id)
.Should().Throw<InvalidCastException>();

[Test]
public void GUID_to_long()
=> Guid.NewGuid().Invoking(id => (Int64Id)id)
.Should().Throw<InvalidCastException>();

[Test]
public void non_GUID_string_to_GUID()
=> "ABC".Invoking(id => (CustomGuid)id)
.Should().Throw<InvalidCastException>();

[Test]
public void long_to_GUID()
=> ((object)123546L).Invoking(id => (CustomGuid)id)
.Should().Throw<InvalidCastException>();

[Test]
public void invalid_JSON_input()
=> (-1L).Invoking(Int64Id.FromJson)
.Should().Throw<InvalidCastException>();
}

0 comments on commit 566d7c7

Please sign in to comment.