Skip to content

Яценко Ирина#235

Open
lholypeachy wants to merge 9 commits intokontur-courses:masterfrom
lholypeachy:master
Open

Яценко Ирина#235
lholypeachy wants to merge 9 commits intokontur-courses:masterfrom
lholypeachy:master

Conversation

@lholypeachy
Copy link

Copy link

@pakapik pakapik left a comment

Choose a reason for hiding this comment

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

Если покажется, что замечаний много, то не переживай - во-первых, нет, во-вторых, это нормально, т.к. ревью для того и делается 🙃

Copy link

Choose a reason for hiding this comment

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

Хорошо. Ещё, как вариант в борьбе с дублированием кода, 2 предыдущих теста можно было бы объединить в один с именем NumberValidator_WhenPassInvalidArguments_ShouldThrowsArgumentException, подтягивая данные из TestCaseSource . Подобный подход хорош тем, что на один тест можно клепать много входных данных, проверяя n сценариев сразу. При этом можно манипулировать параметрами входных данных всякими SetXXX и Object Mother / Test Data Buider. Из минусов можно назвать, что тесту приходится давать чуть более общее имя (которое, впрочем, можно уточнить через SetName) и придумывать какое-то название для TestCaseSource, но это мелочи по сравнению с тем, какого объёма кода иногда можно избежать. Это просто к сведению, переделывать не нужно.

Буду оставлять ещё nit: замечания, которые цепляют глаз только у меня. Ты можешь принимать их к сведению, но не обязана что-то с этим делать - исправлять или даже отвечать.

Copy link

Choose a reason for hiding this comment

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

Ожидаемый результат ShouldReturnFalse не соответствует секции Assert.

nit: к NumberValidator в названии теста я бы добавил ctor: NumberValidatorCtor, чтоб подчеркнуть, что тестируется именно конструктор, а не класс.

Copy link

Choose a reason for hiding this comment

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

nit: в лекции видел, что у вас есть упоминание System Under Test. По некоторым гайдам/книгам/статьям, именно так и стоит называть тестируемый объект - sut. Если бы секция Arrange была больше, то из nit это превратилось в момент, который стоит поправить.

Copy link

Choose a reason for hiding this comment

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

Откровенно говоря, я не понял условия 🙃
Почему PassOnlyPositive - IsFalse ?

Copy link

Choose a reason for hiding this comment

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

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

Обычно я делаю так: [Test][TestOf(nameof(NumberValidator.IsValidNumber))] public void ShouldBe[что-то]_When[что-то].

Copy link

Choose a reason for hiding this comment

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

В комменте уже нет смысла

Copy link

Choose a reason for hiding this comment

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

Казалось бы мелочь, но после // принято ставить пробел - так читается проще 🙃

Copy link

Choose a reason for hiding this comment

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

Да, круто, всё верно.

Copy link

Choose a reason for hiding this comment

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

nit: numbers множественное число, does следовало бы заменить на do - does используется только для he/she/it. Обращаю внимание только по той причине, что можно было сократить название длинного метода на пару буковок🙃

Copy link

Choose a reason for hiding this comment

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

Круто, что коммиты логически разбиты

Copy link

Choose a reason for hiding this comment

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

Оставлю ссылку на этот комментарий, и ещё раз скажу, что тесты, которые выкидывают исключение, можно объединить в один, указав для них TestCaseSource

Copy link

Choose a reason for hiding this comment

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

Тут тоже нужно подумать в сторону TestCaseSource. Вызывать внутри теста другой тест - плохая практика.
Под обобщением создания корректного валидатора я подразумевал немного иное. Подумай, как можно получать в методе / группе методов корректный валидатор, не вызывая непосредственно конструктор?

Но опустим пока этот момент. Сейчас тебе надо сделать так, чтоб все твои 8 тестов, о которых мы говорили, превратились в один, для которых бы использовался один или несколько TestCaseSource.

Copy link

Choose a reason for hiding this comment

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

Очевидно, что слетело форматирование. Если пользуешься rider, то в нем можно прожать ctrl + alt + L / ctrl + alt + shift + L, код отформатируется. Можно так же настроить автоформатирование (можешь погуглить) на каждое сохранение кода ctrl + s - очень удобно, кстати, рекомендую. Если в vs работаешь, то не подскажу, но всё легко гуглится.

Copy link

Choose a reason for hiding this comment

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

Зачем тут геттер?)

Copy link

Choose a reason for hiding this comment

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

Зачем тут yield return?)

Copy link

Choose a reason for hiding this comment

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

Всё тело метода можно упростить до одной строчки, не забудь про expression body

Copy link

Choose a reason for hiding this comment

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

Помимо уже озвученных замечаний InvalidArgumentTestCases и ValidArgumentTestCases стоит разделить пустой строкой друг от друга, но это тоже обычно автоформатируется.

Copy link

@pakapik pakapik Nov 29, 2023

Choose a reason for hiding this comment

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

