Разработка через тестирование: написание тестов для закрытых / защищенных переменных - PullRequest
3 голосов
/ 16 июня 2010

Я изучаю TDD, и у меня есть вопрос о частных / защищенных переменных. У меня вопрос: Если функция, которую я хочу проверить, работает с закрытой переменной, как мне ее проверить?

Вот пример, с которым я работаю:

У меня есть класс с именем Table, который содержит переменную экземпляра с именем internalRepresentation, которая является двумерным массивом. Я хочу создать функцию с именем multiplyValuesByN, которая умножает все значения в двумерном массиве на аргумент n.

Итак, я пишу тест для него (на Python):

def test_multiplyValuesByN (self):  
    t = Table(3, 3) # 3x3 table, filled with 0's
    t.set(0, 0, 4) # Set value at position (0,0) to 4
    t.multiplyValuesByN(3)

    assertEqual(t.internalRepresentation, [[12, 0, 0], [0, 0, 0], [0, 0, 0]])

Теперь, если я сделаю internalRepresentation закрытым или защищенным, этот тест не будет работать. Как мне написать тест, чтобы он не зависел от internalRepresentation, но все равно проверял, что он выглядит правильно после вызова multiplyValuesByN?

Ответы [ 4 ]

10 голосов
/ 16 июня 2010

Вы не должны зависеть от внутреннего представления объекта. Вот почему он помечен как частный или защищенный. Рассмотрим, какие наблюдаемые изменения вносятся в t при вызове t.multiplyValuesByN (3). Затем проверьте, что вы можете наблюдать.

def test_multiplyValuesByN (self):  
    t = Table(3, 3) # 3x3 table, filled with 0's
    t.set(0, 0, 4) # Set value at position (0,0) to 4
    t.multiplyValuesByN(3)

    assertEqual(t.get(0,0), 12)
3 голосов
/ 16 июня 2010

Другие опубликовали хорошие ответы, но ИМХО не смог подчеркнуть одну вещь: аспект дизайна (хотя Питер Тиллеманс упомянул об этом). Поэтому я добавлю немного объяснения по этому поводу.

При выполнении TDD вы эффективно тестируете как дизайн своего API, так и реализацию. Если вы обнаружите, что результат вызова метода трудно или невозможно увидеть извне, это почти всегда является признаком того, что интерфейс вашего класса не разработан должным образом. Если вам сложно написать тесты для вашего класса, то, как правило, будет трудно использовать его и в реальной жизни - ваши юнит-тесты фактически являются первыми клиентами вашего класса. Поэтому, если вы видите, что тестовый пример испытывает трудности с использованием интерфейса вашего класса, вам следует подумать о том, чтобы вернуться и перепроектировать свой API, чтобы упростить его использование (без ущерба для инкапсуляции, если возможно).

3 голосов
/ 16 июня 2010

Если он внутренний, то это не бизнес, не относящийся к классу и включающий тесты.

В TDD вы разрабатываете API своих классов, и будущие клиенты также могут видеть только наблюдаемое поведениекласс.

Я знаю, что это легче сказать, чем сделать.

В тесте вы часто видите повторное повторение шаблона: настройка - работа - проверка (- разборка)

настройкаФаза отвечает за приведение объекта в состояние предусловий.

Фаза проверки должна проверять постусловия посредством наблюдаемого поведения класса.Нет смысла хранить невидимое состояние, если оно никогда и никуда не выйдет.

0 голосов
/ 16 июня 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...