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..a3f6dca 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,15 @@ 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 +28,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 +57,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..a7bd561 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -1,31 +1,80 @@ - +using FluentAssertions; using NUnit.Framework; -using NUnit.Framework.Legacy; + namespace HomeExercise.Tasks.NumberValidator; [TestFixture] public class NumberValidatorTests { - [Test] - public void Test() + + [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) + { + Action act = () => new NumberValidator(precision, scale, onlyPositive); + + act.Should().Throw(); + } + + + [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) + { + 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 = "Положительное число со знаком плюс должно быть валидным")] + [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); + + 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 = "Знак плюс с нулем превышает лимит цифр")] + [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) { - 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)); + var validator = new NumberValidator(precision, scale, onlyPositive); + + var result = validator.IsValidNumber(value); + + result.Should().BeFalse(); + } + - 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")); + [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); + + var result = validator.IsValidNumber(value); + + result.Should().BeTrue(); } } \ No newline at end of file