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