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

Рыбин Леонид #17

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

JavaScriptHaters
Copy link

No description provided.

ClassicAssert.AreEqual(expectedTsar.Parent.Height, actualTsar.Parent.Height);
ClassicAssert.AreEqual(expectedTsar.Parent.Parent, actualTsar.Parent.Parent);
actualTsar.Should().BeEquivalentTo(expectedTsar, options =>
options.Excluding(o => o.Name == "Id" && o.DeclaringType == typeof(Person)));

This comment was marked as resolved.

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

[TestCase(1, 0, true, TestName = "default")]

This comment was marked as resolved.

[TestCase(1, -2, true, TestName = "negative scale")]
[TestCase(1, 2, false, TestName = "scale > precision")]
[TestCase(1, 1, true, TestName = "scale == precision")]
public void NumberValidation_ConstructorHasArgumentException(int precision, int scale, bool onlyPositive)

This comment was marked as resolved.

Assert.Throws<ArgumentException>(() => new NumberValidator(-1, 2, false));
Assert.DoesNotThrow(() => new NumberValidator(1, 0, true));
var action = () => new NumberValidator(precision, scale, onlyPositive);
action.Should().Throw<ArgumentException>();

This comment was marked as resolved.

[TestCase(3, 2, true, "4321.5", ExpectedResult = false)]
[TestCase(3, 0, true, "+145", ExpectedResult = false)]
[TestCase(3, 0, false, "-124", ExpectedResult = false)]
public bool IsValidNumber(int precision, int scale, bool onlyPositive, string value)

This comment was marked as resolved.

[TestCase(10, 9, true, "127.0.0.1", ExpectedResult = false)]
[TestCase(3, 2, true, "4321.5", ExpectedResult = false)]
[TestCase(3, 0, true, "+145", ExpectedResult = false)]
[TestCase(3, 0, false, "-124", ExpectedResult = false)]

This comment was marked as resolved.

.gitignore Outdated
@@ -1,3 +1,5 @@
bin/
obj/
.vs/
Basic.sln
Basic.sln.DotSettings.user

This comment was marked as resolved.

[Test]
public void Test()
[TestCase(-1, 2, true, TestName = "negative precision")]
[TestCase(0, 2, false, TestName = "precision == 0")]

Choose a reason for hiding this comment

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

Всё конечно ситуативно, но лучше прям словами такие кейсы прописывать.

return new NumberValidator(precision, scale, onlyPositive).IsValidNumber(value);
}

public class TrueCasesData

Choose a reason for hiding this comment

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

А зачем в статический класс заворачивать?
Можно же просто было public static IEnumerable MyTestCases а на тест навесить [TestCaseSource(nameof(MyTestCases)].

GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {54C706B2-21C4-4C49-A162-2E765ACC0F80}
EndGlobalSection
EndGlobal

This comment was marked as off-topic.

This comment was marked as off-topic.

Copy link
Author

Choose a reason for hiding this comment

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

Да, вроде бы. Я помню он мне файл .sln предложил сохранить.

Assert.DoesNotThrow(() => new NumberValidator(1, 0, true));
var action = () => new NumberValidator(precision, scale, onlyPositive);
action.Should()
.Throw<ArgumentException>();

Choose a reason for hiding this comment

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

Так вроде ж договорились в прошлый раз на блоки AAA разделить во всех тестах: т.е. нужно явно добавить переносы строк между блоками подготовки данных, непосредственного тестирующего действия и проверки актуального значения с ожидаемым.

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.

Да, всё так

.Throw<ArgumentException>();
}

[Test(Description = "default case")]

Choose a reason for hiding this comment

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

А что нам даёт такое описание теста?

&lt;TestId&gt;NUnit3x::3C8EF388-9BF7-47CF-8B51-CA46F08B9253::net8.0::HomeExercise.Tasks.NumberValidator.NumberValidatorTests&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/Or&gt;&#xD;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>

This comment was marked as off-topic.

Copy link
Author

Choose a reason for hiding this comment

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

Я погуглил и вроде как файл DotSettings.user добавляют в .gitignore. Это обязательно ?

Choose a reason for hiding this comment

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

В DotSettings.user обычно какие-то локальные настройки хранятся, скорее всего он создался из-за того что появился солюшен. В данном случае, да - его логично заигнорить.

В следующей домашке попробуй без солюшена редактировать проект, скорее всего такой проблемы просто не возникнет.

yield return new TestCaseData(2, 0, true, "").SetName("empty string is incorrect").Returns(false);
yield return new TestCaseData(2, 1, true, ".0").SetName("before . always places at least one digit").Returns(false);
yield return new TestCaseData(2, 0, true, "0.").SetName("after . always places at least one digit").Returns(false);
yield return new TestCaseData(2, 0, true, "-1").SetName("- not accounted in precision").Returns(false);

