0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Изученной информации уже достаточно для тестирования в повседневной практике разработки. Перед тем, как погружаться в более сложные темы и возможности библиотек для тестирования и фреймворков, пройдём полный путь тестирования библиотеки, поговорим об организации тестов, хороших и плохих практиках. Это поможет сформировать правильное отношение к тестированию в целом.</p>
1
<p>Изученной информации уже достаточно для тестирования в повседневной практике разработки. Перед тем, как погружаться в более сложные темы и возможности библиотек для тестирования и фреймворков, пройдём полный путь тестирования библиотеки, поговорим об организации тестов, хороших и плохих практиках. Это поможет сформировать правильное отношение к тестированию в целом.</p>
2
<p>В этом уроке мы разберём основы модульного тестирования. Это тестирование направлено на проверку модулей программы в изоляции от всех остальных частей. Эти тесты обычно тестируют базовые конструкции языка: методы, пакеты, классы. Такие тесты не дают никаких гарантий работы всего приложения в целом, но хорошо помогают тогда, когда какой-то модуль программы имеет сложную логику.</p>
2
<p>В этом уроке мы разберём основы модульного тестирования. Это тестирование направлено на проверку модулей программы в изоляции от всех остальных частей. Эти тесты обычно тестируют базовые конструкции языка: методы, пакеты, классы. Такие тесты не дают никаких гарантий работы всего приложения в целом, но хорошо помогают тогда, когда какой-то модуль программы имеет сложную логику.</p>
3
<p>Попробуем протестировать<a>стек</a>. Стек представляет собой список элементов организованных по принципу LIFO. Данные кладутся в стек в одном порядке, а извлекаются в обратном. Сам стек, как правило, используется для реализации алгоритмов. Он часто используется в низкоуровневом коде: например, внутри языков программирования или в операционных системах. В реальной жизни по принципу стека работает магазин в пистолете: последняя добавленная пуля вылетает первой.</p>
3
<p>Попробуем протестировать<a>стек</a>. Стек представляет собой список элементов организованных по принципу LIFO. Данные кладутся в стек в одном порядке, а извлекаются в обратном. Сам стек, как правило, используется для реализации алгоритмов. Он часто используется в низкоуровневом коде: например, внутри языков программирования или в операционных системах. В реальной жизни по принципу стека работает магазин в пистолете: последняя добавленная пуля вылетает первой.</p>
4
<h2>Тестируем основную функциональность</h2>
4
<h2>Тестируем основную функциональность</h2>
5
<p>Теперь напишем первый тест. Первый тест всегда должен проверять позитивный сценарий - тот, в котором задействована основная функциональность тестируемого компонента:</p>
5
<p>Теперь напишем первый тест. Первый тест всегда должен проверять позитивный сценарий - тот, в котором задействована основная функциональность тестируемого компонента:</p>
6
<p>Этот тест проверяет, что правильно работают два основных метода без учёта пограничных случаев. Для этого внутри теста выполняются два матчера, которые по очереди проверяют извлекаемые значения из стека.</p>
6
<p>Этот тест проверяет, что правильно работают два основных метода без учёта пограничных случаев. Для этого внутри теста выполняются два матчера, которые по очереди проверяют извлекаемые значения из стека.</p>
7
<h2>Тестируем дополнительную функциональность</h2>
7
<h2>Тестируем дополнительную функциональность</h2>
8
<p>Следующим тестом будет тест на дополнительные методы стека. К таким у нас относится метод isEmpty(), который проверяет, пустой ли стек:</p>
8
<p>Следующим тестом будет тест на дополнительные методы стека. К таким у нас относится метод isEmpty(), который проверяет, пустой ли стек:</p>
9
<p>В этом тесте проверяются сразу три ситуации:</p>
9
<p>В этом тесте проверяются сразу три ситуации:</p>
10
<ul><li>начальное состояние стека</li>
10
<ul><li>начальное состояние стека</li>
11
<li>состояние стека после добавления элементов</li>
11
<li>состояние стека после добавления элементов</li>
12
<li>состояние стека после извлечения всех элементов</li>
12
<li>состояние стека после извлечения всех элементов</li>
13
</ul><p>В принципе, этого достаточно. Хотя в теории возможны ситуации, при которых isEmpty() всё равно сломается. Нужно ли пытаться найти все варианты? Не нужно. Тесты не даются бесплатно, каждая написанная строчка кода в проекте - потенциальное место для изменения в случае правок. Если есть сомнения, нужно ли писать проверку или нет, то лучше не пишите. Так вы поймёте тот минимум, который стоит писать, и после которого тесты писать не эффективно. Редкие ситуации требуют покрытия тестами только тогда, когда они критичны для работоспособности.</p>
13
</ul><p>В принципе, этого достаточно. Хотя в теории возможны ситуации, при которых isEmpty() всё равно сломается. Нужно ли пытаться найти все варианты? Не нужно. Тесты не даются бесплатно, каждая написанная строчка кода в проекте - потенциальное место для изменения в случае правок. Если есть сомнения, нужно ли писать проверку или нет, то лучше не пишите. Так вы поймёте тот минимум, который стоит писать, и после которого тесты писать не эффективно. Редкие ситуации требуют покрытия тестами только тогда, когда они критичны для работоспособности.</p>
14
<h3>Пограничные случаи</h3>
14
<h3>Пограничные случаи</h3>
15
<p>Ну, и последнее, что можно протестировать - поведение метода pop(), когда в стеке нет ни одного элемента. По задумке, стек выбрасывает исключение EmptyStackException, если из него попытались взять элемент, когда тот был пустой. В библиотеке AssertJ подобные проверки реализуются следующим образом:</p>
15
<p>Ну, и последнее, что можно протестировать - поведение метода pop(), когда в стеке нет ни одного элемента. По задумке, стек выбрасывает исключение EmptyStackException, если из него попытались взять элемент, когда тот был пустой. В библиотеке AssertJ подобные проверки реализуются следующим образом:</p>
16
<p>Но не всегда пограничные случаи так легко увидеть. Маловероятно, что любой программист сможет сразу написать все нужные тесты. Если в коде возникла ошибка, для которой не было теста, то сначала напишите тест, который воспроизводит эту ошибку, и затем уже чините её. Только так можно поддерживать достаточный уровень надежности, не превращая разработку в непрерывную починку багов.</p>
16
<p>Но не всегда пограничные случаи так легко увидеть. Маловероятно, что любой программист сможет сразу написать все нужные тесты. Если в коде возникла ошибка, для которой не было теста, то сначала напишите тест, который воспроизводит эту ошибку, и затем уже чините её. Только так можно поддерживать достаточный уровень надежности, не превращая разработку в непрерывную починку багов.</p>