From 944cfb6d475dd64199d5dfbfa7077cfaeb81e4a5 Mon Sep 17 00:00:00 2001 From: Roman Gleizer Date: Sun, 26 Oct 2025 10:59:37 +0500 Subject: [PATCH 1/4] =?UTF-8?q?=D0=A1=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1. ObjectComparison/ObjectComparison.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index d544c47..2bb5f3c 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 FluentAssertions; +using NUnit.Framework; using NUnit.Framework.Legacy; namespace HomeExercise.Tasks.ObjectComparison; + public class ObjectComparison { [Test] @@ -14,16 +16,14 @@ 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); + /// + /// Такой подход автоматически проверяет все свойства объекта, включая вложенные + /// Тест не будет требовать изменений при добавлении новых свойств в класс 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] @@ -34,7 +34,10 @@ public void CheckCurrentTsar_WithCustomEquality() var expectedTsar = new Person("Ivan IV The Terrible", 54, 170, 70, new Person("Vasili III of Russia", 28, 170, 60, null)); - // Какие недостатки у такого подхода? + // Какие недостатки у такого подхода? + // Недостатки подхода: + // 1) Требуется ручное обновление метода сравнения при добавлении новых свойств в класс Person, + // 2) Тест менее информативен при падении. Он просто укажет, что объекты не равны, не показывая какие именно свойства не совпали. ClassicAssert.True(AreEqual(actualTsar, expectedTsar)); } From f530fb86270e8a1629adf8025bc2e75b46e9fe7a Mon Sep 17 00:00:00 2001 From: Roman Gleizer Date: Sun, 26 Oct 2025 21:14:46 +0500 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NumberValidatorTests.cs | 120 ++++++++++++++---- 1 file changed, 98 insertions(+), 22 deletions(-) diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index 950c9bc..e000ed5 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -1,31 +1,107 @@ - +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")); + [TestCase(-1, 2, true, TestName = "Исключение, когда precision отрицательный")] + [TestCase(0, 2, true, TestName = "Исключение, когда precision равен нулю")] + [TestCase(5, -1, true, TestName = "Исключение, когда scale отрицательный")] + [TestCase(1, 2, true, TestName = "Исключение, когда scale больше precision")] + [TestCase(1, 1, true, TestName = "Исключение исключение, когда scale равен precision")] + public void Ctor_Should_Throw_On_Invalid_Arguments(int precision, int scale, bool onlyPositive) + { + var act = () => new NumberValidator(precision, scale, onlyPositive); + act.Should().Throw(); + } + + [TestCase(1, 0, true, TestName = "Не выбрасывает исключение на корректных элемент")] + public void Ctor_Should_Not_Throw_On_Valid_Arguments(int precision, int scale, bool onlyPositive) + { + var act = () => new NumberValidator(precision, scale, onlyPositive); + act.Should().NotThrow(); + } + + [TestCase("", 17, 2, true, TestName = "Возвращает false, когда значение пустое")] + [TestCase(null, 17, 2, true, TestName = "Возвращает false, когда значение null")] + public void Should_Return_False_On_NullOrEmpty(string value, int precision, int scale, bool onlyPositive) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + var result = validator.IsValidNumber(value); + result.Should().BeFalse(); + } + + [TestCase("1..2", 10, 4, true, + TestName = "Возвращает false, когда число содержит несколько разделителей дробной части")] + [TestCase("+-.", 15, 1, true, TestName = "Возвращает false, когда строка содержит только знаки")] + [TestCase(".", 22, 8, true, TestName = "Возвращает false, когда строка состоит только из точки")] + [TestCase("1.", 9, 4, true, TestName = "Возвращает false, когда число оканчивается точкой")] + [TestCase(".1", 7, 3, true, TestName = "Возвращает false, когда число начинается с точки")] + [TestCase("5 2", 17, 6, true, TestName = "Возвращает false, когда число содержит пробел")] + [TestCase("4_4", 11, 3, true, TestName = "Возвращает false, когда число содержит символ подчёркивания")] + [TestCase("abcd_4", 10, 5, true, TestName = "Возвращает false, когда строка содержит буквы и подчёркивание")] + [TestCase("--1", 12, 2, true, TestName = "Возвращает false, когда число содержит двойной минус")] + public void Should_Return_False_On_InvalidFormat(string value, int precision, int scale, bool onlyPositive) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + var result = validator.IsValidNumber(value); + result.Should().BeFalse(); + } + + [TestCase("+1", 4, 2, true, TestName = "Возвращает true, когда целое число со знаком плюс")] + [TestCase("+0.1", 9, 1, true, TestName = "Возвращает true, когда дробное число со знаком плюс")] + [TestCase("000.10", 5, 2, true, + TestName = "Возвращает true, когда число с ведущими нулями и точкой в качестве разделителя")] + [TestCase("000,10", 8, 4, true, + TestName = "Возвращает true, когда число с ведущими нулями и запятой в качестве разделителя")] + [TestCase("10", 2, 0, true, TestName = "Возвращает true, когда число целое и точно соответствует precision")] + public void Should_Return_True_On_ValidFormat(string value, int precision, int scale, bool onlyPositive) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + var result = validator.IsValidNumber(value); + result.Should().BeTrue(); + } + + [TestCase("17.9", 3, 1, true, true, TestName = "возвращает true, когда общее количество цифр равно precision")] + [TestCase("171.9", 3, 1, true, false, TestName = "возвращает false, когда общее количество цифр больше precision")] + [TestCase("+17", 3, 2, true, true, TestName = "возвращает true, когда знак плюс + цифры = precision")] + [TestCase("+17", 2, 0, true, false, TestName = "возвращает false, когда знак плюс превышает precision")] + public void IsValidNumber_Should_Respect_Precision_Limit(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); + } + + [TestCase("1.0", 10, 0, true, false, TestName = "возвращает false, когда scale равно 0, но есть дробная часть")] + [TestCase("1.44", 10, 2, true, true, TestName = "возвращает true, когда длина дробной части равна scale")] + [TestCase("1.4", 10, 2, true, true, TestName = "возвращает true, когда длина дробной части меньше scale")] + [TestCase("1,040", 10, 3, true, true, + TestName = "возвращает true, когда дробная часть с ведущими нулями помещается в scale")] + [TestCase("1.41414141", 10, 2, true, false, + TestName = "возвращает false, когда длина дробной части больше scale")] + public void IsValid_Respects_Scale(string input, int precision, int scale, + bool onlyPositive, bool expected) + { + var validator = new NumberValidator(10, scale, onlyPositive); + var result = validator.IsValidNumber(input); + result.Should().Be(expected); + } + + [TestCase("-4.59", 4, 2, false, true, + TestName = "возвращает true для отрицательного числа при onlyPositive равно false")] + [TestCase("-6", 2, 0, true, false, + TestName = "возвращает false для отрицательного числа при onlyPositive равно true")] + [TestCase("+5", 2, 0, false, true, + TestName = "возвращает true для положительного числа со знаком плюс, когда onlyPositive равно false")] + public void IsValid_Respects_OnlyPositive(string input, int precision, int scale, + bool onlyPositive, bool expected) + { + var validator = new NumberValidator(precision, scale, onlyPositive); + var result = validator.IsValidNumber(input); + result.Should().Be(expected); } } \ No newline at end of file From e619528abed0ce50db91e3ade1cf3ada93c6d82d Mon Sep 17 00:00:00 2001 From: Roman Gleizer Date: Mon, 27 Oct 2025 19:49:44 +0500 Subject: [PATCH 3/4] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=81=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=86=D0=B0=D1=80=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ObjectComparison стал TsarComparison, добавил named arguments, поправил форматирование Fluent Assertions, выяснил, что могу быть проблемы с рекурсией --- .../1. ObjectComparison/ObjectComparison.cs | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs index 2bb5f3c..0ac7bdd 100644 --- a/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs +++ b/Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs @@ -4,7 +4,7 @@ namespace HomeExercise.Tasks.ObjectComparison; -public class ObjectComparison +public class TsarComparison { [Test] [Description("Проверка текущего царя")] @@ -13,8 +13,19 @@ 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! + ) + ); /// /// Такой подход автоматически проверяет все свойства объекта, включая вложенные @@ -22,8 +33,7 @@ public void CheckCurrentTsar() /// При падении теста, FluentAssertions предоставляет подробную информацию о том, какие именно свойства не совпали /// - actualTsar.Should() - .BeEquivalentTo(expectedTsar, options => options.Excluding(t => t.Id).Excluding(t => t.Parent.Id)); + actualTsar.Should().BeEquivalentTo(expectedTsar, options => options.Excluding(t => t.Id).Excluding(t => t.Parent.Id)); } [Test] @@ -31,14 +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) @@ -52,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 From d6c1c14a7140a6a056876063ee75bca12db65d44 Mon Sep 17 00:00:00 2001 From: Roman Gleizer Date: Tue, 28 Oct 2025 18:46:41 +0500 Subject: [PATCH 4/4] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D1=80=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Убрал избыточный TestName, поправил опечатки, стал придерживаться нейминга Method_Scenario_ExpectedResult, добавил уточнения текстов ошибок, разбил тесты по категориям и избавился от магического числа --- .../NumberValidatorTests.cs | 218 +++++++++++++----- 1 file changed, 160 insertions(+), 58 deletions(-) diff --git a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs index e000ed5..60e4827 100644 --- a/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs +++ b/Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs @@ -6,102 +6,204 @@ namespace HomeExercise.Tasks.NumberValidator; [TestFixture] public class NumberValidatorTests { - [TestCase(-1, 2, true, TestName = "Исключение, когда precision отрицательный")] - [TestCase(0, 2, true, TestName = "Исключение, когда precision равен нулю")] - [TestCase(5, -1, true, TestName = "Исключение, когда scale отрицательный")] - [TestCase(1, 2, true, TestName = "Исключение, когда scale больше precision")] - [TestCase(1, 1, true, TestName = "Исключение исключение, когда scale равен precision")] - public void Ctor_Should_Throw_On_Invalid_Arguments(int precision, int scale, bool onlyPositive) + #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(); + act.Should() + .Throw() + .WithMessage("precision must be a positive number"); } - [TestCase(1, 0, true, TestName = "Не выбрасывает исключение на корректных элемент")] - public void Ctor_Should_Not_Throw_On_Valid_Arguments(int precision, int scale, bool onlyPositive) + #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 - [TestCase("", 17, 2, true, TestName = "Возвращает false, когда значение пустое")] - [TestCase(null, 17, 2, true, TestName = "Возвращает false, когда значение null")] - public void Should_Return_False_On_NullOrEmpty(string value, int precision, int scale, bool onlyPositive) + #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 - [TestCase("1..2", 10, 4, true, - TestName = "Возвращает false, когда число содержит несколько разделителей дробной части")] - [TestCase("+-.", 15, 1, true, TestName = "Возвращает false, когда строка содержит только знаки")] - [TestCase(".", 22, 8, true, TestName = "Возвращает false, когда строка состоит только из точки")] - [TestCase("1.", 9, 4, true, TestName = "Возвращает false, когда число оканчивается точкой")] - [TestCase(".1", 7, 3, true, TestName = "Возвращает false, когда число начинается с точки")] - [TestCase("5 2", 17, 6, true, TestName = "Возвращает false, когда число содержит пробел")] - [TestCase("4_4", 11, 3, true, TestName = "Возвращает false, когда число содержит символ подчёркивания")] - [TestCase("abcd_4", 10, 5, true, TestName = "Возвращает false, когда строка содержит буквы и подчёркивание")] - [TestCase("--1", 12, 2, true, TestName = "Возвращает false, когда число содержит двойной минус")] - public void Should_Return_False_On_InvalidFormat(string value, int precision, int scale, bool onlyPositive) + #region Некорректный формат передаваемого числа + + [Test] + public void IsValidNumber_MultipleFractionSeparators_ReturnsFalse() { - var validator = new NumberValidator(precision, scale, onlyPositive); - var result = validator.IsValidNumber(value); + 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(); } - [TestCase("+1", 4, 2, true, TestName = "Возвращает true, когда целое число со знаком плюс")] - [TestCase("+0.1", 9, 1, true, TestName = "Возвращает true, когда дробное число со знаком плюс")] - [TestCase("000.10", 5, 2, true, - TestName = "Возвращает true, когда число с ведущими нулями и точкой в качестве разделителя")] - [TestCase("000,10", 8, 4, true, - TestName = "Возвращает true, когда число с ведущими нулями и запятой в качестве разделителя")] - [TestCase("10", 2, 0, true, TestName = "Возвращает true, когда число целое и точно соответствует precision")] - public void Should_Return_True_On_ValidFormat(string value, int precision, int scale, bool onlyPositive) + [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 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 - [TestCase("17.9", 3, 1, true, true, TestName = "возвращает true, когда общее количество цифр равно precision")] - [TestCase("171.9", 3, 1, true, false, TestName = "возвращает false, когда общее количество цифр больше precision")] - [TestCase("+17", 3, 2, true, true, TestName = "возвращает true, когда знак плюс + цифры = precision")] - [TestCase("+17", 2, 0, true, false, TestName = "возвращает false, когда знак плюс превышает precision")] - public void IsValidNumber_Should_Respect_Precision_Limit(string value, int precision, int scale, + #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 - [TestCase("1.0", 10, 0, true, false, TestName = "возвращает false, когда scale равно 0, но есть дробная часть")] - [TestCase("1.44", 10, 2, true, true, TestName = "возвращает true, когда длина дробной части равна scale")] - [TestCase("1.4", 10, 2, true, true, TestName = "возвращает true, когда длина дробной части меньше scale")] - [TestCase("1,040", 10, 3, true, true, - TestName = "возвращает true, когда дробная часть с ведущими нулями помещается в scale")] - [TestCase("1.41414141", 10, 2, true, false, - TestName = "возвращает false, когда длина дробной части больше scale")] - public void IsValid_Respects_Scale(string input, int precision, int scale, - bool onlyPositive, bool expected) + #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(10, scale, onlyPositive); - var result = validator.IsValidNumber(input); + var validator = new NumberValidator(precision, scale, onlyPositive); + var result = validator.IsValidNumber(value); result.Should().Be(expected); } + + #endregion - [TestCase("-4.59", 4, 2, false, true, - TestName = "возвращает true для отрицательного числа при onlyPositive равно false")] - [TestCase("-6", 2, 0, true, false, - TestName = "возвращает false для отрицательного числа при onlyPositive равно true")] - [TestCase("+5", 2, 0, false, true, - TestName = "возвращает true для положительного числа со знаком плюс, когда onlyPositive равно false")] - public void IsValid_Respects_OnlyPositive(string input, int precision, int scale, - bool onlyPositive, bool expected) + #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(input); + var result = validator.IsValidNumber(value); result.Should().Be(expected); } + + #endregion } \ No newline at end of file