Как стать автором
Обновить

Комментарии 5

Что у вас со скриншотами? Это же ужас какой то)

Вот только Constraint Assertion из NUnit куда более юзабельны. Fluent Assertion способна описать assertion как входной параметр теста? А вот NUnit позволяет это сделать довольно красиво.

Можно пример, когда это нужно?

Наверное, полезность Fluent Assertions разная в зависимости от типа тестов. Объясню.

В юнит-тестах, в случае наличия ассертов прямо в тест-методе да, вероятно, удобно. А что, если мы имеем интеграционный автотест на большую систему? Что, если при этом хотим, чтобы тело тест-метода содержало только бизнес-шаги, т.е. то, что реально делает пользователь? Т.е. читаем инструкции в тест-методе и это прямо пользовательский сценарий. Пользователь ни про какие ассерты не знает, а потому разумно их убрать в какие-то классы шагов. Там в свою очередь они могут быть вызваны из каких-то дополнительных методов.

Теперь представим, что автотесты запускаются какой-то большой системой по запуску тестов, в этой системе генерируются отчёты и видно ошибку при падении ассерта. При использовании Fluent Assertions из-за того, что сообщение создаётся автоматически, мы не сможем просто так взять скопировать его и найти в коде сразу проблемное место.

Хорошо, добавим сообщение. А вот тут самый ад Fluent Assertions. Потому что постоянно нужно помнить шаблон, который использует библиотека для формирования финального сообщения. Что писать в ассерт: как должно быть или что неправильного случилось? Эта неопределённость порождает временами безумные сообщения.

В случае же со стандартными ассертами, что в MSTest, что в NUnit при наличии сообщений решаются обе проблемы:

  1. сообщение об ошибке будет гарантированно то, какое мы напишем (ну за исключением Expected/Actual);

  2. можно всегда скопировать сообщение, вставить в IDE и найти проблемное место.

Недавно я поработал на проекте, в котором использовались Fluent Assertions.

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

Но вот что мне не понравилось в Fluent Assertions, так это ухудшение читабельности и легкости написания кода из-за безудержного использования Fluent Interface.

Вот это хоть и выглядит короче

    10.May(2020).At(21, 20, 30)

но менее понятно, чем чуть более длинное

    new DateTime(2020, 5, 10, 21, 20, 30)

Здесь вообще очень длинно

    age.Should().BeGreaterThan(9)

по сравнению с

    age > 9

Конечно, эти два выражения не эквивалентны по функциональности и второе нужно еще обернуть в Assert.IsTrue(), но все равно получается читабельнее.

Лично мне читать это сложно:

    persons.Should().ContainSingle(x => x.name == "Егор").Which.age.Should().BeGreaterThan(9);

Я вообще сторонник писать проверку каждого условия в отдельной строке:

    person = persons[1];
    Assert.AreEqual(person.name, "Егор");
    Assert.IsTrue(person.age > 9);

(это не совсем то, что в оригинальном коде, но моя мысль понятна)

С написанием кода с использованием Fluent Assertions у меня тоже проблемы:

  • Надо выучить десятки (а может, их там сотни?) всех этих методов типа BeGreaterThan.

  • Надо помнить, где ставить точку и где не ставить.

  • То же самое касается круглых скобок.

В качестве преимущества использования Fluent Assertions приводится возможность "читать код как книгу на английском языке". Но зачем вообще это нужно? (Тут вспоминается Эдсгер Дейкстра с его высказыванием "Проекты, предлагающие программирование на естественном языке, гибельны по своей сути").

Эти эксперименты с Fluent interface напоминают язык COBOL. Например, в C# мы пишем

    a = b;

а в языке COBOL присваивание записывается так (этот язык тоже создавался для того, чтобы пользователи-непрограммисты могли создавать программы на человеческом языке):

    Move b to a.

Как видим, это правильное предложение на английском, и даже точка в конце. Но потом языки программирования пошли по другому пути, и код стало можно писать короче и выразительнее.

В C# мы тоже можем создать библиотеку при помощи Fluent
interface, чтобы писать в стиле COBOL, что-то в этом роде:

    Move().b.To().a;

но зачем это нужно делать в 2022 году? А Fluent Assertions выглядит так, как будто нам в XXI веке пытаются подсунуть стиль программирования из 1960 года.

Вся история развития искусственно созданных языков (не только языков программирования, но я других, например, языка электрических схем или географических схем) говорит о другом - с течением времени язык становится лаконичнее и выразительнее.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий