HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <h2>Введение</h2>
1 <h2>Введение</h2>
2 <p>Данный урок открывает череду обучающих материалов на тему "Тестирование в Python". В данном мини-курсе будет рассказано об основных инструментах применяющиеся для тестирования.</p>
2 <p>Данный урок открывает череду обучающих материалов на тему "Тестирование в Python". В данном мини-курсе будет рассказано об основных инструментах применяющиеся для тестирования.</p>
3 <p>Этот урок имеет вводный характер и знакомит с общей информацией о тестировании и простой конструкцией, которая позволяет значительно улучшить Python-код.</p>
3 <p>Этот урок имеет вводный характер и знакомит с общей информацией о тестировании и простой конструкцией, которая позволяет значительно улучшить Python-код.</p>
4 <h2>Определение</h2>
4 <h2>Определение</h2>
5 <p><strong>Тестирование программного обеспечения (Software Testing)</strong>- проверка соответствия между реальным и ожидаемым поведением программы, осуществляемая при конечном наборе тестов, выбранном определенным образом. [IEEE Guide to Software Engineering Body of Knowledge, SWEBOK, 2004].</p>
5 <p><strong>Тестирование программного обеспечения (Software Testing)</strong>- проверка соответствия между реальным и ожидаемым поведением программы, осуществляемая при конечном наборе тестов, выбранном определенным образом. [IEEE Guide to Software Engineering Body of Knowledge, SWEBOK, 2004].</p>
6 <p>В более широком смысле,<strong>тестирование</strong>- это одна из техник контроля качества, включающая в себя действия по планированию работ (Test Management), проектированию тестов (Test Design), выполнению тестирования (Test Execution) и анализу полученных результатов (Test Analysis).</p>
6 <p>В более широком смысле,<strong>тестирование</strong>- это одна из техник контроля качества, включающая в себя действия по планированию работ (Test Management), проектированию тестов (Test Design), выполнению тестирования (Test Execution) и анализу полученных результатов (Test Analysis).</p>
7 <p>Для разработчика же интересней следующее определение:</p>
7 <p>Для разработчика же интересней следующее определение:</p>
8 <p><strong>Тестирование</strong>- это проверка соответствия программы требованиям, осуществляемая путём наблюдения за её работой в специальных, искусственно созданных ситуациях, выбранных определённым образом.</p>
8 <p><strong>Тестирование</strong>- это проверка соответствия программы требованиям, осуществляемая путём наблюдения за её работой в специальных, искусственно созданных ситуациях, выбранных определённым образом.</p>
9 <p>Хочется обратить внимание на слова “искусственно созданных ситуациях, выбранных определённым образом”. Это означает, что не имеет смысла тестировать вообще все ситуации, стоит выбирать критически важные места и сценарии.</p>
9 <p>Хочется обратить внимание на слова “искусственно созданных ситуациях, выбранных определённым образом”. Это означает, что не имеет смысла тестировать вообще все ситуации, стоит выбирать критически важные места и сценарии.</p>
10 <h2>Уровни тестирования</h2>
10 <h2>Уровни тестирования</h2>
11 <p>Тестирование для разработчика состоит из написания тестов. Тест - это такой же программный код, который пишется аналогично коду для реализации бизнес-логики. Тесты проверяют сценарии работы программы (test-case).</p>
11 <p>Тестирование для разработчика состоит из написания тестов. Тест - это такой же программный код, который пишется аналогично коду для реализации бизнес-логики. Тесты проверяют сценарии работы программы (test-case).</p>
12 <p>Тест-кейсы встречаются самые различные, один от другого может резко отличаться. По желанию можно тестировать ВСЕ возможные и невозможные ситуации. Однако стоит соблюдать адекватность и покрывать код тестами ровно настолько, насколько требуется для уверенного понимания, что бизнес-логика работает как задумано.</p>
12 <p>Тест-кейсы встречаются самые различные, один от другого может резко отличаться. По желанию можно тестировать ВСЕ возможные и невозможные ситуации. Однако стоит соблюдать адекватность и покрывать код тестами ровно настолько, насколько требуется для уверенного понимания, что бизнес-логика работает как задумано.</p>
13 <blockquote><p>Например, функция, которая возвращает числовое значение от 0 до 100. В тестах стоит проверить не только правильность значений из этого диапазона, но и то, что других значений не возникает.</p>
13 <blockquote><p>Например, функция, которая возвращает числовое значение от 0 до 100. В тестах стоит проверить не только правильность значений из этого диапазона, но и то, что других значений не возникает.</p>
14 </blockquote><p>Негласное правило - если на участке кода проявилась ошибка, то стоит написать тест на этот случай.</p>
14 </blockquote><p>Негласное правило - если на участке кода проявилась ошибка, то стоит написать тест на этот случай.</p>
15 <p>Тестирование смело делится на несколько уровней глубины. Наиболее показательная классификация по уровням тестирования в данном случае такая:</p>
15 <p>Тестирование смело делится на несколько уровней глубины. Наиболее показательная классификация по уровням тестирования в данном случае такая:</p>
16 <ul><li>Системное тестирование - тестирование полностью интегрированного программного приложения</li>
16 <ul><li>Системное тестирование - тестирование полностью интегрированного программного приложения</li>
17 <li>Интеграционное тестирование - тестирование интегрированных групп программных модулей</li>
17 <li>Интеграционное тестирование - тестирование интегрированных групп программных модулей</li>
18 <li>Модульное тестирование или юнит-тестирование - тестирование отдельных модулей исходного кода приложения</li>
18 <li>Модульное тестирование или юнит-тестирование - тестирование отдельных модулей исходного кода приложения</li>
19 </ul><p>Когда говорят "тестирование", не выделяя конкретный тип, то говорят скорее всего о модульном тестировании.</p>
19 </ul><p>Когда говорят "тестирование", не выделяя конкретный тип, то говорят скорее всего о модульном тестировании.</p>
20 <p>Пойдем с низу вверх (от 3 к 1)</p>
20 <p>Пойдем с низу вверх (от 3 к 1)</p>
21 <h3>Модульное тестирование</h3>
21 <h3>Модульное тестирование</h3>
22 <p>Модульное тестирование, или юнит-тестирование (англ. unit testing) - процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.</p>
22 <p>Модульное тестирование, или юнит-тестирование (англ. unit testing) - процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.</p>
23 <p>Идея состоит в том, чтобы писать тесты для каждой нетривиальной функции или метода. Это позволяет достаточно быстро проверить, не привело ли очередное изменение кода к регрессии, то есть к появлению ошибок в уже протестированных местах программы и облегчает обнаружение и устранение таких ошибок.</p>
23 <p>Идея состоит в том, чтобы писать тесты для каждой нетривиальной функции или метода. Это позволяет достаточно быстро проверить, не привело ли очередное изменение кода к регрессии, то есть к появлению ошибок в уже протестированных местах программы и облегчает обнаружение и устранение таких ошибок.</p>
24 <h4>Инструменты</h4>
24 <h4>Инструменты</h4>
25 <p>В Python для модульного тестирования применяют</p>
25 <p>В Python для модульного тестирования применяют</p>
26 <ul><li>PyUnit</li>
26 <ul><li>PyUnit</li>
27 <li>PyTest</li>
27 <li>PyTest</li>
28 <li>Nose</li>
28 <li>Nose</li>
29 </ul><p>Об этих инструментах будет описано в следующих статьях.</p>
29 </ul><p>Об этих инструментах будет описано в следующих статьях.</p>
30 <h3>Интеграционное тестирование</h3>
30 <h3>Интеграционное тестирование</h3>
31 <p>Интеграцио́нное тестирование или функциональное тестирование предназначено для проверки связи между компонентами, а также взаимодействия с различными частями системы (операционной системой, оборудованием либо связи между различными системами).</p>
31 <p>Интеграцио́нное тестирование или функциональное тестирование предназначено для проверки связи между компонентами, а также взаимодействия с различными частями системы (операционной системой, оборудованием либо связи между различными системами).</p>
32 <h4>Подходы к интеграционному тестированию</h4>
32 <h4>Подходы к интеграционному тестированию</h4>
33 <ul><li>Снизу вверх (Bottom Up Integration)<ul><li>Все низкоуровневые модули, процедуры или функции собираются воедино и затем тестируются. После чего собирается следующий уровень модулей для проведения интеграционного тестирования. Данный подход считается полезным, если все или практически все модули разрабатываемого уровня готовы.</li>
33 <ul><li>Снизу вверх (Bottom Up Integration)<ul><li>Все низкоуровневые модули, процедуры или функции собираются воедино и затем тестируются. После чего собирается следующий уровень модулей для проведения интеграционного тестирования. Данный подход считается полезным, если все или практически все модули разрабатываемого уровня готовы.</li>
34 </ul></li>
34 </ul></li>
35 <li>Сверху вниз (Top Down Integration)<ul><li>Вначале тестируются все высокоуровневые модули, и постепенно, один за другим добавляются низкоуровневые. Все модули более низкого уровня симулируются заглушками с аналогичной функциональностью, затем по мере готовности они заменяются реальными активными компонентами.</li>
35 <li>Сверху вниз (Top Down Integration)<ul><li>Вначале тестируются все высокоуровневые модули, и постепенно, один за другим добавляются низкоуровневые. Все модули более низкого уровня симулируются заглушками с аналогичной функциональностью, затем по мере готовности они заменяются реальными активными компонентами.</li>
36 </ul></li>
36 </ul></li>
37 <li>Большой взрыв ("Big Bang" Integration)<ul><li>Все или практически все разработанные модули собираются вместе в виде законченной системы или ее основной части, и затем проводится интеграционное тестирование. Такой подход очень хорош для сохранения времени. Однако, если тест кейсы и их результаты записаны не верно, то сам процесс интеграции сильно осложнится, что станет преградой для команды тестирования при достижении основной цели интеграционного тестирования</li>
37 <li>Большой взрыв ("Big Bang" Integration)<ul><li>Все или практически все разработанные модули собираются вместе в виде законченной системы или ее основной части, и затем проводится интеграционное тестирование. Такой подход очень хорош для сохранения времени. Однако, если тест кейсы и их результаты записаны не верно, то сам процесс интеграции сильно осложнится, что станет преградой для команды тестирования при достижении основной цели интеграционного тестирования</li>
38 </ul></li>
38 </ul></li>
39 </ul><h4>Инструменты</h4>
39 </ul><h4>Инструменты</h4>
40 <p>Для автоматизации интеграционного тестирования применяются системы непрерывной интеграции (Continuous Integration System, CIS). Принцип действия таких систем состоит в следующем:</p>
40 <p>Для автоматизации интеграционного тестирования применяются системы непрерывной интеграции (Continuous Integration System, CIS). Принцип действия таких систем состоит в следующем:</p>
41 <ol><li>CIS производит мониторинг системы контроля версий;</li>
41 <ol><li>CIS производит мониторинг системы контроля версий;</li>
42 <li>При изменении исходных кодов в репозитории производится обновление локального хранилища;</li>
42 <li>При изменении исходных кодов в репозитории производится обновление локального хранилища;</li>
43 <li>Выполняются необходимые проверки и модульные тесты;</li>
43 <li>Выполняются необходимые проверки и модульные тесты;</li>
44 <li>Исходные коды компилируются в готовые выполняемые модули;</li>
44 <li>Исходные коды компилируются в готовые выполняемые модули;</li>
45 <li>Выполняются тесты интеграционного уровня;</li>
45 <li>Выполняются тесты интеграционного уровня;</li>
46 <li>Генерируется отчет о тестировании.</li>
46 <li>Генерируется отчет о тестировании.</li>
47 </ol><p>Примеры инструментов:</p>
47 </ol><p>Примеры инструментов:</p>
48 <ul><li>Bamboo</li>
48 <ul><li>Bamboo</li>
49 <li>Hudson и Jenkins</li>
49 <li>Hudson и Jenkins</li>
50 <li>CruiseControl</li>
50 <li>CruiseControl</li>
51 <li>TeamCity</li>
51 <li>TeamCity</li>
52 <li>BuildBot</li>
52 <li>BuildBot</li>
53 <li>Travis CI</li>
53 <li>Travis CI</li>
54 <li>Team Foundation Server</li>
54 <li>Team Foundation Server</li>
55 </ul><h3>Системное тестирование</h3>
55 </ul><h3>Системное тестирование</h3>
56 <p>Основной задачей системного тестирования является проверка как функциональных, так и не функциональных требований в системе в целом. При этом выявляются дефекты:</p>
56 <p>Основной задачей системного тестирования является проверка как функциональных, так и не функциональных требований в системе в целом. При этом выявляются дефекты:</p>
57 <ul><li>Неверное использование ресурсов системы</li>
57 <ul><li>Неверное использование ресурсов системы</li>
58 <li>Непредусмотренные комбинации данных пользовательского уровня</li>
58 <li>Непредусмотренные комбинации данных пользовательского уровня</li>
59 <li>Несовместимость с окружением</li>
59 <li>Несовместимость с окружением</li>
60 <li>Непредусмотренные сценарии использования</li>
60 <li>Непредусмотренные сценарии использования</li>
61 <li>Отсутствующая или неверная функциональность</li>
61 <li>Отсутствующая или неверная функциональность</li>
62 <li>Неудобство использования</li>
62 <li>Неудобство использования</li>
63 <li>И другие</li>
63 <li>И другие</li>
64 </ul><p>Для минимизации рисков, связанных с особенностями поведения системы в той или иной среде, во время тестирования рекомендуется использовать окружение максимально приближенное к тому, на которое будет установлен продукт после выдачи.</p>
64 </ul><p>Для минимизации рисков, связанных с особенностями поведения системы в той или иной среде, во время тестирования рекомендуется использовать окружение максимально приближенное к тому, на которое будет установлен продукт после выдачи.</p>
65 <p>Стоит выделить два подхода к системному тестированию:</p>
65 <p>Стоит выделить два подхода к системному тестированию:</p>
66 <ul><li>на базе требований (requirements based). Для каждого требования пишутся тестовые случаи (test cases), проверяющие выполнение данного требования.</li>
66 <ul><li>на базе требований (requirements based). Для каждого требования пишутся тестовые случаи (test cases), проверяющие выполнение данного требования.</li>
67 <li>на базе случаев использования (use case based). На основе представления о способах использования продукта создаются случаи использования системы (Use Cases).</li>
67 <li>на базе случаев использования (use case based). На основе представления о способах использования продукта создаются случаи использования системы (Use Cases).</li>
68 </ul><p>По конкретному случаю использования можно определить один или более сценариев. На проверку каждого сценария пишутся тест кейсы (test cases), которые реализуются в виде тестов.</p>
68 </ul><p>По конкретному случаю использования можно определить один или более сценариев. На проверку каждого сценария пишутся тест кейсы (test cases), которые реализуются в виде тестов.</p>
69 <h4>Инструменты</h4>
69 <h4>Инструменты</h4>
70 <p>Для описания сценариев можно использовать BDD (behavior-driven development)</p>
70 <p>Для описания сценариев можно использовать BDD (behavior-driven development)</p>
71 <ul><li>pytest-bdd</li>
71 <ul><li>pytest-bdd</li>
72 <li>behave</li>
72 <li>behave</li>
73 <li>freshen</li>
73 <li>freshen</li>
74 </ul><h2>Простой инструмент проверки данных - assert</h2>
74 </ul><h2>Простой инструмент проверки данных - assert</h2>
75 <p>Так как этот урок почти полностью состоит из теории, то разбавлю конструкцией языка, которая помогает писать код и тесты более высокого качества.</p>
75 <p>Так как этот урок почти полностью состоит из теории, то разбавлю конструкцией языка, которая помогает писать код и тесты более высокого качества.</p>
76 <p>Python - язык с динамической типизацией. Это значит, что при написании Python-кода мы явно не указываем тип данных, а во время исполнения не гарантируется явный тип переменной.</p>
76 <p>Python - язык с динамической типизацией. Это значит, что при написании Python-кода мы явно не указываем тип данных, а во время исполнения не гарантируется явный тип переменной.</p>
77 <p>В следствии этого возникают сложности. Например, в функции ожидаем целое число, а нам передали list. Это может привести к самым неожиданным ошибками. Чтобы попытаться обойти эту проблему стоит воспользоваться assert.</p>
77 <p>В следствии этого возникают сложности. Например, в функции ожидаем целое число, а нам передали list. Это может привести к самым неожиданным ошибками. Чтобы попытаться обойти эту проблему стоит воспользоваться assert.</p>
78 <blockquote><p>Assert - это специальная конструкция, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы.</p>
78 <blockquote><p>Assert - это специальная конструкция, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы.</p>
79 </blockquote><p>Assert'ы позволяют отлавливать ошибки в программах на этапе компиляции либо во время исполнения.</p>
79 </blockquote><p>Assert'ы позволяют отлавливать ошибки в программах на этапе компиляции либо во время исполнения.</p>
80 <p>Использование конструкции весьма простое:</p>
80 <p>Использование конструкции весьма простое:</p>
81 <p>Assert вызывает ошибку, если аргумент равен False. Например так:</p>
81 <p>Assert вызывает ошибку, если аргумент равен False. Например так:</p>
82 <p>Traceback показывает строчку, с которой полетело исключение AssertionError, что порой открывает много нового в понимании, как же в реальности работает написанный код.</p>
82 <p>Traceback показывает строчку, с которой полетело исключение AssertionError, что порой открывает много нового в понимании, как же в реальности работает написанный код.</p>
83 <h2>Выводы</h2>
83 <h2>Выводы</h2>
84 <p>В уроке были кратко описаны виды тестирования: модульное или юнит-тестирование, интеграционное, системное. Для каждого озвучен список инструментов для создания тестов.</p>
84 <p>В уроке были кратко описаны виды тестирования: модульное или юнит-тестирование, интеграционное, системное. Для каждого озвучен список инструментов для создания тестов.</p>
85 <p>В качестве практики описана конструкция assert, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы.</p>
85 <p>В качестве практики описана конструкция assert, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы.</p>