From fb3dacfaba2cf00d29ddcfe43499beacc6379417 Mon Sep 17 00:00:00 2001 From: remyvd Date: Sun, 29 Mar 2020 18:11:54 +0200 Subject: [PATCH] Merged projects, improved testing and removed .NET 4.0-4.5 support - merged NodaMoney.Serialization.AspNet with NodaMoney - improved ISO4127 testing and enabled them - Fix #79 - removed .NET 4.0 and .NET 4.5 support --- NodaMoney.sln | 7 - .../GlobalSuppressions.cs | Bin 1492 -> 0 bytes .../NodaMoney.Serialization.AspNet.csproj | 30 -- src/NodaMoney/NodaMoney.csproj | 13 +- .../MoneyJavaScriptConverter.cs | 8 +- tests/NodaMoney.Tests/CurrencyBuilderSpec.cs | 4 + tests/NodaMoney.Tests/CurrencySpec.cs | 320 ++++-------------- tests/NodaMoney.Tests/ExchangeRateSpec.cs | 4 +- .../MoneyExtensionsSafeDivideSpec.cs | 2 +- .../Helpers/NoParallelization.cs | 12 + tests/NodaMoney.Tests/Helpers/RenderSpecs.cs | 4 +- tests/NodaMoney.Tests/Iso4217Spec.cs | 151 +++++++++ .../MoneyBinaryOperatorsSpec.cs | 122 ++++--- tests/NodaMoney.Tests/MoneyConvertibleSpec.cs | 3 +- .../MoneyFiveMostUsedCurrenciesSpec.cs | 3 +- tests/NodaMoney.Tests/MoneyFormattableSpec.cs | 6 +- tests/NodaMoney.Tests/MoneyParsableSpec.cs | 10 +- tests/NodaMoney.Tests/MoneySpec.cs | 5 +- tests/NodaMoney.Tests/NodaMoney.Tests.csproj | 8 +- tests/NodaMoney.Tests/PerformanceSpec.cs | 72 ++++ tests/NodaMoney.Tests/PerformanceTest.txt | 11 + .../JavaScriptSerializableSpec.cs | 8 +- .../Serialization/MoneySerializableSpec.cs | 3 +- 23 files changed, 425 insertions(+), 381 deletions(-) delete mode 100644 src/NodaMoney.Serialization.AspNet/GlobalSuppressions.cs delete mode 100644 src/NodaMoney.Serialization.AspNet/NodaMoney.Serialization.AspNet.csproj rename src/{NodaMoney.Serialization.AspNet => NodaMoney/Serialization}/MoneyJavaScriptConverter.cs (97%) create mode 100644 tests/NodaMoney.Tests/Helpers/NoParallelization.cs create mode 100644 tests/NodaMoney.Tests/Iso4217Spec.cs create mode 100644 tests/NodaMoney.Tests/PerformanceSpec.cs create mode 100644 tests/NodaMoney.Tests/PerformanceTest.txt diff --git a/NodaMoney.sln b/NodaMoney.sln index b755496..bb85147 100644 --- a/NodaMoney.sln +++ b/NodaMoney.sln @@ -6,7 +6,6 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C8B3C22E-2C66-43E1-B1C3-71E7A384B2C2}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - appveyor.yml = appveyor.yml src\CustomDictionary.xml = src\CustomDictionary.xml src\Directory.build.props = src\Directory.build.props README.md = README.md @@ -14,8 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodaMoney", "src\NodaMoney\NodaMoney.csproj", "{58F0FE5E-E139-4ABF-B9A5-969DBBE69F52}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodaMoney.Serialization.AspNet", "src\NodaMoney.Serialization.AspNet\NodaMoney.Serialization.AspNet.csproj", "{6BBD36B9-D035-4A5D-8770-CC7E30B636A6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodaMoney.Tests", "tests\NodaMoney.Tests\NodaMoney.Tests.csproj", "{CC01DEB3-F862-49A1-9EB5-50A4E52B82E7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{324D342A-2588-4422-AFB1-FA0359EE825D}" @@ -31,10 +28,6 @@ Global {58F0FE5E-E139-4ABF-B9A5-969DBBE69F52}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {58F0FE5E-E139-4ABF-B9A5-969DBBE69F52}.Release|Any CPU.ActiveCfg = Release|Any CPU {58F0FE5E-E139-4ABF-B9A5-969DBBE69F52}.Release|Any CPU.Build.0 = Release|Any CPU - {6BBD36B9-D035-4A5D-8770-CC7E30B636A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BBD36B9-D035-4A5D-8770-CC7E30B636A6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BBD36B9-D035-4A5D-8770-CC7E30B636A6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BBD36B9-D035-4A5D-8770-CC7E30B636A6}.Release|Any CPU.Build.0 = Release|Any CPU {CC01DEB3-F862-49A1-9EB5-50A4E52B82E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CC01DEB3-F862-49A1-9EB5-50A4E52B82E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC01DEB3-F862-49A1-9EB5-50A4E52B82E7}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/src/NodaMoney.Serialization.AspNet/GlobalSuppressions.cs b/src/NodaMoney.Serialization.AspNet/GlobalSuppressions.cs deleted file mode 100644 index 87f97aaa8f618ecd5fa52519983451b6e5dffa80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1492 zcmZ{kL2uJQ5QXQA#D7@jQjlm096=l+5CWtYq@YR&aWIaPm?m~rJ4OBT!24#hBz8fT zwceeXH_tO~_V=%ybyizrD@!)FJMDU_Y->|{qw_-NjkSJSTd8$wueD#uXC_Nw8;_}F zd1(*rfxl;VCbZAC7DA`5rPhri(tc0QN*Kw$D?0r}O!qL8*tGK4DibXG{R-EeUF*3K zQm5y9zrvVIg?xKiYvtJK3op>tZoy6@D<~WJ1*6D^UvMWwYd>Ty6+KnNr@_go|JkkV zo1=g4M(k=~G|r$BF6fm|lCvQ;d6nS@FaDs{S?fNT=}M9KHnJ3YJMo59?e#5nGK?9;{*QRNw-o|7g?uV|;`TfD)eWu5GrPp++P(E@5yJ3H# z0y+PozF8aK)2)?i(%Y%>(38@xbRP8zKJ+^G7)2bcS(pD(QK)1m%wF;2x)$S5ROU3f zr>Qhj)x;xnU5^s1lykpM8nR+D7=iU=0qSLz+TkZ)oMCTfLP}_+ndS=h{ zJhP`lo(*y_X`OPdg+NCZ_D*b2_NB9|but$+S-6)jbQ(GZol2+u^Fi_4S9t=M`CR8$ z&f`KDR5YgeR#t8<6x#UBLj_8qpuFBsP&@Uff>|qZLoy*r-f{coyX>P+3p$+p|J=wU zXNY-=SqCxZIji}^SuxY_uIxk@S6aCde>xVm;f@4vDUPUuUcsLzlvKzbdU|Z%ygGjX Dy0`|e diff --git a/src/NodaMoney.Serialization.AspNet/NodaMoney.Serialization.AspNet.csproj b/src/NodaMoney.Serialization.AspNet/NodaMoney.Serialization.AspNet.csproj deleted file mode 100644 index ec5389d..0000000 --- a/src/NodaMoney.Serialization.AspNet/NodaMoney.Serialization.AspNet.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - NodaMoney.Serialization.AspNet - NodaMoney.Serialization.AspNet - JavaScriptSerializer support for NodaMoney structures. - true - NodaMoney.Serialization.AspNet - Noda;Money;Currency;ExchangeRate;Serialization - net40;net45 - latest - - - - - - - - - - - - - - - - - - - diff --git a/src/NodaMoney/NodaMoney.csproj b/src/NodaMoney/NodaMoney.csproj index 81948d2..1b5e09a 100644 --- a/src/NodaMoney/NodaMoney.csproj +++ b/src/NodaMoney/NodaMoney.csproj @@ -1,4 +1,4 @@ - + NodaMoney @@ -7,7 +7,7 @@ true NodaMoney Noda;Money;Currency;ExchangeRate - netcoreapp3.1;netstandard2.0;netstandard2.1;net40;net461 + netcoreapp3.1;netstandard2.0;netstandard2.1; latest disable @@ -39,11 +39,10 @@ - - - - - + + + ..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Web.Extensions.dll + diff --git a/src/NodaMoney.Serialization.AspNet/MoneyJavaScriptConverter.cs b/src/NodaMoney/Serialization/MoneyJavaScriptConverter.cs similarity index 97% rename from src/NodaMoney.Serialization.AspNet/MoneyJavaScriptConverter.cs rename to src/NodaMoney/Serialization/MoneyJavaScriptConverter.cs index 40f091a..0a64682 100644 --- a/src/NodaMoney.Serialization.AspNet/MoneyJavaScriptConverter.cs +++ b/src/NodaMoney/Serialization/MoneyJavaScriptConverter.cs @@ -1,10 +1,11 @@ -using System; +#if !NETCOREAPP + using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Web.Script.Serialization; -namespace NodaMoney.Serialization.AspNet +namespace NodaMoney.Serialization { /// Provides a custom Money converter for the JavaScriptSerializer in ASP.NET. /// @@ -62,4 +63,5 @@ public override IDictionary Serialize(object obj, JavaScriptSeri return dictionary; } } -} \ No newline at end of file +} +#endif diff --git a/tests/NodaMoney.Tests/CurrencyBuilderSpec.cs b/tests/NodaMoney.Tests/CurrencyBuilderSpec.cs index 04dfc2e..9f620aa 100644 --- a/tests/NodaMoney.Tests/CurrencyBuilderSpec.cs +++ b/tests/NodaMoney.Tests/CurrencyBuilderSpec.cs @@ -1,9 +1,11 @@ using System; using FluentAssertions; using Xunit; +using NodaMoney.Tests.Helpers; namespace NodaMoney.Tests.CurrencyBuilderSpec { + [Collection(nameof(NoParallelization))] public class GivenIWantToCreateCustomCurrency { [Fact] @@ -151,6 +153,7 @@ public void WhenSymbolIsEmpty_ThenSymbolMustBeDefaultCurrencySign() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToUnregisterCurrency { [Fact] @@ -225,6 +228,7 @@ public void WhenNamespaceIsEmpty_ThenThrowException() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToReplaceIsoCurrencyWithOwnVersion { [Fact] diff --git a/tests/NodaMoney.Tests/CurrencySpec.cs b/tests/NodaMoney.Tests/CurrencySpec.cs index 6af83fb..57484c5 100644 --- a/tests/NodaMoney.Tests/CurrencySpec.cs +++ b/tests/NodaMoney.Tests/CurrencySpec.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using FluentAssertions; using Xunit; using System.Xml.Serialization; -using System.Xml.Linq; -using System.Threading.Tasks; -using System.Net; namespace NodaMoney.Tests.CurrencySpec { @@ -24,72 +20,72 @@ public void WhenAskingForIt_ThenAllCurrenciesShouldBeReturned() currencies.Count().Should().BeGreaterThan(100); } - [Fact(Skip = "For debugging.")] - public void WriteAllRegionsToFile() - { - using (var stream = File.Open(@"..\..\Regions.txt", FileMode.Create)) - using (var writer = new StreamWriter(stream)) - { - foreach (var c in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) - { - var reg = new RegionInfo(c.LCID); - writer.WriteLine("CultureName: {0}", c.Name); - writer.WriteLine("CultureEnglishName: {0}", c.EnglishName); - writer.WriteLine("Name: {0}", reg.Name); - writer.WriteLine("NativeName: {0}", reg.NativeName); - writer.WriteLine("EnglishName: {0}", reg.EnglishName); - writer.WriteLine("DisplayName: {0}", reg.DisplayName); - writer.WriteLine("CurrencySymbol: {0}", reg.CurrencySymbol); - writer.WriteLine("ISOCurrencySymbol: {0}", reg.ISOCurrencySymbol); - writer.WriteLine("CurrencyEnglishName: {0}", reg.CurrencyEnglishName); - writer.WriteLine("CurrencyNativeName: {0}", reg.CurrencyNativeName); - writer.WriteLine(string.Empty); - } - } - } - - [Fact(Skip = "For debugging.")] - public void WriteAllCurrenciesToFile() - { - using (var stream = File.Open(@"..\..\ISOCurrencies1.txt", FileMode.Create)) - using (var writer = new StreamWriter(stream)) - { - foreach (var currency in Currency.GetAllCurrencies()) - { - writer.WriteLine("EnglishName: {0}", currency.EnglishName); - writer.WriteLine("Code: {0}, Number: {1}, Sign: {2}", currency.Code, currency.Number, currency.Symbol); - writer.WriteLine( - "MajorUnit: {0}, MinorUnit: {1}, DecimalDigits: {2}", - currency.MajorUnit, - currency.MinorUnit, - currency.DecimalDigits); - writer.WriteLine(string.Empty); - } - } - } - - [Fact(Skip = "For debugging.")] - public void WriteAllCurrencySymbolsToFile() - { - var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); - var symbolLookup = new Dictionary(); - - using (var stream = File.Open(@"..\..\ISOSymbols.txt", FileMode.Create)) - using (var writer = new StreamWriter(stream)) - { - foreach (var culture in cultures) - { - var regionInfo = new RegionInfo(culture.LCID); - symbolLookup[regionInfo.ISOCurrencySymbol] = regionInfo.CurrencySymbol; - } - - foreach (var keyvalue in symbolLookup.OrderBy(s => s.Key)) - { - writer.WriteLine("Code: {0}, Sign: {1}", keyvalue.Key, keyvalue.Value); - writer.WriteLine(string.Empty); - } - } - } + //// [Fact(Skip = "For debugging.")] + //public void WriteAllRegionsToFile() + //{ + // using (var stream = File.Open(@"..\..\Regions.txt", FileMode.Create)) + // using (var writer = new StreamWriter(stream)) + // { + // foreach (var c in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) + // { + // var reg = new RegionInfo(c.LCID); + // writer.WriteLine("CultureName: {0}", c.Name); + // writer.WriteLine("CultureEnglishName: {0}", c.EnglishName); + // writer.WriteLine("Name: {0}", reg.Name); + // writer.WriteLine("NativeName: {0}", reg.NativeName); + // writer.WriteLine("EnglishName: {0}", reg.EnglishName); + // writer.WriteLine("DisplayName: {0}", reg.DisplayName); + // writer.WriteLine("CurrencySymbol: {0}", reg.CurrencySymbol); + // writer.WriteLine("ISOCurrencySymbol: {0}", reg.ISOCurrencySymbol); + // writer.WriteLine("CurrencyEnglishName: {0}", reg.CurrencyEnglishName); + // writer.WriteLine("CurrencyNativeName: {0}", reg.CurrencyNativeName); + // writer.WriteLine(string.Empty); + // } + // } + //} + + //// [Fact(Skip = "For debugging.")] + //public void WriteAllCurrenciesToFile() + //{ + // using (var stream = File.Open(@"..\..\ISOCurrencies1.txt", FileMode.Create)) + // using (var writer = new StreamWriter(stream)) + // { + // foreach (var currency in Currency.GetAllCurrencies()) + // { + // writer.WriteLine("EnglishName: {0}", currency.EnglishName); + // writer.WriteLine("Code: {0}, Number: {1}, Sign: {2}", currency.Code, currency.Number, currency.Symbol); + // writer.WriteLine( + // "MajorUnit: {0}, MinorUnit: {1}, DecimalDigits: {2}", + // currency.MajorUnit, + // currency.MinorUnit, + // currency.DecimalDigits); + // writer.WriteLine(string.Empty); + // } + // } + //} + + //// [Fact(Skip = "For debugging.")] + //public void WriteAllCurrencySymbolsToFile() + //{ + // var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); + // var symbolLookup = new Dictionary(); + + // using (var stream = File.Open(@"..\..\ISOSymbols.txt", FileMode.Create)) + // using (var writer = new StreamWriter(stream)) + // { + // foreach (var culture in cultures) + // { + // var regionInfo = new RegionInfo(culture.LCID); + // symbolLookup[regionInfo.ISOCurrencySymbol] = regionInfo.CurrencySymbol; + // } + + // foreach (var keyvalue in symbolLookup.OrderBy(s => s.Key)) + // { + // writer.WriteLine("Code: {0}, Sign: {1}", keyvalue.Key, keyvalue.Value); + // writer.WriteLine(string.Empty); + // } + // } + //} } public class GivenIWantCurrencyFromIsoCode @@ -428,40 +424,6 @@ public static string StreamToString(Stream stream) } } - public class GivenIWantToUseALotOfCurrencies - { - [Fact] - public void WhenCreatingOneMillion_ThenItShouldBeWithinFourSeconds() - { - var sw = Stopwatch.StartNew(); - var c = Currency.FromCode("EUR"); - // Console.WriteLine("{0} ms for first call.", sw.ElapsedMilliseconds); - - double max = 1000000; - Action action = () => - { - sw.Restart(); - for (int i = 0; i < max; i++) - { - if (i % 3 == 0) - c = Currency.FromCode("EUR"); - else if (i % 2 == 0) - c = Currency.FromCode("USD"); - else - c = Currency.FromCode("JPY"); - } - sw.Stop(); - }; - - action.ExecutionTime().Should().BeLessOrEqualTo(new TimeSpan(0, 0, 4)); - // Console.WriteLine( - // "{0} ms for creating {1:N0} currencies (avg {2:F5} ms).", - // sw.ElapsedMilliseconds, - // max, - // sw.ElapsedMilliseconds / (max)); - } - } - public class GivenIWantToDeconstructCurrency { [Fact] @@ -522,154 +484,4 @@ public void WhenValidatingACurrencyThatIsValidFromACertainDate_ThenShouldBeValid currency.IsValidOn(new DateTime(2018, 8, 20)).Should().BeTrue(); } } - - public class GivenIWantToCompareCurrenciesToIsoXML - { - private IEnumerable _definedCurrencies; - private IEnumerable _isoCurrencies; - - private const string FilePath = @"..\..\iso.xml"; - private bool FileFound { get; set; } - private DateTime Date { get; set; } - - private class IsoCurrency - { - public string CountryName { get; set; } - public string CurrencyName { get; set; } - public string Currency { get; set; } - public string CurrencyNumber { get; set; } - public string CurrencyMinorUnits { get; set; } - } - - public GivenIWantToCompareCurrenciesToIsoXML() - { - _definedCurrencies = - Currency.GetAllCurrencies() - .ToList(); - - FileFound = File.Exists(FilePath); - if (!FileFound) return; - - var document = XDocument.Load(FilePath); - - _isoCurrencies = - document - .Element("ISO_4217") - .Element("CcyTbl") - .Elements("CcyNtry") - .Select(e => - new IsoCurrency - { - CountryName = e.Element("CtryNm").Value, - CurrencyName = e.Element("CcyNm")?.Value, - Currency = e.Element("Ccy")?.Value, - CurrencyNumber = e.Element("CcyNbr")?.Value, - CurrencyMinorUnits = e.Element("CcyMnrUnts")?.Value - }) - .Where(a => !string.IsNullOrEmpty(a.Currency)) // ignore currencies without a currency name - .ToList(); - - Date = DateTime.Parse(document.Element("ISO_4217").Attribute("Pblshd").Value); - } - - [Fact(Skip = "For debugging.")] - public void WhenCurrenciesInISOList_ThenShouldBeDefinedInRegistry() - { - if (!FileFound) return; - - var missingCurrencies = - _isoCurrencies - .Where(a => !_definedCurrencies.Any(c => c.Code == a.Currency)) - .ToList(); - - missingCurrencies.Should().HaveCount(0, $"expected defined currencies to contain {string.Join(", ", missingCurrencies.Select(a => a.Currency + " " + a.CurrencyName))}"); - } - - [Fact(Skip = "For debugging.")] - public void WhenCurrenciesInRegistryAndCurrent_ThenTheyShouldAlsoBeDefinedInTheIsoList() - { - if (!FileFound) return; - - var notDefinedCurrencies = - _definedCurrencies - .Where(c => c.IsValidOn(Date)) - .Where(c => !string.IsNullOrEmpty(c.Number)) - .Where(c => !_isoCurrencies.Any(a => a.Currency == c.Code)) - .ToList(); - - notDefinedCurrencies.Should().HaveCount(0, $"did not expect currencies to contain {string.Join(", ", notDefinedCurrencies.Select(a => a.Code))}"); - } - - [Fact(Skip = "For debugging.")] - public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameEnglishName() - { - if (!FileFound) return; - - var differences = new List(); - foreach (var c in _definedCurrencies) - { - var found = _isoCurrencies.Where(x => x.Currency == c.Code).ToList(); - - if (found.Count == 0) continue; - var a = found.First(); - // ignore casing (for now) - if (!string.Equals(c.EnglishName, a.CurrencyName, StringComparison.InvariantCultureIgnoreCase)) - { - differences.Add($"{ c.Code}: expected '{a.CurrencyName}' but found '{c.EnglishName}'"); - } - } - differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); - } - - [Fact(Skip = "For debugging.")] - public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameNumber() - { - if (!FileFound) return; - - var differences = new List(); - foreach (var c in _definedCurrencies) - { - var found = _isoCurrencies.Where(x => x.Currency == c.Code).ToList(); - - if (found.Count == 0) continue; - var a = found.First(); - // ignore casing (for now) - if (!string.Equals(c.Number, a.CurrencyNumber, StringComparison.InvariantCultureIgnoreCase)) - { - differences.Add($"{c.Code}: expected {a.CurrencyNumber} but found {c.Number}"); - } - } - differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); - } - - [Fact(Skip = "For debugging.")] - public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameNumberOfMinorDigits() - { - if (!FileFound) return; - - var differences = new List(); - foreach (var c in _definedCurrencies) - { - var found = _isoCurrencies.Where(x => x.Currency == c.Code).ToList(); - - if (found.Count == 0) continue; - var a = found.First(); - if (!string.Equals(c.DecimalDigits.ToString(), a.CurrencyMinorUnits, StringComparison.InvariantCultureIgnoreCase)) - { - if (c.DecimalDigits == -1 && a.CurrencyMinorUnits == "N.A.") continue; - differences.Add($"{c.Code}: expected {a.CurrencyMinorUnits} minor units but found {c.DecimalDigits}"); - } - } - differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); - } - - [Fact(Skip = "For debugging.")] - public async Task UpdateTheStoredIsoFileOnDisk() - { - using (var client = new WebClient()) - { - await client.DownloadFileTaskAsync(new Uri("https://www.currency-iso.org/dam/downloads/lists/list_one.xml"), FilePath); - } - } - } } diff --git a/tests/NodaMoney.Tests/ExchangeRateSpec.cs b/tests/NodaMoney.Tests/ExchangeRateSpec.cs index 45e13fe..6b13ae5 100644 --- a/tests/NodaMoney.Tests/ExchangeRateSpec.cs +++ b/tests/NodaMoney.Tests/ExchangeRateSpec.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; - using FluentAssertions; using Xunit; using NodaMoney.Tests.Helpers; @@ -220,6 +219,7 @@ public void WhenBaseAndQuoteCurrencyAreTheSame_ThenCreatingShouldThrow() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToConvertExchangeRateToString { ExchangeRate fx = new ExchangeRate(Currency.FromCode("EUR"), Currency.FromCode("USD"), 1.2524); @@ -237,6 +237,7 @@ public void WhenShowingExchangeRateInNetherlands_ThenReturnCurrencyPairWithComma } } + [Collection(nameof(NoParallelization))] public class GivenIWantToParseACurrencyPair { [Fact, UseCulture("en-US")] @@ -304,6 +305,7 @@ public void WhenCurrencyPairIsEmpty_ThenThrowException() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToTryParseACurrencyPair { [Fact, UseCulture("en-US")] diff --git a/tests/NodaMoney.Tests/Extensions/MoneyExtensionsSafeDivideSpec.cs b/tests/NodaMoney.Tests/Extensions/MoneyExtensionsSafeDivideSpec.cs index aa76298..1c46fe9 100644 --- a/tests/NodaMoney.Tests/Extensions/MoneyExtensionsSafeDivideSpec.cs +++ b/tests/NodaMoney.Tests/Extensions/MoneyExtensionsSafeDivideSpec.cs @@ -4,7 +4,7 @@ using Xunit; using NodaMoney.Extensions; -namespace NodaMoney.Tests.Extensions +namespace NodaMoney.Tests.Extensions.MoneyExtensionsSafeDivideSpec { public class GivenIWantToSafelyDivideMoney { diff --git a/tests/NodaMoney.Tests/Helpers/NoParallelization.cs b/tests/NodaMoney.Tests/Helpers/NoParallelization.cs new file mode 100644 index 0000000..07146d7 --- /dev/null +++ b/tests/NodaMoney.Tests/Helpers/NoParallelization.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace NodaMoney.Tests.Helpers +{ + [CollectionDefinition(nameof(NoParallelization), DisableParallelization = true)] + public class NoParallelization + { + // Place [Collection(nameof(NoParallelization))] as attribute on a test class and it wiil become a parallel-disabled test + // collection. Parallel-capable test collections will be run first (in parallel), followed by parallel-disabled test + // collections (run sequentially). See https://xunit.net/docs/running-tests-in-parallel.html for more info. + } +} diff --git a/tests/NodaMoney.Tests/Helpers/RenderSpecs.cs b/tests/NodaMoney.Tests/Helpers/RenderSpecs.cs index f888a17..bc15656 100644 --- a/tests/NodaMoney.Tests/Helpers/RenderSpecs.cs +++ b/tests/NodaMoney.Tests/Helpers/RenderSpecs.cs @@ -9,13 +9,13 @@ namespace NodaMoney.Tests.Helpers { public class RenderSpecs { - [Fact(Skip="x")] + // [Fact] public void Rendering() { Render("", Console.Out); } - [Fact] + // [Fact] public void RenderAllSpecs() { using (var stream = File.Open(@"Specs.txt", FileMode.Create)) diff --git a/tests/NodaMoney.Tests/Iso4217Spec.cs b/tests/NodaMoney.Tests/Iso4217Spec.cs new file mode 100644 index 0000000..b78a61d --- /dev/null +++ b/tests/NodaMoney.Tests/Iso4217Spec.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using System.Threading.Tasks; +using System.Net; +using Xunit; +using FluentAssertions; + +namespace NodaMoney.Tests.Iso4127Spec +{ + public class Iso4127ListFixture + { + public Iso4127Currency[] currencies { get; private set; } + public DateTime PublishDate { get; private set; } + + public Iso4127ListFixture() + { + var fileName = "iso4127.xml"; + + ServicePointManager.Expect100Continue = true; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + using var client = new WebClient(); + client.DownloadFile(new Uri("https://www.currency-iso.org/dam/downloads/lists/list_one.xml"), fileName); + + var document = XDocument.Load(fileName); + + currencies = document.Element("ISO_4217").Element("CcyTbl").Elements("CcyNtry") + .Select(e => + new Iso4127Currency + { + CountryName = e.Element("CtryNm").Value, + CurrencyName = e.Element("CcyNm")?.Value, + Currency = e.Element("Ccy")?.Value, + CurrencyNumber = e.Element("CcyNbr")?.Value, + CurrencyMinorUnits = e.Element("CcyMnrUnts")?.Value + }) + .Where(a => !string.IsNullOrEmpty(a.Currency)) // ignore currencies without a currency name + .ToArray(); + + PublishDate = DateTime.Parse(document.Element("ISO_4217").Attribute("Pblshd").Value); + } + } + + public class Iso4127Currency + { + public string CountryName { get; set; } + public string CurrencyName { get; set; } + public string Currency { get; set; } + public string CurrencyNumber { get; set; } + public string CurrencyMinorUnits { get; set; } + } + + public class GivenIWantToCompareNodaMoneyWithIso4127 : IClassFixture + { + private Iso4127ListFixture _iso4127List; + + public GivenIWantToCompareNodaMoneyWithIso4127(Iso4127ListFixture fixture) + { + _iso4127List = fixture; + } + + [Fact] + public void WhenCurrenciesInIso4127List_ThenShouldAlsoExistInNodaMoney() + { + var missingCurrencies = _iso4127List.currencies + .Where(a => !Currency.GetAllCurrencies().Any(c => c.Code == a.Currency)) + .ToList(); + + missingCurrencies.Should().HaveCount(0, $"expected defined currencies to contain {string.Join(", ", missingCurrencies.Select(a => a.Currency + " " + a.CurrencyName))}"); + } + + [Fact] + public void WhenCurrenciesInRegistryAndCurrent_ThenTheyShouldAlsoBeDefinedInTheIsoList() + { + var notDefinedCurrencies = + Currency.GetAllCurrencies() + .Where(c => c.IsValidOn(_iso4127List.PublishDate)) + .Where(c => !string.IsNullOrEmpty(c.Number)) + .Where(c => !_iso4127List.currencies.Any(a => a.Currency == c.Code)) + .ToList(); + + notDefinedCurrencies.Should().HaveCount(0, $"did not expect currencies to contain {string.Join(", ", notDefinedCurrencies.Select(a => a.Code))}"); + } + + [Fact(Skip="Names contains countries at the moment")] + public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameEnglishName() + { + var differences = new List(); + foreach (var c in Currency.GetAllCurrencies()) + { + var found = _iso4127List.currencies.Where(x => x.Currency == c.Code).ToList(); + + if (found.Count == 0) + continue; + var a = found.First(); + // ignore casing (for now) + if (!string.Equals(c.EnglishName, a.CurrencyName, StringComparison.InvariantCultureIgnoreCase)) + { + differences.Add($"{ c.Code}: expected '{a.CurrencyName}' but found '{c.EnglishName}'"); + } + } + differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); + } + + [Fact] + public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameNumber() + { + var differences = new List(); + foreach (var c in Currency.GetAllCurrencies()) + { + var found = _iso4127List.currencies.Where(x => x.Currency == c.Code).ToList(); + + if (found.Count == 0) + continue; + var a = found.First(); + // ignore casing (for now) + if (!string.Equals(c.Number, a.CurrencyNumber, StringComparison.InvariantCultureIgnoreCase)) + { + differences.Add($"{c.Code}: expected {a.CurrencyNumber} but found {c.Number}"); + } + } + differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); + } + + [Fact] + public void WhenCompareCurrencies_ThenTheyShouldHaveTheSameNumberOfMinorDigits() + { + var differences = new List(); + foreach (var c in Currency.GetAllCurrencies()) + { + var found = _iso4127List.currencies.Where(x => x.Currency == c.Code).ToList(); + + if (found.Count == 0) + continue; + var a = found.First(); + if (!string.Equals(c.DecimalDigits.ToString(), a.CurrencyMinorUnits, StringComparison.InvariantCultureIgnoreCase)) + { + if (c.DecimalDigits == CurrencyRegistry.NotApplicable && a.CurrencyMinorUnits == "N.A.") + continue; + if (c.DecimalDigits == CurrencyRegistry.Z07 && a.CurrencyMinorUnits == "2") + continue; + + differences.Add($"{c.Code}: expected {a.CurrencyMinorUnits} minor units but found {c.DecimalDigits}"); + } + } + differences.Should().HaveCount(0, string.Join(Environment.NewLine, differences)); + } + } +} diff --git a/tests/NodaMoney.Tests/MoneyBinaryOperatorsSpec.cs b/tests/NodaMoney.Tests/MoneyBinaryOperatorsSpec.cs index 9c27c49..247977b 100644 --- a/tests/NodaMoney.Tests/MoneyBinaryOperatorsSpec.cs +++ b/tests/NodaMoney.Tests/MoneyBinaryOperatorsSpec.cs @@ -1,16 +1,12 @@ using System; using System.Collections.Generic; - using FluentAssertions; -using FluentAssertions.Common; - -using Xunit; using NodaMoney.Tests.Helpers; -// ReSharper disable All +using Xunit; namespace NodaMoney.Tests.MoneyBinaryOperatorsSpec { - public class GivenIWantToAddAndSubstractMoney + public class GivenIWantToAddAndSubtractMoney { public static IEnumerable TestData => new[] { @@ -49,7 +45,7 @@ public void WhenUsingAdditionMethod_ThenMoneyShouldBeAdded(decimal value1, decim } [Theory, MemberData(nameof(TestData))] - public void WhenUsingSubstractionOperator_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) + public void WhenUsingSubtractionOperator_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) { var money1 = new Money(value1); var money2 = new Money(value2); @@ -62,7 +58,7 @@ public void WhenUsingSubstractionOperator_ThenMoneyShouldBeSubtracted(decimal ex } [Theory, MemberData(nameof(TestData))] - public void WhenUsingSubstractionMethod_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) + public void WhenUsingSubtractionMethod_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) { var money1 = new Money(value1); var money2 = new Money(value2); @@ -75,104 +71,118 @@ public void WhenUsingSubstractionMethod_ThenMoneyShouldBeSubtracted(decimal expe } [Theory, MemberData(nameof(TestData))] - [UseCulture("en-us")] - public void WhenUsingAddtionOperatorWithDecimal_ThenMoneyShouldBeAdded(decimal value1, decimal value2, decimal expected) +#pragma warning disable xUnit1026 // Theory methods should use all of their parameters + public void WhenUsingAdditionOperatorWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); + var money2 = new Money(value2, "USD"); - Money result1 = money1 + value2; - Money result2 = value2 + money1; + Action action = () => { var result = money1 + money2; }; - result1.Should().Be(new Money(expected, "EUR")); - result1.Should().NotBeSameAs(money1); - result2.Should().Be(new Money(expected, "EUR")); - result2.Should().NotBeSameAs(money1); + action.Should().Throw().WithMessage("The requested operation expected the currency*"); } [Theory, MemberData(nameof(TestData))] - [UseCulture("en-us")] - public void WhenUsingAdditionMethodWithDecimal_ThenMoneyShouldBeAdded(decimal value1, decimal value2, decimal expected) + public void WhenUsingAdditionMethodWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); + var money2 = new Money(value2, "USD"); - var result = Money.Add(money1, value2); + Action action = () => Money.Add(money1, money2); - result.Should().Be(new Money(expected, "EUR")); - result.Should().NotBeSameAs(money1); + action.Should().Throw().WithMessage("The requested operation expected the currency*"); } [Theory, MemberData(nameof(TestData))] - [UseCulture("en-us")] - public void WhenUsingSubstractionOperatorWithDecimal_ThenMoneyShouldBeAdded(decimal expected, decimal value2, decimal value1) + public void WhenUsingSubtractionOperatorWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); + var money2 = new Money(value2, "USD"); - Money result1 = money1 - value2; - Money result2 = value2 - money1; + Action action = () => { var result = money1 - money2; }; - result1.Should().Be(new Money(expected, "EUR")); - result1.Should().NotBeSameAs(money1); - result2.Should().Be(new Money(expected, "EUR")); - result2.Should().NotBeSameAs(money1); + action.Should().Throw().WithMessage("The requested operation expected the currency*"); } [Theory, MemberData(nameof(TestData))] - [UseCulture("en-us")] - public void WhenUsingSubstractionMethodWithDecimal_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) + public void WhenUsingSubtractionMethodWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); + var money2 = new Money(value2, "USD"); - var result = Money.Subtract(money1, value2); + Action action = () => Money.Subtract(money1, money2); - result.Should().Be(new Money(expected, "EUR")); - result.Should().NotBeSameAs(money1); + action.Should().Throw().WithMessage("The requested operation expected the currency*"); } +#pragma warning restore xUnit1026 // Theory methods should use all of their parameters + } + + [Collection(nameof(NoParallelization))] + public class GivenIWantToAddAndSubtractMoneyWithDecimal + { + public static IEnumerable TestData => new[] + { + new object[] { 101m, 99m, 200m }, // whole numbers + new object[] { 100m, 0.01m, 100.01m }, // fractions + new object[] { 100.999m, 0.9m, 101.899m }, // overflow + new object[] { 100.5m, 0.9m, 101.4m }, // overflow + new object[] { 100.999m, -0.9m, 100.099m }, // negative + new object[] { -100.999m, -0.9m, -101.899m } // negative + }; [Theory, MemberData(nameof(TestData))] -#pragma warning disable xUnit1026 // Theory methods should use all of their parameters - public void WhenUsingAdditionOperatorWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) + [UseCulture("en-us")] + public void WhenUsingAdditionOperator_ThenMoneyShouldBeAdded(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); - var money2 = new Money(value2, "USD"); - Action action = () => { var result = money1 + money2; }; + Money result1 = money1 + value2; + Money result2 = value2 + money1; - action.Should().Throw().WithMessage("The requested operation expected the currency*"); + result1.Should().Be(new Money(expected, "EUR")); + result1.Should().NotBeSameAs(money1); + result2.Should().Be(new Money(expected, "EUR")); + result2.Should().NotBeSameAs(money1); } [Theory, MemberData(nameof(TestData))] - public void WhenUsingAdditionMethodWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) + [UseCulture("en-us")] + public void WhenUsingAdditionMethod_ThenMoneyShouldBeAdded(decimal value1, decimal value2, decimal expected) { var money1 = new Money(value1, "EUR"); - var money2 = new Money(value2, "USD"); - Action action = () => Money.Add(money1, money2); + var result = Money.Add(money1, value2); - action.Should().Throw().WithMessage("The requested operation expected the currency*"); + result.Should().Be(new Money(expected, "EUR")); + result.Should().NotBeSameAs(money1); } [Theory, MemberData(nameof(TestData))] - public void WhenUsingSubstractionOperatorWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) + [UseCulture("en-us")] + public void WhenUsingSubtractionOperator_ThenMoneyShouldBeAdded(decimal expected, decimal value2, decimal value1) { var money1 = new Money(value1, "EUR"); - var money2 = new Money(value2, "USD"); - Action action = () => { var result = money1 - money2; }; + Money result1 = money1 - value2; + Money result2 = value2 - money1; - action.Should().Throw().WithMessage("The requested operation expected the currency*"); + result1.Should().Be(new Money(expected, "EUR")); + result1.Should().NotBeSameAs(money1); + result2.Should().Be(new Money(expected, "EUR")); + result2.Should().NotBeSameAs(money1); } [Theory, MemberData(nameof(TestData))] - public void WhenUsingSubstractionMethodWithDifferentCurrency_ThenThrowException(decimal value1, decimal value2, decimal expected) + [UseCulture("en-us")] + public void WhenUsingSubtractionMethod_ThenMoneyShouldBeSubtracted(decimal expected, decimal value2, decimal value1) { var money1 = new Money(value1, "EUR"); - var money2 = new Money(value2, "USD"); - Action action = () => Money.Subtract(money1, money2); + var result = Money.Subtract(money1, value2); - action.Should().Throw().WithMessage("The requested operation expected the currency*"); + result.Should().Be(new Money(expected, "EUR")); + result.Should().NotBeSameAs(money1); } -#pragma warning restore xUnit1026 // Theory methods should use all of their parameters } public class GivenIWantToMultiplyAndDivideMoney @@ -187,7 +197,7 @@ public class GivenIWantToMultiplyAndDivideMoney }; [Theory, MemberData(nameof(TestDataDecimal))] - public void WhenUsingMultiplyOperatorWithDecimal_ThenMoneyShouldBeMultipled(decimal value, decimal multiplier, decimal expected) + public void WhenUsingMultiplyOperatorWithDecimal_ThenMoneyShouldBeMultiplied(decimal value, decimal multiplier, decimal expected) { var money = new Money(value); @@ -201,7 +211,7 @@ public void WhenUsingMultiplyOperatorWithDecimal_ThenMoneyShouldBeMultipled(deci } [Theory, MemberData(nameof(TestDataDecimal))] - public void WhenUsingMultiplyMethodWithDecimal_ThenMoneyShouldBeMultipled(decimal value, decimal multiplier, decimal expected) + public void WhenUsingMultiplyMethodWithDecimal_ThenMoneyShouldBeMultiplied(decimal value, decimal multiplier, decimal expected) { var money = new Money(value); @@ -243,7 +253,7 @@ public void WhenUsingDivisionMethodWithDecimal_ThenMoneyShouldBeDivided(decimal }; [Theory, MemberData(nameof(TestDataInteger))] - public void WhenUsingMultiplyOperatorWithInteger_ThenMoneyShouldBeMultipled(decimal value, int multiplier, decimal expected) + public void WhenUsingMultiplyOperatorWithInteger_ThenMoneyShouldBeMultiplied(decimal value, int multiplier, decimal expected) { var money = new Money(value); @@ -257,7 +267,7 @@ public void WhenUsingMultiplyOperatorWithInteger_ThenMoneyShouldBeMultipled(deci } [Theory, MemberData(nameof(TestDataInteger))] - public void WhenUsingMultiplyMethodWithInteger_ThenMoneyShouldBeMultipled(decimal value, int multiplier, decimal expected) + public void WhenUsingMultiplyMethodWithInteger_ThenMoneyShouldBeMultiplied(decimal value, int multiplier, decimal expected) { var money = new Money(value); diff --git a/tests/NodaMoney.Tests/MoneyConvertibleSpec.cs b/tests/NodaMoney.Tests/MoneyConvertibleSpec.cs index a164140..3823e41 100644 --- a/tests/NodaMoney.Tests/MoneyConvertibleSpec.cs +++ b/tests/NodaMoney.Tests/MoneyConvertibleSpec.cs @@ -1,5 +1,4 @@ using System.Threading; - using FluentAssertions; using Xunit; @@ -207,4 +206,4 @@ public void WhenValueIsDecimal_ThenCreatingShouldSucceed() money.Amount.Should().Be(25.00m); } } -} \ No newline at end of file +} diff --git a/tests/NodaMoney.Tests/MoneyFiveMostUsedCurrenciesSpec.cs b/tests/NodaMoney.Tests/MoneyFiveMostUsedCurrenciesSpec.cs index de24deb..5399d0f 100644 --- a/tests/NodaMoney.Tests/MoneyFiveMostUsedCurrenciesSpec.cs +++ b/tests/NodaMoney.Tests/MoneyFiveMostUsedCurrenciesSpec.cs @@ -1,5 +1,4 @@ using System; - using FluentAssertions; using Xunit; @@ -347,4 +346,4 @@ public void WhenULong_ThenCreatingShouldSucceed() pounds.Amount.Should().Be(10.00m); } } -} \ No newline at end of file +} diff --git a/tests/NodaMoney.Tests/MoneyFormattableSpec.cs b/tests/NodaMoney.Tests/MoneyFormattableSpec.cs index 0481735..d274850 100644 --- a/tests/NodaMoney.Tests/MoneyFormattableSpec.cs +++ b/tests/NodaMoney.Tests/MoneyFormattableSpec.cs @@ -7,6 +7,7 @@ namespace NodaMoney.Tests.MoneyFormattableSpec { + [Collection(nameof(NoParallelization))] public class GivenIWantMoneyAsString { private Money _yen = new Money(765.4321m, Currency.FromCode("JPY")); @@ -134,6 +135,7 @@ public void WhenNumberOfDecimalsIsNotApplicable_ThenToStringShouldNotFail() } } + [Collection(nameof(NoParallelization))] public class GivenIWantMoneyAsStringWithCurrencySymbol { private Money _yen = new Money(765.4321m, Currency.FromCode("JPY")); @@ -230,6 +232,7 @@ public void WhenFourDecimals_ThenThisShouldSucceed() } } + [Collection(nameof(NoParallelization))] public class GivenIWantMoneyAsStringWithCurrencyCode { private Money _yen = new Money(765.4321m, Currency.FromCode("JPY")); @@ -325,7 +328,8 @@ public void WhenFourDecimals_ThenThisShouldSucceed() _dinar.ToString("I4").Should().Be("BHD 765.4320"); } } - + + [Collection(nameof(NoParallelization))] public class GivenIWantMoneyAsStringWithEnglishCurrencyName { private Money _yen = new Money(765.4321m, Currency.FromCode("JPY")); diff --git a/tests/NodaMoney.Tests/MoneyParsableSpec.cs b/tests/NodaMoney.Tests/MoneyParsableSpec.cs index 67bd8ae..6749f0a 100644 --- a/tests/NodaMoney.Tests/MoneyParsableSpec.cs +++ b/tests/NodaMoney.Tests/MoneyParsableSpec.cs @@ -1,13 +1,12 @@ using System; using System.Globalization; -using System.Threading; - using FluentAssertions; -using Xunit; using NodaMoney.Tests.Helpers; +using Xunit; namespace NodaMoney.Tests.MoneyParsableSpec { + [Collection(nameof(NoParallelization))] public class GivenIWantToParseImplicitCurrency { [Fact, UseCulture("nl-BE")] @@ -117,6 +116,7 @@ public void WhenCurrencyIsUnknown_ThenThowExeception() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToParseExplicitCurrency { [Fact, UseCulture("nl-NL")] @@ -217,6 +217,7 @@ public void WhenValueIsEmptyWithOverrideMethod_ThenThowExeception() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToParseNegativeMoney { [Fact, UseCulture("en-US")] @@ -274,6 +275,7 @@ public void WhenEurosWithParentheses_ThenThisShouldSucceed() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToParseMoneyWithMoreDecimalPossibleForCurrency { [Fact, UseCulture("ja-JP")] @@ -293,6 +295,7 @@ public void WhenParsingJapaneseYen_ThenThisShouldBeRoundedUp() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToTryParseImplicitCurrency { [Fact, UseCulture("nl-BE")] @@ -397,6 +400,7 @@ public void WhenValueIsEmpty_ThenReturnFalse() } } + [Collection(nameof(NoParallelization))] public class GivenIWantToTryParseExplicitCurrency { [Fact, UseCulture("nl-NL")] diff --git a/tests/NodaMoney.Tests/MoneySpec.cs b/tests/NodaMoney.Tests/MoneySpec.cs index 652f08e..c35f10e 100644 --- a/tests/NodaMoney.Tests/MoneySpec.cs +++ b/tests/NodaMoney.Tests/MoneySpec.cs @@ -1,12 +1,9 @@ using System; -using System.Diagnostics; using System.Globalization; using System.Threading; using FluentAssertions; -using Xunit; using NodaMoney.Tests.Helpers; - -using Xunit.Abstractions; +using Xunit; namespace NodaMoney.Tests.MoneySpec { diff --git a/tests/NodaMoney.Tests/NodaMoney.Tests.csproj b/tests/NodaMoney.Tests/NodaMoney.Tests.csproj index b93dedb..1b87e1b 100644 --- a/tests/NodaMoney.Tests/NodaMoney.Tests.csproj +++ b/tests/NodaMoney.Tests/NodaMoney.Tests.csproj @@ -1,7 +1,7 @@  - net48 + net48;netcoreapp3.1 NodaMoney.Tests NodaMoney.Tests true @@ -9,11 +9,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -33,7 +33,9 @@ - + + ..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Web.Extensions.dll + diff --git a/tests/NodaMoney.Tests/PerformanceSpec.cs b/tests/NodaMoney.Tests/PerformanceSpec.cs new file mode 100644 index 0000000..8d93d97 --- /dev/null +++ b/tests/NodaMoney.Tests/PerformanceSpec.cs @@ -0,0 +1,72 @@ +using Xunit; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; + +namespace NodaMoney.Tests.PerformanceSpec +{ + + public class GivenIWantToUseALotOfCurrencies + { + [Fact] + public void StartBenchmark() + { + var summary1 = BenchmarkRunner.Run(); + + var summary2 = BenchmarkRunner.Run(); + } + } + + [MemoryDiagnoser] + public class DefaultBenchmarks + { + [Benchmark] + public void CreateCurrency() + { + Currency currency = Currency.FromCode("EUR"); + } + + [Benchmark] + public void CreateMoney() + { + Money money = new Money(10M, "EUR"); + } + } + + [MemoryDiagnoser] + public class MemoryBenchmarks + { + [Benchmark] + public void CreatingOneMillionCurrency() + { + int max = 1_000_000; + Currency[] currencies = new Currency[max]; + + for (int i = 0; i < max; i++) + { + if (i % 3 == 0) + currencies[i] = Currency.FromCode("EUR"); + else if (i % 2 == 0) + currencies[i] = Currency.FromCode("USD"); + else + currencies[i] = Currency.FromCode("JPY"); + } + } + + [Benchmark] + public void CreatingOneMillionMoney() + { + int max = 1_000_000; + Money[] money = new Money[max]; + + for (int i = 0; i < max; i++) + { + if (i % 3 == 0) + money[i] = new Money(10M, "EUR"); + else if (i % 2 == 0) + money[i] = new Money(10M, "USD"); + else + money[i] = new Money(10M, "JPY"); + } + } + } +} diff --git a/tests/NodaMoney.Tests/PerformanceTest.txt b/tests/NodaMoney.Tests/PerformanceTest.txt new file mode 100644 index 0000000..e99d135 --- /dev/null +++ b/tests/NodaMoney.Tests/PerformanceTest.txt @@ -0,0 +1,11 @@ +29/3 Baseline + +| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | +|--------------- |---------:|--------:|--------:|-------:|------:|------:|----------:| +| CreateCurrency | 611.6 ns | 5.56 ns | 5.20 ns | 0.1354 | - | - | 429 B | +| CreateMoney | 725.9 ns | 3.37 ns | 2.99 ns | 0.1354 | - | - | 429 B | + +| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | +|--------------------------- |---------:|--------:|--------:|------------:|----------:|----------:|----------:| +| CreatingOneMillionCurrency | 660.3 ms | 3.74 ms | 3.50 ms | 137000.0000 | 1000.0000 | 1000.0000 | 458.38 MB | +| CreatingOneMillionMoney | 787.5 ms | 8.06 ms | 7.54 ms | 137000.0000 | 1000.0000 | 1000.0000 | 473.63 MB | \ No newline at end of file diff --git a/tests/NodaMoney.Tests/Serialization/JavaScriptSerializableSpec.cs b/tests/NodaMoney.Tests/Serialization/JavaScriptSerializableSpec.cs index 2aebf22..e90c677 100644 --- a/tests/NodaMoney.Tests/Serialization/JavaScriptSerializableSpec.cs +++ b/tests/NodaMoney.Tests/Serialization/JavaScriptSerializableSpec.cs @@ -1,12 +1,13 @@ -using System; +#if !NETCOREAPP +using System; using System.Collections.Generic; using System.Globalization; using System.Web.Script.Serialization; using FluentAssertions; -using NodaMoney.Serialization.AspNet; +using NodaMoney.Serialization; using Xunit; -namespace NodaMoney.Tests.Serialization.AspNet +namespace NodaMoney.Tests.Serialization.JavaScriptSerializableSpec { public class GivenIWantToSerializeMoneyWithJavaScriptSerializer { @@ -142,3 +143,4 @@ public void WhenDeserializingWithNestedNullable_ThenThisShouldSucceed(string jso } } } +#endif diff --git a/tests/NodaMoney.Tests/Serialization/MoneySerializableSpec.cs b/tests/NodaMoney.Tests/Serialization/MoneySerializableSpec.cs index 68b9ab3..c1d624b 100644 --- a/tests/NodaMoney.Tests/Serialization/MoneySerializableSpec.cs +++ b/tests/NodaMoney.Tests/Serialization/MoneySerializableSpec.cs @@ -6,11 +6,10 @@ using FluentAssertions; using Xunit; using Newtonsoft.Json; -using System.Diagnostics; using System.Runtime.Serialization.Formatters.Binary; using System.Collections.Generic; -namespace NodaMoney.Tests.Serialization +namespace NodaMoney.Tests.Serialization.MoneySerializableSpec { public class GivenIWantToDeserializeMoneyWithJsonNetSerializer {