diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
index d544c47..0ac7bdd 100644
--- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
+++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
@@ -1,8 +1,10 @@
-using NUnit.Framework;
+using FluentAssertions;
+using NUnit.Framework;
using NUnit.Framework.Legacy;
namespace HomeExercise.Tasks.ObjectComparison;
-public class ObjectComparison
+
+public class TsarComparison
{
[Test]
[Description("Проверка текущего царя")]
@@ -11,19 +13,27 @@ 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));
+ var expectedTsar = new Person(
+ name: "Ivan IV The Terrible",
+ age: 54,
+ height: 170,
+ weight: 70,
+ parent: new Person(
+ name: "Vasili III of Russia",
+ age: 28,
+ height: 170,
+ weight: 60,
+ parent: 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);
+ ///
+ /// Такой подход автоматически проверяет все свойства объекта, включая вложенные
+ /// Тест не будет требовать изменений при добавлении новых свойств в класс Person
+ /// При падении теста, FluentAssertions предоставляет подробную информацию о том, какие именно свойства не совпали
+ ///
- 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, options => options.Excluding(t => t.Id).Excluding(t => t.Parent.Id));
}
[Test]
@@ -31,11 +41,35 @@ public void CheckCurrentTsar()
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));
-
- // Какие недостатки у такого подхода?
+
+ var expectedTsar = new Person(
+ name: "Ivan IV The Terrible",
+ age: 54,
+ height: 170,
+ weight: 70,
+ new Person(
+ name: "Vasili III of Russia",
+ age: 28,
+ height: 170,
+ weight: 60,
+ parent: null!
+ )
+ );
+
+ // Какие недостатки у такого подхода?
+ // Недостатки подхода:
+ // 1) Требуется ручное обновление метода сравнения при добавлении новых свойств в класс Person,
+ // 2) Тест менее информативен при падении. Он просто укажет, что объекты не равны, не показывая какие именно свойства не совпали.
ClassicAssert.True(AreEqual(actualTsar, expectedTsar));
+
+ // Вызываем Stack Overflow exception
+ // var p1 = new Person("A", 1, 1, 1, null!);
+ // p1.Parent = p1;
+ //
+ // var p2 = new Person("A", 1, 1, 1, null!);
+ // p2.Parent = p2;
+ //
+ // ClassicAssert.True(AreEqual(p1, p2));
}
private bool AreEqual(Person? actual, Person? expected)
@@ -49,4 +83,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..60e4827 100644
--- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
+++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
@@ -1,31 +1,209 @@
-
+using FluentAssertions;
using NUnit.Framework;
-using NUnit.Framework.Legacy;
namespace HomeExercise.Tasks.NumberValidator;
[TestFixture]
public class NumberValidatorTests
{
+ #region Допустимая разрядность
+
+ [TestCase(-1, 2, true)]
+ [TestCase(0, 2, true)]
+ public void Ctor_InvalidPrecision_ThrowsArgumentException(int precision, int scale, bool onlyPositive)
+ {
+ var act = () => new NumberValidator(precision, scale, onlyPositive);
+ act.Should()
+ .Throw()
+ .WithMessage("precision must be a positive number");
+ }
+
+ #endregion
+
+ #region Некорректная дробность
+
+ [TestCase(5, -1, true)]
+ public void Ctor_InvalidScale_Negative_ThrowsArgumentException(int precision, int scale, bool onlyPositive)
+ {
+ var act = () => new NumberValidator(precision, scale, onlyPositive);
+ act.Should()
+ .Throw()
+ .WithMessage("*non-negative*"); // узнал, что можно передавать часть строки
+ }
+
+ [TestCase(1, 2, true)]
+ [TestCase(1, 1, true)]
+ public void Ctor_WithScaleGreaterOrEqualToPrecision_ThrowsArgumentException(int precision, int scale, bool onlyPositive)
+ {
+ var act = () => new NumberValidator(precision, scale, onlyPositive);
+ act.Should()
+ .Throw()
+ .WithMessage("*less or equal*"); // узнал, что можно передавать часть строки
+ }
+
+ #endregion
+
+ #region Корректные аргументы для конструктора
+
+ [Test]
+ public void Ctor_ValidArguments_DoesNotThrow()
+ {
+ var act = () => new NumberValidator(1, 0, true);
+ act.Should().NotThrow();
+ }
+
+ #endregion
+
+ #region Передаваемое число в формате пустой строки или null
+
+ [TestCase("", 17, 2, true)]
+ [TestCase(null, 17, 2, true)]
+ public void IsValidNumber_NullOrEmpty_ReturnsFalse(string value, int precision, int scale, bool onlyPositive)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ var result = validator.IsValidNumber(value);
+ result.Should().BeFalse();
+ }
+
+ #endregion
+
+ #region Некорректный формат передаваемого числа
+
+ [Test]
+ public void IsValidNumber_MultipleFractionSeparators_ReturnsFalse()
+ {
+ var validator = new NumberValidator(10, 4, true);
+ var result = validator.IsValidNumber("1..2");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_OnlySigns_ReturnsFalse()
+ {
+ var validator = new NumberValidator(15, 1, true);
+ var result = validator.IsValidNumber("+-.");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_OnlyDot_ReturnsFalse()
+ {
+ var validator = new NumberValidator(22, 8, true);
+ var result = validator.IsValidNumber(".");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_DotLastSign_ReturnsFalse()
+ {
+ var validator = new NumberValidator(9, 4, true);
+ var result = validator.IsValidNumber("1.");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_DotFirstSign_ReturnsFalse()
+ {
+ var validator = new NumberValidator(7, 3, true);
+ var result = validator.IsValidNumber(".1");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_ContainsSpace_ReturnsFalse()
+ {
+ var validator = new NumberValidator(17, 6, true);
+ var result = validator.IsValidNumber("5 2");
+ result.Should().BeFalse();
+ }
+
[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 IsValidNumber_ContainsUnderscore_ReturnsFalse()
+ {
+ var validator = new NumberValidator(11, 3, true);
+ var result = validator.IsValidNumber("4_4");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_ContainsLettersAndUnderscore_ReturnsFalse()
+ {
+ var validator = new NumberValidator(10, 5, true);
+ var result = validator.IsValidNumber("abcd_4");
+ result.Should().BeFalse();
+ }
+
+ [Test]
+ public void IsValidNumber_DoubleMinus_ReturnsFalse()
+ {
+ var validator = new NumberValidator(12, 2, true);
+ var result = validator.IsValidNumber("--1");
+ result.Should().BeFalse();
+ }
+
+ #endregion
+
+ #region Корректное передаваемое число
+
+ [TestCase("+1", 4, 2, true)]
+ [TestCase("+0.1", 9, 1, true)]
+ [TestCase("000.10", 5, 2, true)]
+ [TestCase("000,10", 8, 4, true)]
+ [TestCase("10", 2, 0, true)]
+ public void IsValidNumber_ValidFormat_ReturnsTrue(string value, int precision, int scale, bool onlyPositive)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ var result = validator.IsValidNumber(value);
+ result.Should().BeTrue();
+ }
+
+ #endregion
+
+ #region Количество допустимых цифр в числе, включая знак, целую и дробную часть, без точки
+
+ [TestCase("17.9", 3, 1, true, true)]
+ [TestCase("171.9", 3, 1, true, false)]
+ [TestCase("+17", 3, 2, true, true)]
+ [TestCase("+17", 2, 0, true, false)]
+ public void IsValidNumber_RespectsPrecisionLimit_ReturnsExpected(string value, int precision, int scale,
+ bool onlyPositive, bool expected)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ var result = validator.IsValidNumber(value);
+ result.Should().Be(expected);
+ }
+
+ #endregion
+
+ #region Количество знаков после запятой
+
+ [TestCase("1.0", 10, 0, true, false)]
+ [TestCase("1.44", 10, 2, true, true)]
+ [TestCase("1.4", 10, 2, true, true)]
+ [TestCase("1,040", 10, 3, true, true)]
+ [TestCase("1.41414141", 10, 2, true, false)]
+ public void IsValidNumber_RespectsScale_ReturnsExpected(string value, int precision, int scale, bool onlyPositive,
+ bool expected)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ var result = validator.IsValidNumber(value);
+ result.Should().Be(expected);
+ }
+
+ #endregion
+
+ #region Проверка параметра onlyPositive (только положительные)
+
+ [TestCase("-4.59", 4, 2, false, true)]
+ [TestCase("-6", 2, 0, true, false)]
+ [TestCase("+5", 2, 0, false, true)]
+ public void IsValidNumber_RespectsOnlyPositive_ReturnsExpected(string value, int precision, int scale, bool onlyPositive,
+ bool expected)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ var result = validator.IsValidNumber(value);
+ result.Should().Be(expected);
}
+
+ #endregion
}
\ No newline at end of file