HTML Diff
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>