Вы вызываете интересный вопрос. По правде говоря, вам нужно протестировать ADT на основе шаблонов использования, а не отдельных методов.
Рассмотрит требование к стеке:
- Когда я вытолкнуть элемент X в стек, я не ожидаю никакого ответа.
Ну, это, конечно, проверяемы, но он встроен в возвращаемый тип, который void
или unit
.
Нет ничего, что можно было бы непосредственно наблюдать за действием push. Скорее, это конкретные комбинации действий, которые определяют поведение.
- Когда я нажимаю элемент X в пустой стек, я ожидаю, что X окажется на вершине стека ничем под ним.
Хм. Это тесты push
, но, как вы отметили, вы не можете разрешить вторую половину без других функций стека.
В таком случае, имеет значение, что происходит, когда вы нажимаете? Нет! Вы заботитесь о том, что некоторая последовательность операций приводит к достоверному и согласованному результату.
Это относится к модульным испытаниям в целом: когда вы можете, каждый из них проверяет каждую функцию отдельно. Но когда это не имеет смысла, используйте вместо этого шаблоны поведения.
Часть причины, по которой вы не можете предположить, что нажатие на стек немедленно приводит к тому, что вам никогда не дается эта гарантия. Например, представьте, что ваша реализация стека использует причудливый буфер: каждый раз, когда вы нажимаете, он добавляет элемент в буфер, но не помещает его в формальный стек. Затем, когда вы вызываете peek
или pop
, он берет на себя все буферизованные элементы одновременно, а затем выполняет операцию. Для вас внутренности невидимы: все, что вам нужно, - это то, что общее поведение было согласовано с общим положением стека.
И это, в сущности, то, что делает его ADT. Мы заботимся о моделях поведения, а не о детальной реализации.