diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index d544c47..1f97bf7 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using FluentAssertions; +using NUnit.Framework; using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.ObjectComparison; @@ -12,18 +13,12 @@ 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); + new Person("Vasili III of Russia", 28, 170, 60, null!)); + + actualTsar.Should().BeEquivalentTo(expectedTsar, options => options + .Excluding(info => + info.Path == nameof(Person.Id) + || info.Path.EndsWith($".{nameof(Person.Id)}"))); } [Test] @@ -32,13 +27,25 @@ 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)); + new Person("Vasili III of Russia", 28, 170, 60, null!)); // Какие недостатки у такого подхода? + + /* + * Мы не получаем полезной информации при падении теста. + * Было бы полезно знать в каком поле наблюдается различие. + * Также мы не знаем в каком поколении находится это различие. + * Кроме того, реализация AreEqual рекурсивная + * и при этом не защищена от замыкания (зацикливания) цепочки родословной. + * Несколько лучшим решением было бы реализовать класс с интерфейсом IEqualityComparer. + * Реализация равенства не связана с классом Person, + * поэтому при изменении класса нужно не забывать о необходимости внесения правок в эту реализацию. + */ + ClassicAssert.True(AreEqual(actualTsar, expectedTsar)); } - private bool AreEqual(Person? actual, Person? expected) + private bool AreEqual(Person? actual, Person? expected) { if (actual == expected) return true; if (actual == null || expected == null) return false; diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 950c9bc..7c92b9d 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -1,31 +1,151 @@ - +using FluentAssertions; using NUnit.Framework; -using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.NumberValidator; [TestFixture] public class NumberValidatorTests { - [Test] - public void Test() + [TestCase(-1, 0, false)] + public void Constructor_ShouldThrow_ArgumentException_When_NegativeTotalNumberOfDigits( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, true); + + [TestCase(0, 0, false)] + public void Constructor_ShouldThrow_ArgumentException_When_ZeroTotalNumberOfDigits( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, true); + + [TestCase(1, -1, false)] + public void Constructor_ShouldThrow_ArgumentException_When_NegativeNumberOfDigitsInFractionalPart( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, true); + + [TestCase(1, 1, false)] + public void Constructor_ShouldThrow_ArgumentException_When_NumberOfDigitsInFractionalPartEqualTotalNumberOfDigits( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, true); + + [TestCase(1, 2, false)] + public void Constructor_ShouldThrow_ArgumentException_When_NumberOfDigitsInFractionalPartGreaterTotalNumberOfDigits( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, true); + + [TestCase(1, 0, false)] + public void Constructor_ShouldNotThrow_Exception_When_PositivePrecisionNonNegativeScaleAndScaleLessPrecision( + int precision, + int scale, + bool onlyPositive) + => CheckConstructorThrowArgumentException(precision, scale, onlyPositive, false); + + [TestCase(null, 17, 2, true)] + [TestCase("", 17, 2, true)] + [TestCase(" \n\t ", 17, 2, true)] + public void IsValidNumber_ShouldBe_False_When_NullOrEmpty( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, false); + + [TestCase("asd", 17, 2, true)] + [TestCase(" 0", 17, 2, true)] + [TestCase("0 ", 17, 2, true)] + [TestCase(".0", 17, 2, true)] + [TestCase("0.", 17, 2, true)] + [TestCase("a23", 17, 2, true)] + [TestCase("1e3", 17, 2, true)] + [TestCase("1.a23", 17, 5, true)] + public void IsValidNumber_ShouldBe_False_When_DoesNotMatchFormat( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, false); + + [TestCase("00.00", 3, 2, true)] + [TestCase("-0.00", 3, 2, false)] + [TestCase("+123", 3, 2, true)] + [TestCase("1234", 3, 2, true)] + public void IsValidNumber_ShouldBe_False_When_DigitsPlusSignGreaterPrecision( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, false); + + [TestCase("00.00", 4, 2, true)] + [TestCase("-0.00", 4, 2, false)] + [TestCase("+123", 4, 2, true)] + [TestCase("1234", 4, 2, true)] + public void IsValidNumber_ShouldBe_True_When_DigitsPlusSignLessOrEqualPrecision( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, true); + + [TestCase("0.000", 17, 2, true)] + public void IsValidNumber_ShouldBe_False_When_FractionGreaterScale( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, false); + + [TestCase("0", 17, 2, true)] + [TestCase("0.0", 17, 2, true)] + [TestCase("0.00", 17, 2, true)] + public void IsValidNumber_ShouldBe_True_When_FractionLessOrEqualScale( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, true); + + [TestCase("-0.00", 4, 2, true)] + [TestCase("-123", 4, 2, true)] + public void IsValidNumber_ShouldBe_False_When_MinusAndOnlyPositive( + string number, + int precision, + int scale, + bool onlyPositive) + => CheckNumberValidation(number, precision, scale, onlyPositive, false); + + private void CheckNumberValidation( + string number, + int precision, + int scale, + bool onlyPositive, + bool isValid) { - 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")); - } + new NumberValidator(precision, scale, onlyPositive) + .IsValidNumber(number) + .Should() + .Be(isValid); + } + + private void CheckConstructorThrowArgumentException( + int precision, + int scale, + bool onlyPositive, + bool shouldThrow) + { + var func = () => new NumberValidator(precision, scale, onlyPositive); + + if (shouldThrow) + func.Should().Throw(); + else + func.Should().NotThrow(); + } } \ No newline at end of file