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

Сахабутдинов Ильфир #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
using NUnit.Framework;
using FluentAssertions;
using FluentAssertions.Equivalency;
using NUnit.Framework;
using NUnit.Framework.Legacy;

namespace HomeExercise.Tasks.ObjectComparison;
public class ObjectComparison
{
private Person actualTsar;
private Person expectedTsar;

[SetUp]
public void SetUp()
{
actualTsar = TsarRegistry.GetCurrentTsar();
expectedTsar = GetExpectedTsar();
}

private Person GetExpectedTsar()
{
return new Person("Ivan IV The Terrible", 54, 170, 70,
new Person("Vasili III of Russia", 28, 170, 60, null));
}

[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.
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);
// Это решение лучше, чем CheckCurrentTsar_WithCustomEquality по следующим причинам:
// 1) Нет зависимостей от конкретных имен свойств и полей,
// нужно лишь менять GetExpectedTsar() при изменении класса по необходимости
// 2) Более лаконичное решение за счет Fluent Assertions
// 3) Легко настраивать под нужные условия проверки
// (например если добавится другой класс и там нужно исключить какое-то определенное свойство)
// 4) У этого решения есть подробное описание почему упал тест
// 5) Есть защита от бесконечной рекурсии, Fluent Assertions по умолчанию выполняет рекурсию до 10 уровней,
// но это можно настраивать
// 6) Используется подготовка данных к тесту в SetUp
actualTsar.Should().BeEquivalentTo(expectedTsar, options =>
options.Excluding((IMemberInfo x) => x.Name == nameof(Person.Id)));
}

[Test]
Expand All @@ -35,6 +50,10 @@ public void CheckCurrentTsar_WithCustomEquality()
new Person("Vasili III of Russia", 28, 170, 60, null));

// Какие недостатки у такого подхода?
// 1) Нужно актуализировать метод AreEqual при изменениях
// 2) Нет детальной информации почему упал тест
// 3) Трудно читать и можно запутаться в условии проверки
// 4) Возможно переполнение из-за рекурсии
ClassicAssert.True(AreEqual(actualTsar, expectedTsar));
}

Expand Down
252 changes: 233 additions & 19 deletions Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,245 @@

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

namespace HomeExercise.Tasks.NumberValidator;

[TestFixture]
public class NumberValidatorTests
{
private NumberValidator baseValidNumberValidator;

[SetUp]
public void SetUp()
{
baseValidNumberValidator = new NumberValidator(5);
}

[Test]
[TestCaseSource(nameof(notPositivePrecisionTestCases))]
public void Constructor_ShouldWithException_WhenNotPositivePrecision(int precision)
{
var action = () => new NumberValidator(precision);

action.Should()
.Throw<ArgumentException>()
.WithMessage("precision must be a positive number");
}

private static IEnumerable<TestCaseData> notPositivePrecisionTestCases =
[
new TestCaseData(-1)
.SetName("negativePrecision"),
new TestCaseData(0)
.SetName("zeroPrecision"),
];

[Test]
[TestCaseSource(nameof(badScaleTestCases))]
public void Constructor_ShouldWithException_WhenBadScale(int precision, int scale)
{
var action = () => new NumberValidator(precision, scale);

action.Should()
.Throw<ArgumentException>()
.WithMessage("precision must be a non-negative number less or equal than precision");
}

private static IEnumerable<TestCaseData> badScaleTestCases =
[
new TestCaseData(1, -1)
.SetName("negativeScale"),
new TestCaseData(1, 2)
.SetName("scaleGreaterThanPrecision"),
new TestCaseData(1, 1)
.SetName("scaleEqualPrecision"),
];

[Test]
[TestCaseSource(nameof(validParametersTestCases))]
public void Constructor_ShouldNotException_WhenValidParameters(int precision, int scale, bool onlyPositive)
{
var action = () => new NumberValidator(precision, scale);

action.Should()
.NotThrow<ArgumentException>();
}

private static IEnumerable<TestCaseData> validParametersTestCases =
[
new TestCaseData(5, 0, false)
.SetName("zeroScaleAndPositivePrecision"),
new TestCaseData(5, 0, true)
.SetName("zeroScalePositivePrecisionOnlyPositive"),
new TestCaseData(5, 1, false)
.SetName("positiveScaleAndPositivePrecision"),
];

[Test]
[TestCaseSource(nameof(badValueParametersTestCases))]
public void IsValidNumber_ShouldFalse_WhenBadValueParameter(string value)
{
var isValid = baseValidNumberValidator.IsValidNumber(value);

isValid.Should().BeFalse();
}

private static IEnumerable<TestCaseData> badValueParametersTestCases =
[
new TestCaseData(null)
.SetName("nullValue"),
new TestCaseData(string.Empty)
.SetName("emptyValue"),
new TestCaseData(" ")
.SetName("whitespaceValue"),
];

[Test]
[TestCaseSource(nameof(baseInvalidValueParametersTestCases))]
public void IsValidNumber_ShouldFalse_WhenBaseInvalidFormat(string value)
{
var isValid = baseValidNumberValidator.IsValidNumber(value);

isValid.Should().BeFalse();
}

private static IEnumerable<TestCaseData> baseInvalidValueParametersTestCases =
[
new TestCaseData("abc")
.SetName("notNumber"),
new TestCaseData("123a")
.SetName("numberWithLetter"),
new TestCaseData("a.sd")
.SetName("lettersAndPoint"),
new TestCaseData("123привет")
.SetName("numberWithRussianLetters"),
new TestCaseData("0.")
.SetName("unfinishedFractionalNumber"),
new TestCaseData(".")
.SetName("onlyPointWithoutDigits"),
new TestCaseData(",")
.SetName("onlyPointWithoutDigits"),
new TestCaseData(".1")
.SetName("withoutNumberBeforePoint"),
new TestCaseData("1.1.0")
.SetName("manyPoint"),
new TestCaseData("++1")
.SetName("manyPlusSymbolsBeforeNumber"),
new TestCaseData("--1")
.SetName("manyMinusSymbolsBeforeNumber"),
new TestCaseData("#@1")
.SetName("manyInvalidSymbolsBeforeNumber"),
new TestCaseData("12 34")
.SetName("numberWithWhiteSpace"),
new TestCaseData("12!34")
.SetName("numberWithSymbol"),
];

[Test]
public void Test()
[TestCaseSource(nameof(manyIntegerPartNumberInvalidValueParametersTestCases))]
[TestCaseSource(nameof(manyFractionalPartNumberInvalidValueParametersTestCases))]
public void IsValidNumber_ShouldFalse_WhenManyDigitsInvalidFormat(string value)
{
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));
var numberValidator = new NumberValidator(3, 1);

