Какие тестовые сценарии реализовать для проверки методов push и pop стека?
Что проверяют
Умеете ли вы превращать контракт структуры данных в набор проверок, а не ограничиваетесь «положил и достал». Интервьюер смотрит на граничные случаи и на то, тестируете ли вы поведение через публичный интерфейс. Часто следом просят написать пару тестов на pytest.
Как отвечать
Сначала уточните контракт: что делает pop на пустом стеке, есть ли ограничение ёмкости, есть ли peek и len. От ответа зависят ожидаемые результаты. Дальше сценарии:
- push в пустой стек:
lenстановится 1,peek()возвращает элемент; - порядок LIFO: после
push(1),push(2),push(3)три вызоваpop()дают 3, 2, 1; - pop возвращает и удаляет: значение совпадает с последним добавленным, размер уменьшился на единицу, следующий
popотдаёт предыдущий элемент; - pop на пустом стеке: ожидаемое исключение, у встроенного
listэтоIndexError. Проверяется черезwith pytest.raises(IndexError):; - опустошение и повторное использование: вытащили всё, стек пуст, после нового
pushснова работает корректно; - чередование:
push,pop,push,push,popс проверкой состояния после каждого шага; - разные значения:
None, изменяемые объекты, дубликаты.Noneособенно коварен, если реализация сигналит о пустоте возвратомNone; - ограниченная ёмкость, если она есть:
pushв полный стек даёт оговоренное исключение, содержимое не меняется.
Покажите технику: фикстура с новым стеком на каждый тест, @pytest.mark.parametrize для наборов данных. Хороший плюс это свойство на Hypothesis: для любого стека push(x) и следом pop() возвращают x и не меняют остальное содержимое.
Где спотыкаются
Проверяют внутренний список stack.items вместо pop, peek и len. Такие тесты ломаются при любом рефакторинге реализации, хотя поведение не изменилось.
Для переполнения предлагают OverflowError. Это исключение для арифметики, для полной коллекции лучше своё, например StackFullError.
Держат один стек на уровне модуля. Тесты начинают зависеть от порядка запуска и падают, стоит прогнать их по одному.