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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bin/
obj/
.vs/
.idea/
40 changes: 24 additions & 16 deletions Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
using FluentAssertions;

namespace HomeExercise.Tasks.ObjectComparison;

public class ObjectComparison
{
[Test]
Expand All @@ -10,34 +12,40 @@ public class ObjectComparison
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);

actualTsar.Should().BeEquivalentTo(expectedTsar, option => option
.Excluding(it => it.Id)
.Excluding(it => it.Parent.Id));
}

[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));

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

//Недостатки
//1. Если тест падает мы просто видим, что ожидалось true, почему упало не видим
//2. Если добавляем новые свойства в класс человека, то здесь нужно также это учитывать
//3. Есть рекурсия без обработки случая циклов
//(в последней строке метода AreEqual вызывается рекурсивно
//-> появляется риск StackOverflow и из-за циклической ссылки,
//FluentAssertions может обработать циклические ссылки, если я отмечу .IgnoringCyclicReferences())
//4. Если бы наш тест был с большим количеством сравнений person, и блок Assert бы не выполнялся на первом,
//то остальные бы вариант не проверялись. FluentAssertions при этом выполняет всегда все тесты,
//и потом просто выводит, что выполнилось, а что нет
//5. Читаемость :)



private bool AreEqual(Person? actual, Person? expected)
{
if (actual == expected) return true;
Expand All @@ -49,4 +57,4 @@ private bool AreEqual(Person? actual, Person? expected)
&& actual.Weight == expected.Weight
&& AreEqual(actual.Parent, expected.Parent);
}
}
}
89 changes: 69 additions & 20 deletions Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,80 @@

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


namespace HomeExercise.Tasks.NumberValidator;

[TestFixture]
public class NumberValidatorTests
{
[Test]
public void Test()

[TestCase(-1, 2, true, TestName = "Отрицательная precision")]
[TestCase(5, -1, true, TestName = "Отрицательная scale")]
[TestCase(5, 5, true, TestName = "Scale равен precision")]
[TestCase(5, 6, true, TestName = "Scale больше precision")]
[TestCase(0, 0, true, TestName = "Precision ноль")]
public void Constructor_ThrowExceptions_InvalidParameter(int precision, int scale, bool onlyPositive)
{
Action act = () => new NumberValidator(precision, scale, onlyPositive);

act.Should().Throw<ArgumentException>();
}


[TestCase(1, 0, true, TestName = "Минимальные валидные параметры")]
[TestCase(1, 0, false, TestName = "OnlyPositive false")]
[TestCase(5, 2, true, TestName = "Scale меньше precision")]
[TestCase(3, 0, true, TestName = "Scale ноль")]
public void Constructor_DoesNotThrowExceptions_CorrectParameter(int precision, int scale, bool onlyPositive)
{
Action act = () => new NumberValidator(precision, scale, onlyPositive);

act.Should().NotThrow();
}


[TestCase(17, 2, true, "0", TestName = "Целое число ноль должно быть валидным")]
[TestCase(17, 2, true, "0.0", TestName = "Дробное число ноль должно быть валидным")]
[TestCase(4, 2, true, "+1.23", TestName = "Положительное число со знаком плюс должно быть валидным")]
[TestCase(17, 2, false, "-1.23", TestName = "Отрицательное число должно быть валидным когда onlyPositive=false")]
[TestCase(3, 0, true, "123", TestName = "Целое число без дробной части должно быть валидным")]
public void IsValidNumber_ReturnTrue_ValidCases(int precision, int scale, bool onlyPositive, string value)
{
var validator = new NumberValidator(precision, scale, onlyPositive);

var result = validator.IsValidNumber(value);

result.Should().BeTrue();
}


[TestCase(3, 2, true, "00.00", TestName = "Превышение общего лимита цифр")]
[TestCase(3, 2, true, "-0.00", TestName = "Отрицательное число при запрете отрицательных")]
[TestCase(3, 2, true, "+0.00", TestName = "Знак плюс с нулем превышает лимит цифр")]
[TestCase(3, 2, true, "+1.23", TestName = "Превышение лимита цифр в целом числе")]
[TestCase(17, 2, true, "0.000", TestName = "Превышение лимита цифр в дробной части")]
[TestCase(3, 2, true, "a.sd", TestName = "Символы не являющиеся цифрами")]
[TestCase(3, 2, true, "", TestName = "Пустая строка как входное значение")]
[TestCase(3, 2, true, null, TestName = "Null как входное значение")]
public void IsValidNumber_ReturnFalse_InvalidCases(int precision, int scale, bool onlyPositive, 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 validator = new NumberValidator(precision, scale, onlyPositive);

var result = validator.IsValidNumber(value);

result.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"));
[TestCase(1, 0, true, "0", TestName = "Минимальная precision с нулем")]
[TestCase(2, 1, true, "0.1", TestName = "Граничные значения precision и scale")]
[TestCase(3, 2, true, "1.23", TestName = "Максимальное количество цифр в дробной части")]
public void IsValidNumber_BoundaryCases_ReturnsTrue(int precision, int scale, bool onlyPositive, string value)
{
var validator = new NumberValidator(precision, scale, onlyPositive);

var result = validator.IsValidNumber(value);

result.Should().BeTrue();
}
}