Choose a reason for hiding this comment

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

В этом тесте не условие precision проверяется, а другое.

yield return new TestCaseData(10, 9, true, "127.0.0.1").SetName("only real numbers format").Returns(false);
yield return new TestCaseData(3, 2, true, "4321.5").SetName("precision must be >= sum of all digits").Returns(false);
yield return new TestCaseData(3, 0, true, "+145").SetName("+ not accounted in precision").Returns(false);
yield return new TestCaseData(3, 0, false, "-124").SetName("- not accounted in precision for number > 9").Returns(false);

Choose a reason for hiding this comment

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

Почему именно для цифр больше 9?

yield return new TestCaseData(10, 2, true, "abcde.f").SetName("use only digits").Returns(false);
yield return new TestCaseData(10, 9, true, "127.0.0.1").SetName("only real numbers format").Returns(false);
yield return new TestCaseData(3, 2, true, "4321.5").SetName("precision must be >= sum of all digits").Returns(false);
yield return new TestCaseData(3, 0, true, "+145").SetName("+ not accounted in precision").Returns(false);

Choose a reason for hiding this comment

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

По текущему наименованию теста я не могу понять - плюс должен учитываться или нет в точности.

yield return new TestCaseData(3, 0, true, "+145").SetName("+ not accounted in precision").Returns(false);
yield return new TestCaseData(3, 0, false, "-124").SetName("- not accounted in precision for number > 9").Returns(false);
}
}

This comment was marked as resolved.

Copy link
Author

Choose a reason for hiding this comment

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

Я переписал название тестов в развернутом виде, но PascalCase требует каждое слово с большой буквы писать, но в названии теста там предложение обычное, и как-то не очень в предложении каждое слово с большой буквы писать.

This comment was marked as resolved.

This comment was marked as resolved.

ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("-1.23"));
ClassicAssert.IsFalse(new NumberValidator(3, 2, true).IsValidNumber("a.sd"));
[TestCaseSource(typeof(FalseCasesData), nameof(FalseCasesData.TestCases))]
public bool IsValidNumber_ReturnFalse(int precision, int scale, bool onlyPositive, string value)

Choose a reason for hiding this comment

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

Давай так:

[TestCaseSource(nameof(TestCases1))]
[TestCaseSource(nameof(TestCases2))]
public bool IsValidNumber_WorksCorrectly()

А ожидания уже в наименовании тест-кейсов

return new NumberValidator(precision, scale, onlyPositive).IsValidNumber(value);
}

public static IEnumerable TestCase1

Choose a reason for hiding this comment

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

Ну давай уж осмысленно назовем: ValidNumbersCases и InvalidNumbersCases
Можно даже ещё отдельно выделить InvalidInputCases и туда разместить тесты с некорректным инпутом: пустая строка, нет целой части у Decimal и прочие

