Написание макетов / заглушек для объекта до того, как вы написали класс для этого объекта? - PullRequest
8 голосов
/ 18 января 2012

Я разрабатываю класс, который имеет две зависимости.Один из классов зависимостей был написан и протестирован.Другой еще не был написан.

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

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

Итак: как мне это сделать?Создайте класс скелета, который я изменяю по мере продвижения.Возможно, что-то вроде:

class NonExistantSkeleton
{
    public function requiredMethod1()
    {
    }

    public function newlyDiscoveredRequirement()
    {
    }
}

, а затем смоделируйте его, используя PHPUnit, настройку заглушек и т. Д., Чтобы поддерживать мой класс в процессе разработки?

Так ли это?*

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

Ответы [ 2 ]

8 голосов
/ 18 января 2012

Короче говоря:

Да.По крайней мере, это то, что я делаю прямо сейчас.


Более длинная версия:

Если ожидаемые сотрудники вашего класса не существуют в тот момент, когда они вам нужнываши тесты для класса, который вы создаете, у вас есть несколько вариантов :

  • Макет несуществующих классов (что может делать phpunit)
  • Создание каркасов классов и макет
  • Просто создайте интерфейсы и получите макеты для тех (что может делать phpunit)
  • Возможно, вам не нужно ничего из перечисленного в зависимости отобъект

Если вы программируете с интерфейсом в любом случае, все, что вам нужно сделать, это создать этот интерфейс и сказать PHPUnit создать заглушку / макет изit

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

Когда высмеивая несуществующие классы вы получаете некоторые недостатки, которыеМне не нравится:

  • -Высокие затраты на техническое обслуживание макета
  • -Изменение методов для этих классов медленное и утомительное
  • -Если вы создали класс, то выследует снова переработать макеты

, поэтому я бы посоветовал против этого.

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

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

Наличие базовых классов с общедоступными apis дляменя, это не нарушение TDD.


Есть классы, которые вам не нужно высмеивать.

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

Это помогает сделать ваши тесты немного чище, пока выне нужно издеваться / ожидать много методов получения / установки и т. д.

7 голосов
/ 18 января 2012

Если вы используете , тогда обычный подход будет следующим:

  1. Выясните, для чего предназначены ваши классы, и какими должны быть их общедоступные API.
  2. Реализуйте "пустые" классы, которые состоят только из сигнатур открытых методов с пустыми телами (как вы сделали в приведенном выше примере кода).
  3. Разработка стратегии реализации. Это означает, что нужно определить, какие классы зависят друг от друга, и реализовать их в порядке, означающем, что зависимые классы не будут реализованы до тех пор, пока классы, от которых они зависят, не будут закончены или, по крайней мере, не будут достаточно функциональными для разработки. Это означает, что сначала нужно создавать классы без зависимостей, затем классы, которые зависят только от завершенных классов, и так далее.
  4. Напишите свои тесты. Теперь можно написать тесты, потому что вы знаете, как выглядит черный ящик для ваших классов, что они должны принимать в качестве входных данных и что они должны возвращать в качестве выходных данных.
  5. Запустите тесты. Вы должны получить 0% успеха, а также 100% покрытия кода. Теперь это ваша базовая линия.
  6. Начните реализовывать свои классы в соответствии со своей стратегией реализации. Во время этого процесса время от времени запускайте свои модульные тесты, скажем, когда вы закончите класс, чтобы убедиться, что он соответствует его спецификации, изложенной в модульном тесте. В идеале каждый тест должен показывать увеличение числа проходов, сохраняя при этом 100% покрытия кода.

РЕДАКТИРОВАТЬ: Как отметил edorian, интерфейсы PHP здесь очень помогают, потому что PHPUnit может генерировать макеты и заглушки как из интерфейсов, так и из классов. Они также являются отличным инструментом для снижения сцепления и улучшения взаимозаменяемости в целом. Они позволяют вам заменять любой класс, который реализует ожидаемый интерфейс, а не просто подклассы ожидаемого класса.

...