diff --git a/cs/HomeExercises/NumberValidatorTests.cs b/cs/HomeExercises/NumberValidatorTests.cs index a2878113..342c2b65 100644 --- a/cs/HomeExercises/NumberValidatorTests.cs +++ b/cs/HomeExercises/NumberValidatorTests.cs @@ -1,32 +1,82 @@ using System; +using System.Collections.Generic; using System.Text.RegularExpressions; -using FluentAssertions; using NUnit.Framework; namespace HomeExercises { public class NumberValidatorTests { - [Test] - public void Test() + private static NumberValidator _numberValidatorOnlyPositiv = new NumberValidator(4, 2, true); + private static NumberValidator _numberValidatorAllValues = new NumberValidator(4, 2); + + [TestCase(-1, 2, true, TestName = "When_Precision_Is_Not_Positive")] + [TestCase(1, -2, true, TestName = "When_Scale_Is_Negative(")] + [TestCase(12, 14, true, TestName = "When_Scale_More_Than_Precision")] + public void NumberValidator_Should_Throw_ArgumentException(int precision, int scale, bool onlyPositive) + { + Assert.Throws(() => new NumberValidator(precision, scale, onlyPositive)); + } + + [TestCaseSource(nameof(IsValidNumberShouldReturnFalse))] + [TestCaseSource(nameof(IsValidNumberShouldReturnFalse))] + public bool IsValidNumber_Should_Return(NumberValidator numberValidator, string value) + { + return numberValidator.IsValidNumber(value); + } + + private static IEnumerable IsValidNumberShouldReturnFalse() + { + yield return new TestCaseData(_numberValidatorAllValues, null) + .SetName("False_When_Value_Is_Null") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, "") + .SetName("False_When_Value_Is_Empty") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, "ab.c") + .SetName("False_When_Value_Is_Not_Match_Regex") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, "000.00") + .SetName("False_When_Value_Length_More_Than_Precision") + .Returns(false); + + yield return new TestCaseData(_numberValidatorOnlyPositiv, "-0.0") + .SetName("False_When_OnlyPositive_Is_True_And_Value_Is_Negative") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, "+00.00") + .SetName("False_When_Value_Starts_With_Sign_And_Numbers_Length_Is_Equal_To_Precision") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, " +00.00") + .SetName("False_When_Value_Has_Symbols_Before_Number") + .Returns(false); + + yield return new TestCaseData(_numberValidatorAllValues, "+00.00 ") + .SetName("False_When_Value_Has_Symbols_After_Number") + .Returns(false); + } + + private static IEnumerable IsValidNumberShouldReturnTrue() { - Assert.Throws(() => new NumberValidator(-1, 2, true)); - Assert.DoesNotThrow(() => new NumberValidator(1, 0, true)); - Assert.Throws(() => new NumberValidator(-1, 2, false)); - Assert.DoesNotThrow(() => new NumberValidator(1, 0, true)); - - Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0")); - Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("00.00")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-0.00")); - Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+0.00")); - Assert.IsTrue(new NumberValidator(4, 2, true).IsValidNumber("+1.23")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+1.23")); - Assert.IsFalse(new NumberValidator(17, 2, true).IsValidNumber("0.000")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-1.23")); - Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("a.sd")); + yield return new TestCaseData(_numberValidatorAllValues, "+0.0") + .SetName("True_When_Value_Starts_With_Plus") + .Returns(true); + + yield return new TestCaseData(_numberValidatorAllValues, "0.0") + .SetName("True_When_Value_Is_Positive") + .Returns(true); + + yield return new TestCaseData(_numberValidatorAllValues, "0,0") + .SetName("True_When_IntPart_And_FracPart_Separate_By_Comma") + .Returns(true); + + yield return new TestCaseData(_numberValidatorAllValues, "0!0") + .SetName("True_When_IntPart_And_FracPart_Separate_By_Another_Symbol_As_Comma_Or_Dot") + .Returns(false); } } diff --git a/cs/HomeExercises/ObjectComparison.cs b/cs/HomeExercises/ObjectComparison.cs index 44d9aed4..b26cc368 100644 --- a/cs/HomeExercises/ObjectComparison.cs +++ b/cs/HomeExercises/ObjectComparison.cs @@ -15,16 +15,18 @@ public void CheckCurrentTsar() var expectedTsar = new Person("Ivan IV The Terrible", 54, 170, 70, new Person("Vasili III of Russia", 28, 170, 60, null)); - // Перепишите код на использование Fluent Assertions. - Assert.AreEqual(actualTsar.Name, expectedTsar.Name); - Assert.AreEqual(actualTsar.Age, expectedTsar.Age); - Assert.AreEqual(actualTsar.Height, expectedTsar.Height); - Assert.AreEqual(actualTsar.Weight, expectedTsar.Weight); + /* + * Данный тест рекурсивно пройдется по всем полям объекта и сравнит их по значению рекурсивно + * По умолчанию рекурсия проходит на глубину 10, для того чтобы снять ограничение + * используется опция AllowingInfiniteRecursion, но она может стать бесконечной, если цепь проверки замкнется. + * Мой способ лучше тем, что в случае добавления новых полей в объект Person, будут проверяться все поля без изменения теста. + * Изменения нужно будет вносить только в случае если мы хотим убрать какие-то поля из проверки. + */ - Assert.AreEqual(expectedTsar.Parent!.Name, actualTsar.Parent!.Name); - Assert.AreEqual(expectedTsar.Parent.Age, actualTsar.Parent.Age); - Assert.AreEqual(expectedTsar.Parent.Height, actualTsar.Parent.Height); - Assert.AreEqual(expectedTsar.Parent.Parent, actualTsar.Parent.Parent); + actualTsar.Should().BeEquivalentTo(expectedTsar, options => + options.Excluding(o => o.SelectedMemberInfo.Name == nameof(Person.Id) && + o.SelectedMemberInfo.DeclaringType == typeof(Person)) + .IgnoringCyclicReferences()); } [Test] @@ -34,8 +36,13 @@ public void CheckCurrentTsar_WithCustomEquality() var actualTsar = TsarRegistry.GetCurrentTsar(); var expectedTsar = new Person("Ivan IV The Terrible", 54, 170, 70, new Person("Vasili III of Russia", 28, 170, 60, null)); - - // Какие недостатки у такого подхода? + /* + * Какие недостатки у такого подхода? + * 1. Придется менять метод AreEqual, если в объект добавятся еще поля. + * 2. Рекурсия может стать бесконечной, если в каком-то Person Parent будет равен Person, который уже был в цепи проверки + * 3. Имя теста никак не сигнализирует о том какой особый случай оно проверяет + * 4. Тест никак не показывает в чем проблема, тест просто становится красным + */ Assert.True(AreEqual(actualTsar, expectedTsar)); } @@ -64,11 +71,11 @@ public static Person GetCurrentTsar() public class Person { - public static int IdCounter = 0; + public static int IdCounter; public int Age, Height, Weight; + public int Id; public string Name; public Person? Parent; - public int Id; public Person(string name, int age, int height, int weight, Person? parent) { diff --git a/cs/testing.sln b/cs/testing.sln index 4642966f..be154766 100644 --- a/cs/testing.sln +++ b/cs/testing.sln @@ -1,13 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.13 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples", "Samples\Samples.csproj", "{E7A56C48-8E36-465B-9F8E-67BC8525CFE5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples", "Samples\Samples.csproj", "{E7A56C48-8E36-465B-9F8E-67BC8525CFE5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HomeExercises", "HomeExercises\HomeExercises.csproj", "{4F9FBCCA-43E0-431B-944D-834D16AD18F9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HomeExercises", "HomeExercises\HomeExercises.csproj", "{4F9FBCCA-43E0-431B-944D-834D16AD18F9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Challenge", "Challenge\Challenge.csproj", "{BB8C2EFB-6AE9-45BD-8468-829D5AB79DCB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Challenge", "Challenge\Challenge.csproj", "{BB8C2EFB-6AE9-45BD-8468-829D5AB79DCB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -31,4 +31,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F870899-F9CC-4FC5-8908-E2FD1AAC0AD7} + EndGlobalSection EndGlobal