Files
specs/openspec/changes/archive/2026-11-02-account-top-positions/analysis/qa-analysis.md
T
codex-bot 3821d9ed58
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 14s
refactor: group canonical specs by domain and archive account-top-positions (#74)
2026-11-02 21:50:49 +03:00

30 KiB
Raw Blame History

QA Analysis

Ревизия спеков: G2 approved (comment 3082). Источник ожидаемого поведения — только Delta Specs portfolio-concentration (28 ADDED, ниже PC) и portfolio-view (2 MODIFIED + 2 ADDED, ниже PVΔ) этого change. Design пишется параллельно; на его внутреннее устройство не опираемся. Case пишется только там, где нужны данные, шаги или oracle сверх Scenario; остальные строки Coverage Matrix ссылаются на Scenarios. Написанные cases — в analysis/test-cases/{conc,meta,reg}.md.

Risk Assessment

Риск Затронутые требования Вероятность Ущерб Глубина проверки
Неверная классификация исхода получения (NOT_FOUND vs иная ошибка) ломает 24h-отсчёт и last-known «Результат получения сектора и эмитента», F02–F05 Высокая (клиент AS-IS отображает NOT_FOUND как Unavailable — failure-model:75) Средний: группы «не указан» вместо значений Интеграционные проверки всех 4 строк таблицы исходов + exploratory Q-F3
Доли/суммы считаются от неверной базы (Cash Balance, нули, другие валюты, отрицательные) PC:129, PC:144, PC:289 Средняя Высокий: недоверие владельца к цифрам Компонентные проверки с числовыми оракулами из сценариев
Потеря/порча финансового Snapshot из-за обогащения (token, публикация, границы подключения) «Свежесть и fallback полного Portfolio Snapshot», F08–F11 Низкая Критический: потеря данных портфеля Интеграционные: token-отказ, гонка публикации, смена подключения; регрессия обхода
Ошибка округления/формата долей (,0, < 0,1 %, половина вверх) PC:304, PC:324 Средняя Низкий Компонентные с точными строками-эталонами
Ухудшение существующей вкладки «Позиций» / структуры портфеля PC:9, регрессия Средняя Высокий Регрессионный прогон (TC-REG)
Доступность диаграммы только цветом / недоступна скринридеру PC:443 Средняя Средний Ручная проверка + текстовый эквивалент в component
Квоты T-Bank при суточном обходе (до U + A вызовов) F07, Q-F3 Неизвестная Средний: деградация синхронизации Exploratory Q-F3 на тестовом токене; norm от квот не зависит

Coverage Matrix

Уровни: unit / integration (backend, configured HTTP tests) / component (frontend) / e2e / manual. Ссылки на сценарии — PC:<строка> / PVΔ:<строка> файлов спек.

Requirement Сценарии / ветви Проверка / ожидаемое наблюдение Уровень Test cases
PC:9 Вкладка «Концентрация» страницы счёта 2 сценария (есть вкладка; «Все счета» — нет) + инвариант «прочие вкладки не меняются» Вкладка рядом с «Позициями»; в «Всех счетах» отсутствует; дефолтная вкладка прежняя e2e Scenario «Вкладка на странице одного счёта», «Режим “Все счета”»; TC-REG-001
PC:20 Вкладка в состояниях страницы загрузка/ошибка/пусто/только Cash Balance Вкладки нет при загрузке, ошибке и пустом Portfolio; есть при любом Cash Balance component + e2e TC-CONC-002 + Scenario «Загрузка и ошибка»
PC:37 Переключение разрезов 4 разреза, один одновременно, порядок Показан ровно один разрез, переключатели в заданном порядке component Scenario «Открытие вкладки», «Переключение разреза»
PC:49 Начальное состояние вкладки новый заход/reload → «Акции»+первая валюта; вкладки страницы → сохранение Reset при новом заходе и смене счёта, persist при переключении вкладок e2e TC-CONC-005, TC-CONC-006
PC:69 Состав разрезов 3 сценария (сектор объединяет; эмитент stock+bond без фонда; фонд вне акций/облигаций) Агрегация и исключение типов по таблице component TC-CONC-007
PC:96 Названия элементов без name → ticker; issuer.name; разные issuer.id не сливаются Название по цепочке name→ticker→FIGI; раздельные элементы при равных именах component TC-CONC-008
PC:114 Название эмитента при разных названиях бренда наибольшее currentValue; равные → меньший по алфавиту Элемент назван по большей позиции; при равенстве — «Сбер» < «Сбербанк» component Scenario «Название по наибольшей позиции», «Равные наибольшие значения»
PC:129 Позиции, учитываемые в разрезе положительные; 0 — не учитывается и не неучтённая; null/отрицательные исключены Сумма разреза только из положительных позиций выбранной валюты component Scenario «Отрицательная и неоценённая позиции», «Позиция с нулевой стоимостью»
PC:144 Сноска о не учтённых позициях N: null в любой валюте + отрицательные в выбранной; 0 → нет сноски Точный N по правилу; сценарии 149–167 покрывают все ветви component Scenario «Сноска с числом позиций», «Неоценённая позиция при смене валюты», «Отрицательная позиция другой валюты», «Нет неучтённых позиций»
PC:169 Одна валюта за раз смена валюты пересчитывает; сохраняется между разрезами; нет конвертации Значения только в выбранной валюте, без смешанного итога component Scenario «Смена валюты», «Валюта сохраняется при смене разреза»
PC:184 Доступные валюты вкладки STOCK/BOND/FUND ненулевые, включая отрицательные; 0 исключён; Select скрыт при ≤1; сортировка ISO Список и сортировка точны; скрытие Select; пустое состояние без выбора component Scenario «Начальная валюта», «Единственная валюта», «Валюта только у позиции с нулевой стоимостью», «Валюта только у отрицательной позиции», «Нет оценённых позиций»
PC:214 Независимый выбор валюты вкладки независимость от «Структуры портфеля»; пропавшая валюта → первая списка Валюта вкладки не меняется от внешнего Select; fallback при исчезновении component + e2e TC-CONC-015
PC:229 Топ-5 и строка «Прочее» ≤6 строк без «Прочее» (5, 6, <5); ≥7 → топ-5 + «Прочее» с числом элементов Границы 5/6/7 и формулировка числа элементов («2 элемента», «5 элементов») component TC-CONC-016
PC:254 Раскрытие строки «Прочее» раскрытие/сворачивание (мышь и клавиатура); не меняет топ-5 и диаграмму; свёрнуто при показе/смене валюты Список остальных в порядке ранжирования; инвариант неизменности топ-5 component + e2e Scenario «Раскрытие “Прочее”», «Повторное нажатие», «Смена валюты сворачивает “Прочее”»; клавиатура — TC-CONC-027
PC:274 Порядок элементов с равной суммой цифры < латиница < кириллица, без регистра; граница 5-й строки Порядок «VK», «X5», «Сбер»; «Альфа» в топ-5 при равенстве component Scenario «Равные суммы на границе пятой строки», «Цифры, латиница и кириллица при равных суммах»
PC:289 Расчёт долей точные доли суммируются в 100 %; доля «Прочее» = сумма долей элементов; Cash Balance вне Числовые оракулы сценариев 294–302 component Scenario «Доля без денежных остатков», «Доля “Прочее”»; числовой прогон — TC-CONC-007
PC:304 Показ долей округление до десятых, половина вверх, без «,0», «< 0,1 %», сумма ≠ 100 % допустима Строки-эталоны «93,8 %», «6,3 %», «< 0,1 %», 100,1 % в сумме component TC-CONC-020 (все три ветви: середина вверх, «< 0,1 %», без «,0», сумма ≠ 100 %)
PC:324 Суммарная доля топ-5 показ при ≥6, скрыта при ≤5 (7/6/5/1 элементы) «Топ-5 · N %» только при ≥6; значения 95 %, 96 % component Ветви покрыты TC-CONC-016 (наборы 1–4)
PC:349 Группы «Сектор/Эмитент не указан» группа ранжируется наравне, попадает в «Прочее», имя видно Сценарии 354–362 component Scenario «Позиции без эмитента в топе», «Группа без сектора в “Прочее”»
PC:364 Подписи секторов известные — русская подпись, неизвестные — как получено; нет своей классификации Неизвестный код показан буквально component Scenario «Неизвестное значение сектора»
PC:374 Русские подписи известных секторов 11 значений таблицы, включая government Каждое значение → своя подпись (таблица — эталон) component TC-CONC-024
PC:402 Диаграмма распределения разреза 6 сегментов при ≤6; 5+«Прочее» при ≥7; одинаково при раскрытии; нет при пустом разрезе Число сегментов и доли совпадают со списком component + manual Scenario «Семь элементов», «Ровно шесть элементов» (обе диаграммные нормы); визуальный блок — TC-CONC-027
PC:415 Центр диаграммы сумма точная; «Топ-5 · N %» при метрике; текстовый эквивалент Центр: «95 %» + «1 000 ₽» / только сумма при ≤5 component + manual Scenario «Семь элементов», «Ровно шесть элементов» (обе диаграммные нормы); визуальный блок — TC-CONC-027
PC:430 Строки без переходов клик по строке — нет навигации; эмитенты без логотипов URL не меняется; нет <img> логотипов e2e Scenario «Нажатие на строку акции», «Строка эмитента»
PC:443 Доступность диаграммы без цвета текстовый эквивалент, сопоставимость сегментов без цвета Скринридер читает название/сумму/долю каждого сегмента manual + component TC-CONC-027
PC:451 Пустое состояние разреза пустой разрез: заголовок + валюта, без списка/диаграммы; сноска и выбор сохраняются Сценарий «Валюта только у отрицательной позиции» component Scenario «Валюта только у отрицательной позиции» (пустое состояние)
PC:464 Предупреждение о неполных данных неполнота meta → одно «Данные неполные» на вкладке, без дублирования на странице; неоценённые позиции не вызывают Одно сообщение; доли по доступным данным component + e2e Scenario «Неполный Portfolio», «Предупреждение не дублируется»
PC:484 Состояния Portfolio на вкладке соответствие «Состояниям и ошибкам Portfolio на клиенте» isStale/загрузка/ошибка отображаются как на «Позициях» component Scenario «Состояния Portfolio на вкладке “Концентрация”»; сверка с canonical — существующий regression-прогон frontend
«Нормализованный состав Portfolio» (MODIFIED) sector/issuer nullable; обрезка пробелов; только пробелы = отсутствие; sector только у STOCK/BOND/FUND; issuer.id+name; запрет эмитента по названию Поля по правилам; сценарии 30–60 delta; GET-контракт не сломан integration (configured HTTP tests) PVΔ Scenario «Сектор инструмента доступен/отсутствует», «Эмитент позиции доступен/отсутствует», «Эмитент не определяется по названию», «Недоступность сектора и эмитента не нарушает Snapshot»; обратная совместимость GET — существующий contract-прогон
«Свежесть и fallback полного Portfolio Snapshot» (MODIFIED) исключение: token-отказ при sector/brand = 400 INVALID_TBANK_TOKEN; сектор/бренд — last-known, обновление по «Обновление сектора и эмитента»; GET не ждёт T-Bank Fallback не маскирует token-отказ; хранимые sector/brand читаются локально integration TC-META-002; существующий backend contract-прогон
«Обновление сектора и эмитента» (ADDED) первый обход ≥24 ч после успеха; интервал из hourly-investment-sync; «не найдено» тоже успех Сценарии 149–152: значение обновляется в первый обход после 24 ч integration TC-META-003
«Результат получения сектора и эмитента» (ADDED) 4 строки таблицы: значение / нет значения / другой инструмент / иная ошибка; каждая — поле + отсчёт 24 ч Каждая строка: точное поле и отсчёт (сценарии 170–202, включая перезапуск отсчёта от «не найдено») integration TC-META-004

Negative and Boundary Focus

  • Границы элементов: 1 / 5 / 6 / 7 (строки и метрика топ-5) — TC-CONC-016.
  • Границы стоимости: 0 (исключена и не в N), отрицательная (в N только своей валюты), null (в N в любой валюте), крайне малая доля «< 0,1 %» — Scenario «Отрицательная и неоценённая»/«Нулевая стоимость»/«Сноска о не учтённых позициях», TC-CONC-020.
  • Округление: точная половина вверх (6,25 → «6,3»), сумма показанных ≠ 100 % — TC-CONC-020.
  • Валютные границы: единственная валюта (Select скрыт), валюта только отрицательной позиции (есть в выборе, разрез пуст), валюта пропала после обновления — Scenario «Доступные валюты вкладки», TC-CONC-015.
  • Тайбрейки: равные суммы (цифры/латиница/кириллица), граница 5-й строки, равные currentValue у одного issuer.id, одинаковые issuer.name при разных id — Scenario «Порядок элементов с равной суммой»/«Название эмитента при разных названиях», TC-CONC-008.
  • 24h-отсчёт: успех → сброс; «не найдено» → сброс; иной инструмент / иная ошибка → без сброса, повтор каждый обход; систематический сбой дольше 24 ч — TC-META-003/004.
  • Запрещённые эффекты: GET не запускает T-Bank, sector/brand не освежают Snapshot, enrichment не отменяет финансовый успех, «Прочее»-раскрытие не меняет топ-5 и диаграмму, строка не ведёт на другую страницу — TC-META-002, Scenario «Раскрытие “Прочее”», «Нажатие на строку акции».

Cross-system Verification

T-Bank → sync → хранилище → GET → frontend. Каждый F-сценарий failure-model:

ID Проверка Test cases
F01 Финансовый отказ не замещается успехом sector/brand; прежний Snapshot TC-META-002, TC-REG-004
F02 Иная ошибка: прежнее значение/null, отсчёт не меняется TC-META-004
F03 Сбой любого звена цепочки инструмента → бренда — как F02; поля независимы TC-META-004
F04 «Не найдено»/пусто/пробелы → null + сброс отсчёта TC-META-004 + PVΔ Scenario «Ответ без значения заменяет известное значение»
F05 Чужой UID/asset_uid → прежнее значение, повтор TC-META-004
F06 Частичное обогащение: Snapshot публикуется целиком, группы наравне PVΔ Scenario «Недоступность сектора и эмитента не нарушает Snapshot», Scenario «Позиции без эмитента в топе»
F07 RESOURCE_EXHAUSTED → как F02 после повторов клиента; (квоты — Q-F3) TC-META-004
F08 Token-отказ при sector/brand → 400 INVALID_TBANK_TOKEN, без fallback TC-META-002, TC-REG-004
F09 Отказ публикации: нет ложного lastSuccessfulAt TC-META-002
F10 Отказ сохранения sector/brand: поле и отсчёт прежние, финансовый успех цел TC-META-003
F11 Смена/удаление подключения: 404/409/400, sector/brand не переходят в новое TC-META-005, TC-REG-004
F12 Ошибка HTTP-чтения на клиенте: вкладка скрыта, данные не теряются TC-CONC-002
F13 Старый JSON без sector/issuer → null, группы «не указан» PVΔ Scenario «Недоступность сектора и эмитента не нарушает Snapshot», Scenario «Позиции без эмитента в топе»
F14 Время sector/brand не освежает Snapshot; неполное meta — одно сообщение TC-META-002; Scenario «Неполный Portfolio»
F15 Пустой разрез: нет NaN и фиктивных 100 % Scenario «Валюта только у отрицательной позиции»
F16 Сбой дольше 24 ч: значение остаётся, повтор каждый обход TC-META-003

Инварианты data-mapping: сумма разреза = сумма учитываемых позиций; доли в сумме ровно 100 % (точные); отсутствие подстановки нуля вместо null — точные доли Scenario «Расчёт долей» и прогоны TC-CONC-007/016.

Test Data and Environment Needs

  • Портфель (мультивалютный, ≥10 позиций): акции ≥7 (для «Прочее»), ровно 6 и 5 вариантов; облигации; ≥2 фонда; позиция CURRENCY; FUTURE/OTHER для исключения. Валюты: RUB + USD (два Select-варианта), одиночный RUB-вариант отдельным набором.
  • Стоимости: положительные, 0, отрицательная, null (в т.ч. в невыполненной валюте); 1 RUB против 100 000 000 RUB («< 0,1 %»); пары с равными суммами (граница топ-5).
  • Бренды: один issuer.id с разными issuer.name и разными суммами; равные суммы; два issuer.id с одинаковым issuer.name; акции + облигации одного бренда; позиции без бренда (группа «Эмитент не указан»).
  • Секторы: каждый из 11 кодов таблицы PC:374 (минимум it, government, energy), неизвестный код (other), пустой/пробельный, отсутствующий; один сектор у разных типов (STOCK+BOND+FUND); ≥6 секторов для «Прочее» в «Секторах».
  • Upstream-моки (integration): ответы T-Bank для всех 4 исходов таблицы «Результат получения сектора и эмитента» (значение / «не найдено» NOT_FOUND и пустой объект / чужой UID / UNAVAILABLE-timeout / PERMISSION_DENIED-token), частичный ответ, отказ публикации; meta неполноты.
  • Окружение: локальное backend + frontend с тестовым T-Bank-подключением; для Q-D1/Q-D2/Q-F3 — read-only доступ к реальному токену владельца.

Manual / Exploratory Scope

  • Соответствие макетам ux-design v2 (visuals/): кольцевая диаграмма, центр, бары строк, «Прочее», предупреждение — по всем четырём разрезам.
  • Контраст тёмной/светлой темы: сегменты, подписи, «< 0,1 %», сноска.
  • Клавиатура: Tab по переключателям разрезов, строкам и «Прочее»; Enter/Space раскрытие (PC:254), видимый focus, отсутствие «клик-ловушек».
  • Скринридер (VoiceOver/NVDA): текстовый эквивалент диаграммы — название, сумма, доля каждого сегмента в порядке списка; центр; сопоставление сегмент↔строка без цвета (PC:443).
  • Русская локаль чисел: неразрывный пробел, ₽/$, запятая в долях.
  • Exploratory: поведение при переключении счёта, глубоких ссылок на вкладку (если есть), медленной сети при раскрытии «Прочее».

Automation Candidates

  • Компонентный вычислитель разреза (состав, ранжирование, тайбрейки, доли, границы 5/6/7, формат долей) — чистая функция от Portfolio: детерминированные оракулы из сценариев, максимум ценности на единицу поддержки.
  • Интеграционные проверки таблицы исходов «Результат получения сектора и эмитента» и 24h-логики (управляемое время) — регрессионно-критичны, зависят от классификации ошибок клиента.
  • e2e smoke: вкладка есть/нет, reset/persist состояния, отсутствие навигации по строкам, одно «Данные неполные».

Regression Impact

Область Риск Проверка
Вкладка «Позиции» существующего счёта Вкладки/состояния страницы изменены TC-REG-001: прежний дефолт, состав и порядок вкладок
PortfolioStructure («Структура портфеля») Общий выбор валюты «протекает» на вкладку TC-CONC-015; существующий regression-прогон PortfolioStructure
GET-контракт Portfolio Новые поля sector/issuer ломают клиентов; старый JSON Существующий backend contract-прогон (OpenAPI); обратная совместимость ответа
Часовой обход hourly-investment-sync Новые вызовы сектора/бренда меняют нагрузку и успех обхода TC-REG-004: успех/причины обхода без sector/brand-сбоев; F07/F11
Инвалидация token Новое ветвление token-отказа TC-META-002/005: 400 INVALID_TBANK_TOKEN во всех точках, замена/удаление подключения — 404/409

Entry / Exit Criteria

Вход: G2 approved (есть); design готов или проверка не зависит от него (component- вычислитель и integration по спекам можно начинать); тестовые данные раздела выше доступны. Выход: все строки Coverage Matrix зелёные либо явные not verified ниже; все F01–F16 покрыты; регрессия TC-REG-001/004 и существующие contract/regression-прогоны пройдены; ручной блок (макеты, контраст, клавиатура, скринридер) зафиксирован; findings по Q-D1/Q-D2/Q-F3 записаны.

Gaps / Blockers

  • not verified: соответствие квотам T-Bank при суточном обходе — риск деградации синхронизации; закрывается Q-F3 (измерение на реальном токене), норма исходов от результата не зависит.
  • not verified (до реализации): фактический вид «не найдено» у EtfBy/BondBy/GetAssetBy (Q-F3) — до подтверждения классификация NOT_FOUND в проверках задаётся моком по proto; расхождение с реальностью выявит Q-F3-проверка.
  • Открытый data-fact: Q-D1 (покрытие brand-пары) и Q-D2 (реальные sector фондов и госбумаг) — одноразовые read-only проверки на реальном Portfolio владельца; влияют на ожидаемый вид разрезов, не на нормы. Результат фиксируется в QA-отчёте change.
  • Пробелов в Specs, блокирующих проверку, нет (после G2 approved).