Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Брозовский Максим #12

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
18 changes: 7 additions & 11 deletions Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
using FluentAssertions;

namespace HomeExercise.Tasks.ObjectComparison;
public class ObjectComparison
Expand All @@ -13,17 +14,9 @@ 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);

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(p => p.Name == nameof(Person.Id) && p.DeclaringType == typeof(Person)));
}

[Test]
Expand All @@ -36,6 +29,9 @@ public void CheckCurrentTsar_WithCustomEquality()

// Какие недостатки у такого подхода?
ClassicAssert.True(AreEqual(actualTsar, expectedTsar));
// Нужно писать сам предикат AreEqual (лишний код в котором можно ошибиться)
// + его надо поддерживать (при расширении класса Person нужно менять логику AreEqual)
// В AreEqual нет Assert, значит при падении теста не будет информации о том как упал тест (причина падения)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Рассмотри еще кейс, когда у царя поле parent будет указывать на уже встречающегося царя в родословной. Нам же ничего не мешает так сделать :)

Copy link
Author

@BMV989 BMV989 Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Случай несколько вырожден, но формально возможен.
В таком случае возникнет бесконечная рекурсия.
Рассмотрим простой случай: есть actualTsar и пусть actualTsar.Parent.Parent = actualTsar.
Тогда при сравнении AreEqual(actualTsar, actualTsar) мы будем сравнивать их Parent, но у них тоже есть Parent, а значит их мы тоже будем сравнивать и т. д.
Таким образом мы получим бесконечную последовательность вызовов AreEqual для каждого Parent.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему вырожден?
Ты не смотри на это как в жизни реально есть, у тебя написан код, который такое допускает.
И т.к мы не можем менять с тобой сурсы, давай обложимся на уровне тестов хотя бы

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Окей согласен

}

private bool AreEqual(Person? actual, Person? expected)
Expand Down
112 changes: 92 additions & 20 deletions Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,103 @@

using NUnit.Framework;
using NUnit.Framework.Legacy;
using FluentAssertions;

namespace HomeExercise.Tasks.NumberValidator;

[TestFixture]
public class NumberValidatorTests
{
[Test]
public void Test()
{
Assert.Throws<ArgumentException>(() => new NumberValidator(-1, 2, true));
Assert.DoesNotThrow(() => new NumberValidator(1, 0, true));
Assert.Throws<ArgumentException>(() => new NumberValidator(-1, 2, false));
Assert.DoesNotThrow(() => new NumberValidator(1, 0, true));
private const string PrecisionErrorMessage = "precision must be a positive number";
private const string ScaleErrorMessage = "precision must be a non-negative number less or equal than precision";

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, PrecisionErrorMessage, TestName = "precision < 0")]
[TestCase(-10, 1, PrecisionErrorMessage, TestName = "precision < 0")]
[TestCase(0, 0, PrecisionErrorMessage, TestName = "precision == 0")]
[TestCase(0, 2, PrecisionErrorMessage, TestName = "precision == 0")]
[TestCase(5, -1, ScaleErrorMessage, TestName = "scale < 0")]
[TestCase(5, -6, ScaleErrorMessage, TestName = "scale < 0")]
[TestCase(1, 2, ScaleErrorMessage, TestName = "scale > precision")]
[TestCase(1, 10, ScaleErrorMessage, TestName = "scale > precision")]
[TestCase(1, 1, ScaleErrorMessage, TestName = "scale == precision")]
[TestCase(2, 2, ScaleErrorMessage, TestName = "scale == precision")]
public void NumberValidator_ThrowsArgumentException_WithInvalidParams(int precision, int scale, string msg)
{
Action act = () => new NumberValidator(precision, scale);
act.Should().Throw<ArgumentException>().WithMessage(msg);
}

[TestCase("2", 1, 0, true, TestName = "When value is one digit integer")]
[TestCase("52", 2, 1, true, TestName = "When value is two digit integer")]
[TestCase("-300", 4, 0, false, TestName = "When value is integer with negative sign")]
[TestCase("+300", 4, 0, true, TestName = "When value is integer with positive sign")]
[TestCase("-99", 3, 2, false, TestName = "When value is integer with negative sign and non zero scale")]
[TestCase("9999999", 7, 1, false, TestName = "When value is integer and has 7 digits and non zero scale")]
[TestCase("2147483649", 10, 1, false, TestName = "When value is Int overflow")]
[TestCase("-1234567890", 11, 8, false, TestName = "When value is integer with negative sign 10 digits and non zero scale")]
[TestCase("0101010", 20, 12, false, TestName = "When value with leading zero")]
[TestCase("01110.01010", 10, 5, true, TestName = "When value is fraction with leading zero in integer part and leading zero in fraction part and separator is dot")]
[TestCase("01110,01010", 10, 5, true, TestName = "When value is fraction with leading zero in integer part and leading zero in fraction part and separator is comma")]
[TestCase("+01110,01010", 11, 5, true, TestName = "When value is fraction with leading zero in integer part and leading zero in fraction part and separator is comma with positive sign")]
[TestCase("-1234567890.1234567890", 21, 10, false, TestName = "When value is fraction with negative sign")]
[TestCase("+0.0", 3, 1, false, TestName = "When value is zero with zero fraction with sign and separator is dot")]
[TestCase("0.000", 4, 3, true, TestName = "When value is zero with zero fraction and separator is dot")]
[TestCase("300.52", 5, 2, true, TestName = "When value is fraction and separator is dot")]
[TestCase("+3.52", 15, 10, false, TestName = "When value is fraction with sign and separator is dot")]
[TestCase("+300,52", 17, 10, false, TestName = "When value is fraction and has sign and separator is comma")]
[TestCase("1,23", 17, 10, false, TestName = "When value is fraction and separator is comma")]
[TestCase("+100", 4, 1, true, TestName = "When value is integer with sign")]
[TestCase("100\n", 4, 2, true, TestName = "When \n at the end of a value")]
public void IsValidNumber_ShouldBeTrue_WithValidParams(string value, int precision, int scale, bool onlyPositive) =>
new NumberValidator(precision, scale, onlyPositive)
.IsValidNumber(value)
.Should().BeTrue();

