diff --git a/cs/Challenge/Challenge.csproj b/cs/Challenge/Challenge.csproj
index 0f41e066..a13acb1a 100644
--- a/cs/Challenge/Challenge.csproj
+++ b/cs/Challenge/Challenge.csproj
@@ -13,6 +13,7 @@
+
diff --git a/cs/HomeExercises/HomeExercises.csproj b/cs/HomeExercises/HomeExercises.csproj
index ede81aec..26a773ec 100644
--- a/cs/HomeExercises/HomeExercises.csproj
+++ b/cs/HomeExercises/HomeExercises.csproj
@@ -14,7 +14,8 @@
-
+
+
\ No newline at end of file
diff --git a/cs/HomeExercises/NumberValidator.cs b/cs/HomeExercises/NumberValidator.cs
new file mode 100644
index 00000000..b357db83
--- /dev/null
+++ b/cs/HomeExercises/NumberValidator.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace HomeExercises
+{
+ public class NumberValidator
+ {
+ private readonly Regex numberRegex;
+ private readonly bool onlyPositive;
+ private readonly int precision;
+ private readonly int scale;
+
+ public NumberValidator(int precision, int scale = 0, bool onlyPositive = false)
+ {
+ this.precision = precision;
+ this.scale = scale;
+ this.onlyPositive = onlyPositive;
+ if (precision <= 0)
+ throw new ArgumentException("precision must be a positive number");
+ if (scale < 0 || scale >= precision)
+ throw new ArgumentException("precision must be a non-negative number less or equal than precision");
+ numberRegex = new Regex(@"^([+-]?)(\d+)([.,](\d+))?$", RegexOptions.IgnoreCase);
+ }
+
+ public bool IsValidNumber(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ return false;
+
+ var match = numberRegex.Match(value);
+ if (!match.Success)
+ return false;
+
+ var intPart = match.Groups[1].Value.Length + match.Groups[2].Value.Length;
+ var fracPart = match.Groups[4].Value.Length;
+
+ if (intPart + fracPart > precision || fracPart > scale)
+ return false;
+
+ if (onlyPositive && match.Groups[1].Value == "-")
+ return false;
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/cs/HomeExercises/NumberValidatorTests.cs b/cs/HomeExercises/NumberValidatorTests.cs
deleted file mode 100644
index a2878113..00000000
--- a/cs/HomeExercises/NumberValidatorTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using System.Text.RegularExpressions;
-using FluentAssertions;
-using NUnit.Framework;
-
-namespace HomeExercises
-{
- 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));
-
- Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0"));
- Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0"));
- Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("00.00"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-0.00"));
- Assert.IsTrue(new NumberValidator(17, 2, true).IsValidNumber("0.0"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+0.00"));
- Assert.IsTrue(new NumberValidator(4, 2, true).IsValidNumber("+1.23"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("+1.23"));
- Assert.IsFalse(new NumberValidator(17, 2, true).IsValidNumber("0.000"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-1.23"));
- Assert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("a.sd"));
- }
- }
-
- public class NumberValidator
- {
- private readonly Regex numberRegex;
- private readonly bool onlyPositive;
- private readonly int precision;
- private readonly int scale;
-
- public NumberValidator(int precision, int scale = 0, bool onlyPositive = false)
- {
- this.precision = precision;
- this.scale = scale;
- this.onlyPositive = onlyPositive;
- if (precision <= 0)
- throw new ArgumentException("precision must be a positive number");
- if (scale < 0 || scale >= precision)
- throw new ArgumentException("precision must be a non-negative number less or equal than precision");
- numberRegex = new Regex(@"^([+-]?)(\d+)([.,](\d+))?$", RegexOptions.IgnoreCase);
- }
-
- public bool IsValidNumber(string value)
- {
- // Проверяем соответствие входного значения формату N(m,k), в соответствии с правилом,
- // описанным в Формате описи документов, направляемых в налоговый орган в электронном виде по телекоммуникационным каналам связи:
- // Формат числового значения указывается в виде N(m.к), где m – максимальное количество знаков в числе, включая знак (для отрицательного числа),
- // целую и дробную часть числа без разделяющей десятичной точки, k – максимальное число знаков дробной части числа.
- // Если число знаков дробной части числа равно 0 (т.е. число целое), то формат числового значения имеет вид N(m).
-
- if (string.IsNullOrEmpty(value))
- return false;
-
- var match = numberRegex.Match(value);
- if (!match.Success)
- return false;
-
- // Знак и целая часть
- var intPart = match.Groups[1].Value.Length + match.Groups[2].Value.Length;
- // Дробная часть
- var fracPart = match.Groups[4].Value.Length;
-
- if (intPart + fracPart > precision || fracPart > scale)
- return false;
-
- if (onlyPositive && match.Groups[1].Value == "-")
- return false;
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/cs/HomeExercises/ObjectComparison.cs b/cs/HomeExercises/ObjectComparison.cs
index 44d9aed4..804fee89 100644
--- a/cs/HomeExercises/ObjectComparison.cs
+++ b/cs/HomeExercises/ObjectComparison.cs
@@ -1,76 +1,14 @@
-using FluentAssertions;
-using NUnit.Framework;
-
-namespace HomeExercises
+namespace HomeExercises
{
public class ObjectComparison
- {
- [Test]
- [Description("Проверка текущего царя")]
- [Category("ToRefactor")]
- 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.
- Assert.AreEqual(actualTsar.Name, expectedTsar.Name);
- Assert.AreEqual(actualTsar.Age, expectedTsar.Age);
- Assert.AreEqual(actualTsar.Height, expectedTsar.Height);
- Assert.AreEqual(actualTsar.Weight, expectedTsar.Weight);
-
- Assert.AreEqual(expectedTsar.Parent!.Name, actualTsar.Parent!.Name);
- Assert.AreEqual(expectedTsar.Parent.Age, actualTsar.Parent.Age);
- Assert.AreEqual(expectedTsar.Parent.Height, actualTsar.Parent.Height);
- Assert.AreEqual(expectedTsar.Parent.Parent, actualTsar.Parent.Parent);
- }
-
- [Test]
- [Description("Альтернативное решение. Какие у него недостатки?")]
- 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));
-
- // Какие недостатки у такого подхода?
- Assert.True(AreEqual(actualTsar, expectedTsar));
- }
-
- private bool AreEqual(Person? actual, Person? expected)
- {
- if (actual == expected) return true;
- if (actual == null || expected == null) return false;
- return
- actual.Name == expected.Name
- && actual.Age == expected.Age
- && actual.Height == expected.Height
- && actual.Weight == expected.Weight
- && AreEqual(actual.Parent, expected.Parent);
- }
- }
-
- public class TsarRegistry
- {
- public static Person GetCurrentTsar()
- {
- return new Person(
- "Ivan IV The Terrible", 54, 170, 70,
- new Person("Vasili III of Russia", 28, 170, 60, null));
- }
- }
-
- public class Person
{
public static int IdCounter = 0;
public int Age, Height, Weight;
public string Name;
- public Person? Parent;
+ public ObjectComparison? Parent;
public int Id;
- public Person(string name, int age, int height, int weight, Person? parent)
+ public ObjectComparison(string name, int age, int height, int weight, ObjectComparison? parent)
{
Id = IdCounter++;
Name = name;
diff --git a/cs/HomeExercises/tests/NumberValidator_Should.cs b/cs/HomeExercises/tests/NumberValidator_Should.cs
new file mode 100644
index 00000000..2a333492
--- /dev/null
+++ b/cs/HomeExercises/tests/NumberValidator_Should.cs
@@ -0,0 +1,56 @@
+using FluentAssertions;
+using NUnit.Framework;
+using System;
+
+namespace HomeExercises.tests
+{
+ public class NumberValidator_Should
+ {
+ [TestCase(-1, 2, false, TestName = "NegativePrecision")]
+ [TestCase(0, 0, false, TestName = "PrecisionIsZero")]
+ [TestCase(3, -1, false, TestName = "NegativeScale")]
+ [TestCase(1, 2, false, TestName = "ScaleIsGreaterThanPrecision")]
+ [TestCase(1, 1, true, TestName = "PrecisionEqualsScale")]
+ public void Creation_ShouldThrowArgumentException(int precision, int scale, bool onlyPositive)
+ {
+ Action creation = () => new NumberValidator(precision, scale, onlyPositive);
+ creation.Should().Throw();
+ }
+ [Test]
+ public void Creation_ShouldNotThrow()
+ {
+ Action creation = () => new NumberValidator(1, 0);
+ creation
+ .Should()
+ .NotThrow();
+
+ }
+
+ [TestCase(3, 2, false, "-+0.0", TestName = "TwoSigns")]
+ [TestCase(3, 2, false, " -0.0", TestName = "SpaceFirstDigitInNumber")]
+ [TestCase(3, 2, false, "0,", TestName ="Aren'tDigitsAfterCommas")]
+ [TestCase(3, 2, false, "0.0.0", TestName = "ThreeDigitsInNumberByTwoDots")]
+ [TestCase(3, 2, false, "0,0,0", TestName = "ThreeDigitsInNumberByTwoCommas")]
+ [TestCase(3, 2, false, "00.00", TestName = "NumberPrecisionGreaterThanValidatorPrecision")]
+ [TestCase(3, 2, false, null, TestName = "NumberNull")]
+ [TestCase(3, 2, false, "", TestName = "NumberEmpty")]
+ [TestCase(3, 2, false, "+1.23", TestName = "NumberPrecisionGreaterThanValidatorPrecision")]
+ [TestCase(3, 2, false, "-1.23", TestName = "NumberNegativeInNumberOnlyPositive")]
+ [TestCase(17, 2, true, "0.000", TestName = "NumberScaleGreaterThanValidatorScale")]
+ [TestCase(17, 2, true, "a.sd", TestName = "IncorrectNumberFormatBecauseLettersArePresent")]
+ public void IsValidNumber_ShouldFalse_When(int precision, int scale, bool onlyPositive, string number)
+ {
+ var validator = new NumberValidator(precision, scale, onlyPositive);
+ validator.IsValidNumber(number).Should().BeFalse();
+ }
+
+ [TestCase(17, 2, false, "0.0", TestName = "NumberWithFractionalPart")]
+ [TestCase(17, 2, false, "0", TestName = "OnlyInteger")]
+ [TestCase(4, 2, true, "+1.23", TestName = "NumberWithSign")]
+ public void IsValidNumber_ShouldTrue_When(int precision, int scale, bool onlyPositive, string number)
+ {
+ var validator = new NumberValidator(precision, scale);
+ validator.IsValidNumber(number).Should().BeTrue();
+ }
+ }
+}
diff --git a/cs/HomeExercises/tests/ObjectComparison_Should.cs b/cs/HomeExercises/tests/ObjectComparison_Should.cs
new file mode 100644
index 00000000..89509860
--- /dev/null
+++ b/cs/HomeExercises/tests/ObjectComparison_Should.cs
@@ -0,0 +1,61 @@
+using FluentAssertions;
+using NUnit.Framework;
+
+namespace HomeExercises.tests
+{
+ public class ObjectComparison_Should
+ {
+ [Test]
+ [Description("Проверка текущего царя")]
+ [Category("ToRefactor")]
+ public void CheckValuesOfTheCurrentTsar()
+ {
+ var actualTsar = TsarRegistry.GetCurrentTsar();
+
+ var expectedTsar = new ObjectComparison("Ivan IV The Terrible", 54, 170, 70,
+ new ObjectComparison("Vasili III of Russia", 28, 170, 60, null));
+
+ actualTsar.Should().BeEquivalentTo(expectedTsar, options => options
+ .Excluding(tsar =>
+ tsar.SelectedMemberInfo.Name == nameof(ObjectComparison.Id)
+ && tsar.SelectedMemberInfo.DeclaringType == typeof(ObjectComparison)));
+ }
+
+ [Test]
+ [Description("Альтернативное решение. Какие у него недостатки?")]
+ public void CheckCurrentTsar_WithCustomEquality()
+ {
+ var actualTsar = TsarRegistry.GetCurrentTsar();
+ var expectedTsar = new ObjectComparison("Ivan IV The Terrible", 54, 170, 70,
+ new ObjectComparison("Vasili III of Russia", 28, 170, 60, null));
+
+ //Какие недостатки у такого подхода?
+ //Нужно будет переписывать AreEqual в случае изменения полей ObjectComparison
+ //Возможна ошибка при написании метода
+ //Если тест упадет, сообщение об ошибке будет малоинформативным
+ Assert.True(AreEqual(actualTsar, expectedTsar));
+ }
+
+ private bool AreEqual(ObjectComparison? actual, ObjectComparison? expected)
+ {
+ if (actual == expected) return true;
+ if (actual == null || expected == null) return false;
+ return
+ actual.Name == expected.Name
+ && actual.Age == expected.Age
+ && actual.Height == expected.Height
+ && actual.Weight == expected.Weight
+ && AreEqual(actual.Parent, expected.Parent);
+ }
+ }
+
+ public class TsarRegistry
+ {
+ public static ObjectComparison GetCurrentTsar()
+ {
+ return new ObjectComparison(
+ "Ivan IV The Terrible", 54, 170, 70,
+ new ObjectComparison("Vasili III of Russia", 28, 170, 60, null));
+ }
+ }
+}
\ No newline at end of file
diff --git a/cs/Samples/Samples.csproj b/cs/Samples/Samples.csproj
index c2c8798a..dc0b5716 100644
--- a/cs/Samples/Samples.csproj
+++ b/cs/Samples/Samples.csproj
@@ -12,7 +12,6 @@
-