# Модульное тестирование

### Что такое unit-тестирование? <a href="#what-is-unit-testing" id="what-is-unit-testing"></a>

Unit-тестирование – это не новая концепция. Обычно разработчики и иногда тестировщики, использующие подход “белого ящика”, пишут модульные тесты для улучшения качества кода путем проверки каждой единицы кода, используемой для реализации функциональных требований (также известная как разработка на основе тестов (TDD) или test-first разработка).

Большинство из нас знают классическое определение: “Unit-тестирование – это метод проверки самого маленького тестируемого фрагмента кода на соответствие его цели”. Если цель или требование не выполняются, значит, unit-тестирование провалено.

Простыми словами, это означает – написание части кода (модульного теста) для проверки кода (модуля), написанного для реализации требований.

### Важность написания unit-тестов <a href="#importance-of-writing-unit-tests" id="importance-of-writing-unit-tests"></a>

Unit-тестирование используется для разработки надежных компонентов ПО, которые помогают поддерживать код и устранять проблемы в его отдельных блоках. Все мы знаем, как важно находить и устранять дефекты на ранних стадиях цикла разработки программного обеспечения. Тестирование служит той же цели.

Оно является неотъемлемой частью agile-процесса разработки ПО. При ночной сборке должен запускаться набор модульных тестов и генерироваться отчет. Если какой-либо из unit-тестов не прошел, то команда QA не должна принимать эту сборку для проверки.

Если мы сделаем это стандартным процессом, многие дефекты будут отлавливаться на ранних стадиях разработки, что позволит сэкономить много времени на тестирование.

Я знаю, что многие разработчики ненавидят писать unit-тесты. Они либо игнорируют, либо пишут плохие unit-тесты из-за жесткого графика или недостаточной серьезности (да, они пишут пустые unit-тесты, поэтому 100% из них проходят успешно ;)). Важно писать хорошие модульные тесты или не писать их вообще. Еще важнее предоставить достаточно времени и благоприятную среду для получения от них реальной пользы.

### Методы unit-тестирования <a href="#unit-testing-methods" id="unit-testing-methods"></a>

**Оно может быть выполнено двумя способами:**

1. Ручное тестирование
2. Автоматизированное тестирование

При **ручном тестировании** тестировщик вручную выполняет тест-кейсы без использования каких-либо средств автоматизации. Здесь каждый этап теста выполняется вручную. Такое тестирование утомительно, особенно для тестов, которые повторяются и требуют больших усилий для создания и выполнения тест-кейсов. Ручное тестирование не требует знания какого-либо инструмента автоматизации.

Фактом является то, что 100% автоматизация невозможна, поэтому определенный процент тест-кейсов всегда будет выполняться вручную.

В **автоматизированном тестировании** используются специальные инструменты для автоматизации тест-кейсов. Инструмент автоматизации может записать и сохранить ваш тест, и он может быть воспроизведен столько раз, сколько необходимо, без дальнейшего вмешательства человека.

Эти инструменты могут даже вводить тестовые данные в тестируемую систему, а также сравнивать ожидаемые результаты с фактическими и автоматически генерировать отчеты. Однако первоначальные затраты на создание средств автоматизации тестирования достаточно высоки.

### Преимущества unit-тестирования <a href="#benefits-of-unit-testing" id="benefits-of-unit-testing"></a>

1. **Процесс становится гибким:** Чтобы добавить новые функции или возможности в существующее ПО, необходимо внести изменения в старый код. Но внесение изменений в уже протестированный код может быть рискованным и дорогостоящим.
2. **Улучшается качество кода:** Качество кода автоматически улучшается, когда проводится модульное тестирование. Ошибки, выявленные в ходе такого тестирования, исправляются до того, как они будут отправлены на этап интеграционного тестирования. Это приводит к надежности проектирования и разработки, поскольку разработчики пишут тест-кейсы, предварительно разобравшись в спецификациях.
3. **Раннее обнаружение ошибок:** Выполняя unit-тесты, разработчики обнаруживают ошибки на ранних этапах жизненного цикла разработки ПО и устраняют их. Это касается как недостатков или отсутствующих частей в спецификации, так и ошибок в реализации программиста.
4. **Более легкие изменения и упрощенная интеграция:** Проведение unit-тестирования облегчает разработчику реструктуризацию кода, внесение изменений и сопровождение кода. Это также значительно упрощает тестирование кода после интеграции. Исправление проблемы при unit-тестировании может застраховать от ряда других дефектов, возникающих на последующих этапах разработки и тестирования.
5. **Доступность документации:** Разработчики, которые изучают функциональность на более поздних этапах, могут обратиться к документации по unit-тестированию и легко найти интерфейс модульного теста – затем быстро и легко исправить работу.
6. **Простой процесс отладки:** Это помогает упростить процесс отладки. Если тест не прошел на каком-либо этапе, код необходимо отлаживать, иначе процесс можно продолжать без каких-либо препятствий.
7. **Более низкая стоимость:** Когда ошибки обнаруживаются и устраняются во время unit-тестирования, снижается стоимость и время разработки. Без такого тестирования, если те же ошибки будут обнаружены на более позднем этапе после интеграции кода, их будет сложнее отследить и устранить, что приведет к увеличению времени разработки и, следовательно, стоимости.
8. **С помощью unit-тестов можно проверить полноту кода:** Это более полезно в agile-процессах. Тестировщики не получают функциональные сборки для тестирования до завершения интеграции. Полноту кода нельзя обосновать, показав, что вы написали и проверили код. Однако выполнение unit-тестов может продемонстрировать завершенность кода.
9. **Экономия времени разработки:** Завершение реализации какой-либо функциональности может занять больше времени, но благодаря меньшему количеству ошибок при системном и приемочном тестировании можно сэкономить общее время разработки.
10. **Покрытие кода** может быть измерено.