var isValid = numberValidator.IsValidNumber(value);

isValid.Should().BeFalse();
}

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"));
private static IEnumerable<TestCaseData> manyIntegerPartNumberInvalidValueParametersTestCases =
[
new TestCaseData("9999")
.SetName("manyDigits"),
new TestCaseData("-123")
.SetName("manyDigitsCountInNegativeNumber"),
new TestCaseData("+123")
.SetName("manyDigitsWithPlus"),
];

private static IEnumerable<TestCaseData> manyFractionalPartNumberInvalidValueParametersTestCases =
[
new TestCaseData("-12.3")
.SetName("manyNegativeNumberWithPoint"),
new TestCaseData("0.34")
.SetName("tooManyDigitsBeforeDecimalPoint"),
new TestCaseData("123.4")
.SetName("manyDigitsWithPoint"),
];

[Test]
[TestCaseSource(nameof(negativeValueTestCases))]
public void IsValidNumber_ShouldFalse_WhenOnlyPositiveNumberValidator(string value)
{
var numberValidator = new NumberValidator(3, 1, true);

var isValid = numberValidator.IsValidNumber(value);

isValid.Should().BeFalse();
}

[Test]
[TestCaseSource(nameof(negativeValueTestCases))]
[TestCaseSource(nameof(positiveValueTestCases))]
public void IsValidNumber_ShouldTrue_WhenNotOnlyPositiveNumberValidator(string value)
{
var numberValidator = new NumberValidator(3, 1, false);

var isValid = numberValidator.IsValidNumber(value);

isValid.Should().BeTrue();
}

private static IEnumerable<TestCaseData> negativeValueTestCases =
[
new TestCaseData("-12")
.SetName("NegativeNumber"),
new TestCaseData("-1.2")
.SetName("negativeNumberWithDecimalPoint"),
];

private static IEnumerable<TestCaseData> positiveValueTestCases =
[
new TestCaseData("12")
.SetName("PositiveNumber"),
new TestCaseData("1.2")
.SetName("PositiveNumberWithPoint"),
];

[Test]
[TestCaseSource(nameof(validIntegerPartNumberTestCases))]
[TestCaseSource(nameof(validFractionalPartNumberTestCases))]
public void IsValidNumber_ShouldTrue_WhenValidValue(string value)
{
var numberValidator = new NumberValidator(3, 2);

var isValid = numberValidator.IsValidNumber(value);

isValid.Should().BeTrue();
}

private static IEnumerable<TestCaseData> validIntegerPartNumberTestCases =
[
new TestCaseData("0")
.SetName("oneDigit"),
new TestCaseData("999")
.SetName("maxNumber"),
new TestCaseData("-99")
.SetName("minNumber"),
];

private static IEnumerable<TestCaseData> validFractionalPartNumberTestCases =
[
new TestCaseData("0.00")
.SetName("onlyZeroFractionalNumber"),
new TestCaseData("0,00")
.SetName("numberWithCommaSeparator"),
new TestCaseData("-0.0")
.SetName("onlyZeroFractionalNegativeNumber"),
new TestCaseData("-1.0")
.SetName("negativeNumber"),
new TestCaseData("9.99")
.SetName("maxFractionalNumber"),
new TestCaseData("-9.9")
.SetName("minFractionalNumber"),
];
}