Перспектива:
Итак, давайте сделаем шаг назад и спросим, с чем TDD пытается нам помочь. TDD пытается помочь нам определить, верен ли наш код или нет. И по правде говоря, я имею в виду "соответствует ли код бизнес-требованиям?" Суть в том, что мы знаем, что в будущем потребуются изменения, и мы хотим убедиться, что наш код останется верным после того, как мы внесем эти изменения.
Я поднимаю эту точку зрения, потому что думаю, что легко потеряться в деталях и упустить из виду то, что мы пытаемся достичь.
Принципы - SAP:
Хотя я не эксперт по TDD, я думаю, что вы упускаете часть того, чему пытается научить принцип единого утверждения (SAP). SAP можно переформулировать как «проверять по одной вещи за раз». Но TOTAT не так легко скатывается с языка, как SAP.
Тестирование по одной вещи за раз означает, что вы сосредоточены на одном случае; один путь; одно граничное условие; один случай ошибки; один независимо один тест. И основная идея заключается в том, что вам нужно знать, что сломалось при неудачном тестировании, чтобы вы могли решить проблему быстрее. Если вы тестируете несколько условий (т. Е. Более чем одно) в одном тесте, и тест не пройден, у вас намного больше работы. Сначала нужно определить , какие из многочисленных случаев не удалось , а затем выяснить , почему , что дело не удалось.
Если вы тестируете что-то одно за раз, область поиска становится намного меньше, и дефект выявляется быстрее. Имейте в виду, что «тестирование по одной вещи за раз» не обязательно исключает возможность просмотра более чем одного результата процесса за раз. Например, при тестировании «известного правильного пути» я могу ожидать увидеть конкретное результирующее значение, foo
а также другое значение, bar
и я могу проверить это foo != bar
как часть моего теста. Ключ заключается в том, чтобы логически сгруппировать проверки выходных данных на основе проверяемого случая.
Принципы - PMP:
Кроме того, я думаю, что вы немного упускаете из виду то, чему нас учит принцип частного метода (PMP). PMP призывает нас относиться к системе как к черному ящику. Для данного ввода вы должны получить данный вывод. Вам все равно, как черный ящик генерирует вывод. Вам важно только, чтобы ваши результаты совпадали с вашими.
PMP действительно хорошая перспектива для рассмотрения аспектов API вашего кода. Это также может помочь вам оценить то, что вы должны проверить. Определите свои точки интерфейса и убедитесь, что они соответствуют условиям их контрактов. Вам не нужно заботиться о том, как методы за интерфейсом (или частные) делают свою работу. Вам просто нужно убедиться, что они сделали то, что должны были сделать.
Прикладной TDD ( для вас )
Таким образом, ваша ситуация представляет собой небольшую складку за пределами обычного применения. Методы вашего приложения с отслеживанием состояния, поэтому их вывод зависит не только от ввода, но и от того, что было сделано ранее. Я уверен, что я должен <insert some lecture>
сказать о ужасном состоянии и бла-бла-бла, но это действительно не поможет решить вашу проблему.
Я собираюсь предположить, что у вас есть какая-то таблица диаграмм состояний, которая показывает различные потенциальные состояния и что нужно сделать, чтобы инициировать переход. Если вы этого не сделаете, он вам понадобится, поскольку он поможет выразить бизнес-требования для этой системы.
Тесты: во- первых, вы получите набор тестов, которые изменяют состояние. В идеале у вас должны быть тесты, которые осуществляют весь спектр возможных изменений состояния, но я вижу несколько сценариев, в которых вам может не потребоваться проходить этот полный объем.
Далее вам нужно построить тесты для проверки обработки данных. Некоторые из этих тестов состояния будут повторно использованы при создании тестов обработки данных. Например, предположим, у вас есть метод, Foo()
который имеет разные выходные данные, основанные на состояниях Init
и State1
. Вы захотите использовать свой ChangeFooToState1
тест в качестве шага настройки, чтобы проверить вывод, когда « Foo()
в State1
».
У этого подхода есть некоторые последствия, о которых я хочу упомянуть. Спойлер, это где я буду бесить пуристов
Прежде всего, вы должны признать, что вы используете что-то в качестве теста в одной ситуации и настройку в другой ситуации. С одной стороны, это кажется прямым нарушением SAP. Но если вы логически объявляете, ChangeFooToState1
что преследуете две цели, вы все равно отвечаете духу того, чему нас учит SAP. Когда вам нужно убедиться, что Foo()
изменения состояний, то вы используете ChangeFooToState1
в качестве теста. А когда нужно проверить « Foo()
вывод, когда в State1
», то вы используете ChangeFooToState1
в качестве установки.
Второй момент заключается в том, что с практической точки зрения вам не понадобится полностью рандомизированное модульное тестирование для вашей системы. Вы должны запустить все тесты изменения состояния перед запуском выходных проверочных тестов. SAP является своего рода руководящим принципом этого заказа. Чтобы заявить, что должно быть очевидным - вы не можете использовать что-то в качестве установки, если оно не проходит как тест.
Собираем это вместе:
Используя диаграмму состояний, вы будете генерировать тесты для покрытия переходов. Опять же, используя вашу диаграмму, вы генерируете тесты, чтобы охватить все случаи обработки ввода / вывода данных в зависимости от состояния.
Если вы будете следовать этому подходу, bloated, complicated, long, and difficult to write
тесты станут немного проще в управлении. В общем, они должны быть меньше, и они должны быть более краткими (то есть менее сложными). Вы должны заметить, что тесты также более разрозненные или модульные.
Я не говорю, что этот процесс будет совершенно безболезненным, потому что написание хороших тестов требует определенных усилий. И некоторые из них по-прежнему будут трудными, потому что вы отображаете второй параметр (состояние) для довольно многих ваших случаев. И, кроме того, должно быть немного более очевидно, почему систему без состояния легче создавать для тестов. Но если вы адаптируете этот подход для своего приложения, вы должны обнаружить, что можете доказать, что ваше приложение работает правильно.