Принципы балансировки: модульное тестирование - PullRequest
2 голосов
/ 26 декабря 2009

Я пишу симуляцию бананаграмм. В настоящее время у меня есть класс GameMaster, который поддерживает общую коллекцию произведений. Метод deal(Player) раздает этому игроку определенное количество фигур.

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

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

Что мне здесь делать? В любом случае добавить геттеры, загромождая публичный API (или надеясь, что они понадобятся в будущем)? Отказаться от юнит-тестирования? (Звучит как плохая идея.)

Или это означает, что мой публичный интерфейс имеет недостатки?

Ответы [ 8 ]

3 голосов
/ 26 декабря 2009

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

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

Это также преимущество, поскольку оно означает, что тесты для GameMaster будут зависеть только от поведения класса GameMaster, и к ним не нужно прикасаться, если класс Player меняет свое поведение.

Избегайте добавления геттеров для юнит-тестов. Когда у вас возникнет желание добавить геттер, вместо этого используйте тестирование взаимодействия (как я только что описал) вместо тестирования на основе состояния.

2 голосов
/ 28 декабря 2009

Существует несколько способов проверки того, что фрагмент кода работает. Первое, о чем большинство из нас думает, - это тестирование на основе состояния (т. Е. Использование геттеров для проверки того, что конечное состояние вашего объекта соответствует ожидаемому). Однако другой способ проверить, работает ли ваш код, - это использовать тестирование на основе поведения или взаимодействия.

У Мартина Фаулера есть приличная статья о разнице здесь

0 голосов
/ 28 декабря 2009

модульные тесты не улучшают ваш код , они делают ваше приложение более стабильным с течением времени с изменениями и добавленными функциями. Вот почему, если у вас нет общедоступных методов получения в классе GameMaster, вам не нужно создавать их для юнит-тестов.

отсутствие получателей не означает, что ваш интерфейс работает, концепция разработки, управляемой тестами, заключается в написании минимального кода для прохождения теста (что вытекает из требований), если вы не нуждаетесь в этом, вы не пишете print, trace, log будет здесь долго после того, как модульные тесты исчезнут (хорошо, они также здесь, чтобы остаться, но во многих случаях переусердствовали и злоупотребили)

0 голосов
/ 26 декабря 2009

Я не вижу ничего плохого в добавлении кода специально для тестирования. Модульные тесты неоценимы для регрессионного тестирования.

Однако также правильно, что это не должно влиять на ваш публичный API. Поэтому я предлагаю сделать пакет геттеров защищенным и поместить ваши модульные тесты в тот же пакет, что и класс Player. (Тем не менее, в другой исходной папке, чтобы иметь четкое разделение между рабочим кодом и тестовым кодом.)

0 голосов
/ 26 декабря 2009

Одна вещь, которую вы могли бы сделать, это создать подкласс вашего основного класса, чтобы обеспечить геттеры для тестирования. Это было бы проще, если бы у вас были интерфейсы для работы.

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

0 голосов
/ 26 декабря 2009

Я бы сказал, что ваши уроки могут быть слишком большими. Звучит так, будто они хранят состояние и делают другие вещи.

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

GameMaster gameMaster = new GameMaster;
playerOne.Score = gameMaster.ComputePlayerScore(newScore);

вы бы передали экземпляр GameState только для состояния в конструктор подпрограммы GameMaster:

GameState gameState = new GameState;    
GameMaster gameMaster = new GameMaster(gameState);
playerOne.Score = gameMaster.ComputePlayerScore(newScore);

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

0 голосов
/ 26 декабря 2009

Вы должны проверить функциональность, которая внутренне использует эти переменные, хранящие состояние. Если их не использует общедоступная функциональность, то это мертвый код.

0 голосов
/ 26 декабря 2009

Что мне здесь делать? В любом случае добавить геттеры, загромождая публичный API (или надеясь, что они понадобятся в будущем)?

Я не получил этот ответ. Как геттер "беспорядок"?

Вы занимаетесь разработкой на основе тестирования. Дизайн обусловлен абсолютной необходимостью проверить все.

Геттеры не являются "беспорядком". Они как вы проверяете вещи.

«Отказаться от юнит-тестирования?»

Не думаю, что это хорошая идея.

...