Как вы действуете, если на проекте отсутствует формальная спецификация?

Ответ

При отсутствии спецификации я собираю требования и формирую тестовую модель самостоятельно:

  1. Коммуникация с командой: интервью с PM, аналитиками и разработчиками для выяснения ожиданий.
  2. Анализ кода и API: изучение исходного кода, тестов, контрактов или документации к API (например, OpenAPI/Swagger).
  3. Экспертиза и реверс-инжиниринг: исследование работающей системы для документирования фактического поведения.
  4. Анализ аналогов: изучение похожих продуктов для формирования базовых ожиданий.

Ключевой шаг — документирование и согласование. Найденные правила фиксируются (например, в виде тест-кейсов или чек-листов) и утверждаются командой как эталон.

Пример для недокументированного API:

# Эмпирическое определение спецификации через тесты
response = requests.get("/api/v1/users/1")
# На основе анализа нескольких запросов выясняем ожидаемый статус
assert response.status_code == 200
assert "id" in response.json()  # Ожидаемое поле в ответе

Ответ 18+ 🔞

О, смотри-ка, классика жанра! Работаешь, а тебе говорят: «Спецификации? А, ну это... её как бы... нету». И сидишь ты такой, как мудя в проруби, с круглыми глазами. Ну что ж, придётся самому становиться этим самым, блядь, реверс-инжиниринг-детективом.

Вот как я обычно из этого дерьма выкручиваюсь, по пунктам, чтобы не сойти с ума:

  1. Иду на разведку к людям. Беру кружку, иду к продакту, аналитикам, разработчикам — ко всем, кто хоть что-то знает. Задаю вопросы, пока у них из глаз не пойдут искры. «А что эта кнопка должна делать? А если юзер нажмёт сюда, а потом сядет на хуй? А это поле — оно обязательно или можно оставить пустым, как голову у того, кто не написал документацию?». Выясняю ожидания, пока они не начнут меня посылать. Это хороший знак — значит, границы терпения найдены.

  2. Копаюсь в коде, как крот в огороде. Смотрю на то, что уже есть. Исходники, старые тесты (если они, конечно, есть, а не «ой, мы их пока не написали»). Если это API — пытаюсь найти хоть какой-то намёк на контракт. Swagger? OpenAPI? Хоть комментарий в коде «// TODO: описать это ебало»? Иногда удаётся найти сокровище — старый постман-коллекшн в общем чате, завалявшийся с прошлого года. Ура, есть за что зацепиться!

  3. Включаю режим «Шерлок Холмс от тестирования». Если система уже живая, сажусь и просто исследую её, как первобытный человек огонь. Нажимаю все кнопки подряд, ввожу хуйню в поля, пытаюсь сломать то, что работает. И записываю, записываю, записываю! «О, так вот ты как фактически работаешь, сука!». Реверс-инжиниринг в чистом виде — по поведению системы восстанавливаю её скрытые правила.

  4. Смотрю, как другие это делают. Иногда помогает просто открыть похожий продукт — конкурента или просто известный сервис. «Ага, у них тут валидация email такая-то, логично... А тут после успешного действия показывается зелёная плашка...». Не чтобы слепо копировать, а чтобы понять общепринятые паттерны и сформировать хоть какие-то базовые ожидания. Чтобы не изобретать велосипед, у которого квадратные колёса.

И вот тут, блядь, самое важное — нельзя держать это всё в голове! Голова — она для того, чтобы волосы носить, а не чтобы в ней овердохуища недокументированных правил хранить.

Ключевой шаг — записал, обсудил, утвердил. Всё, что нашёл, вываливаю в виде тест-кейсов, чек-листов или просто списка в Confluence/Google Docs. А потом собираю этих самых разработчиков и продактов и говорю: «Народ, я тут поисследовал. Получается, система работает вот так и так. Вы согласны, что это и есть правильное поведение? Или я не так понял?». И пока они не кивнут и не скажут «да, вот эта вот хуйня — это и есть спецификация», — я не успокоюсь. Потому что иначе потом окажется, что «ой, а мы думали, ты сам догадаешься, что нужно тестировать вот эдак».

Ну и примерчик, для наглядности, когда API как чёрный ящик:

# Ситуация: есть endpoint, но что он возвращает — загадка.
# Берём и эмпирически, методом научного тыка, выясняем контракт.

import requests

# Дёргаем неизвестный зверь
response = requests.get("/api/v1/users/1")

# Анализируем труп. О, статус 200! Значит, юзер с id=1 существует — это теперь правило.
assert response.status_code == 200

# Смотрим, что внутри тела. О, есть поле 'id'! И 'name'! Фиксируем.
user_data = response.json()
assert "id" in user_data
assert "name" in user_data

# Вот она, рождённая в муках, спецификация. Записываем и идём согласовывать.

Вот так вот, из хаоса и неопределённости рождается хоть какая-то структура. А иначе — пиши пропало, волнение ебать.