[TestCase("", 17, 10, false, TestName = "When value is empty string")]
[TestCase(null, 17, 10, false, TestName = "When value is null")]
[TestCase("II", 17, 10, false, TestName = "When value is II in roman numeric system")]
[TestCase("III", 17, 10, false, TestName = "When value is III in roman numeric system")]
[TestCase("VI", 17, 10, false, TestName = "When value is IV in roman numeric system")]
[TestCase("X", 17, 10, false, TestName = "When value is X in roman numeric system")]
[TestCase("ఎనమద", 4, 0 , true, TestName = "When value is ఎనమద in telugu numeric system")]
[TestCase("తమమద", 4, 0 , true, TestName = "When value is తమమద in telugu numeric system")]
[TestCase("0xFF", 4, 0, true, TestName = "When value is FF and is hexadecimal number")]
[TestCase("0x1A", 4, 0, true, TestName = "When value is 1A and is hexadecimal number")]
[TestCase("0o75", 4, 0, true, TestName = "When value is 75 and is octal number")]
[TestCase("0o44", 4, 0, true, TestName = "When value is 44 and is octal number")]
[TestCase("0b1010", 6, 0, true, TestName = "When value is 1010 and is binary number")]
[TestCase("0b01110.01010", 10, 5, true, TestName = "When value is binary number with fraction")]
[TestCase("seven.eleven", 17, 10, false, TestName = "When value is two english words separated by dot")]
[TestCase("five/two", 17, 10, false, TestName = "When value is two english words separated by /")]
[TestCase("11.11.11", 17, 10, false, TestName = "When value has two dots")]
[TestCase("+127.000.001", 17, 10, false, TestName = "When value has two dots and sign")]
[TestCase("11.22,33", 17, 10, false, TestName = "When value has one dot and one comma")]
[TestCase("55,22,33", 17, 10, false, TestName = "When value has two commas")]
[TestCase("+1\\2", 17, 10, false, TestName = "When value has sign and \\ separator")]
[TestCase("X,Y", 3, 2, true, TestName = "When value is two capital letters with comma separator")]
[TestCase("a.sd", 17, 10, false, TestName = "When value have letters with dot separator")]
[TestCase("1\n.5", 3, 2, true, TestName = "When \n in the middle of a value")]
[TestCase("\n2.4", 3, 2, true, TestName = "When \n is in front of a value")]
[TestCase("+-15", 3, 2, false, TestName = "When value has two different signs")]
[TestCase("--10", 4, 2, false, TestName = "When value has two negative signs")]
[TestCase("++1", 3, 0, true, TestName = "When value has two positive signs")]
[TestCase("300_000", 17, 10, false, TestName = "When value has underscore separator")]
[TestCase("52 000", 17, 10, false, TestName = "When value has space separator")]
[TestCase("1/2", 17, 10, false, TestName = "When value has / separator")]
[TestCase("12 . 22", 17, 10, false, TestName = "When value has `space dot space` separator")]
[TestCase("12 , 22", 17, 10, false, TestName = "When value has `space comma space` separator")]
[TestCase("-100", 4, 0, true, TestName = "When value is negative and onlyPositive is true")]
[TestCase("+1,23", 3, 2, true, TestName = "When value is 3 digit fraction with sign and precision is 3 (Not 4)")]
[TestCase("1.123", 4, 2, true, TestName = "When value is fraction with 3 digit in fraction part and scale is 2 (Not 3)")]
[TestCase("0.00", 5, 1, true, TestName = "When value is fraction with 2 digit in fraction part and scale is 1 (Not 2)")]
[TestCase("52", 1, 0, true, TestName = "When value is 2 digit integer and precision is 1 (Not 2)")]
[TestCase("-300", 3, 0, false, TestName = "When value is 3 digit integer with negative sign and precision is 3 (Not 4)")]
[TestCase("300", 2, 0, false, TestName = "When value is 3 digit integer and precision is 2 (Not 3)")]
[TestCase("+100", 3, 0, false, TestName = "When value is 3 digit integer with positive sign and precision is 3 (Not 4)")]
[TestCase("-1.23", 3, 2, false, TestName = "When value is 3 digit fraction with negative sign and precision is 3 (Not 4)")]
[TestCase("-1234567890.1234567890", 20, 10, false, TestName = "When value is 20 digit fraction with negative sign and precision is 20 (Not 21)")]
public void IsValidNumber_ShouldBeFalse_WithInvalidParams(string value, int precision, int scale,
bool onlyPositive) =>
new NumberValidator(precision, scale, onlyPositive)
.IsValidNumber(value)
.Should().BeFalse();
}