Skip to content

Нухов Руслан#58

Open
Dobvik wants to merge 3 commits intokontur-courses:masterfrom
Dobvik:master
Open

Нухов Руслан#58
Dobvik wants to merge 3 commits intokontur-courses:masterfrom
Dobvik:master

Conversation

@Dobvik
Copy link

@Dobvik Dobvik commented Oct 29, 2025

@Dobvik Dobvik changed the title PR Нухов Руслан Нухов Руслан Oct 29, 2025
Copy link

@FnaTikJK FnaTikJK left a comment

Choose a reason for hiding this comment

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

Отписал коммы

@@ -8,24 +9,57 @@ namespace HomeExercise.Tasks.NumberValidator;
public class NumberValidatorTests
{
[Test]

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]
public void Test()
[TestCase(-1, 2, true)]

Choose a reason for hiding this comment

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

В идеале хотелось бы ещё пояснения в виде текста увидеть. TestName = ...

[TestCase(-1, 2, false)]
[TestCase(1, -1, false)]
[TestCase(1, 1, false)]
public void ThrowArgumentException_AfterCallingConstructor(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.

Кажется что добавлять onlyPositive в аргументы TestCase скорее лишнее, тк он никак не влияет на проверяемое состояние

Copy link
Author

Choose a reason for hiding this comment

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

Да, вы правы. Исправил. Я исходил из той мысли, что тесты не знают, как реализован метод, соответственно, человек, который написал метод, мог его написать так, что onlyPositive влиял бы на тест. (При одних и тех же данных, кроме onlyPositive тест показывал бы разный результат)

Choose a reason for hiding this comment

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

Поверять все аргументы есть смысл когда тестируешь логику как "чёрный ящик", но это скорее про Интеграционные тесты. Unit-тесты это скорее "белый ящик", в котором тебе нужно проверить тонкости работы конкретных строчек кода, а не логики в целом. В таком кейсе ты знаешь как код устроен внутри и с какими аргументами взаимодействует. Добавление "лишних" аргументов только спутает читателя кода. Unit-тесты не обязаны покрывать "будущие" сценарии, когда кто-то решит в контейнере проверять ещё один аргумент - они проверяют что-то очень конкретное и нынешнее. Когда добавят ещё проверок в контейнер, тогда и стоит расширять тест

[TestCase(3, 2, false, "-0.0")]
[TestCase(4, 2, true, "+1.23")]
[TestCase(4, 2, true, "+12")]
public void IsTrue_AfterCallingIsValidNumber(int precision, int scale, bool onlyPositive, string number)

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.

Например тут IsValidNumber_ReturnsTrue_WhenCorrectConditions/etc

}

[Test]
[TestCase(3, 2, true, "0000")]

Choose a reason for hiding this comment

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

Не хватает проверок из начала метода IsValidNumber

Choose a reason for hiding this comment

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

Ещё немного вариаций с числами можно добавить

}

[Test]
[TestCase(17, 2, true, "0.0")]

Choose a reason for hiding this comment

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

Не хватает ещё проверок по регулярке

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

// Ответ от студента: Если тест упадёт, не будет конкретно понятно, в чём проблема, ведь мы просто получим false.

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.

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

ClassicAssert.AreEqual(expectedTsar.Parent.Height, actualTsar.Parent.Height);
ClassicAssert.AreEqual(expectedTsar.Parent.Parent, actualTsar.Parent.Parent);

actualTsar.Should().BeEquivalentTo(expectedTsar, options => options.ExcludingMembersNamed("Id").AllowingInfiniteRecursion());

Choose a reason for hiding this comment

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

На подумать:
А можно сделать так чтобы при изменении названия поля(с помощью IDE), например Id => identifier, здесь не пришлось ничего менять?

Copy link
Author

Choose a reason for hiding this comment

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

Да, поменять "Id" на nameof(Person.Id).


actualTsar.Should().BeEquivalentTo(expectedTsar, options => options.ExcludingMembersNamed("Id").AllowingInfiniteRecursion());

// Комментарий от студента:

Choose a reason for hiding this comment

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

Правильно

Copy link

@FnaTikJK FnaTikJK left a comment

Choose a reason for hiding this comment

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

2 итерация

[TestCase(1, -1, false)]
[TestCase(1, 1, false)]
public void ThrowArgumentException_AfterCallingConstructor(int precision, int scale, bool onlyPositive)
[TestCase(-1, 2, TestName = "Precision should be <= 0")]

Choose a reason for hiding this comment

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

TestName немного противоречит логике. Слово should как будто бы отсылает к реальной логике, а не к конкретным входным данным твоего кейса. Ты проверяешь негативные кейсы - то есть в реальности нужно наоборот этого избегать. В таких случаях лучше описать не каким должен быть(should) а каким не должен быть(can't/should not)

Choose a reason for hiding this comment

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

То есть по твоим тестам хочется ещё понимать логику кода, который ты тестируешь. Сейчас условия приходится инвертировать, что усложняет чтение.
Если хочется описать именно с точки зрения входных данных, то можно просто Precision <= 0, но это кажется малоинформативным

[TestCase(20, 2, true, "++123")]
public void IsFalse_AfterCallingIsValidNumber(int precision, int scale, bool onlyPositive, string number)
[TestCase(3, 2, true, null, TestName = "Null")]
[TestCase(3, 2, true, "", TestName = "Empty string")]

Choose a reason for hiding this comment

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

Обычно WhiteSpace тоже хорошо бы проверять

[TestCase(3, 2, true, "", TestName = "Empty string")]
[TestCase(3, 2, true, "0.", TestName = "Fractional part missing")]
[TestCase(3, 2, true, ".0", TestName = "Integer part is missing")]
[TestCase(3, 2, true, "0000", TestName = "Integer")]

Choose a reason for hiding this comment

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

Здесь не хватает объяснения, что int-овая часть превышает размер

[TestCase(3, 2, true, "+000", TestName = "Positive signed integer")]
[TestCase(3, 2, true, "-00", TestName = "Negative integer")]
[TestCase(3, 2, true, "00.00", TestName = "Fractional number")]
[TestCase(3, 2, true, "+0.00", TestName = "Signed fractional number")]

Choose a reason for hiding this comment

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

Тут тоже не хватает объяснения, что знак тоже имеет вес

[TestCase(3, 2, true, "00.00", TestName = "Fractional number")]
[TestCase(3, 2, true, "+0.00", TestName = "Signed fractional number")]
[TestCase(3, 2, true, "-0.0", TestName = "Negative fractional number")]
[TestCase(17, 2, true, "0.000", TestName = "Very long fractional part")]

Choose a reason for hiding this comment

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

Она не просто very long, она именно больше конкретной переменной

[TestCase(3, 2, true, "-00", TestName = "Negative integer")]
[TestCase(3, 2, true, "00.00", TestName = "Fractional number")]
[TestCase(3, 2, true, "+0.00", TestName = "Signed fractional number")]
[TestCase(3, 2, true, "-0.0", TestName = "Negative fractional number")]

Choose a reason for hiding this comment

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

Тут, как и выше Negative integer всё таки важно, что onlyPositive = true. А твоё название как будто смещает акцент с этой переменной к тому, что число просто отрицательное. Хотелось бы в названии видеть все факторы, которые влияют на результат

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