**Цикл модульного тестирования**

<figure><img src="https://qarocks.ru/wp-content/uploads/2023/08/unit-testing-cycle1.jpg" alt="Цикл модульного тестирования." height="352" width="366"><figcaption></figcaption></figure>

### Фреймворки для unit-тестирования <a href="#unit-testing-frameworks" id="unit-testing-frameworks"></a>

Фреймворки для unit-тестирования в основном используются для того, чтобы помочь быстро и легко написать модульные тесты. Большинство языков программирования не поддерживают модульное тестирование встроенным компилятором. Чтобы сделать unit-тестирование еще более увлекательным, можно использовать сторонние инструменты с открытым исходным кодом и платные инструменты.

**Список популярных инструментов unit-тестирования для различных языков программирования:**

1. Java framework – [JUnit](http://www.junit.org/)
2. PHP-фреймворк – [PHPUnit](https://github.com/sebastianbergmann/phpunit/)
3. Фреймворки C++ – [UnitTest++](https://sourceforge.net/projects/unittest/) и [Google C++](https://code.google.com/p/googletest/)
4. Фреймворк .NET – [NUnit](http://www.nunit.org/)
5. Фреймворк Python – [pytest](http://pytest.org/)

**Частые заблуждения о unit-тестировании:**

* Написание кода с применением unit-тестов занимает больше времени, которого у нас и так нет – в действительности, это сэкономит время разработки в долгосрочной перспективе.
* Unit-тестирование поможет найти все ошибки – не поможет, поскольку цель unit-тестирования заключается не в поиске ошибок, а в разработке надежных программных компонентов, которые будут иметь меньше дефектов на последующих этапах SDLC.
* 100% покрытие кода означает 100% покрытие тестов – это не гарантирует, что код не содержит ошибок.

### Как создавать и выполнять unit-тесты? <a href="#how-to-accept-unit-testing" id="how-to-accept-unit-testing"></a>

Хорошее модульное тестирование может состоять из 3 основных частей.

1. Написать код unit-теста.
2. Запустите код модульного тестирования, чтобы проверить, соответствует ли он системным требованиям.
3. Выполнить программный код, чтобы проверить его на наличие дефектов и убедиться, что код соответствует системным требованиям.

После выполнения вышеуказанных трех шагов, если код отрабатывает корректно, то считается, что модульный тест пройден. Если он не соответствует системным требованиям, то тест провален. В этом случае разработчику необходимо перепроверить и исправить код.

В некоторых случаях для более точного тестирования необходимо разделить код.

### Лучшие практики <a href="#best-practice" id="best-practice"></a>

**Чтобы создать наиболее качественный код, учитывайте следующие моменты во время тестирования:**

* **Код должен быть стабильным:** Бывают случаи, когда тест проваливается или в худшем случае вообще не выполняется, если код сломан.
* **Понятным и полезным:** Код должен быть простым для понимания. Это облегчает написание кода для разработчика, и даже другие разработчики, которые будут работать над кодом впоследствии, смогут легко его отладить.
* **Должен быть один случай:** Тесты, которые определяют несколько тест-кейсов с разными входными данными в одной функции, сложны в работе. Таким образом, написание кода для одного тест-кейса является лучшей практикой, что делает код более простым для понимания и отладки.
* **Автоматизируйте запуск тестов:** Разработчики должны позаботиться о том, чтобы тест выполнялся автоматически. Это должно быть в рамках непрерывного процесса доставки или интеграции (CI/CD).

**Другие моменты, которые следует иметь в виду:**

* Вместо того чтобы создавать тест-кейсы для всех существующих входных данных, сосредоточьтесь на тесте, который влияет на поведение системы.
* Существует вероятность повторения ошибки из-за кэша браузера.
* Тест-кейсы не должны быть взаимозависимыми.
* Обращайте внимание на циклы и условия в коде.
* Планируйте тест-кейсы чаще.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://qabook.gitbook.io/start/teoriya-testirovaniya/osnovy-testirovaniya/vidy-testirovaniya/funkcionalnoe-testirovanie-i-ikh-vidy/modulnoe-testirovanie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
