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

Галичев Артем #13

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
37 changes: 25 additions & 12 deletions Testing/Basic/Homework/1. ObjectComparison/ObjectComparison.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using FluentAssertions;

Choose a reason for hiding this comment

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

Привет) давай сначала общие рекомендации:

  1. Именование коммитов) Имена должны быть емкими (и желательно на английском языке, как стандарте в ИТ индустрии) у меня в github desktop'e они даже не влезают в строчку имени и уезжают в описание

  2. Содержание коммитов должно быть атомарным. Один коммит - одно логическое изменение. Например, в коммите NumberValidatorTests. Написал недостающие тесты, разделил разные тестовые случаи на разные тестовые методы. Создал класс TestNumberValidatorBuilder для удобного создания класса NumberValidator ты уже сам видишь, что завел много различных независимых изменений, которые просто завернул в один коммит и отправил. Рекомендую стараться разделять независимое. Зачем это нужно? Чтобы по истории коммитов, понимать, что произошло. Или уметь ревертить только "плохие" части. Или уметь их черри-пикать. И тд

Прямо сейчас что-либо делать с коммитами не надо. Это рекомендации на будущее

Choose a reason for hiding this comment

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

Также могу порекомендовать отмечать мои сообщения какой-нибудь эмодзи, чтобы отмечать проработанное и не запутаться перед отправкой на следующую итерацию ревью)

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

namespace HomeExercise.Tasks.ObjectComparison;
Expand All @@ -13,17 +14,8 @@ 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.IsEqual(expectedTsar);

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.

Я подумал что без экстеншн в проверке будет избыточная информация из за настройки проверки. Избыточная информация замедляла бы скорость понимания всего теста. Можно было вынести и в приватный метод тестового класса, но я посчитал что через экстеншн проверка читается проще, как обычное английское предложение.

Choose a reason for hiding this comment

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

Понял, корректно)
Могу только немного со стороны накинуть, что пока использование единственное и сама проверка не супер сложная (всего шесть строк, когнитивная нагрузка низкая).ю то можно оставлять прямо в тесте. А вот при дублировании или усложнении проверки - да, вынести в метод или экстешн хорошее повышение читаемости)

}

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

// Какие недостатки у такого подхода?
/*
* 1) Если у класса изменять поля (удалять или добавлять), то также придется изменять

This comment was marked as resolved.

* логику проверки на соответствие сущностей. В случае с удалением поля программа вообще не скомпилируется
* 2) Возможна бесконечная рекурсия
* 3) При падении теста не поймем в чем была причина. Ожидался True, а получили False, вот и вся инфа(
* 4) Использование FluentAssertion ускоряет понимание логики секции проверки, за счет использования
* method chaining. В данном тесте вникнуть в логику проверки теста сложнее, чем в первом.
*/
ClassicAssert.True(AreEqual(actualTsar, expectedTsar));
}

Expand All @@ -50,3 +50,16 @@ private bool AreEqual(Person? actual, Person? expected)
&& AreEqual(actual.Parent, expected.Parent);
}
}

internal static class ObjectComparisonAssertExtensions
{
public static void IsEqual(this Person actualTsar, Person expectedTsar)
{
actualTsar.Should().BeEquivalentTo(
expectedTsar,
options => options
.Excluding(x => x.Name == nameof(Person.Id) && x.DeclaringType == typeof(Person))
.AllowingInfiniteRecursion()
.IgnoringCyclicReferences());
}
}
163 changes: 144 additions & 19 deletions Testing/Basic/Homework/2. NumberValidator/NumberValidatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

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

Expand All @@ -8,24 +9,148 @@ namespace HomeExercise.Tasks.NumberValidator;
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));

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"));
public void Should_Throw_ArgumentException_If_Precision_Is_Negative()
{
var builder = new TestNumberValidatorBuilder().WithPrecision(-1);

Assert.Throws<ArgumentException>(() => builder.Build());

This comment was marked as resolved.

This comment was marked as resolved.

}

[Test]
public void Should_Throw_ArgumentException_If_Scale_Is_Negative()
{
var builder = new TestNumberValidatorBuilder().WithScale(-1);

Assert.Throws<ArgumentException>(() => builder.Build());
}

