From 25052a93ae020cdd7e20c0aefdded3f44f8eaeed Mon Sep 17 00:00:00 2001 From: Krotkaya Date: Mon, 27 Oct 2025 16:51:37 +0500 Subject: [PATCH 1/2] =?UTF-8?q?=D0=94=D0=BE=D0=BC=D0=B0=D1=88=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8E,=20=D1=87=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D1=8C=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ДЗ включало в себя: - Использование FluentAssertions при написании тестов --- .gitignore | 1 + .../1. ObjectComparison/ObjectComparison.cs | 34 ++++++++--- .../NumberValidatorTests.cs | 59 ++++++++++++++++++- 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 03c9b93..e65d90e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin/ obj/ .vs/ +.idea/ \ No newline at end of file diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index d544c47..0a7e0c8 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -1,7 +1,9 @@ using NUnit.Framework; using NUnit.Framework.Legacy; +using FluentAssertions; namespace HomeExercise.Tasks.ObjectComparison; + public class ObjectComparison { [Test] @@ -10,22 +12,27 @@ public class ObjectComparison 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)); - + // Перепишите код на использование 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.Should().BeEquivalentTo(expectedTsar, option => option + .Excluding(it => it.Id) + .Excluding(it => it.Parent.Id)); + } - + [Test] [Description("Альтернативное решение. Какие у него недостатки?")] public void CheckCurrentTsar_WithCustomEquality() @@ -33,11 +40,24 @@ 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)); } - + //Недостатки + //1. Если тест падает мы просто видим, что ожидалось true, почему упало не видим + //2. Если добавляем новые свойства в класс человека, то здесь нужно также это учитывать + //3. Есть рекурсия без обработки случая циклов + //(в последней строке метода AreEqual вызывается рекурсивно + //-> появляется риск StackOverflow и из-за циклической ссылки, + //FluentAssertions может обработать циклические ссылки, если я отмечу .IgnoringCyclicReferences()) + //4. Если бы наш тест был с большим количеством сравнений person, и блок Assert бы не выполнялся на первом, + //то остальные бы вариант не проверялись. FluentAssertions при этом выполняет всегда все тесты, + //и потом просто выводит, что выполнилось, а что нет + //5. Читаемость :) + + + private bool AreEqual(Person? actual, Person? expected) { if (actual == expected) return true; @@ -49,4 +69,4 @@ private bool AreEqual(Person? actual, Person? expected) && actual.Weight == expected.Weight && AreEqual(actual.Parent, expected.Parent); } -} +} \ No newline at end of file diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 950c9bc..58b6157 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -14,7 +14,7 @@ public void Test() 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")); @@ -28,4 +28,61 @@ public void Test() ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-1.23")); ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("a.sd")); } + + + [Test] + public void Constructor_ThrowExceptions_InvalidParameter() + { + Assert.Throws(() => new NumberValidator(-1, 2, true)); + Assert.Throws(() => new NumberValidator(5, -1)); + Assert.Throws(() => new NumberValidator(5, 5)); + Assert.Throws(() => new NumberValidator(5, 6)); + Assert.Throws(() => new NumberValidator(0, 0)); + } + + [Test] + public void Constructor_DoesNotThrowExceptions_CorrectParameter() + { + Assert.DoesNotThrow(() => new NumberValidator(1, 0, true)); + Assert.DoesNotThrow(() => new NumberValidator(1)); + Assert.DoesNotThrow(() => new NumberValidator(5, 2)); + Assert.DoesNotThrow(() => new NumberValidator(5, 2, true)); + } + + [TestCase(17, 2, true, "0", TestName = "Целое число ноль должно быть валидным")] + [TestCase(17, 2, true, "0.0", TestName = "Дробное число ноль должно быть валидным")] + [TestCase(4, 2, true, "+1.23", TestName = "Положительное число со знаком плюс должно быть валидным")] + [TestCase(17, 2, false, "-1.23", TestName = "Отрицательное число должно быть валидным когда onlyPositive=false")] + [TestCase(3, 0, true, "123", TestName = "Целое число без дробной части должно быть валидным")] + public void IsValidNumber_ReturnTrue_ValidCases(int precision, int scale, bool onlyPositive, string value) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + + ClassicAssert.IsTrue(validator.IsValidNumber(value)); + } + + [TestCase(3, 2, true, "00.00", TestName = "Превышение общего лимита цифр")] + [TestCase(3, 2, true, "-0.00", TestName = "Отрицательное число при запрете отрицательных")] + [TestCase(3, 2, true, "+0.00", TestName = "Знак плюс с нулем превышает лимит цифр")] + [TestCase(3, 2, true, "+1.23", TestName = "Превышение лимита цифр в целом числе")] + [TestCase(17, 2, true, "0.000", TestName = "Превышение лимита цифр в дробной части")] + [TestCase(3, 2, true, "a.sd", TestName = "Символы не являющиеся цифрами")] + [TestCase(3, 2, true, "", TestName = "Пустая строка как входное значение")] + [TestCase(3, 2, true, null, TestName = "Null как входное значение")] + public void IsValidNumber_ReturnFalse_InvalidCases(int precision, int scale, bool onlyPositive, string value) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + + ClassicAssert.IsFalse(validator.IsValidNumber(value)); + } + + + [TestCase(1, 0, true, "0", TestName = "Минимальная precision с нулем")] + [TestCase(2, 1, true, "0.1", TestName = "Граничные значения precision и scale")] + [TestCase(3, 2, true, "1.23", TestName = "Максимальное количество цифр в дробной части")] + public void IsValidNumber_BoundaryCases_ReturnsTrue(int precision, int scale, bool onlyPositive, string value) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + ClassicAssert.IsTrue(validator.IsValidNumber(value)); + } } \ No newline at end of file From 3e8edea83a9e7ae8a2f7363ce5557e39698e941d Mon Sep 17 00:00:00 2001 From: Krotkaya Date: Mon, 27 Oct 2025 23:17:17 +0500 Subject: [PATCH 2/2] =?UTF-8?q?=D0=92=D0=BD=D0=B5=D1=81=D0=BB=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Изменения: - Убрала лишний код с заданием на ClassicAssert - NumberValidatorTests добавила FluentAssertions - Вынесла проверки на exceptions в TestCase --- .../1. ObjectComparison/ObjectComparison.cs | 12 ---- .../NumberValidatorTests.cs | 72 +++++++++---------- 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index 0a7e0c8..a3f6dca 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -16,21 +16,9 @@ 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. - 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.Should().BeEquivalentTo(expectedTsar, option => option .Excluding(it => it.Id) .Excluding(it => it.Parent.Id)); - } [Test] diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 58b6157..a7bd561 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -1,54 +1,38 @@ - +using FluentAssertions; using NUnit.Framework; -using NUnit.Framework.Legacy; + namespace HomeExercise.Tasks.NumberValidator; [TestFixture] 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")); - } - - - [Test] - public void Constructor_ThrowExceptions_InvalidParameter() + [TestCase(-1, 2, true, TestName = "Отрицательная precision")] + [TestCase(5, -1, true, TestName = "Отрицательная scale")] + [TestCase(5, 5, true, TestName = "Scale равен precision")] + [TestCase(5, 6, true, TestName = "Scale больше precision")] + [TestCase(0, 0, true, TestName = "Precision ноль")] + public void Constructor_ThrowExceptions_InvalidParameter(int precision, int scale, bool onlyPositive) { - Assert.Throws(() => new NumberValidator(-1, 2, true)); - Assert.Throws(() => new NumberValidator(5, -1)); - Assert.Throws(() => new NumberValidator(5, 5)); - Assert.Throws(() => new NumberValidator(5, 6)); - Assert.Throws(() => new NumberValidator(0, 0)); + Action act = () => new NumberValidator(precision, scale, onlyPositive); + + act.Should().Throw(); } - [Test] - public void Constructor_DoesNotThrowExceptions_CorrectParameter() + + [TestCase(1, 0, true, TestName = "Минимальные валидные параметры")] + [TestCase(1, 0, false, TestName = "OnlyPositive false")] + [TestCase(5, 2, true, TestName = "Scale меньше precision")] + [TestCase(3, 0, true, TestName = "Scale ноль")] + public void Constructor_DoesNotThrowExceptions_CorrectParameter(int precision, int scale, bool onlyPositive) { - Assert.DoesNotThrow(() => new NumberValidator(1, 0, true)); - Assert.DoesNotThrow(() => new NumberValidator(1)); - Assert.DoesNotThrow(() => new NumberValidator(5, 2)); - Assert.DoesNotThrow(() => new NumberValidator(5, 2, true)); + Action act = () => new NumberValidator(precision, scale, onlyPositive); + + act.Should().NotThrow(); } + [TestCase(17, 2, true, "0", TestName = "Целое число ноль должно быть валидным")] [TestCase(17, 2, true, "0.0", TestName = "Дробное число ноль должно быть валидным")] [TestCase(4, 2, true, "+1.23", TestName = "Положительное число со знаком плюс должно быть валидным")] @@ -58,9 +42,12 @@ public void IsValidNumber_ReturnTrue_ValidCases(int precision, int scale, bool o { var validator = new NumberValidator(precision, scale, onlyPositive); - ClassicAssert.IsTrue(validator.IsValidNumber(value)); + var result = validator.IsValidNumber(value); + + result.Should().BeTrue(); } + [TestCase(3, 2, true, "00.00", TestName = "Превышение общего лимита цифр")] [TestCase(3, 2, true, "-0.00", TestName = "Отрицательное число при запрете отрицательных")] [TestCase(3, 2, true, "+0.00", TestName = "Знак плюс с нулем превышает лимит цифр")] @@ -73,7 +60,9 @@ public void IsValidNumber_ReturnFalse_InvalidCases(int precision, int scale, boo { var validator = new NumberValidator(precision, scale, onlyPositive); - ClassicAssert.IsFalse(validator.IsValidNumber(value)); + var result = validator.IsValidNumber(value); + + result.Should().BeFalse(); } @@ -83,6 +72,9 @@ public void IsValidNumber_ReturnFalse_InvalidCases(int precision, int scale, boo public void IsValidNumber_BoundaryCases_ReturnsTrue(int precision, int scale, bool onlyPositive, string value) { var validator = new NumberValidator(precision, scale, onlyPositive); - ClassicAssert.IsTrue(validator.IsValidNumber(value)); + + var result = validator.IsValidNumber(value); + + result.Should().BeTrue(); } } \ No newline at end of file