Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
bin/
obj/
.vs/
.idea/
*.sln.DotSettings.user
35 changes: 34 additions & 1 deletion Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
using FluentAssertions;
using FluentAssertions.Equivalency;

namespace HomeExercise.Tasks.ObjectComparison;
public class ObjectComparison
Expand All @@ -19,13 +21,40 @@ public void CheckCurrentTsar()
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);



}

[Test]
[Description("Проверка текущего царя")]
[Category("ToRefactor")]
public void CheckCurrentTsarFluentAssertions()
{
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));


actualTsar.Should().BeEquivalentTo(expectedTsar, options =>
options.Excluding((IMemberInfo p) => p.Name == nameof(Person.Id))
);

// Тест с FluentAssertions имеет следующие приемущества:
// 1) Автоматически расширяется при добавлении новых свойств в класс Person
// 2) Лучшая читаемость кода
// 3) При ошибке видно сразу каке свойтво не совпало, например если изменить возраст в expectedTsar вывод будет содержать "Expected field actualTsar.Age to be 53, but found 54."
// а при Assert "Assert.That(actual, Is.EqualTo(expected)) Expected: 54 But was: 53" - не понятно какое именно свойтво провалило тест
Comment on lines +49 to +53
Copy link

Choose a reason for hiding this comment

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

Тут все верно, но у кастмного решения есть еще проблема с рекурсией, там она потенциально бесконечная. У FluentAssertions есть ограничение по глубине рекурсии


}


[Test]
[Description("Альтернативное решение. Какие у него недостатки?")]
public void CheckCurrentTsar_WithCustomEquality()
Expand All @@ -36,6 +65,10 @@ public void CheckCurrentTsar_WithCustomEquality()

// Какие недостатки у такого подхода?
ClassicAssert.True(AreEqual(actualTsar, expectedTsar));

// Недостатки такого подхода следущие:
// 1) Есть отдельный метод AreEqual и при изменении класса Person нужно будет идти в него менять т.е. сложно поддреживать
// 2) В стек-трейсе нет информации о том, какое именно свойство не совпало
}

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

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

namespace HomeExercise.Tasks.NumberValidator;


[TestFixture]
public class NumberValidatorTests
{
[Test]
public void Test()
[TestCase(-1, 2, "Исключение, когда precision отрицательная")]
[TestCase(5, -1, "Исключение, когда scale отрицательный")]
[TestCase(5, 6, "Исключение, когда scale больше precision")]
public void Constructor_WithInvalidParameters_ThrowsArgumentException(int precision, int scale, string description)
{
Action action = () => new NumberValidator(precision, scale);

action.Should().Throw<ArgumentException>(description);
}


[TestCase("0", "Целый ноль")]
[TestCase("0.0", "Десятичный ноль")]
[TestCase("123.45", "Корректное десятичное")]
[TestCase("+1.23", "С явным плюсом")]
public void IsValidNumber_WithValidNumberFormats_ReturnsTrue(string number, string description)
{
var validator = new NumberValidator(5, 2, true);

validator.IsValidNumber(number).Should().BeTrue(description);
}

[TestCase("-1.23", "Отрицательное при onlyPositive=true")]
[TestCase("00.000", "Превышение precision в дробной части")]
[TestCase("1234.56", "Превышение precision в целой части")]
[TestCase("0.000", "Превышение scale")]
[TestCase("a.sd", "Нечисловой формат")]
[TestCase("", "Пустая строка")]
[TestCase(null, "Null")]
public void IsValidNumber_WithInvalidNumberFormats_ReturnsFalse(string number, string description)
{
var validator = new NumberValidator(5, 2, true);

validator.IsValidNumber(number).Should().BeFalse(description);
}

[TestCase("1.23", "Максимальная precision и scale")]
[TestCase("12.3", "Граница precision")]
[TestCase("0.12", "Граница scale")]
[TestCase("1,23", "Запятая в качестве разделителя")]
Copy link

Choose a reason for hiding this comment

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

Этот тест с запятой все таки должен лежать в группе WithValidNumberFormats потому что по смыслу как раз туда подходит, а не в WithValidPrecisionAndScale

public void IsValidNumber_WithValidPrecisionAndScale_ReturnsTrue(string number, string description)
{
var strictValidator = new NumberValidator(3, 2);

strictValidator.IsValidNumber(number).Should().BeTrue(description);
}



[TestCase("-1.23", "Отрицательное число")]
[TestCase("-0", "Отрицательный ноль")]
public void IsValidNumber_WithOnlyPositiveFalse_AcceptsNegativeNumbers(string number, string description)
{
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));

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"));
var anyNum = new NumberValidator(5, 2, false);

anyNum.IsValidNumber(number).Should().BeTrue(description);
}



[TestCase("12..34", "Две точки")]
[TestCase(".123", "Начинается с точки")]
[TestCase("123.", "Оканчивается точкой")]
public void IsValidNumber_WithInvalidFormats_ReturnsFalse(string number, string description)
{
var validator = new NumberValidator(10, 2);

validator.IsValidNumber(number).Should().BeFalse(description);
}

}