[Test]
public void Should_Throw_ArgumentException_If_Scale_Greater_Precision()
{
var builder = new TestNumberValidatorBuilder().WithScale(5).WithPrecision(2);

Assert.Throws<ArgumentException>(() => builder.Build());
}

[Test]
public void Should_Throw_ArgumentException_If_Scale_Equal_Precision()
{
var builder = new TestNumberValidatorBuilder().WithScale(2).WithPrecision(2);

Assert.Throws<ArgumentException>(() => builder.Build());
}

[Test]
public void Should_DoesNotThrow_Exception_If_Scale_And_Precision_Is_Correct()
{
var builder = new TestNumberValidatorBuilder();

Assert.DoesNotThrow(() => builder.Build());
}

[Test]
public void IsValidNumber_Should_Return_False_If_Value_Is_Null()
{
var numberValidator = new TestNumberValidatorBuilder().Build();

var actual = numberValidator.IsValidNumber(null);

actual.Should().BeFalse();
}

[Test]

This comment was marked as resolved.

[TestCase("")]
[TestCase(" ")]
[TestCase(" ")]
public void IsValidNumber_Should_Return_False_If_Value_Is_Empty(string value)
{
var numberValidator = new TestNumberValidatorBuilder().Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeFalse();
}

[Test]
[TestCase("a.sd")]
[TestCase("0.")]
[TestCase(",0")]
[TestCase("0*0")]
[TestCase("!0,0")]
public void IsValidNumber_Should_Return_False_If_Match_With_Value_Fail(string value)
{
var numberValidator = new TestNumberValidatorBuilder().Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeFalse();
}

[Test]
[TestCase("1,234")]
[TestCase("1111")]
[TestCase("22,32")]
[TestCase("+1,23")]
[TestCase("+0,00")]
[TestCase("-0,00")]
public void IsValidNumber_Should_Return_False_If_Sum_Of_IntPart_And_FracPart_More_Than_Precision(string value)
{
var numberValidator = new TestNumberValidatorBuilder().WithPrecision(3).WithScale(2).Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeFalse();
}

[Test]
public void IsValidNumber_Should_Return_False_If_FracPart_More_Than_Scale()
{
var numberValidator = new TestNumberValidatorBuilder().WithScale(2).Build();
var value = "0,000";

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeFalse();
}

[Test]
[TestCase("-0,0")]
[TestCase("-0,000")]
[TestCase("-0")]
public void IsValidNumber_Should_Return_False_If_OnlyPositive_True_And_Value_Contains_Minus(string value)
{
var numberValidator = new TestNumberValidatorBuilder().Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeFalse();

This comment was marked as resolved.

}

[Test]
[TestCase("-0,0")]
[TestCase("-0,000")]
[TestCase("-0")]
public void IsValidNumber_Should_Return_True_If_OnlyPositive_False_And_Value_Contains_Minus(string value)
{
var numberValidator = new TestNumberValidatorBuilder().WithOnlyPositive(false).Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeTrue();
}

[Test]
[TestCase("0.0")]
[TestCase("0")]
[TestCase("+1.23")]
[TestCase("1.444")]
[TestCase("+1.444")]
public void IsValidNumber_Should_Return_True_If_Value_Correct(string value)
{
var numberValidator = new TestNumberValidatorBuilder().Build();

var actual = numberValidator.IsValidNumber(value);

actual.Should().BeTrue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace HomeExercise.Tasks.NumberValidator;

public class TestNumberValidatorBuilder

This comment was marked as resolved.

{
public const int DEFAULT_PRECISION = 5;
public const int DEFAULT_SCALE = 3;
public const bool DEFAULT_ONLY_POSITIVE = true;
private int precision = DEFAULT_PRECISION;
private int scale = DEFAULT_SCALE;
private bool onlyPositive = DEFAULT_ONLY_POSITIVE;

public TestNumberValidatorBuilder WithPrecision(int precision)
{
this.precision = precision;
return this;
}

public TestNumberValidatorBuilder WithScale(int scale)
{
this.scale = scale;
return this;
}

public TestNumberValidatorBuilder WithOnlyPositive(bool onlyPositive)
{
this.onlyPositive = onlyPositive;
return this;
}

public NumberValidator Build()
{
return new NumberValidator(precision, scale, onlyPositive);

This comment was marked as resolved.

This comment was marked as resolved.

}
}