get
{
yield return new TestCaseData(10, 9, true, "127.0.0.1").SetName("ForNumber_WithNonRealNumberFormat_ReturnFalse").Returns(false);
yield return new TestCaseData(2, 0, true, "").SetName("ForNumber_IsEmptyString_ReturnFalse").Returns(false);

Choose a reason for hiding this comment

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

Вот тут хорошо просто зайдет "ForEmptyString_ReturnFalse" - префикс "ForNumber" только путает

yield return new TestCaseData(2, 0, true, "").SetName("ForNumber_IsEmptyString_ReturnFalse").Returns(false);
yield return new TestCaseData(2, 1, true, ".0").SetName("ForNumber_WithMissingIntegerPart_ReturnFalse").Returns(false);
yield return new TestCaseData(2, 0, true, "0.").SetName("ForNumber_WithMissingFractionalPart_ReturnFalse").Returns(false);
yield return new TestCaseData(10, 2, true, "abcde.f").SetName("ForNumber_WithNonDigitCharacters_ReturnFalse").Returns(false);

Choose a reason for hiding this comment

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

Как будто бы этот тест дублирует первый - тут нужен один с понятным названием "ForNotNumberInput_ReturnFalse"

{
get
{
yield return new TestCaseData(2, 0, true, "-1").SetName("ForNegativeInteger_WithMinusSign_OnlyPositiveIsFalse").Returns(false);

Choose a reason for hiding this comment

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

Вот тут что-то не то "ForNegativeInteger_WithMinusSign" - у нас уже есть информация, что на входе отрицательное целое, зачем уточнять, что оно со знаком?) Может отрицательное без знака как-то быть?)
Я бы тут просто написал "ForNegativeNumber_WhenOnlyPositiveConfigured_ReturnFalse"

Choose a reason for hiding this comment

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

Можно 2 теста добавить: один ForDecimal, другой ForInteger

get
{
yield return new TestCaseData(2, 0, true, "-1").SetName("ForNegativeInteger_WithMinusSign_OnlyPositiveIsFalse").Returns(false);
yield return new TestCaseData(3, 2, true, "4321.5").SetName("ForDecimal_WithIncorrectPrecision_ReturnFalse").Returns(false);

Choose a reason for hiding this comment

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

Вот я вижу тест для decimal, логичный вопрос возникает: а где для integer такой же?

{
yield return new TestCaseData(2, 0, true, "-1").SetName("ForNegativeInteger_WithMinusSign_OnlyPositiveIsFalse").Returns(false);
yield return new TestCaseData(3, 2, true, "4321.5").SetName("ForDecimal_WithIncorrectPrecision_ReturnFalse").Returns(false);
yield return new TestCaseData(3, 0, true, "+145").SetName("ForPositiveDecimal_WithPlusSign_PrecisionCalculationAccountPlusSign").Returns(false);

Choose a reason for hiding this comment

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

"ForPositiveDecimal" - а в тесте integer

yield return new TestCaseData(2, 0, true, "-1").SetName("ForNegativeInteger_WithMinusSign_OnlyPositiveIsFalse").Returns(false);
yield return new TestCaseData(3, 2, true, "4321.5").SetName("ForDecimal_WithIncorrectPrecision_ReturnFalse").Returns(false);
yield return new TestCaseData(3, 0, true, "+145").SetName("ForPositiveDecimal_WithPlusSign_PrecisionCalculationAccountPlusSign").Returns(false);
yield return new TestCaseData(3, 0, false, "-124").SetName("ForNegativeDecimal_WithMinusSign_PrecisionCalculationAccountMinusSign").Returns(false);

Choose a reason for hiding this comment

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

Также - в тесте передаем integer, а в наименовании decimal

yield return new TestCaseData(3, 2, true, "4321.5").SetName("ForDecimal_WithIncorrectPrecision_ReturnFalse").Returns(false);
yield return new TestCaseData(3, 0, true, "+145").SetName("ForPositiveDecimal_WithPlusSign_PrecisionCalculationAccountPlusSign").Returns(false);
yield return new TestCaseData(3, 0, false, "-124").SetName("ForNegativeDecimal_WithMinusSign_PrecisionCalculationAccountMinusSign").Returns(false);
}
Copy link

@SlavikGh0st SlavikGh0st Nov 6, 2024

Choose a reason for hiding this comment

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

Вот сейчас, когда все тесты однообразно проименованы, я невооруженным глазом вижу:

  1. Что работа Precision проверяется только для integer, хотя по хорошему бы и для decimal аналогичных кейсов накидать.
  2. Нету тестов проверки на scale: когда у нас число не будет соответствовать этому параметру, должно вернуться false.

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

[Test(Description = "NumberValidator_WithCorrectParameters_NotThrowException")]

Choose a reason for hiding this comment

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

До сих пор не понимаю, для чего тут описание теста)

Description - это не TestName, для атрибута [Test] за имя теста будет браться наименование метода.
Description обычно используется как коммент к тесту, и в нём в свободной форме можно написать, что делает тест, если он неочевиден.

В данном случае я по имени метода всё прекрасно понимаю, что делается и что ожидается.
Но есть замечания:

  1. Не указаны условия, когда конструктор не должен вбросить ошибку (хотя бы просто WhenCorrectParameters).
  2. В наименовании теста ты пишешь, что "конструктор не должен вбросить ArgumentException", а по факту у тебя проверка внутри на любую ошибку.

[TestCase(1, -2, true, TestName = "NumberValidator_WithNegativeScale_ThrowsException")]
[TestCase(1, 2, false, TestName = "NumberValidator_WithScaleGreaterThanPrecision_ThrowsException")]
[TestCase(1, 1, true, TestName = "NumberValidator_WithScaleEqualsPrecision_ThrowsException")]
public void NumberValidation_ConstructorThrowsArgumentException(int precision, int scale, bool onlyPositive)

Choose a reason for hiding this comment

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

Тут всё хорошо, править не будем, но на будущее:
Здесь наименование метода уже говорит нам о действии и об ожиданиях, поэтому в тест-кейсах необязательно прописывать "NumberValidator_" и "_ThrowsException".

Сейчас теряются из вида условия, когда должна быть вкинута ошибка:
image

Choose a reason for hiding this comment

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

И вот как можно сделать:
У меня информация о том, что проверятся и что ожидается есть - она взята из наименования тест-метода
Все тест-кейсы объединились в группу этого тест-метода, и я точно и чётко вижу все условия, когда конструктор должен упасть с ошибкой
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants