ORM (django), frontend (django, websocket, jsonrpc), frontend API, самодельный cron, большая голова, маленькая голова, backend api, источник энтропии (asterisk).
Головы общаются между собой прямыми вызовами методов, defered/callbacks и observable/events.
Логика компонентов определяется их поведением и реакцией на всяческие ситуации, сигнализируемые через евенты.
Изменения состояний тоже сигнализируется через евенты.
Все возможные режимы поведения сосредоточены в одном центральном компоненте.
Поток управления прямыми вызовами боле-менее линеен: API -> большая голова -> маленькая -> backend -> asterisk.
Поток евентов в общем-то тоже (в обратном направлении).
Общая логика поведения организутся в кучу микро-workflow (обработка звонков), которые относительно слабо связаны.
Вопрос — как тестировать такую конструкцию?
Какие вообще методологии бывают на такие случаи?
Как разделять — понятно, но как властвовать — не очень.
Основной источник энтропии и асинхронности (asterisk) я могу с некоторой достоверностью сэмулировать говорящей болванкой, чтобы генерить предсказуемые входные данные.
Но вот что делать со всем остальным, и особенно с время-зависимыми процессами — совсем нет идей. И страшно.
Обучен только методу unit-testing, который тут совсем не в тему.
Вопрос сформулирован не очень четко, не вполне понятно, в чем именно заключается проблема это всё протестить, и почему время-зависимые процессы тут представляют сложность. Рискну предложить столь же расплывчатую схему действий (безо всяких методологий, а на пальцах):
1. В идеале — написать подробные сценарии использования (Use Case) для регулярной проверки правильной работы бизнес-логики.
2. Описать каждый интерфейс, который там есть.
3. Для каждого интерфейса понаписать заглушек, которые возвращают правильные значения, но ничего не делают.
4. Протестировать интерфейсы каждого компонента отдельно с помощью заглушек.
5. Протестировать каждый workflow по сценариям использования. Где есть временные лакуны — можно поставить искусственные задержки, лучше случайные, но чтобы из значение писалось в логи.
6. Написать автоматические тесты для всех интерфейсов и для прогона сценариев, если это возможно, и запускать после каждой доработки. Курить логи.
7. Проводить творческое тестирование на тему «как бы его еще обрушить»?
Проблема в понимании пунктов «протестировать каждый workflow по сценариям использования» и «написать автоматические тесты»
В юнит-тестировании есть готовые входные данные и оижидаемый результат. Всё кристально понятно. Сунуть данные сравнить результат.
Тут же вместо этого на входе некая ситуация и ожидаемое поведение. И то и другое процессы. Причом они переплетены так, что активную роль играют попеременно тестируемый и тестирующий. Да и инициирует процесс (в реальности) тестируемый.
Например, ситуация (поведение теста):
2. получить номер телефона
3. набрать его и посигналить об этом
5. подождать < N сек
6. обломать соединение, посигналить об этом
9. подождать немного и посигналить таймером
11. просигналить об освобождении ресурсов
Ожидаемое поведение юнита:
1. отправить номер телефона
4. получить сигнал и отметить его как зашибись
7. получить сигнал облома, расстроиться
8. повесить номер на таймер
10. дождаться таймера, засунуть номер в очередь
12. дождаться освобождения ресурсов
13. повторить пункты 1-7 N раз
7n+1. сделать грустное лицо, пометить номер телефона как плохой
Если оборудование позволяет, можно на каждое событие (набрал, посигналил, сделал грустное лицо) класть в лог запись соответствующего вида, и потом шерстить логи скриптом на предмет правильной последовательности событий.
Если хотите проверить на корректность модель взаимодействия, то можете (упростив до необходимого минимума) выписать на специальном языке свою систему и проверить на наличие проблем в графе — LTSA