Тоже как вариант обобщения. Иногда SetUp очень удобен, но он запускается для каждого теста - в том числе для тестов, где ты проверяешь конструктор.

Помимо прочего, не беря во внимание SetUp (т.е. вообще не юзаем SetUp), хотел бы услышать ответ на вопрос - что может пойти не так, если использовать в тест-классе поле, тем более, если это поле-sut? Представь, что у тебя не несколько тестов, а 100-200 штук, и в каждом по своему разумению используется поле numberValidator?

По тому, как я бы хотел видеть создание numberValidator, дам подсказку - тебе нужно сделать обертку над созданием numberValidator, своего рода фабрику (не в ортодоксальном её понимании), какой-то мини-член класса, который отвечал бы только за что, что возвращал бы корректный валидатор)

К слову, поля обычно начинается с нижнего подчеркивания: _numberValidator. Это позволяет не использовать конструкцию this внутри класса, да и в целом сразу видно, что это поле, а не просто локальная переменная. Это тоже где-то настраивается в настройках среды. В Rider Settings (ctrl + alt + s)EditorCode StyleC#. И тут куча всяких настроек, можешь попробовать настроить под себя + выставить в подсказки мои замечания, чтоб среда сама тебе всё подсказывала в будущем. Но поле numberValidator тебе тут вообще не нужно)

Copy link

Choose a reason for hiding this comment

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

Ещё один минус SetUp - это непонятно, в каком состоянии находится сейчас numberValidator. Очевидно, что он проинициализирован, но с какими параметрами? Сейчас название теста не соответствует проверяемым кейсам - ValidArgumentTestCases как источник данных, но при этом WhenPassInvalidArguments_ShouldReturnFalse.

Copy link

Choose a reason for hiding this comment

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

Ранее не обратил внимание, но объясни ещё, пж, про 52 строку - в чем тут потенциальная опасность?

Copy link

Choose a reason for hiding this comment

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

Тут тоже можно до одной строки упростить.

Copy link

Choose a reason for hiding this comment

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

Ранее об этом не говорил, но класс тоже можно пометить атрибутом TestFixture, причем туда же можно по желанию так же впихнуть TestOf: [TestFixture(TestOf = typeof(NumberValidator))]

Copy link

Choose a reason for hiding this comment

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

[TestFixture] дублировать не надо, хватит одной записи - первой или второй (на мой взгляд более предпочтительной)

Copy link

Choose a reason for hiding this comment

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

nit: очень странный перенос аргументов. Мб, у тебя по ширине строки это форматируется, не знаю. Обычно пишут либо в одну строку:
(int precision, int scale, bool onlyPositive, string number, bool expectedResult),
либо переносят вообще всё:

 (
int precision, 
int scale, 
bool onlyPositive, 
string number,
bool expectedResult)

Copy link

Choose a reason for hiding this comment

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

new TestCaseData(3,2,true,"0.0", true).Returns().SetName("WhenNumberIsValid")

А bool expectedResult можешь убрать. Соответственно, тебе придется возвращать результат вызова IsValidNumber.

Copy link

Choose a reason for hiding this comment

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

Все ещё неверное название теста. У тебя в источнике есть кейсы, которые проверяют, что IsValidNumber вернет true + туда подаются валидные аргументы.

Copy link

Choose a reason for hiding this comment

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

Не надо смешивать секцию Act и Assert. Отдельно напиши в var actualResult = correctValidator.IsValidNumber(number);, затем отдельно Assert.AreEqual(expectedResult, actualResult). Впрочем, когда ты переделаешь с учетом замечаний сверху, тебе вообще не понадобится писать Assert.

Но совет про не смешивать всё ещё актуальный (во всех смыслах🙃🙃🙃)

Copy link

@pakapik pakapik Nov 29, 2023

Choose a reason for hiding this comment

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

Давай добавим чуть больше данных для проверок - null, спец.символы - /r , /n, просто символы %$# и т.д. Число с каким-то символом? Символ с каким-то числом? Строка из пробелов?

Что будет, если разделитель не точка, а запятая? А если разделителей несколько? А если в строке только разделитель?

Как валидатор ведет себя с очень большими числами? С очень большой точностью? А все вместе? Умеет ли он понимать числа в экспоненциальном формате?

А может, валидатор считает верным число в другой системе счисления? Иррациональные числа?

Возвращает ли валидатор на один и тот же входной параметр один и тот же результат? Для этого можно использовать атрибут [Repeat()].

А может, валидатор как-то меняет свой стейт? Что будет если подать сначала одно число, затем второе, а затем снова первое? Кстати, для того, чтоб обозначить, что метод ничего не изменяет (что-то внутри себя / входные параметры), то его можно пометить атрибутом [Pure] из неймспейса System.Diagnostics.Contracts или JetBrains.Annotations. В данном случае [Pure] применяться должен к IsValidNumber, раз он внутри себя не делает ничего такого криминального.

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

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

Comments