В прогоне курса за П6 агент трижды убирал или ослаблял тесты. Один раз удалил два главных теста закрытия кабинета и написал «Два теста добавлены». Другой раз переписал файл с тестами оплаты целиком и пять прежних пропали. В третий раз вернул тест на поддельное уведомление перевёрнутым: тест проверял, что подделка становится оплаченной, и стоял зелёным. Каждый раз итог pytest выглядел прилично. Поэтому сдача этой практики устроена так, чтобы зелёный итог ничего не доказывал сам по себе.
Чему научишься в этом уроке:
• считать тесты и замечать, что их стало меньше;
• читать сам тест и понимать, что он проверяет;
• доказывать работу сервиса живой тестовой оплатой и запросом к базе сервера;
• сдавать сервис вместе с расчётом безубыточности.
Что продолжаем
Не начинай с нуля. Продолжай кабинет из уроков 7.3–7.5: школы, оплата через тестовый магазин ЮKassa, закрытие при неоплате, выкладка на сервер в Москве. Если у тебя свой заказчик и свой кабинет из П4–П5, превращай в сервис его. Нет своего, доделывай «Кодиум», это засчитывается. Паттерн по желанию: если ты его проходишь, доведи до сдачи, полсервиса без оплаты и проверки пользы не принесёт.
Шаг 1. Считай тесты
Число тестов как число страниц в договоре. Если в новой редакции страниц стало меньше, а тебе говорят «добавили два пункта», что-то убрали. Перед каждым заданием агенту и после него запиши последнюю строку pytest -q. Число прошедших тестов не уменьшается никогда. В прогоне было 33, потом 38, 42, 46 и в конце 49.
Обязательные тесты для сдачи. Названия у тебя могут быть свои, смысл тот же:
- Изоляция: школа А не видит заявки школы Б в списке, по прямому адресу (ответ 404), в выгрузке xlsx, на дашборде и в «Выводах недели».
- Ключ приёма: заявка попадает в ту школу, чей ключ приёма указан в запросе.
- Поддельное уведомление: на /pay/notify приходит уведомление, ЮKassa на повторный запрос отвечает «ещё не оплачен» (pending), оплата не засчитывается: paid 0, срок школы не изменился.
- Повтор: второе уведомление об одном платеже не продлевает доступ ещё раз.
- Гонка: два одновременных уведомления продлевают ровно один раз; тест проходит 10 раз подряд.
- Закрытие: при истёкших сроках кабинет ведёт на «Тариф», приём заявок работает; после оплаты кабинет открыт.
Шаг 2. Прочитай тест подделки
Открой файл с тестами оплаты и найди тест поддельного уведомления. Ты не обязан писать такие тесты сам, но прочитать три вещи обязан:
- тест отправляет запрос именно на
/pay/notify, а не вызывает функцию базы напрямую в обход; - подменённая ЮKassa в тесте отвечает status=pending;
- в конце тест проверяет, что paid остался 0 и срок школы не изменился. Если в проверке стоит paid == 1 или succeeded, тест перевёрнут.
Перевёрнутый тест в прогоне агент объяснил словами «скорректированы ожидания». Если видишь такую фразу в отчёте, читай тест первым делом.
Шаг 3. Живая тестовая оплата
Зарегистрируй на своём поддомене тестовую школу, зайди её владельцем и на странице «Тариф» нажми «Оплатить». Тестовую карту возьми из урока 7.4 (в прогоне 5555 5555 5555 4477) или со страницы тестирования в документации ЮKassa, деньги не списываются. После оплаты проверь в кабинете школы, что срок продлился, а в таблице платежей на сервере появилась ровно одна оплаченная запись.
ssh root@<адрес сервера>
sqlite3 -readonly /opt/crm-kodium/crm.db ".schema payments"
sqlite3 -readonly /opt/crm-kodium/crm.db "<запрос, который напишет агент по .schema payments: платежи тестовой школы, статус и paid>"
В прогоне по этой таблице нашлись три огреха, которых тесты не ловили: 7 платежей за 18 секунд от повторных нажатий «Оплатить», статус pending у оплаченного платежа и «Тариф» без общего меню. Посмотри на свою таблицу тем же взглядом: сколько записей на одно нажатие, совпадают ли статус и отметка об оплате.
Снимок для сдачи делай со страниц своего кабинета: «Тариф» после оплаты и страница «спасибо». В личном кабинете ЮKassa видны твои ФИО, ИНН и номер магазина: такие экраны не прикладывай или закрась это до отправки.
Шаг 4. Сервер запросом
Повтори проверку из урока 7.5 на итоговой версии: служба active, метка версии, роли и школы пользователей, сроки школ, число заявок первой школы, число копий в backups до и после перезапуска, список переменных .env без значений.
Шаг 5. Расчёт
Возьми таблицу из миссии урока 7.7 и подставь комиссию из своего тестового платежа. Сколько платящих школ нужно, чтобы окупить сервер, и сколько времени в неделю ты готов тратить на поддержку одной школы.
Если не получилось
- Тестов стало меньше →
git diffпо файлам тестов, верни удалённые: «верни все, проверки не ослабляй, подготовку данных поправь под новую схему». - Тест подделки проверяет paid == 1 → дай агенту задание, как в прогоне: «через /pay/notify, ЮKassa отвечает pending, paid остаётся 0, срок не изменился, ничего другого не меняй».
- Тест гонки то проходит, то падает → запусти его 10 раз подряд; нестабильный тест надо чинить, а не перезапускать до зелёного.
- Несколько платежей на одно нажатие → нужен ключ идемпотентности от номера записи, а не от времени, и переход на уже созданный неоплаченный платёж.
- Оплата прошла, а срок не продлился → смотри журнал службы на сервере: пришло ли уведомление и что ответил сервер.
Контрольный вопрос. Агент пишет «Добавил два теста, все проходят». До задания было 46 passed, после 44 passed. Что делаешь?
Подсказка: Сколько тестов должно было стать после «добавил два»?
На курсе задания проверяются автоматически. Решить первое задание бесплатно → · Подобрать курс
Контрольный вопрос. В тесте поддельного уведомления в конце стоит проверка, что платёж стал оплаченным. Тест зелёный. Что это значит?
Подсказка: Чем должна закончиться обработка поддельного уведомления?
На курсе задания проверяются автоматически. Решить первое задание бесплатно → · Подобрать курс
Задание. МИССИЯ «Мини-SaaS, который проверен». Продолжай кабинет из уроков 7.3–7.5 (свой заказчик или «Кодиум»). 1. Тесты: последняя строка pytest -q и список тестов изоляции и оплаты из шага 1 с их названиями в твоём проекте. Число тестов на каждом шаге П6 не уменьшалось. 2. Текст теста поддельного уведомления и три строки своими словами: куда он отправляет запрос, что отвечает подменённая ЮKassa, что проверяется в конце. 3. Живая тестовая оплата: снимки «Тариф» после оплаты и страницы «спасибо» из своего кабинета, вывод запроса к таблице платежей на сервере (одна оплаченная запись, статус совпадает с отметкой об оплате). 4. Сервер: служба active, метка версии, роли и школы пользователей, число заявок первой школы, число копий в backups до и после перезапуска, cut -d= -f1 .env. 5. Расчёт: остаток с одной школы, число платящих школ для безубыточности, время на поддержку. Принято, если: всё из пунктов 1–5 приложено, тест подделки проверяет paid 0 и неизменный срок через /pay/notify, в таблице платежей нет лишних записей на одно нажатие, расчёт опирается на комиссию из своего платежа. На снимках кабинета ЮKassa закрашены ФИО, ИНН и номер магазина; ФИО, ИНН, ключей, паролей и данных учеников в приложенном нет.
Подсказка: Начни с пункта 2: если тест подделки перевёрнут, остальное придётся проверять заново после починки.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
На курсе задания проверяются автоматически. Решить первое задание бесплатно → · Подобрать курс
Что дальше
Паттерн «Мини-SaaS» закрыт: кабинет для одной школы стал сервисом для многих, с оплатой, изоляцией и проверкой, которой ты веришь. Если школы не набрались, это тоже результат: ты проверил идею и знаешь, сколько стоит её запуск. Следующий паттерн про продукт, в котором модель работает в самой сердцевине.
Итог:
• число тестов записано до и после каждого шага и не уменьшалось;
• тест подделки прочитан глазами и проверяет, что подделка не проходит;
• работа сервиса доказана живой тестовой оплатой и запросами к базе сервера;
• у сервиса есть расчёт безубыточности на своих цифрах.
