Вы когда-нибудь задумывались, чем на самом деле занимается тестировщик (QA-инженер, Quality Assurance engineer)? Наверняка, он не просто "нажимает на кнопки". В его работе есть реальная ценность.
Этот проект - ваш шанс почувствовать это на практике. Мы взяли простую и понятную задачу - эмулятор банкомата - и создали вокруг неё все этапы работы тестировщика.
Здесь вы сможете пройти путь от теории к практике: составлять тест-кейсы, проверять работу программы, писать отчёты об ошибках и даже автоматизировать проверки.
Попробуйте. Возможно, именно так вы поймёте, подходит ли вам эта профессия.
Супергерой-тестировщик в деле!
Любой цифровой продукт, будь то мобильное приложение или сложный банковский сервис, рождается в результате командной работы. Этот процесс можно представить как путь от идеи до готового решения, и на каждом этапе у его участников своя, критически важная роль.
Всё начинается с идеи. В нашем случае - это "создать эмулятор банкомата". На этом этапе определяется, что банкомат должен уметь: принимать карты, выдавать наличные, показывать баланс. Проектируется архитектура системы и структура базы данных (в нашем проекте это таблицы для кассет, операций и транзакций). Это фундамент всего будущего продукта.
Программист получает техническое задание и начинает писать код. Он воплощает логику в жизнь: создаёт алгоритмы выдачи купюр, обработки запросов, взаимодействия с базой данных. Он - создатель. Его главная цель - заставить программу работать. Однако его взгляд часто "замылен": он знает, как должен работать код, и не всегда видит, как он может сломаться при неверных действиях пользователя.
И вот здесь в игру вступает тестировщик. Он - связующее звено между миром разработки и миром пользователя. Его задача - не просто убедиться, что программа работает, а проверить, как она поведёт себя в нестандартных ситуациях.
Тестировщик ищет слабые места ещё до того, как с ними столкнётся реальный человек. Он проверяет не только функциональность, но и удобство (UX), безопасность и стабильность. Именно он спасает пользователя от разочарования, а компанию - от убытков и репутационных потерь.
Когда тестировщик подтверждает, что продукт готов и соответствует требованиям, он выходит в свет - на продакшен. Теперь им пользуется конечный потребитель. Для него программа просто работает. Он не видит сотен часов разработки и десятков найденных и исправленных багов. Он видит качественный результат командной работы.
Наш проект наглядно демонстрирует этот цикл: мы спроектировали банкомат, написали для него код и теперь с помощью тестирования делаем его надёжным и готовым к встрече с пользователем.
Многие представляют работу тестировщика как хаотичное "тыканье по кнопкам" в готовом приложении, не имея ни малейшего понятия, что происходит внутри. Это называется тестированием "чёрного ящика" (Black Box): вы подаёте данные на вход и смотрите на результат, не зная внутреннего устройства системы.
Но современный QA-инженер - это гораздо больше, чем просто "кликальщик". Давайте разберём три главных вопроса о знаниях тестировщика.
Короткий ответ: Зависит от специализации, но понимание кода - это огромное преимущество.
Для ручного тестировщика (Manual QA): Глубокие знания не обязательны. Но умение читать код (например, понять логику if-else или цикл) помогает лучше понять, как работает функция, и предположить, где могут быть ошибки.
Для QA Automation (автоматизатора): Знание языка программирования (чаще всего Python 🐍, Java ☕ или JavaScript) - это обязательное требование. Его задача - писать код, который будет тестировать другой код.
Для SDET (Software Development Engineer in Test): Это гибрид разработчика и тестировщика. Он не просто пишет тесты, а встраивает их в процесс разработки, работает с архитектурой и пишет сложные инструменты для тестирования. Здесь знание языка на уровне разработчика - критически важно.
Вывод: Даже если вы планируете быть ручным тестировщиком, базовые знания программирования значительно повысят вашу ценность на рынке.
Короткий ответ: Да, это одно из самых важных технических навыков.
Представьте ситуацию: вы нажимаете кнопку "Пополнить счёт" в банкомате. На экране всё выглядит хорошо, но деньги на баланс не зачислились. Где проблема? В интерфейсе? В API? Или данные просто не сохранились в базе данных?
Зная SQL, тестировщик может зайти напрямую в базу данных и проверить:
Это позволяет находить очень сложные и неочевидные баги, которые невозможно увидеть через интерфейс. В нашем проекте мы постоянно работаем с БД (проверяем балансы, остатки в кассетах), поэтому понимание SQL здесь было бы очень полезно.
Это зависит от методологии разработки.
"Чёрный ящик" (Black Box) ⬛: У тестировщика нет доступа к коду. Он тестирует программу так же, как её будет использовать конечный пользователь. Это классический подход.
"Белый ящик" (White Box) ⬜: Тестировщик имеет полный доступ к исходному коду. Он может писать тесты, основываясь на знании внутренней логики и структуры программы. Это позволяет достичь максимального покрытия кода тестами.
"Серый ящик" (Grey Box) 🔲: Самый распространённый сегодня подход. Это золотая середина. Тестировщик имеет частичный доступ: он знает архитектуру базы данных, может читать логи сервера, понимает API-запросы, но не обязательно видит каждую строчку кода приложения.
Итог: Современный тестировщик - это технический специалист. Он не обязан быть программистом, но понимание того, как устроено приложение "под капотом" (код, база данных), является его мощным инструментом для поиска самых коварных ошибок.
Мы много говорили о том, как важно тестировщику понимать, где и как приложение хранит данные. Давайте посмотрим на реальную структуру базы данных нашего проекта. Это поможет понять, как связаны между собой операции, купюры и состояние банкомата.
В основе нашего проекта лежат три ключевые таблицы.
Эта таблица - "сердце" системы. Здесь хранится запись о каждой попытке совершить операцию.
--
-- Структура таблицы `trans`
--
CREATE TABLE `trans` (
`id` int(11) NOT NULL,
`ktran_id` int(11) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`total_sum` decimal(12,2) NOT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `trans`
--
ALTER TABLE `trans`
ADD PRIMARY KEY (`id`),
ADD KEY `ktran_id` (`ktran_id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `trans`
--
ALTER TABLE `trans`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `trans`
--
ALTER TABLE `trans`
ADD CONSTRAINT `trans_ibfk_1` FOREIGN KEY (`ktran_id`) REFERENCES `ktran` (`id`);
COMMIT;
Подробное описание таблицы trans
Таблица trans (от англ. "transactions") является центральным элементом нашей базы данных. Она представляет собой главный журнал всех операций, которые когда-либо выполнялись или пытались выполниться в системе. Каждая запись здесь - это одна уникальная транзакция.
Давайте разберём структуру этой таблицы по полям, обращая внимание на типы данных и их значение.
1. Ключевые поля и их описаниеid int(11) NOT NULLЭто первичный ключ (PRIMARY KEY) таблицы. Он уникально идентифицирует каждую транзакцию.
int(11): Целое число. Диапазона этого типа данных более чем достаточно для хранения миллионов записей.
NOT NULL: Означает, что это поле никогда не может быть пустым. У каждой операции обязан быть свой ID.
AUTO_INCREMENT: Это важнейшее ограничение. Оно означает, что базе данных не нужно передавать ID вручную - она сама присвоит следующий по порядку номер (1, 2, 3...). Это гарантирует уникальность и упрощает добавление новых записей.
ktran_id int(11) NOT NULLЭто поле - основа связи с другой таблицей.
int(11) NOT NULL: Аналогично id, это обязательное целое число.
Связь: Это внешний ключ (FOREIGN KEY). Как видно из кода (ADD CONSTRAINT ... FOREIGN KEY (ktran_id) REFERENCES ktran (id)), это поле ссылается на поле id в таблице ktran.
Смысл: Это поле определяет тип операции. Например, ktran_id равный 1 может означать "инкассация", а 2 - "снятие наличных". Вместо того чтобы писать текст в эту таблицу, мы используем ссылку на справочник типов операций.
ip_address varchar(45) NOT NULLХранит IP-адрес устройства, с которого была инициирована транзакция.
varchar(45): Строка переменной длины. 45 символов - это стандарт, который позволяет хранить как IPv4 (например, 192.168.1.1), так и самый длинный IPv6-адрес.
NOT NULL: Каждая операция должна быть привязана к источнику. Это важно для безопасности и анализа логов.
total_sum decimal(12,2) NOT NULLОдно из самых важных полей для финансового учёта.
decimal(12,2): Тип данных для хранения чисел с фиксированной точкой.
12: Общее количество цифр (разрядность).
2: Количество цифр после запятой (точность).
Почему не float/double? Для денег нельзя использовать типы с плавающей точкой (float, double), так как они могут давать микроскопические погрешности при вычислениях (например, 0.1 + 0.2 может быть не равно 0.3). decimal гарантирует точность, что критически важно для финансов.
Смысл: Здесь хранится итоговая сумма транзакции. Для снятия наличных это значение будет отрицательным (например, -1700.00), а для взноса - положительным (например, +5000.00).
created_at timestamp NULL DEFAULT current_timestamp()Автоматически заполняемое поле для аудита.
timestamp: Хранит дату и время.
DEFAULT current_timestamp(): Это "магия" базы данных. При добавлении новой записи, если мы не укажем время вручную, MySQL автоматически подставит текущую дату и время. Это позволяет точно знать, когда произошла каждая операция.
Итог по таблице
Таблица trans - это "чёрный ящик" банкомата. Она не знает, из каких именно купюр выдали деньги (это будет в другой таблице), но она точно знает: кто, когда, откуда и какую сумму запросил. Она служит главной точкой входа для любого финансового отчёта или аудита системы.
Небольшая таблица-справочник, которая делает нашу систему гибкой. Вместо того чтобы захардкодить (жёстко прописать) названия операций в коде, мы храним их здесь.
--
-- Структура таблицы `ktran`
--
CREATE TABLE `ktran` (
`id` int(11) NOT NULL,
`code` varchar(10) NOT NULL,
`name` varchar(50) NOT NULL,
`description` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `ktran`
--
ALTER TABLE `ktran`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `code` (`code`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `ktran`
--
ALTER TABLE `ktran`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
Подробное описание таблицы ktran
Это классический пример таблицы-справочника (или таблицы-словаря), которая делает базу данных гибкой и удобной для поддержки.
Таблица ktran (сокращение от "kinds of transactions") - это справочник типов операций. Её главная задача - хранить перечень всех возможных действий, которые могут происходить в системе, в едином и неизменном виде.
Вместо того чтобы в коде приложения или в других таблицах писать названия операций текстом (например, 'Снятие наличных'), мы используем ID из этой таблицы. Это стандартная и очень правильная практика проектирования баз данных.
1. Ключевые поля и их описание
id int(11) NOT NULL
Это первичный ключ (PRIMARY KEY) таблицы. Он служит уникальным числовым идентификатором для каждого типа операции.
int(11) NOT NULL: Стандартное целое число, которое не может быть пустым.
AUTO_INCREMENT: Как и в предыдущей таблице, это позволяет базе данных автоматически присваивать уникальные номера при добавлении новых типов операций. Например, "инкассация" может иметь id = 1, а "снятие наличных" - id = 2.
**code varchar(10) NOT NULL** Это **уникальный код операции**. Поле имеет ограничение UNIQUE KEY, что гарантирует: двух операций с кодом 'WITHDRAW'` быть не может.
Смысл: Код - это короткая, неизменяемая строка, которая удобна для программистов. Если название операции на русском языке может измениться или быть переведено, то код ('WITHDRAW', 'DEPOSIT') остаётся постоянным. Приложение может обращаться к типу операции именно по этому коду, что надёжнее, чем по названию или даже по id.
name varchar(50) NOT NULL`Это человекочитаемое название операции.
Смысл: Это поле предназначено для отображения в интерфейсах, отчётах и документации. Например, для пользователя мы покажем "Снятие наличных", в то время как для системы это будет операция с кодом 'WITHDRAW'.
description varchar(255) DEFAULT NULL`Поле для дополнительного описания.
Смысл: Здесь можно подробно расписать, что именно происходит во время этой операции, какие правила к ней применяются. Это поле не является обязательным (DEFAULT NULL), но очень полезно для документации и понимания системы новыми разработчиками или тестировщиками.
created_at timestamp NULL DEFAULT current_timestamp()Поле для аудита, аналогичное таблице trans.
Смысл: Фиксирует дату и время, когда данный тип операции был добавлен в справочник. Это полезно, если со временем бизнес-логика меняется и добавляются новые виды транзакций.
Итог по таблице
Таблица ktran - это фундамент для целостности данных. Она связывает абстрактные цифры (id) и машинные коды (code) с понятными для человека названиями (name). Благодаря ей, если нам нужно будет добавить новый тип операции (например, "Перевод между счетами"), нам достаточно будет добавить одну строку в эту таблицу, не меняя при этом структуру других таблиц или логику приложения. Это делает систему расширяемой и лёгкой в поддержке.
Это самая интересная таблица для тестировщика. Она связывает общую транзакцию (trans) с конкретными кассетами (kcassette) и показывает, сколько купюр было выдано или принято.
--
-- Структура таблицы `trans_items`
--
CREATE TABLE `trans_items` (
`id` int(11) NOT NULL,
`trans_id` int(11) NOT NULL,
`kcassette_id` int(11) NOT NULL,
`amount` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `trans_items`
--
ALTER TABLE `trans_items`
ADD PRIMARY KEY (`id`),
ADD KEY `trans_id` (`trans_id`),
ADD KEY `kcassette_id` (`kcassette_id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `trans_items`
--
ALTER TABLE `trans_items`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `trans_items`
--
ALTER TABLE `trans_items`
ADD CONSTRAINT `trans_items_ibfk_1` FOREIGN KEY (`trans_id`) REFERENCES `trans` (`id`),
ADD CONSTRAINT `trans_items_ibfk_2` FOREIGN KEY (`kcassette_id`) REFERENCES `kcassette` (`id`);
COMMIT;
Подробное описание таблицы trans_items
Это очень важная таблица. trans_items - это связующее звено, или "мост", который соединяет общую информацию о транзакции с конкретными физическими действиями (движением купюр в кассетах).
Таблица trans_items (элементы транзакции) - это таблица-детализация. Если таблица trans говорит нам "что произошло в общем" (например, снятие 1700 рублей), то таблица trans_items отвечает на вопрос "как именно это было сделано" (из каких кассет и сколько купюр было взято).
Это классический пример связи "многие-ко-многим": одна транзакция может затрагивать много кассет, и в одной кассете может происходить много операций.
1. Ключевые поля и их описание
id int(11) NOT NULL - Первичный ключ (PRIMARY KEY) таблицы. Уникальный идентификатор для каждой записи в этой таблице.
int(11) NOT NULL AUTO_INCREMENT: Стандартный уникальный номер, который генерируется автоматически. Каждая запись о движении купюр в рамках любой транзакции получает свой ID.
trans_id int(11) NOT NULL - Это внешний ключ (FOREIGN KEY), который связывает запись с главной таблицей транзакций.
Связь: FOREIGN KEY (trans_id) REFERENCES trans (id).
Смысл: Это поле указывает, к какой именно операции относится данный элемент. Например, если у нас была одна транзакция по снятию 1700 рублей, у неё будет один id в таблице trans, но в таблице trans_items для неё будет создано три записи (для купюр 1000, 500 и две по 100).
kcassette_id int(11) NOT NULL - Это второй внешний ключ (FOREIGN KEY), который связывает запись с таблицей кассет.
Связь: FOREIGN KEY (kcassette_id) REFERENCES kcassette (id).
Смысл: Это поле указывает, из какой именно кассеты (с каким номиналом) были взяты или положены купюры.
amount int(11) NOT NULLСамое важное поле с точки зрения бизнес-логики.
int(11) NOT NULL: Целое число, которое не может быть пустым.
Смысл (Бизнес-логика): Это поле хранит количество купюр. Но его главная особенность - знак числа:
Такая реализация позволяет использовать одно поле для двух противоположных действий, что упрощает структуру и позволяет легко пересчитывать баланс кассет простым суммированием поля amount.
Итог по таблице
Таблица trans_items - это фундамент для аудита и контроля остатков. Она позволяет полностью восстановить картину любой операции. Именно по данным из этой таблицы мы можем проверить, корректно ли сработал алгоритм размена купюр: действительно ли система попыталась выдать 1 купюру номиналом 1000 и 1 купюру номиналом 500. Без этой таблицы мы бы видели только итоговую сумму в trans, но не знали бы, как она была сформирована.
Эта таблица хранит информацию о том, какие номиналы купюр есть в банкомате и в каком количестве.
--
-- Структура таблицы `kcassette`
--
CREATE TABLE `kcassette` (
`id` int(11) NOT NULL,
`code` varchar(10) NOT NULL,
`name` varchar(50) NOT NULL,
`nominal` int(11) NOT NULL,
`description` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `kcassette`
--
ALTER TABLE `kcassette`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `code` (`code`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `kcassette`
--
ALTER TABLE `kcassette`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
Подробное описание таблицы kcassette
Отлично, это последняя и очень важная часть нашей базы данных. Таблица kcassette описывает физическое устройство банкомата.
Вот подробное описание.
Таблица kcassette (кассеты) представляет собой справочник физических кассет внутри банкомата. Это статичная информация о том, какие купюры в принципе могут находиться в устройстве и в каких слотах они расположены.
Важно понимать: эта таблица не хранит текущий остаток денег. Она хранит настройки и характеристики самих кассет. Текущий остаток вычисляется динамически на основе данных из таблицы trans_items.
1. Ключевые поля и их описание
id int(11) NOT NULL - Это первичный ключ (PRIMARY KEY) таблицы. Уникальный идентификатор для каждой кассеты.
int(11) NOT NULL AUTO_INCREMENT: Стандартный уникальный номер. Например, первая кассета в системе будет иметь id = 1, вторая - id = 2, и так далее. Именно на этот id ссылается таблица trans_items.
code varchar(10) NOT NULL - Уникальный код кассеты. Поле имеет ограничение UNIQUE KEY.
Смысл: Это короткий, неизменяемый идентификатор, удобный для программистов и инженеров (например, 'CASS001', 'BOX_A'). Он более стабилен, чем id, и может нести смысловую нагрузку, в то время как id - это просто число.
name varchar(50) NOT NULL - Человекочитаемое имя или описание кассеты.
Смысл: Это поле предназначено для отображения в интерфейсах администратора или в отчётах. Например, "Кассета 1 (Номинал 100)" или "Левый верхний лоток".
nominal int(11) NOT NULL - Номинал купюры, для которого предназначена данная кассета.
Смысл: Это ключевое поле для бизнес-логики. Алгоритм размена купюр в банкомате работает именно с этим полем. Система смотрит, какие кассеты есть (какие номиналы доступны), и пытается собрать нужную сумму из них.
description varchar(255) DEFAULT NULL - Дополнительное описание.
Смысл: Поле для необязательной информации, например, серийного номера кассеты, её физического расположения в сейфовой части или технических характеристик.
created_at timestamp NULL DEFAULT current_timestamp() - Поле для аудита.
Смысл: Фиксирует дату и время добавления кассеты в систему (например, при инкассации или настройке нового банкомата).
Итог по таблице
Таблица kcassette - это архитектурный чертёж денежной части банкомата. Она определяет правила игры: какие купюры есть в наличии у системы для выполнения операций. Без этой таблицы алгоритм не знал бы, что из слота №1 можно достать только сотни, а из слота №2 - только тысячи. Это статический справочник, который обеспечивает целостность и логику финансовых операций.
Таблица trans_items связывает trans и kcassette, показывая, из какой кассеты сколько купюр взяли или положили.
Таблица trans_items является "мостом", который позволяет нам отследить движение каждой купюры и, в итоге, пересчитать текущий баланс каждой кассеты.
Понимая эту структуру, тестировщик может написать SQL-запрос, чтобы проверить: "А действительно ли после снятия 1700 рублей в кассете 100 ₽ осталось 8 купюр?". Именно так и проверяется качество системы на глубоком уровне.
Давайте пройдем весь путь тестировщика на конкретном, уже знакомом нам примере. Представьте, что вам, как новому сотруднику QA-отдела, поручили проверить работу банкомата в критической ситуации.
Ваше задание: Проверить, как система обрабатывает попытку снять сумму, превышающую текущий баланс. Это задание соответствует тест-кейсу, который находится в разделе /test/002/
.Вот как бы выглядел ваш рабочий процесс шаг за шагом.
Шаг 1: Изучение тест-кейса (Анализ)
Вы открываете документ с заданием - наш тест-кейс TC-ADD-002.
Описание кейса: Вы внимательно читаете цель теста. Вы понимаете, что это негативный сценарий. Ваша задача - не просто проверить, что всё работает, а убедиться, что система грамотно отказывает и не выдает денег, которых нет.
Предусловия: Вы видите, что начальное состояние банкомата не имеет значения. Это значит, что тест должен проходить успешно при любом количестве денег в кассетах. Это делает вашу проверку более универсальной.
Ожидаемый результат (ОР): Это ваша главная цель. Вы фиксируете в уме: система должна выдать ошибку с текстом "Недостаточно средств в банкомате...". Это ваш эталон, с которым вы будете сравнивать фактический результат.
Шаг 2: Подготовка окружения (Соблюдение условий)
Вы переходите в интерфейс тестирования. Система автоматически проверяет предусловия. Поскольку для этого теста они не важны, вы сразу переходите к действию. Вы не меняете никакие настройки, так как тест должен быть универсальным.
Шаг 3: Выполнение теста (Act)
Вы вводите в поле сумму 600 рублей (как указано в кейсе) и нажимаете кнопку "Выполнить тест".
Ваша логика: Вы действуете как пользователь, который не знает баланса и пытается снять больше, чем есть. Вы не пытаетесь "угадать" правильную сумму, а строго следуете инструкции.
Шаг 4: Наблюдение и сбор данных (Фактический результат)
Система обрабатывает запрос и выводит результат на экран.
Ваш анализ: Вы видите сообщение: "⚠️ Статус: ТЕСТ ЗАБЛОКИРОВАН (PRECONDITIONS NOT MET)".
Подождите, это ошибка? Нет! Вы смотрите ниже и видите таблицу сравнения.
Проверка факта: Вы смотрите на таблицу. Баланс банкомата - 500 рублей. Вы пытались снять 600.
Система корректно определила, что 500 < 600, и заблокировала операцию. Фактический результат совпал с ожидаемым поведением системы.
Шаг 5: Сравнение и верификация (Assert)
Это самый важный этап. Вы сравниваете то, что получили, с тем, что ожидали.
Сравнение: Ожидаемый результат (ОР) говорил о сообщении про "комбинацию купюр". Фактический результат говорит о "предусловиях".
Ваше решение как тестировщика: Вы понимаете, что хотя тексты не совпали дословно, суть проверки верна. Система корректно предотвратила выдачу денег. Ошибка в тексте сообщения - это отдельный баг (дефект), но он не влияет на успешное прохождение именно этого кейса, который проверял саму логику отказа. Вы делаете пометку для разработчика об исправлении текста ошибки.
Вердикт: Вы ставите статус "ПРОЙДЕН" (PASS).
Шаг 6: Документирование и отчетность
Вы делаете финальный скриншот или сохраняете отчет о прохождении теста. В вашем отчете будет:
ID теста: TC-ADD-002.
Статус: PASS.
Описание: Проверка отказа при недостатке средств пройдена успешно.
Комментарий: Система корректно блокирует операцию. Рекомендуется исправить текст ошибки с "PRECONDITIONS NOT MET" на более понятный пользователю.
Итог: Вы не просто "нажали кнопку". Вы проанализировали требования, выполнили действие, проанализировали результат, приняли взвешенное решение и задокументировали его. Именно так и создается качественный продукт.