В статье рассмотрим основные подходы к тестированию бэкенда на PHP, обсудим преимущества и проблемы, связанные с этим процессом. Также узнаем о методах обнаружения и устранения багов, инструментах и книгах для более глубокого изучения тестирования. Материал будет полезен как начинающим тестировщикам, так и разработчикам, которые хотят освоить тестирование бэкенда, но не знают с чего начать. Современные инструменты разработки помогают создавать веб-приложения в кратчайшие сроки. Чтобы быстрее запустить новый продукт или добавить функционал, разработчики часто пренебрегают тестированием. А ведь даже опытные программисты допускают ошибки в своём коде. Мы понимаем, что ошибки в программировании неизбежны, а их исправление — это естественная часть разработки.  Хорошо, когда багов мало, они не критичные и могут подождать. Очень плохо, когда багов выше допустимой нормы и трудно их отловить. Невоспроизводимые баги — это настоящее испытание. Особенно если они вызывают сбой приложения или повреждение данных. Повторяя шаги клиента, не всегда получается легко и быстро обнаружить баг в коде. Что ещё хуже, после исправления ошибка может вернуться, но уже в другой части программы. Ошибку трудно поймать, а иногда вообще сложно определить — да был ли баг-то, может, бага-то и не было? Если не уследить за этим своевременно, последствия могут быть горькими. «Да — что вы озорничаете?» — звучат возмущённые вопросы пользователей, которые снова сталкиваются с неприятной ошибкой. Отмазка «баги есть, но вы держитесь» здесь не поможет. Время на поиск и исправление бага зависит от сложности проекта, его особенностей, качества кода и опыта разработчиков. Именно поэтому тестирование становится жизненно важным. Оно сохранит доверие пользователей и обеспечит высокое качество продукта. Почему не писать код сразу правильно и без ошибок? Вот действительно, почему? Ну, на это есть много причин: Над проектом работала команда с малым опытом. И хотя они создали рабочий проект, но что-то вечно отваливается. В случае стартапа или MVP приоритет уделяется быстрому запуску продукта. На проекте было ограничено количество ресурсов и денег. Даже если есть деньги, времени на тестирование всегда мало. В стремлении быстрее выпустить хотя бы что-то работоспособное и начать получать прибыль, тестированием пренебрегают. Всё зависит от компании и проекта. По классической схеме, программисты — пишут код и делают баги 🙂, а тестировщики эти баги ищут и передают разработчикам для исправления. Вот такой вот круговорот багов в разработке. В небольших компаниях и стартапах, задачи тестирования ложатся целиком на программистов. Они должны проводить code review, обнаруживать опечатки и использовать инструменты тестирования. Без тестирования качество продукта может сильно пострадать и привести к негативным последствиям: повышенные затраты на исправление ошибок, задержки в запуске продукта, недовольные пользователи. В больших командах тестирование и обеспечение качества продукта выполняют целые отделы специалистов. Они занимаются процессом тестирования, включая анализ и планирование, создание сценариев тестирования, составление отчётов и прочее. Для проекта могут выделить QA-инженера, который обычно занимается тестированием и контролем качества продукта на всех этапах. Он проверяет продукт на ошибки, участвует в его выпуске и консультирует разработчиков. Тестирование — это всегда хорошо, у него множество преимуществ: Улучшение клиентского опыта. Тестирование гарантирует надёжную работу продукта с минимальным количеством багов. Без них продукт получает положительные отзывы клиентов, становится популярным и приносит больше прибыли. Выявление багов на ранней стадии. Тестирование помогает выявить ошибки на ранней стадии и устранить до того, как функционал будет доступен пользователям. Защита данных от потери. Тестирование помогает избежать потерю или повреждение данных. Вы получаете уверенность в том, что функционал правильно выполняет работу с базой данных. Масштабируемость тестирования. Автоматические тесты помогают в будущем сократить время на тестирование, масштабировать этот процесс и адаптировать набор тестов под изменяемые требования продукта. Общая стабильность. Тестирование позволяет найти и устранить критические ошибки, которые способны вызвать проблемы производительности и краха приложения. Однако тестирование имеет проблемы, с которыми часто сталкиваются разработчики. Недостаточно тестов. Набор тестов должен охватывать весь функционал,  чтобы проверить продукт полностью. Необходимо проводить достаточное количество тестов, чтобы не пропустить ошибки. Коммуникация отделов. Важна связь между отделами. Тестировщики должны быть в курсе всех изменений, вносимых программистами, чтобы понимать что именно нужно тестировать. Отсутствие связи между отделами может привести к неожиданным последствиям, таким, как пропуск критического бага. Недостаточно данных. Программисты часто используют готовые наборы данных для проверки определённого функционала. В случае сложной системы, эти данные могут быть недостаточными. Расходы на тестирование. В некоторых случаях разработчики могут пренебрегать автоматическими тестами, особенно в небольших проектах, поскольку они требуют времени и считаются более затратными, чем ручное тестирование. Обычное тестирование сводится к тому, чтобы зайти на сайт и «потыкать» каждый элемент. Это называется — ручное тестирование. Такой подход применим только для небольших проектов. По мере роста приложения и появления новых зависимостей, ручное тестирование может быть менее точным и занимать больше времени. К тому же, от пропуска ошибки со стороны тестировщика ещё никто не застрахован. Не говоря уже о том, что есть множество вещей, которые вручную не «потыкаешь». Например, задачи выполняемые бэкэндом в фоновом режиме: работа очередей, отправка писем и всё то, что не видно невооружённым глазом. Автоматические тесты имеют особую ценность для проверки производительности и стресс-тестировании, поскольку они упрощают тестирование и находят человеческие ошибки на ранних этапах. Это приводит к сокращению переделок в дальнейшем. Возможно, придётся провести тесты вручную перед автоматизацией, чтобы убедиться, что они соответствуют структуре и требованиям приложения. Важно найти баланс между ручным и автоматизированным тестированием, чтобы ваш проект чувствовал себя лучше.  Для тестирования, помимо внимательности и любви к исследованиям, нужно мыслить нестандартно и быть готовым к монотонным задачам. Есть множество требований для успешного тестирования, которые необходимо учитывать. План тестирования. Первым шагом в тестировании становится создание документа, описывающего точные процедуры тестирования. Этот документ служит руководством для тестировщиков и программистов, чтобы убедиться, что они выполняют правильные процессы. Документация содержит тест-кейсы и чек-листы для проверки работы продукта. Выполнение плана тестирования. Планировать тестирование нужно с учётом разумного времени и тестировать новые функции по мере их готовности. Важно, чтобы все члены команды знали свои задачи и какие аспекты бэкенда они тестируют. Набор данных. Для тестирования нужно подготовить достаточный объём данных или базу данных. Вы можете автоматически сгенерировать набор данных или создать копию производственной базы данных. Информация должна быть сохранена в первоначальном виде, чтобы её возможно было корректно использовать. Результаты тестирования. По завершении тестов, приступают к анализу результатов и сравнивают с требованиями. Если обнаруживается значительное расхождение между ожидаемыми и полученными результатами, необходимо провести повторные тесты.  Повторное тестирование. Если продукт часто обновляется, то повторные тесты должны обязательно проводиться. Автоматические тесты помогут ускорить этот процесс, предоставив больше времени для внесения изменений. Теперь пришло время поговорить о самих багах. Какие они вообще есть? Обычно баги подразделяют на несколько основных видов. Функциональные баги  — приложение работает не так, как задумано. Например: не работает регистрация не удаляется товар из корзины не добавляется пост в блог Логические баги  — приложение логически работает неправильно. форма отправляется без имени пользователя при заказе товара нельзя указать номер телефона или адрес доставки выпадающие поля не выводят нужные списки  Ошибки в наборе текста — связанные с человеческим фактором, часто возникают в процессе разработки и могут привести к различным проблемам. Неправильное написание слов, орфографические и пунктуационные ошибки, или некорректный синтаксис могут нарушить работу приложения.  Мёртвый код — проекты проходят через множество итераций и это иногда приводит к появлению мёртвого кода. Мёртвый код может значительно замедлить работу определённых частей продукта и приводить к ошибкам в будущем. Удаление мёртвого кода поможет уменьшить размер приложения и повысить его производительность. Ошибки безопасности  — в этом случае могут быть затронуты пользовательские данные, делающие приложение уязвимым для вторжений. Тестирование может выявить недостатки безопасности, чтобы разработчики смогли обеспечить своевременную защиту и не дать злоумышленникам использовать уязвимости для кражи данных. Любое современное веб-приложение должно придерживаться основным принципам безопасности. Во-первых, обеспечить конфиденциальность доступа к данным только для определённых пользователей. Во-вторых, обеспечить целостность данных, позволив восстановить данные в случае их потери или повреждения. В третьих, соблюдать строгий уровень доступа к данным. Вот классический набор уязвимостей, которые часто встречаются: XSS (межсайтовый скриптинг) — создание скриптов на странице, которые могут представлять опасность для пользователей. XSRF (межсайтовая подделка запроса) — уязвимость, при которой злоумышленник может перенаправить пользователя с доверенной страницы на вредоносную, чтобы получить доступ к его данным. Инъекция кода (PHP, SQL) — внедрение исполняемого кода, позволяющего получать доступ к программному коду или базе данных. Обход авторизации — уязвимость, позволяющая получить несанкционированный доступ к учётной записи пользователя. Переполнение буфера — использование свободного пространства за пределами выделенного буфера памяти. Вопросы безопасности приложений регламентируются:  OWASP Guide CHECK NIST Guideline OSSTMM.  Для проверки уязвимых мест можно использовать чек-листы: XSS Filter Evasion Cheat Sheet MySQL SQL Injection Cheat Sheet Website Security Checklist Securing Web Application Technologies Checklist The Quick-and-Dirty Web Application Security Checklist Web Application Security Guide/Checklist Прежде всего, необходимо повторить баг в условиях, при которых он был обнаружен. Если баг не повторится, следует проверить всё заново. Чтобы точно определить условия бага, его нужно локализовать.  Чтобы проверить соответствуют ли результаты тестированию ожидаемым, нужно учитывать требования к продукту. Для этого должна быть документация, где подробно описана информация о функциональности продукта и процессе работы. Отсутствие этого может привести к ошибкам и неправильному пониманию работы продукта, особенно для малоопытных специалистов. Каждый баг должен быть занесён в баг-трекер для дальнейшей обработки. Например, в Jira, Trello или любой другой удобный для ваших задач инструмент. Баг-репорт должен содержать максимально точное и подробное описание бага, информацию о ситуации или последовательности действий, которые привели к некорректной работе, а также указание причин и ожидаемого результата.  Список атрибутов в баг-трекере может быть индивидуален для каждого проекта, но некоторые из них обычно такие: Заголовок — краткий и информативный, отражающий суть ошибки. Версия —  номер версии приложения или ветвь, в которой ошибка воспроизводится. Серьёзность — определяет влияние бага на функциональность: от критических ошибок, препятствующих использованию приложения, до незначительных проблем, таких как опечатки или визуальные несоответствия.  Приоритет — помогает установить приоритет исправления бага в зависимости от важности и срочности.  Статус — определяет текущий этап жизненного цикла бага, такой как исправление, тестирование, исправлено. Ответственный — исполнитель задачи по найденному багу, например, менеджер проекта, тимлид, тестировщик или разработчик.  Устройство — определяет устройство, на котором был обнаружен баг, такое как компьютер, телефон, указывает наименование и версию устройства, а также используемый браузер. Такой подход поможет разработчикам воспроизвести баг и упростит его исправление. Важно указать ожидаемое поведение приложения, которое должно соответствовать описанию в спецификации проекта. Это поможет понять, какое конкретное поведение следует ожидать от программы. Все разрабатываемые программы и приложения имеют базовую систему логирования. Обычно это текстовые журналы, в которых записывается информация о действиях программы или пользователя. Дополнительно необходимо предоставить любые полезные данные, которые помогут понять и исправить баг. Например, скриншот или видеозапись экрана, информацию об окружении, используемую версию ПО и другие факторы, которые могут быть связаны с возникновением бага.  Скриншоты и видеозаписи являются простым и эффективным способом демонстрации найденного бага. Они помогают тестировщику повторить баг и передать программисту для исправления. Для записи экрана можно использовать инструменты:  Стандартные «Ножницы» в Windows или утилита в macOS Monosnap LightShot ShareX Movavi Screen Capture Тестирование условно разделяется на три основных группы: Функциональное Нефункциональное Связанное с изменениями Функциональные виды тестирования Функциональное тестирование (Functional testing) — основано на функциях и взаимодействии с другими системами. Оно выполняется на всех уровнях тестирования: компонентном, интеграционном, системном и приёмочном. Тестирование пользовательского интерфейса (GUI Testing) — проверяет внешний вид, расположение элементов, взаимодействие с пользователем, удобство и функциональность интерфейса. Тестирование безопасности (Security and Access Control Testing) — проверяет безопасность и анализирует риски, связанные с защитой от хакеров, вирусов и несанкционированного доступа к конфиденциальным данным. Тестирование взаимодействия (Interoperability Testing) — позволяет проверить правильную работу систем, сервисов и приложений которые взаимодействуют друг с другом. Нефункциональные виды тестирования Нагрузочное тестирование (Performance and Load Testing) — проверяет производительность и устойчивость приложения к различным нагрузкам, как приложение будет работать при большом количестве пользователей, обработке большого объёма данных и нагрузке на сервер. Стрессовое тестирование (Stress Testing) — один из видов нагрузочного тестирования, для проверки стабильности и надёжности системы в условиях максимальной нагрузки. Приложению даётся большая нагрузка, превышающая обычные рабочие нагрузки, чтобы проверить, как приложение справляется с экстремальными условиями. Тестирование стабильности или надёжности (Stability / Reliability Testing) — проверяет, не часто ли приложение выходит из строя. Тестирование оценивает производительность при высоких нагрузках и выявляет утечки памяти или базы данных. Объёмное тестирование (Volume Testing) — подвергает приложение большому объёму данных для анализа производительности. Помогает выявить проблемы с нагрузкой и проверить приложение к использованию в реальных условиях. Тестирование установки (Installation testing) — проверяет корректность установки приложения.  Включает проверку установочных процедур, наличие и правильность необходимых файлов и настроек, а также функциональность после установки. Тестирование удобства использования (Usability Testing) — оценивает понятность и удобство интерфейса для пользователей. Выявляет проблемы с внешним видом, размещением элементов, взаимодействием с пользователем и функциональностью интерфейса.  Тестирование на отказ и восстановление (Failover and Recovery Testing) — проверяет способность приложения сохранять данные и ресурсы при сбоях системы. Конфигурационное тестирование (Configuration Testing) — проверяет работу приложения с настройками различных конфигураций, которые могут быть использованы пользователями. Связанные с изменениями виды тестирования Дымовое тестирование (Smoke Testing) — это первичный тип тестирования, выполняющий проверку основных функций приложения перед более подробным тестированием. Проводится быстрая проверка приложения с минимальным количеством тест-кейсов. Регрессионное тестирование (Regression Testing) — проверяет, что недавние изменения кода не повлияли на работу уже существующего функционала. Применяется после любых изменений кода, исправлений багов, рефакторинге, добавления нового функционала. Повторное тестирование (Re-testing) — проверка тестовых случаев, которые ранее не прошли успешную проверку. Тестирование сборки (Build Verification Test) — проверяет основные функции и стабильность приложения перед его передачей на следующий этап тестирования. Санитарное тестирование (Sanity Testing) — выполняется для быстрой проверки основных ошибок после внесения небольших правок в код приложения. Однако далеко не все из этих видов тестирования применяются на практике. Как всегда все зависит от проекта и команды разработчиков. Юнит-тестирование проверяет работу отдельных модулей кодовой базы и обнаруживает дефекты в отдельных частях приложения, таких как модули, объекты, классы и функции. Юнит-тесты вызывают функции с различными параметрами и проверяют возвращаемые значения. Они не взаимодействуют с базой данных, сетью или файловой системой, не могут быть запущены одновременно с другими юнит-тестами и не требуют предварительной настройки окружения для запуска. Проще говоря, юнит-тесты проверяют работу отдельного участка приложения. Например, какой-то функции или класса. Вместо обращения к другим классам, базе данных, файлам используются специальные классы заглушки — моки и стабы. Моки (Mock) — классы заглушки, проверяющие выполнение кода.  Например, проверить, что определённый метод успешно выполнился с передачей в него конкретных аргументов. Стабы (Stub) — тоже классы заглушки, возвращающие определённые данные при передаче каких-либо входных данных. Иными словами, моки вызываются тестируемым классом для проверки действий, а стабы проверяют и отдают для него данные. Интеграционные тесты проверяют работу независимых модулей приложения при их взаимодействии. Основная цель интеграционного тестирования - проверить, как работают вместе отдельно разработанные модули. Для этого активируются несколько модулей и проводятся тесты на более высоком уровне, чтобы убедиться, что они эффективно взаимодействуют. Модули могут быть как частями одного исполняемого файла, так и отдельными. Основной целью системного тестирования является проверка как функциональных, так и нефункциональных требований в целом. В процессе тестирования выявляются различные дефекты, такие как неправильное использование ресурсов, неожиданные комбинации пользовательских данных, несовместимость с окружением, непредусмотренные сценарии использования, отсутствие или неправильная функциональность, неудобство использования и другие. Важно учитывать, что тестирование является технической и экономической задачей, где требуется баланс между временем и полнотой. Даже если приложение полностью соответствует требованиям, важно проверить, что оно удовлетворяет потребностям пользователей и выполняет свою роль, как определено в бизнес-модели. Следует учитывать, что бизнес-модель также может содержать ошибки. Поэтому операционное тестирование играет важную роль и позволяет выявить не функциональные проблемы, такие как конфликты с другими системами, связанными с бизнесом или программным обеспечением, а также недостаточную производительность. Приёмочное тестирование проверяет, соответствует ли приложение требованиям, оценивает соответствие приёмочным критериям и принимает или отклоняет приложение заказчиком или другими уполномоченными лицами. Хороший тест должен быть небольшим, понятным для других, проверять не больше одного требования за раз. Необходимо убедиться, что тест не повторяет ошибку в проверяемом коде, иначе он просто может посчитать, что всё работает правильно. Кроме того, тесты должны проверять не только успешные сценарии, но и не успешные. Например, как себя поведёт форма обратной связи, если отправить email неправильного формата. Отдаст ли она сообщение о неправильном email или проигнорирует его и продолжит попытку отправить письмо. Часто или почти всегда, тесты проводят с помощью PhpUnit или Codeception. Они помогают написать тесты, использовать моки и стабы. Чтобы организовать структуру тестов используется несколько шаблонов: AAA (Arrange, Act, Assert) — организация, действие, утверждение. Шаблон помогает настроить и организовать тесты, выполнить тестируемый сценарий и подтвердить, что тест повёл себя как ожидалось. AAS (Act, Assert, Setup) — действие, утверждение, настройка. Это по сути такой же шаблон, как и AAA, но немного в другом порядке. Также вместо Arrange, здесь Setup. Чтобы находить ошибки без фактического запуска PHP кода, используется статический анализ кода. Он проводится специальными анализаторами, например, PhpStan, Psalm, Phan. Такое тестировать помогает найти различные ошибки: опечатки, лишние точки с запятой или кавычки, несуществующие переменные, пропущенные скобки и тому подобное. Теперь давайте рассмотрим несколько основных инструментов, которые разработчику необходимо уметь использовать для тестирования своего кода. PHPUnit — предоставляет набор инструментов и функций для написания и выполнения автоматических тестов в PHP-приложениях. PHPUnit позволяет создавать модульные тесты для проверки отдельных компонентов кода, интеграционные тесты для проверки взаимодействия между компонентами, а также функциональные тесты для проверки работы всего приложения в целом. Codeception — это инструмент для функциональных, модульных и приёмочных тестов, которые позволяют автоматизировать процесс тестирования. Он также обладает гибкой архитектурой, что позволяет легко создавать и поддерживать тесты. Codeception интегрируется с различными инструментами, такими как PHPUnit, Selenium и WebDriver. Behat — это инструмент для автоматизации тестирования на основе Behavior-Driven Development (BDD). Он позволяет писать тесты на естественном языке, похожем на английский, чтобы описывать поведение приложения. Behat интегрируется с языком PHP и предоставляет возможность тестировать PHP-код на бэкэнде. Он также взаимодействует с пользовательским интерфейсом через браузер. Selenium  — это инструмент для автоматизации тестирования веб-приложений. Он позволяет разработчикам и тестировщикам создавать и запускать тесты, которые взаимодействуют с веб-приложением, как если бы это делал пользователь. Selenium может выполнять различные действия, такие как ввод текста, клики на элементы, выбор элементов из выпадающего списка. Xdebug — это расширение PHP , предоставляющее ряд функций для улучшения процесса разработки PHP. PHP Debug Bar — легко интегрируется в любые проекты и может отображать данные профилирования из любой части приложения. Инструмент поставляется со встроенными сборщиками данных для стандартных функций PHP и популярных фреймворков, например, для Laravel. Atoum — среда модульного тестирования для PHP. Разработана чтобы писать надёжные, читаемые и понятные модульные тесты. Laravel Dusk — простой в использовании API для автоматизации и тестирования браузера. Dusk не требует установки JDK или Selenium, а использует автономный Chromedriver или любой другой драйвер. Test-Driven Development (TDD) — это метод разработки, основанный на циклах тестирования. Разработчик сначала создает тест, который описывает требуемое изменение, затем пишет код, который позволяет пройти этот тест. Затем происходит проверка, проводится рефакторинг кода и цикл начинается заново. TDD способствует созданию простого и понятного кода. DBbeaver - это инструмент администрирования баз данных с открытым исходным кодом, который поддерживает различные СУБД, такие как MySQL, PostgreSQL, Oracle, Microsoft SQL Server, SQLite и другие. Он предоставляет мощные функции для работы с базами данных, включая создание и редактирование таблиц, выполнение SQL-запросов, импорт и экспорт данных, анализ выполнения запросов и многое другое. DBbeaver имеет простой и интуитивно понятный интерфейс, который делает его удобным для использования как для опытных разработчиков, так и для новичков. HeidiSQL - это бесплатный инструмент администрирования для баз данных MariaDB, MySQL, а также Microsoft SQL Server, PostgreSQL и SQLite. Он предлагает различные функции, такие как подключение к серверу, управление пользователями и привилегиями, экспорт баз данных, выполнение нескольких запросов и просмотр статистики сервера и базы данных. DTM Data Generator — это инструмент, который производит тестовое заполнение базы данных, анализ производительности, тестирование качества или выполнение нагрузочных тестов. Генератор был разработан, чтобы проводить высококачественные и реалистичные тесты баз данных. Он автоматически создаёт таблицы, представления, процедуры, триггеры. HammerDB — программа для сравнительного анализа и нагрузочного тестирования Oracle, Microsoft SQL Server, IBM Db2, MySQL, MariaDB и PostgreSQL. SQLTest — бесплатный онлайн-инструмент для тестирования SQL-запросов, разработанный на основе фреймворка tSQLt. Позволяет делать заполнение базы данных, анализ производительности, тестирование качества и нагрузочное тестирование. SQLMap — инструмент тестирования на проникновение, который автоматизирует обнаружение SQL-инъекций, ошибок и уязвимостей базы данных. Он содержит множество специализированных функций для теста на проникновение: снятие слепков с базой данных, выборки данных из БД, доступ к базовой файловой системе, выполнение команд в ОС через внешний интерфейс и прочее. Postman — это HTTP-клиент, используемый для тестирования REST API. Он позволяет тестировщикам создавать интерфейсы API, мок-серверы и проверять различные функции, такие как регистрация пользователей и управление данными. Postman упрощает отправку HTTP-запросов к API, организацию запросов в коллекции и папки, изменение параметров запросов и окружения, добавление точек проверки, автоматизацию тестирования API с помощью Collection Runner и использование JavaScript-скриптов. Swagger — инструмент для описания структуры API, чтение которой возможно не только людям, но и машинам. Он позволяет генерировать шаблоны серверов и клиентских библиотек для API на разных языках программирования. Swagger также создаёт интерактивную документацию и поддерживает автоматическое тестирование. Для этого он использует YAML или JSON-файлы с подробными описаниями API, включающими операции, параметры, возвращаемые значения и требования авторизации. Swagger можно использовать вручную или генерировать автоматически из аннотаций в исходном коде. Кроме того, существуют интеграции Swagger с другими инструментами для разработки API. Sentry — сервис для мониторинга производительности и отслеживания ошибок PHP и JavaScript в режиме реального времени. «Гибкое тестирование. Практическое руководство для тестировщиков ПО и гибких команд» (авторы Лиза Криспин и Джанет Грегори) — практическое руководство для тестировщиков программного обеспечения и команд Agile. «Быстрое тестирование» (авторы Роберт Калбертсон, Крис Браун и Гэри Кобб) — включает в себя лучшие практики, рекомендации и решения для улучшения процесса внедрения программного обеспечения. Касается таких тем, как интеграция тестирования в жизненном цикле разработки программного обеспечения и методы тестирования. «Practical PHP Testing» (автор Джорджо Сирони) — предлагает практические руководства и советы по написанию автоматических тестов для PHP-приложений. «PHPUnit Pocket Guide» (автор Себастьян Бергман) — компактное руководство по использованию PHPUnit для тестирования PHP-кода. Объясняет основные концепции, такие как написание тестовых случаев, настройку тестовой среды и анализ результатов тестирования. «Selenium Testing Tools Cookbook» (автор Унмеш Гундеча)— книга предлагает практические примеры и советы по использованию инструментов Selenium для автоматизации тестирования веб-приложений на PHP. «Testing PHP Applications» (авторы Дэвид Склад и Уильям Штейнмец) — книга охватывает различные аспекты тестирования PHP-приложений, включая модульное тестирование, функциональное тестирование, интеграционное тестирование и тестирование пользовательского интерфейса. Она также предлагает рекомендации по выбору инструментов и организации тестового процесса. Чистые тесты с помощью PHP и PHPUnit Тестирование PHP проектов на примере Symfony Советы по тестированию Практики при работе с PHPUnit Мутационное тестирование Unit тестирование в Laravel Общая картина модульного тестирования Тестирование не для новичков Мы же всё протестировали, или откуда берутся баги на проде Как не надо заводить баги. Часто встречающиеся ошибки Тестирование — это не поиск ошибок! Тесты не всегда гарантируют 100% отсутствие багов. Ведь по сути, тесты — это тот же код, в котором также можно сделать логическую ошибку или упустить важную проверку. Не для всякого кода возможно написать тесты. Если система хитро устроена и её части сплетены в один снежный ком, вероятно потребуется провести рефакторинг приложения. Следует разделить код приложения на менее связанные куски, использовать dependency injection, не использовать статические методы, где они не требуются. Тогда покрыть код тестами будет намного легче. В любом случае, написание тестов требует времени, как и их последующая поддержка в актуальном состоянии. Если затраченное на тесты время не принесёт выгоды, то тесты и не понадобятся. Например, если вы создаёте небольшой и простой сайт, где основной функционал это обычная регистрация, профили пользователей, добавление материалов и комментариев, то такой сайт проще протестировать вручную, чем создавать тесты. Но когда вы работаете над сложным сайтом, где множество различных модулей и интеграций с внешними сервисами, то наверняка вам будет сложно проверить всё вручную. Обычная невнимательность может пропустить сломанный функционал. Именно в этом случае помогут автоматические тесты. Конечно это не всё, что можно сказать о тестировании, ведь эта тема очень обширна. Делитесь в комментариях вашим опытом, инструментами, книгами тестирования и неуловимыми багами с которыми пришлось сразиться!  Backend-разработчик