Inc testing

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

Введение

Модульные тесты стали неотъемлемой частью процесса разработки внутри нашей компании, но так было не всегда и тому был  ряд причин по которым мои коллеги избегали тестов:

  • Время – не все понимают, что время затраченное на написание тестов, на код который и так работает  в дальнейшем окупится
     примечание: долгое время в компании ходила поговорка “нету тестов, нет проблем” ))))
  • Сложность – тесты требуют от разработчика определенных знаний, по этому начинающим разработчикам тесты даются очень сложно, особенно если плохая декомпозиция приложения.

Сложность времени

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

Создание объектов

Описание: создание новых объектов это неотъемлемая часть всех тестовых сценариев, но так же и одна из самых рутинных работ, требующих от программиста внимательности.

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

Решение 1: уникальные значения.

примечание: теперь переменные будут уникальные в рамках теста, то есть значение IsActive может меняться после каждого или через несколько проходов теста, но осталась проблема если мы не укажем IsActive при инициализации. Pleasure.Generator позволяет создавать разные уникальные типы данных.

Решение 2: динамически проставлять все поля.

примечание: код решает проблему если пропустить поле при инициализации объекта.

Вывод: мы изучили проблемы связанные с созданием объекта и нашли пути их решения, применив инструмент для генерации объектов , можно найти много разных библиотек для создания уникальных объектов, но incoding framework предлагает уже готовое средство, которое обладает рядом особенностей:
  • Tuning – позволяет настроить значение поля объекта.

             справка: пример демонстрирует, как проверить  ветку условия теста, когда order должен иметь номер 1.

  • Empty – позволяет указать, что при создание объекта установить в поле значение по умолчанию ( default(T) )

              справка: пример демонстрирует, как проверить ветку условия теста, когда order должен иметь нулевую цену. Стоит отметить, что можно переписать код выше используя tuning, но так читабельно.

  • GenerateTo- позволяет указать, что при создание объекта установить в поле значение  Pleasure.Generator.Invent()

            справка: пример демонстрирует, как проверить ветку условия теста, когда order должен иметь user.  Стоит отметить, что можно переписать код выше используя tuning, но так читабельно.

  • Ignore - позволяет указать, что при создание объекта не надо учитывать поле

    справка: пример демонстрирует, как проверить ветку условия теста, когда order проставляет дату автоматически , например в ctor.  Второй параметр это комментарий, который используется для объяснения игнорирования поля, причина этому то что , сам метод Ignore чаще всего говорит о проблемах дизайна приложения.
  • Callback - позволяет обратится к объекту после его создания.

    справка: пример демонстрирует, как проверить ветку условия теста, когда order должен иметь 2 уникальных order item . Данный пример можно переписать следующим образом:

     справка: предыдущий способ мне импонирует больше из-за наглядности контекста выполняемого кода, особенно это становится заметно когда рядом есть другие инициализации объектов

Сравнение объектов

Описание: сравнение объектов , так же на равнее с созданием встречается в большинстве сценариев и тоже требует повышенной внимательности от программиста.

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

Решение : сравнить объекты на основе схемы полей.

 примечание: такой вариант снимает с программиста груз ответственности за контроль над добавлением новых полей.

Вывод: мы изучили проблемы связанные с сравнением разных объектов и нашли пути их решения, воспользовавшись готовым набором методов из incoding framework. В .net представлено большое количество инструментов для сравнения объектов разных или одинаковых типов , но incframework имеет ряд особенностей :

  • Forward – возможность настроить соответствие схемы объектов

     справка: пример демонстрирует, как можно перенаправить значение поля Price на значение поля Cost
  • ForwardToValue – возможность указать конкретное значение поля вместо поиска поля в сравниваемом объекте.

    справка: пример демонстрирует, как можно сравнить поле CreateDt с строковым его представлением.
  • ForwardToAction – возможность выполнить действия с объектом вместо поиска поля в сравниваемом объекте.

    справка: пример демонстрирует, как можно выполнить действия над объектом.
  • Ignore –  возможность пропустить поле при сравнение

    справка: пример демонстрирует, как можно проигнорировать поле которое вычисляется автоматически и не зависит от сравниваемого объекта
  • ShouldEqualWeakEach – возможность сравнивать коллекции

 справка: данный код сравнивает коллекции объектов, что важно можно сравнивать разные типы коллекций. Для WeakEach так же доступны Forward , Ignore  и т.д. , но с  учетом индекса

 справка: переменная i является номером текущей позиции перечисления.

Сценарии

Сценарий command и query

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

Leave a Reply