From cbe2146ed6d6639c8b34417ae52675ad2e46a6a8 Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Sat, 2 Nov 2024 16:57:23 +0500 Subject: [PATCH 1/6] =?UTF-8?q?ObjectComparison.=20=D0=9F=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=BF=D0=B8=D1=81=D0=B0=D0=BB=20=D0=BF=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=82=D0=B5=D1=81=D1=82=20=D0=BD=D0=B0=20Fluent?= =?UTF-8?q?Assertions,=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D1=83=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1. ObjectComparison/ObjectComparison.cs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index d544c47..a6a4f3c 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -1,39 +1,40 @@ -using NUnit.Framework; +using FluentAssertions; +using NUnit.Framework; using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.ObjectComparison; public class ObjectComparison { + private Person actualTsar; + private Person expectedTsar; + + [SetUp] + public void Setup() + { + actualTsar = TsarRegistry.GetCurrentTsar(); + expectedTsar = CreateDefaultTsar(); + } + [Test] [Description("Проверка текущего царя")] [Category("ToRefactor")] public void CheckCurrentTsar() { - 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)); + actualTsar.Name.Should().Be(expectedTsar.Name); + actualTsar.Age.Should().Be(expectedTsar.Age); + actualTsar.Height.Should().Be(expectedTsar.Height); + actualTsar.Weight.Should().Be(expectedTsar.Weight); - // Перепишите код на использование Fluent Assertions. - ClassicAssert.AreEqual(actualTsar.Name, expectedTsar.Name); - ClassicAssert.AreEqual(actualTsar.Age, expectedTsar.Age); - ClassicAssert.AreEqual(actualTsar.Height, expectedTsar.Height); - ClassicAssert.AreEqual(actualTsar.Weight, expectedTsar.Weight); - - ClassicAssert.AreEqual(expectedTsar.Parent!.Name, actualTsar.Parent!.Name); - ClassicAssert.AreEqual(expectedTsar.Parent.Age, actualTsar.Parent.Age); - ClassicAssert.AreEqual(expectedTsar.Parent.Height, actualTsar.Parent.Height); - ClassicAssert.AreEqual(expectedTsar.Parent.Parent, actualTsar.Parent.Parent); + actualTsar.Parent!.Name.Should().Be(expectedTsar.Parent!.Name); + actualTsar.Parent.Age.Should().Be(expectedTsar.Parent.Age); + actualTsar.Parent.Height.Should().Be(expectedTsar.Parent.Height); + actualTsar.Parent.Parent.Should().Be(expectedTsar.Parent.Parent); } [Test] [Description("Альтернативное решение. Какие у него недостатки?")] 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)); - // Какие недостатки у такого подхода? ClassicAssert.True(AreEqual(actualTsar, expectedTsar)); } @@ -49,4 +50,10 @@ private bool AreEqual(Person? actual, Person? expected) && actual.Weight == expected.Weight && AreEqual(actual.Parent, expected.Parent); } + + private static Person CreateDefaultTsar() + => new ("Ivan IV The Terrible", 54, 170, 70, CreateDefaultParent()); + + private static Person CreateDefaultParent() + => new ("Vasili III of Russia", 28, 170, 60, null); } From 45cb66adef1bf82defca22b705812f2ac501da9d Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Sat, 2 Nov 2024 17:04:06 +0500 Subject: [PATCH 2/6] =?UTF-8?q?ObjectComparison.=20=D0=A0=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=20=D1=82=D0=B5=D1=81=D1=82=D0=B0?= =?UTF-8?q?,=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1. ObjectComparison/ObjectComparison.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index a6a4f3c..b76586e 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -1,8 +1,8 @@ using FluentAssertions; using NUnit.Framework; -using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.ObjectComparison; + public class ObjectComparison { private Person actualTsar; @@ -14,7 +14,7 @@ public void Setup() actualTsar = TsarRegistry.GetCurrentTsar(); expectedTsar = CreateDefaultTsar(); } - + [Test] [Description("Проверка текущего царя")] [Category("ToRefactor")] @@ -25,7 +25,7 @@ public void CheckCurrentTsar() actualTsar.Height.Should().Be(expectedTsar.Height); actualTsar.Weight.Should().Be(expectedTsar.Weight); - actualTsar.Parent!.Name.Should().Be(expectedTsar.Parent!.Name); + actualTsar.Parent.Name.Should().Be(expectedTsar.Parent.Name); actualTsar.Parent.Age.Should().Be(expectedTsar.Parent.Age); actualTsar.Parent.Height.Should().Be(expectedTsar.Parent.Height); actualTsar.Parent.Parent.Should().Be(expectedTsar.Parent.Parent); @@ -36,24 +36,24 @@ public void CheckCurrentTsar() public void CheckCurrentTsar_WithCustomEquality() { // Какие недостатки у такого подхода? - ClassicAssert.True(AreEqual(actualTsar, expectedTsar)); - } + // AreEqual не содержит в себе Assert, при падении теста мы не знаем, что произошло (неинформативный вывод) + // При расширении класса Person, нам необходимо менять код уже написанного метода AreEqual + // и компилятор нам не подскажет, что это нужно сделать + // В тесте только вызывается метод AreEqual, приходится писать инфраструктурный код для его создания - private bool AreEqual(Person? actual, Person? expected) - { - if (actual == expected) return true; - if (actual == null || expected == null) return false; - return - actual.Name == expected.Name - && actual.Age == expected.Age - && actual.Height == expected.Height - && actual.Weight == expected.Weight - && AreEqual(actual.Parent, expected.Parent); + // Плюсы моего подхода: + // При расширении класса Person, программа не скомпилируется, если не поменять код (предотвращает ошибки). + // Код приходится менять только в генераторах объектов + // При расширении класса Person, нам не нужно изменять тест (первый тест придется, компилятор не подскажет) + // Логика сравнения перенесена в сам тест, не приходится писать лишний инфраструктурный код + // P.S. создание объектов вынесено в Setup. Мы не сравниваем Id, создавать каждый раз новые данные для теста нет необходимости + actualTsar.Should().BeEquivalentTo(expectedTsar, options => + options.Excluding(y => y.Id).Excluding(y => y.Parent.Id)); } - + private static Person CreateDefaultTsar() - => new ("Ivan IV The Terrible", 54, 170, 70, CreateDefaultParent()); + => new("Ivan IV The Terrible", 54, 170, 70, CreateDefaultParent()); private static Person CreateDefaultParent() - => new ("Vasili III of Russia", 28, 170, 60, null); + => new("Vasili III of Russia", 28, 170, 60, null); } From daaa494ee51afbcad6d82d07238e884e44593268 Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Sat, 2 Nov 2024 17:08:46 +0500 Subject: [PATCH 3/6] =?UTF-8?q?NumberValidatorTests.=20=D0=94=D0=B5=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BF=D0=BE=D0=B7=D0=B8=D1=86=D0=B8=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BD=D0=B0=D0=B3=D1=80=D1=83=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=82=D0=B5=D1=81=D1=82=D0=B0?= =?UTF-8?q?,=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B8=D1=85=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=BA,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D0=B4=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8E=D1=89=D0=B8=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NumberValidatorTests.cs | 156 +++++++++++++++--- 1 file changed, 135 insertions(+), 21 deletions(-) diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 950c9bc..613e761 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -1,6 +1,5 @@ - +using FluentAssertions; using NUnit.Framework; -using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.NumberValidator; @@ -8,24 +7,139 @@ namespace HomeExercise.Tasks.NumberValidator; public class NumberValidatorTests { [Test] - public void Test() - { - 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)); - - ClassicAssert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - ClassicAssert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0")); - ClassicAssert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("00.00")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-0.00")); - ClassicAssert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+0.00")); - ClassicAssert.IsTrue(new NumberValidator(4, 2, true).IsValidNumber("+1.23")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+1.23")); - ClassicAssert.IsFalse(new NumberValidator(17, 2, true).IsValidNumber("0.000")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-1.23")); - ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("a.sd")); + public void NumberValidator_Throws_WhenNegativePrecision() + { + Action action = () => new NumberValidator(-1, 2, true); + action.Should().Throw(); + } + + [Test] + public void NumberValidator_Throws_WhenNegativeScale() + { + Action action = () => new NumberValidator(2, -1, true); + action.Should().Throw(); + } + + [Test] + public void NumberValidator_Throws_WhenScaleGreaterThanPrecision() + { + Action action = () => new NumberValidator(2, 3, true); + action.Should().Throw(); + } + + [Test] + public void NumberValidator_Throws_WhenScaleEqualPrecision() + { + Action action = () => new NumberValidator(2, 2, true); + action.Should().Throw(); + } + + [Test] + public void NumberValidator_DontThrows_WhenPrecisionIsPositive() + { + Action action = () => new NumberValidator(2, 1, true); + action.Should().NotThrow(); + } + + [Test] + public void NumberValidator_DontThrows_WhenScaleLessThanPrecision() + { + Action action = () => new NumberValidator(2, 1, true); + action.Should().NotThrow(); + } + + [TestCase(1, true, "1")] + [TestCase(2, true, "21")] + [TestCase(3, true, "13")] + [TestCase(5, true, "514")] + [TestCase(10, false, "-314")] + [TestCase(2, false, "-3")] + [TestCase(3, false, "-99")] + public void NumberValidator_ReturnsTrue_WithValidIntegerNumbers_WithScaleZero(int precision, bool onlyPositive, + string number) => TestWithValidParameters(precision, 0, onlyPositive, number); + + [TestCase(1, true, "11")] + [TestCase(2, true, "001")] + [TestCase(3, true, "4134124")] + [TestCase(10, false, "-031442424324243")] + [TestCase(2, false, "-13")] + [TestCase(3, false, "-993")] + public void NumberValidator_ReturnsFalse_WithInvalidIntegerNumbers_WithScaleZero(int precision, + bool onlyPositive, string number) => TestWithInvalidParameters(precision, 0, onlyPositive, number); + + [TestCase(2, 1, true, "1.1")] + [TestCase(4, 3, true, "2.21")] + [TestCase(4, 3, true, "0.000")] + [TestCase(4, 3, true, "00.00")] + [TestCase(5, 1, true, "51.4")] + [TestCase(10, 5, false, "-31.414")] + [TestCase(3, 1, false, "-3.2")] + [TestCase(2, 1, false, "-1")] + public void NumberValidator_ReturnsTrue_WithValidFloatNumbers(int precision, int scale, bool onlyPositive, + string number) => TestWithValidParameters(precision, scale, onlyPositive, number); + + [TestCase(2, 1, true, "1.12")] + [TestCase(4, 3, true, "2.2112")] + [TestCase(5, 1, true, "51.43")] + [TestCase(10, 5, false, "-31.41431231")] + [TestCase(3, 1, false, "-3.21")] + [TestCase(2, 1, false, "-1.1")] + public void NumberValidator_ReturnsFalse_WithInvalidFloatNumbers(int precision, int scale, bool onlyPositive, + string number) => TestWithInvalidParameters(precision, scale, onlyPositive, number); + + [TestCase("a")] + [TestCase("seven")] + [TestCase("one.five")] + [TestCase(" ")] + [TestCase("")] + [TestCase(null)] + public void NumberValidator_ReturnsFalse_WithNonNumber(string number) + => TestWithInvalidParameters(5, 4, false, number); + + [TestCase("IV")] + [TestCase("1 . 1")] + [TestCase("1. 1")] + [TestCase("1 .1")] + [TestCase("10_000")] + [TestCase("10 000")] + [TestCase("10.")] + [TestCase(".1")] + [TestCase("+.1")] + [TestCase("-.1")] + [TestCase("5*3")] + public void NumberValidator_ReturnsFalse_WithWrongFormat(string number) + => TestWithInvalidParameters(5, 4, false, number); + + [TestCase("1,1")] + [TestCase("1.1")] + [TestCase("11")] + public void NumberValidator_CorrectWork_WithCorrectSeparatorFormat(string number) + => TestWithValidParameters(5, 4, false, number); + + [TestCase("+11")] + [TestCase("+1111")] + [TestCase("+1.111")] + [TestCase("-1111")] + [TestCase("-1.111")] + [TestCase("-1.1")] + [TestCase("-11")] + [TestCase("+1.1")] + [TestCase("1.1")] + [TestCase("11")] + public void NumberValidator_CorrectWork_WithAndWithoutSign(string number) + => TestWithValidParameters(5, 3, false, number); + + private static void TestWithValidParameters(int precision, int scale, bool onlyPositive, + string number) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + validator.IsValidNumber(number).Should().BeTrue(); + } + + private static void TestWithInvalidParameters(int precision, int scale, bool onlyPositive, + string number) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + validator.IsValidNumber(number).Should().BeFalse(); } } \ No newline at end of file From 6370813f8455b7e9790d4eb48ab73dcc0e335781 Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Fri, 8 Nov 2024 22:22:34 +0500 Subject: [PATCH 4/6] =?UTF-8?q?NumberValidator.=20=D0=A0=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=B2,=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= =?UTF-8?q?=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2. NumberValidator/NumberValidator.cs | 2 +- .../NumberValidatorTests.cs | 176 ++++++------------ 2 files changed, 55 insertions(+), 123 deletions(-) diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidator.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidator.cs index 327ce9c..9ec611c 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidator.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidator.cs @@ -17,7 +17,7 @@ public NumberValidator(int precision, int scale = 0, bool onlyPositive = false) if (precision <= 0) throw new ArgumentException("precision must be a positive number"); if (scale < 0 || scale >= precision) - throw new ArgumentException("precision must be a non-negative number less or equal than precision"); + throw new ArgumentException("scale must be a non-negative number less than precision"); numberRegex = new Regex(@"^([+-]?)(\d+)([.,](\d+))?$", RegexOptions.IgnoreCase); } diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 613e761..7b20b4b 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -6,140 +6,72 @@ namespace HomeExercise.Tasks.NumberValidator; [TestFixture] public class NumberValidatorTests { - [Test] - public void NumberValidator_Throws_WhenNegativePrecision() + private const string InvalidPrecisionError = "precision must be a positive number"; + private const string InvalidScaleError = "scale must be a non-negative number less than precision"; + + [TestCase(2, -1, InvalidScaleError, TestName = "WhenNegativeScale")] + [TestCase(-1, 2, InvalidPrecisionError, TestName = "WhenNegativePrecision")] + [TestCase(2, 3, InvalidScaleError, TestName = "WhenScaleGreaterThanPrecision")] + [TestCase(2, 2, InvalidScaleError, TestName = "WhenScaleEqualPrecision")] + public void NumberValidatorConstructor_Throws(int precision, int scale, string message) { - Action action = () => new NumberValidator(-1, 2, true); - action.Should().Throw(); + Action action = () => new NumberValidator(precision, scale); + action.Should().Throw().WithMessage(message); } - [Test] - public void NumberValidator_Throws_WhenNegativeScale() + [TestCase(2, 0, TestName = "WhenPrecisionIsPositive")] + [TestCase(2, 1, TestName = "WhenScaleLessThanPrecision")] + public void NumberValidatorConstructor_DontThrows(int precision, int scale) { - Action action = () => new NumberValidator(2, -1, true); - action.Should().Throw(); - } - - [Test] - public void NumberValidator_Throws_WhenScaleGreaterThanPrecision() - { - Action action = () => new NumberValidator(2, 3, true); - action.Should().Throw(); - } - - [Test] - public void NumberValidator_Throws_WhenScaleEqualPrecision() - { - Action action = () => new NumberValidator(2, 2, true); - action.Should().Throw(); - } - - [Test] - public void NumberValidator_DontThrows_WhenPrecisionIsPositive() - { - Action action = () => new NumberValidator(2, 1, true); + Action action = () => new NumberValidator(precision, scale); action.Should().NotThrow(); } - [Test] - public void NumberValidator_DontThrows_WhenScaleLessThanPrecision() - { - Action action = () => new NumberValidator(2, 1, true); - action.Should().NotThrow(); - } - - [TestCase(1, true, "1")] - [TestCase(2, true, "21")] - [TestCase(3, true, "13")] - [TestCase(5, true, "514")] - [TestCase(10, false, "-314")] - [TestCase(2, false, "-3")] - [TestCase(3, false, "-99")] - public void NumberValidator_ReturnsTrue_WithValidIntegerNumbers_WithScaleZero(int precision, bool onlyPositive, - string number) => TestWithValidParameters(precision, 0, onlyPositive, number); - - [TestCase(1, true, "11")] - [TestCase(2, true, "001")] - [TestCase(3, true, "4134124")] - [TestCase(10, false, "-031442424324243")] - [TestCase(2, false, "-13")] - [TestCase(3, false, "-993")] - public void NumberValidator_ReturnsFalse_WithInvalidIntegerNumbers_WithScaleZero(int precision, - bool onlyPositive, string number) => TestWithInvalidParameters(precision, 0, onlyPositive, number); - - [TestCase(2, 1, true, "1.1")] - [TestCase(4, 3, true, "2.21")] - [TestCase(4, 3, true, "0.000")] - [TestCase(4, 3, true, "00.00")] - [TestCase(5, 1, true, "51.4")] - [TestCase(10, 5, false, "-31.414")] - [TestCase(3, 1, false, "-3.2")] - [TestCase(2, 1, false, "-1")] - public void NumberValidator_ReturnsTrue_WithValidFloatNumbers(int precision, int scale, bool onlyPositive, - string number) => TestWithValidParameters(precision, scale, onlyPositive, number); - - [TestCase(2, 1, true, "1.12")] - [TestCase(4, 3, true, "2.2112")] - [TestCase(5, 1, true, "51.43")] - [TestCase(10, 5, false, "-31.41431231")] - [TestCase(3, 1, false, "-3.21")] - [TestCase(2, 1, false, "-1.1")] - public void NumberValidator_ReturnsFalse_WithInvalidFloatNumbers(int precision, int scale, bool onlyPositive, - string number) => TestWithInvalidParameters(precision, scale, onlyPositive, number); - - [TestCase("a")] - [TestCase("seven")] - [TestCase("one.five")] - [TestCase(" ")] - [TestCase("")] - [TestCase(null)] - public void NumberValidator_ReturnsFalse_WithNonNumber(string number) - => TestWithInvalidParameters(5, 4, false, number); - - [TestCase("IV")] - [TestCase("1 . 1")] - [TestCase("1. 1")] - [TestCase("1 .1")] - [TestCase("10_000")] - [TestCase("10 000")] - [TestCase("10.")] - [TestCase(".1")] - [TestCase("+.1")] - [TestCase("-.1")] - [TestCase("5*3")] - public void NumberValidator_ReturnsFalse_WithWrongFormat(string number) - => TestWithInvalidParameters(5, 4, false, number); - - [TestCase("1,1")] - [TestCase("1.1")] - [TestCase("11")] - public void NumberValidator_CorrectWork_WithCorrectSeparatorFormat(string number) - => TestWithValidParameters(5, 4, false, number); - - [TestCase("+11")] - [TestCase("+1111")] - [TestCase("+1.111")] - [TestCase("-1111")] - [TestCase("-1.111")] - [TestCase("-1.1")] - [TestCase("-11")] - [TestCase("+1.1")] - [TestCase("1.1")] - [TestCase("11")] - public void NumberValidator_CorrectWork_WithAndWithoutSign(string number) - => TestWithValidParameters(5, 3, false, number); - - private static void TestWithValidParameters(int precision, int scale, bool onlyPositive, - string number) + [TestCase(2, 1, true, "1.12", TestName = "FracPartGreaterThanScaleWhenPositive")] + [TestCase(3, 1, false, "-3.21", TestName = "FracPartGreaterThanScaleWhenNegative")] + [TestCase(2, 1, false, "11.1", TestName = "ValueGreaterThanPrecision")] + [TestCase(3, 1, true, "-1.1", TestName = "WithSignWhenOnlyPositive")] + [TestCase(5, 4, false, "a", TestName = "Letter")] + [TestCase(5, 4, false, "seven", TestName = "Word")] + [TestCase(5, 4, false, "one.five", TestName = "WordsWithCorrectSeparator")] + [TestCase(5, 4, false, " ", TestName = "Spaces")] + [TestCase(5, 4, false, "", TestName = "EmptyString")] + [TestCase(5, 4, false, null, TestName = "NumberIsNull")] + [TestCase(5, 4, false, "IV", TestName = "NotArabicNumber")] + [TestCase(5, 4, false, "1 . 1", TestName = "SpacesAroundSeparator")] + [TestCase(5, 4, false, "1. 1", TestName = "SpaceAfterSeparator")] + [TestCase(5, 4, false, "1 .1", TestName = "SpaceBeforeSeparator")] + [TestCase(5, 4, false, "10_000", TestName = "NumberFormatWithUnderscore")] + [TestCase(5, 4, false, "10 000", TestName = "NumberFormatWithSpaces")] + [TestCase(5, 4, false, "10.", TestName = "WithSeparatorWithoutFracPart")] + [TestCase(5, 4, false, ".1", TestName = "WithSeparatorWithoutIntPart")] + [TestCase(5, 4, false, "+.1", TestName = "WithSeparatorWithoutIntPartWithPlusSign")] + [TestCase(5, 4, false, "-.1", TestName = "WithSeparatorWithoutIntPartWithMinusSign")] + [TestCase(5, 4, false, "5*3", TestName = "MathExpression")] + [TestCase(5, 4, false, "+-1", TestName = "GreaterThanOneSign")] + public void IsNumberValid_ReturnsFalse_WithInvalidNumber(int precision, int scale, bool onlyPositive, string number) { var validator = new NumberValidator(precision, scale, onlyPositive); - validator.IsValidNumber(number).Should().BeTrue(); + validator.IsValidNumber(number).Should().BeFalse(); } - private static void TestWithInvalidParameters(int precision, int scale, bool onlyPositive, - string number) + [TestCase(4, 0, true, "123", TestName = "CorrectInt")] + [TestCase(4, 3, true, "1.23", TestName = "CorrectFloat")] + [TestCase(4, 3, true, "0.000", TestName = "OnlyZeros")] + [TestCase(4, 3, true, "00.00", TestName = "LeadingZeros")] + [TestCase(1, 0, true, "1", TestName = "PositiveIntWhenPrecisionEqualsNumberLength")] + [TestCase(5, 0, true, "514", TestName = "PositiveIntWhenPrecisionGreaterThanNumberLength")] + [TestCase(3, 0, false, "-99", TestName = "NegativeIntWhenPrecisionEqualsNumberLength")] + [TestCase(10, 0, false, "-314", TestName = "NegativeIntWhenPrecisionGreaterThanNumberLength")] + [TestCase(5, 4, false, "1.1", TestName = "DotSeparator")] + [TestCase(5, 4, false, "1,1", TestName = "CommaSeparator")] + [TestCase(5, 3, false, "+11", TestName = "IntWithPlusSign")] + [TestCase(5, 3, false, "-11", TestName = "IntWithMinusSign")] + [TestCase(5, 3, false, "+1.111", TestName = "FloatWithPlusSign")] + [TestCase(5, 3, false, "-1.111", TestName = "FloatWithMinusSign")] + public void IsNumberValid_ReturnsTrue_WithValidNumber(int precision, int scale, bool onlyPositive, string number) { var validator = new NumberValidator(precision, scale, onlyPositive); - validator.IsValidNumber(number).Should().BeFalse(); + validator.IsValidNumber(number).Should().BeTrue(); } } \ No newline at end of file From 2ced4e17f264d6a34b6965123d829f3586d60b71 Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Fri, 8 Nov 2024 23:23:35 +0500 Subject: [PATCH 5/6] =?UTF-8?q?ObjectComparison.=20=D0=92=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D1=83=D0=BB=20`AreEqual`,=20=D1=80=D0=B5=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20`IEquatble`=20=D0=B2=20'?= =?UTF-8?q?Person?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1. ObjectComparison/ObjectComparison.cs | 44 +++++++++---------- .../Homework/1. ObjectComparison/Person.cs | 20 ++++++++- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index b76586e..af34b7c 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -15,24 +15,18 @@ public void Setup() expectedTsar = CreateDefaultTsar(); } + // Плюсы моего подхода: + // При расширении класса Person, программа не скомпилируется, если не поменять код (предотвращает ошибки). + // Код приходится менять только в генераторах объектов + // При расширении класса Person, нам не нужно изменять тест (первый тест придется, компилятор не подскажет) + // Засчет рефлексии нам не нужно менять код Equals в Person даже при расширении + // Тест в одну строчку + // P.S. создание объектов вынесено в Setup. Мы не сравниваем Id, создавать каждый раз новые данные для теста нет необходимости + [Test] - [Description("Проверка текущего царя")] - [Category("ToRefactor")] - public void CheckCurrentTsar() - { - actualTsar.Name.Should().Be(expectedTsar.Name); - actualTsar.Age.Should().Be(expectedTsar.Age); - actualTsar.Height.Should().Be(expectedTsar.Height); - actualTsar.Weight.Should().Be(expectedTsar.Weight); - - actualTsar.Parent.Name.Should().Be(expectedTsar.Parent.Name); - actualTsar.Parent.Age.Should().Be(expectedTsar.Parent.Age); - actualTsar.Parent.Height.Should().Be(expectedTsar.Parent.Height); - actualTsar.Parent.Parent.Should().Be(expectedTsar.Parent.Parent); - } + public void GetCurrentTsar_ShouldReturn_ValidTsar() => actualTsar.Should().BeEquivalentTo(expectedTsar); [Test] - [Description("Альтернативное решение. Какие у него недостатки?")] public void CheckCurrentTsar_WithCustomEquality() { // Какие недостатки у такого подхода? @@ -40,15 +34,19 @@ public void CheckCurrentTsar_WithCustomEquality() // При расширении класса Person, нам необходимо менять код уже написанного метода AreEqual // и компилятор нам не подскажет, что это нужно сделать // В тесте только вызывается метод AreEqual, приходится писать инфраструктурный код для его создания + AreEqual(actualTsar, expectedTsar).Should().BeTrue(); + } - // Плюсы моего подхода: - // При расширении класса Person, программа не скомпилируется, если не поменять код (предотвращает ошибки). - // Код приходится менять только в генераторах объектов - // При расширении класса Person, нам не нужно изменять тест (первый тест придется, компилятор не подскажет) - // Логика сравнения перенесена в сам тест, не приходится писать лишний инфраструктурный код - // P.S. создание объектов вынесено в Setup. Мы не сравниваем Id, создавать каждый раз новые данные для теста нет необходимости - actualTsar.Should().BeEquivalentTo(expectedTsar, options => - options.Excluding(y => y.Id).Excluding(y => y.Parent.Id)); + private static bool AreEqual(Person? actual, Person? expected) + { + if (actual == expected) return true; + if (actual == null || expected == null) return false; + return + actual.Name == expected.Name + && actual.Age == expected.Age + && actual.Height == expected.Height + && actual.Weight == expected.Weight + && AreEqual(actual.Parent, expected.Parent); } private static Person CreateDefaultTsar() diff --git a/Testing/Basic/Homework/1. ObjectComparison/Person.cs b/Testing/Basic/Homework/1. ObjectComparison/Person.cs index 4846867..83cb536 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/Person.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/Person.cs @@ -1,13 +1,21 @@ -namespace HomeExercise.Tasks.ObjectComparison; +using System.Reflection; +namespace HomeExercise.Tasks.ObjectComparison; -public class Person +public class Person : IEquatable { public static int IdCounter = 0; public int Age, Height, Weight; public string Name; public Person Parent; public int Id; + + private static readonly FieldInfo[] Fields; + + static Person() + { + Fields = typeof(Person).GetFields(); + } public Person(string name, int age, int height, int weight, Person parent) { @@ -18,4 +26,12 @@ public Person(string name, int age, int height, int weight, Person parent) Weight = weight; Parent = parent; } + + public bool Equals(Person? other) + => Fields + .Where(field => field.Name != nameof(Id)) + .Where(field => field.GetValue(this) != null || field.GetValue(other) != null) + .All(field => field.GetValue(this) != null && field.GetValue(this)!.Equals(field.GetValue(other))); + + public override bool Equals(object obj) => obj is Person person && Equals(person); } \ No newline at end of file From e072a019fa27032b23221bb30e6d02fe170e977d Mon Sep 17 00:00:00 2001 From: Maxim Mineev Date: Sun, 26 Jan 2025 19:54:36 +0500 Subject: [PATCH 6/6] gitignore --- .../Basic/.idea/.idea.Basic.dir/.idea/.gitignore | 13 +++++++++++++ .../Basic/.idea/.idea.Basic.dir/.idea/encodings.xml | 4 ++++ .../.idea/.idea.Basic.dir/.idea/indexLayout.xml | 8 ++++++++ Testing/Basic/.idea/.idea.Basic.dir/.idea/vcs.xml | 6 ++++++ Testing/Basic/Folder.DotSettings.user | 12 ++++++++++++ .../Homework/1. ObjectComparison/TsarRegistry.cs | 3 ++- 6 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 Testing/Basic/.idea/.idea.Basic.dir/.idea/.gitignore create mode 100644 Testing/Basic/.idea/.idea.Basic.dir/.idea/encodings.xml create mode 100644 Testing/Basic/.idea/.idea.Basic.dir/.idea/indexLayout.xml create mode 100644 Testing/Basic/.idea/.idea.Basic.dir/.idea/vcs.xml create mode 100644 Testing/Basic/Folder.DotSettings.user diff --git a/Testing/Basic/.idea/.idea.Basic.dir/.idea/.gitignore b/Testing/Basic/.idea/.idea.Basic.dir/.idea/.gitignore new file mode 100644 index 0000000..4994802 --- /dev/null +++ b/Testing/Basic/.idea/.idea.Basic.dir/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/.idea.Basic.iml +/modules.xml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/Testing/Basic/.idea/.idea.Basic.dir/.idea/encodings.xml b/Testing/Basic/.idea/.idea.Basic.dir/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/Testing/Basic/.idea/.idea.Basic.dir/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Testing/Basic/.idea/.idea.Basic.dir/.idea/indexLayout.xml b/Testing/Basic/.idea/.idea.Basic.dir/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/Testing/Basic/.idea/.idea.Basic.dir/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Testing/Basic/.idea/.idea.Basic.dir/.idea/vcs.xml b/Testing/Basic/.idea/.idea.Basic.dir/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/Testing/Basic/.idea/.idea.Basic.dir/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Testing/Basic/Folder.DotSettings.user b/Testing/Basic/Folder.DotSettings.user new file mode 100644 index 0000000..95f2eb8 --- /dev/null +++ b/Testing/Basic/Folder.DotSettings.user @@ -0,0 +1,12 @@ + + ForceIncluded + ForceIncluded + <SessionState ContinuousTestingMode="0" Name="All tests from Solution #3" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> + <SessionState ContinuousTestingMode="0" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> \ No newline at end of file diff --git a/Testing/Basic/Homework/1. ObjectComparison/TsarRegistry.cs b/Testing/Basic/Homework/1. ObjectComparison/TsarRegistry.cs index f852e90..8155fdb 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/TsarRegistry.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/TsarRegistry.cs @@ -8,4 +8,5 @@ public static Person GetCurrentTsar() "Ivan IV The Terrible", 54, 170, 70, new Person("Vasili III of Russia", 28, 170, 60, null)); } -} \ No newline at end of file +} +