From 4eac30dc20a0b33700b277a3dcd2a9db30a311c3 Mon Sep 17 00:00:00 2001 From: xhafan Date: Mon, 31 Oct 2022 12:37:50 +0100 Subject: [PATCH 1/3] Added missing tests for FactorialCalculator --- .../HitF5.Factorial.Tests.csproj | 19 +++++++++++++++++++ .../when_calculating_factorial.cs | 19 +++++++++++++++++++ src/HitF5.sln | 19 +++++++++++++++---- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/HitF5.Factorial.Tests/HitF5.Factorial.Tests.csproj create mode 100644 src/HitF5.Factorial.Tests/when_calculating_factorial.cs diff --git a/src/HitF5.Factorial.Tests/HitF5.Factorial.Tests.csproj b/src/HitF5.Factorial.Tests/HitF5.Factorial.Tests.csproj new file mode 100644 index 0000000..29c78b7 --- /dev/null +++ b/src/HitF5.Factorial.Tests/HitF5.Factorial.Tests.csproj @@ -0,0 +1,19 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + diff --git a/src/HitF5.Factorial.Tests/when_calculating_factorial.cs b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs new file mode 100644 index 0000000..00c60ba --- /dev/null +++ b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs @@ -0,0 +1,19 @@ +using NUnit.Framework; +using Shouldly; + +namespace HitF5.Factorial.Tests +{ + [TestFixture] + public class when_calculating_factorial + { + [TestCase(2, 2)] + [TestCase(3, 6)] + [TestCase(4, 24)] + public void factorial_is_calculated_correctly(int value, int expectedFactorialValue) + { + var factorial = new FactorialCalculator().Calculate(value); + + factorial.ShouldBe(expectedFactorialValue); + } + } +} \ No newline at end of file diff --git a/src/HitF5.sln b/src/HitF5.sln index 20e5159..a859d2d 100644 --- a/src/HitF5.sln +++ b/src/HitF5.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29020.237 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32922.545 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitF5.Random", "HitF5.Random\HitF5.Random.csproj", "{F45D20CB-4922-4255-BA12-DD34D2049BCE}" EndProject @@ -9,9 +9,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitF5.Custom", "HitF5.Custo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitF5.Factorial", "HitF5.Factorial\HitF5.Factorial.csproj", "{338903E4-54D9-4443-A5C8-B27130BAD0FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitF5.Api", "HitF5.Api\HitF5.Api.csproj", "{0750FB3B-BFFD-451E-BA6C-954044A735D0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitF5.Api", "HitF5.Api\HitF5.Api.csproj", "{0750FB3B-BFFD-451E-BA6C-954044A735D0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitF5.Api.Client", "HitF5.Api.Client\HitF5.Api.Client.csproj", "{4D6833CC-F7E9-4791-A371-FA40B32B0C37}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitF5.Api.Client", "HitF5.Api.Client\HitF5.Api.Client.csproj", "{4D6833CC-F7E9-4791-A371-FA40B32B0C37}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{516F625A-3EDB-4B85-96F0-F20B3010815E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitF5.Factorial.Tests", "HitF5.Factorial.Tests\HitF5.Factorial.Tests.csproj", "{5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,10 +43,17 @@ Global {4D6833CC-F7E9-4791-A371-FA40B32B0C37}.Debug|Any CPU.Build.0 = Debug|Any CPU {4D6833CC-F7E9-4791-A371-FA40B32B0C37}.Release|Any CPU.ActiveCfg = Release|Any CPU {4D6833CC-F7E9-4791-A371-FA40B32B0C37}.Release|Any CPU.Build.0 = Release|Any CPU + {5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5D2DDF72-EEC2-48B0-BDB0-33DCBDC5BA27} = {516F625A-3EDB-4B85-96F0-F20B3010815E} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {51A73852-7393-4087-87E4-17E1AB8490A3} EndGlobalSection From be674130263cae5f0f35d2e1f1dd4eb997392d32 Mon Sep 17 00:00:00 2001 From: xhafan Date: Mon, 31 Oct 2022 12:58:05 +0100 Subject: [PATCH 2/3] Refactored FactorialCalculator to return the factorial in BigInteger type in order to handle numbers where the factorial is larger than long.MaxValue; added missing test for "minimum" values --- .../when_calculating_factorial.cs | 29 ++++++++++++++--- src/HitF5.Factorial/FactorialCalculator.cs | 32 ++++++++----------- src/HitF5.Factorial/IFactorialCalculator.cs | 6 ++-- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/HitF5.Factorial.Tests/when_calculating_factorial.cs b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs index 00c60ba..ba2d245 100644 --- a/src/HitF5.Factorial.Tests/when_calculating_factorial.cs +++ b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Numerics; +using NUnit.Framework; using Shouldly; namespace HitF5.Factorial.Tests @@ -6,14 +7,32 @@ namespace HitF5.Factorial.Tests [TestFixture] public class when_calculating_factorial { - [TestCase(2, 2)] - [TestCase(3, 6)] - [TestCase(4, 24)] - public void factorial_is_calculated_correctly(int value, int expectedFactorialValue) + protected static IEnumerable FactorialIsCalculatedCorrectlyTestCases() + { + yield return new TestCaseData(2, new BigInteger(2)) + .SetName("2"); + yield return new TestCaseData(3, new BigInteger(6)) + .SetName("3"); + yield return new TestCaseData(4, new BigInteger(24)) + .SetName("4"); + yield return new TestCaseData(50, BigInteger.Parse("30414093201713378043612608166064768844377641568960512000000000000")) + .SetName("50"); + } + [TestCaseSource(nameof(FactorialIsCalculatedCorrectlyTestCases))] + public void factorial_is_calculated_correctly(int value, BigInteger expectedFactorialValue) { var factorial = new FactorialCalculator().Calculate(value); factorial.ShouldBe(expectedFactorialValue); } + + [TestCase(1)] + [TestCase(0)] + public void factorial_is_calculated_correctly_for_values_less_or_equal_to_one(int value) + { + var factorial = new FactorialCalculator().Calculate(value); + + factorial.ShouldBe(1); + } } } \ No newline at end of file diff --git a/src/HitF5.Factorial/FactorialCalculator.cs b/src/HitF5.Factorial/FactorialCalculator.cs index e694c35..11e76ff 100644 --- a/src/HitF5.Factorial/FactorialCalculator.cs +++ b/src/HitF5.Factorial/FactorialCalculator.cs @@ -1,34 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics; +using System.Numerics; namespace HitF5.Factorial { - [DebuggerDisplay("FactorialCalculator s minimem {minimum}.")] + [DebuggerDisplay("FactorialCalculator s minimem {Minimum}.")] public class FactorialCalculator : IFactorialCalculator { - private static readonly int minimum = 1; + private const int Minimum = 1; - public int Calculate(int value) + public BigInteger Calculate(int value) { - if (value <= minimum) + if (value <= Minimum) { - return minimum; + return Minimum; } - else + + var bi = new BigInteger(1); + var factorial = value; + for (var i = 1; i <= factorial; i++) { - return value * this.Calculate(this.GetNext(value)); + bi *= i; } - } - - private int GetNext(int value) - { - return value - 1; - } - public override string ToString() - { - return "ToString"; + return bi; } } } diff --git a/src/HitF5.Factorial/IFactorialCalculator.cs b/src/HitF5.Factorial/IFactorialCalculator.cs index f72c5c4..11f646a 100644 --- a/src/HitF5.Factorial/IFactorialCalculator.cs +++ b/src/HitF5.Factorial/IFactorialCalculator.cs @@ -1,7 +1,9 @@ -namespace HitF5.Factorial +using System.Numerics; + +namespace HitF5.Factorial { public interface IFactorialCalculator { - int Calculate(int value); + BigInteger Calculate(int value); } } \ No newline at end of file From 30b3c6d15977dfd4815b7b2cb3fabf0547d47570 Mon Sep 17 00:00:00 2001 From: xhafan Date: Mon, 31 Oct 2022 13:12:37 +0100 Subject: [PATCH 3/3] Fixed the FactorialCalculator behaviour for negative values --- .../when_calculating_factorial.cs | 15 +++++++++------ src/HitF5.Factorial/FactorialCalculator.cs | 10 ++-------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/HitF5.Factorial.Tests/when_calculating_factorial.cs b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs index ba2d245..7330c60 100644 --- a/src/HitF5.Factorial.Tests/when_calculating_factorial.cs +++ b/src/HitF5.Factorial.Tests/when_calculating_factorial.cs @@ -9,6 +9,10 @@ public class when_calculating_factorial { protected static IEnumerable FactorialIsCalculatedCorrectlyTestCases() { + yield return new TestCaseData(0, new BigInteger(1)) + .SetName("0"); + yield return new TestCaseData(1, new BigInteger(1)) + .SetName("1"); yield return new TestCaseData(2, new BigInteger(2)) .SetName("2"); yield return new TestCaseData(3, new BigInteger(6)) @@ -26,13 +30,12 @@ public void factorial_is_calculated_correctly(int value, BigInteger expectedFact factorial.ShouldBe(expectedFactorialValue); } - [TestCase(1)] - [TestCase(0)] - public void factorial_is_calculated_correctly_for_values_less_or_equal_to_one(int value) + [Test] + public void exception_is_thrown_for_negative_value() { - var factorial = new FactorialCalculator().Calculate(value); - - factorial.ShouldBe(1); + var ex = Should.Throw(() => new FactorialCalculator().Calculate(-1)); + + ex.Message.ShouldBe("Value has to be non-negative. (Parameter 'value')"); } } } \ No newline at end of file diff --git a/src/HitF5.Factorial/FactorialCalculator.cs b/src/HitF5.Factorial/FactorialCalculator.cs index 11e76ff..1b82ed1 100644 --- a/src/HitF5.Factorial/FactorialCalculator.cs +++ b/src/HitF5.Factorial/FactorialCalculator.cs @@ -1,19 +1,13 @@ -using System.Diagnostics; +using System; using System.Numerics; namespace HitF5.Factorial { - [DebuggerDisplay("FactorialCalculator s minimem {Minimum}.")] public class FactorialCalculator : IFactorialCalculator { - private const int Minimum = 1; - public BigInteger Calculate(int value) { - if (value <= Minimum) - { - return Minimum; - } + if (value < 0) throw new ArgumentOutOfRangeException(nameof(value), "Value has to be non-negative."); var bi = new BigInteger(1); var factorial = value;