@thewizardplusplus

Как тестировать мелкие классы?

Когда внутри одного класса используется другой, то в общем случае подход к тестированию мне ясен. Для внутреннего класса создаётся интерфейс и далее используется внедрение зависимости, когда конкретную реализацию этого класса мы подставляем при создании внешнего (через конструктор, через сеттер или ещё как-нибудь). Тогда при тестировании создаётся stub или mock, в зависимости от того, что в данный момент тестируется, и просто подставляется вместо этого внутреннего класса.

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

Допустим, я пишу некий графический движок, и у меня есть класс меша, который представляет собой сетку полигонов. Для простоты примера примем, что в меше хранятся не отдельные полигоны, а просто массив вершин, и при рендере считается, что каждые три вершины, идущие подряд - это один полигон. Каждая вершина представлена её координатами (хранящимися в векторе - классе Vector3D).

Класс Mesh тестировать нужно - там, например, может быть метод getBoundingBox(), вычисляющий ограничивающий сетку параллепипед. Нужен тест для контроля верности таких вычислений.

Но точно так же нужны тесты и для класса Vector3D! Например, у него может быть метод cross(), вычисляющий векторное произведение, что достаточно нетривиально, чтобы это тестировать.

Использовать в этом случае интерфейс Vector3DInterface нереально - вершин в меше может быть сотни тысяч и тогда тот самый небольшой оверхед на вызов виртуальных методов и хранение таблицы виртуальных функций станет весьма ощутимым.

Использовать вместо Vector3D именно в классе Mesh более простой класс Point с тремя публичными полями x, y, z и без методов тоже не вариант - в некоторых других классах или в методах класса Mesh могут потребоваться именно методы класса Vector3D и создавать в них каждый раз Vector3D из Point - те же самые тормоза на сотнях тысяч вершин.

Если же просто написать тесты и для Vector3D, и для Mesh, то придётся нарушить правило тестирования - не привязываться к порядку тестов. Чтобы сначала тестировать внутренний класс, а потом внешний.

Ну, и, наконец, данный пример - просто пример, вопрос касается не этой конкретной ситуации, а проблемы в целом.

Так как же тестировать мелкий внутренний класс, когда внедрение зависимости недопустимо?
  • Вопрос задан
  • 3103 просмотра
Решения вопроса 1
Trrrrr
@Trrrrr
Лично я не вижу в этом проблемы, только я б разделил бы на 3 части
1) тесты для вектора
2) тесты для всяких алгоритмов меша (сама реализация getBoundingBox не обзятально должна сидеть в меше ). Вот кстати сами алгоритмы можешь вынести в отдельный интерфейс и использовать депенденси инжекшн для мокинга.
3) тесты самого меша.

Вообще класс вектора это не обьект (в понимании ООП) а абстрактный тип данных (АТД). В С++ например, довольно важно понимать, что у тебя подразумевается под ключевым словом class.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@lookid
Пишете консольное приложение и там гоняете тесты. Параллельно на листочке пишете своё решение и сверяете ответы. Пишете свой assert. Вектор и матрица же умеет в operator ==, operator !=, вывести на экран и прочее? Посмотрите Google C++ Testing Framework.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы