Здравствуйте, FrozenHeart, Вы писали:
FH>Приветствую.
FH>Скажите, пожалуйста, какие правила используете Вы / Ваша компания при выделении кода в отдельные классы и функции используемого Вами testing framework'а?
Ну обычно начинают с того, что именно проверяет тест — сценарий использования (последовательность вызовов), или отдельный api point (набор перегрузок / родственных методов).
Для первого, понятное дело, никто не пишет перебор всех возможных комбинаций — их слишком много. Вместо этого тестами покрывают ключевые сценарии, желательно с помощью bdd-фреймворка, чтоб придерживаться одного стиля. Эти тесты заодно работают как тех.документация к API.
Для второго — есть варианты, я предпочитаю использовать подходящий по обстоятельствам.
* можно написать один тест на один метод и запихнуть в него все варианты. Удобно, если вариантов мало.
* можно сделать пару тестов — первый проверяет все корректные вызовы, второй — все некорректные.
* можно в одном тесте объединять проверки "парных" методов, если они тривиальны. Например для операторов сравнения <, <=, >, >= отдельные тесты городить часто лень.
Два главных правила:
* не смешивать разнородные проверки в тестах
* не лепить в один класс тесты, проверяющие принципиально разные вещи.
FH>Как видите, внутри функций test_dict_join и test_split_first_n находится код, проверяющий одновременно как ожидаемые входные значения, так и "исключительные" (всякие None, -1, 0 и т.д.). FH>Такой подход нормален?
Абсолютно. Чисто с прагматичной точки зрения в большинстве случаев нет никакого смысла лепить тесты на порядок большие по объёму, чем ммелкий хелпер.
FH>Другой пример. Имеется класс TCPSocket, являющийся обёрткой над socket из стандартной библиотеки Python (с поддержкой with-statement'ов, read_until и прочим). Для него я поступил схожим образом:
а в питоне setup вызывается для всего suite или для каждого теста в отдельности? Если второе — ок. Если первое — fail, легко в одном тесте спрятать побочные эффекты для другого.
FH>*Какой функционал выносите в отдельные функции test case'ов? FH>*Тестируете ли одновременно несколько входных значений внутри одного такого метода? FH>*Когда и в каких ситуациях объединяете test case'ы в test suite?
По обстоятельствам, да, по обстоятельствам соответственно.
Серьёзно, главная цель юнит-теста — отловить ситуацию "мой код поломался". Смысл заморачиваться с этими проверками настолько серьёзно, чтоб прям подводить под них методическую базу?
Обычный подход: сделали базовое соглашение по стилю, правим в местах, когда оно мешает — все щасливы. Зачем что-то ещё?