Дізнайтеся, як тестувати свої вправи з Python на Exercism.
Ми використовуємо pytest як засіб запуску тестів на сайті.
Щоб завантажити й запускати тести вправ треку Python локально, потрібно встановити pytest на власній машині для розробки.
Також варто встановити такі плагіни pytest:
Радимо скористатися і програмою для лінтування коду pylint: вона є частиною автоматичного фідбеку на сайті й може стати дуже корисним інструментом статичного аналізу коду.
Для зручності плагін pytest-pylint для pytest дає змогу запускати pylint через pytest у командному рядку.
Налаштування pylint може здатися складним, тож стати в пригоді для початку може цей туторіал із pylint.readthedocs.io, а також цей огляд Code Quality: Tools and Best Practices від Real Python.
pytest можна встановити й оновити за допомогою вбудованої утиліти Python pip.
За додатковими порадами звернімося до швидкого посібника Бретта Кеннона про те, як встановлювати пакунки для Python, а також до ґрунтовного пояснення чому варто використовувати python -m pip.
Докладніше про аргументи командного рядка Python читайте в розділі command line and environment документації Python.
Примітка: Python3 і py можуть бути, а можуть і не бути псевдонімами Python на компʼютері.
Відповідно скоригуйте наведені нижче команди встановлення.
Щоб встановити pytest у віртуальному середовищі, переконайтеся, що середовище активоване, перш ніж виконувати команди.
Інакше встановлення pytest буде глобальним.
PS C:\Users\foobar> py -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...
$ python3 -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...
Щоб перевірити, чи встановлення було успішним:
$ python3 -m pytest --version
pytest 8.3.3
Щоб запустити тести, перейдіть у теку, де зберігається вправа, за допомогою cd у терміналі (замініть <exercise-folder-location> нижче на свій шлях).
$ cd <exercise-folder-location>
<exercise-folder-location> або більшість того, що стоїть у кутових дужках, позначає значення-заповнювач.
Звичайний шлях або імʼя файлу слід писати без жодних дужок.
Наприклад: /Users/janedoe/exercism/python/exercises/concept/chaitanas-colossal-coaster (у *nix-системах), C:\Users\janedoe\exercism\python\exercises\practice\hello-world\ (у Windows), myFolder або my_file.py.
Файл, який потрібно запустити, зазвичай закінчується на _test.py.
Цей файл містить тести для рішення вправи, і це ті самі тести, що виконуються на сайті, коли рішення завантажують.
Далі виконайте таку команду в терміналі, замінивши <exercise_test.py> на шлях або назву файлу з тестами:
$ python3 -m pytest -o markers=task <exercise_test.py>
==================== 7 passed in 0.08s ====================
Якщо не додати pytest -o markers=task до наведеної вище команди, під час запуску тесту з нашим новим синтаксисом можуть зʼявитися warnings про «unknown markers».
Щоб не набирати pytest -o markers=task для кожного запуску тестів, можна скористатися файлом налаштувань pytest.ini, який можна завантажити з кореня теки треку Python: pytest.ini.
Можна також створити власний файл pytest.ini з таким вмістом:
[pytest]
markers =
task: A concept exercise task.
Якщо покласти цей файл у кореневу або робочу теку вправ Exercism, позначки зареєструються й попередження зникнуть.
Більше про позначки pytest можна дізнатися з документації pytest щодо marking test functions і з документації pytest щодо working with custom markers.
Більше про налаштування конфігурацій pytest можна дізнатися з документації pytest щодо configuration file formats
Коли тести не проходять, pytest виводить у термінал текст кожного невдалого тесту, а також очікувані та фактичні значення return кожного з них.
Нижче наведено загальний приклад невдалого тесту:
$(my_venv) python3 -m pytest -o markers=task <exercise_test.py>
=================== FAILURES ====================
______________ name_of_failed_test ______________
# Test code inside of <exercise_test.py> that failed.
...
E TypeOfError: ReturnedValue != ExpectedValue
exercise_test.py:<line_of_failed_test>: TypeOfError
============ short test summary info ============
FAILED exercise_test.py::ExerciseTest::name_of_failed_test
========== 1 failed, 2 passed in 0.13s ==========
Якщо хочеться точно керувати тим, що pytest показує на екрані, ось кілька зручних аргументів командного рядка, за допомогою яких можна налаштувати поведінку pytest.
-v]Додавання прапорця -v (verbose) покаже не лише невдалі тести, а й інформацію про середовище та підсумок тестування:
$(my_venv) python3 -m pytest -o markers=task -v exercises/<exercise_name>/<test_file_test.py>
======================================== test session starts ===========================================
platform darwin -- Python 3.9.0, pytest-6.2.5, -- /usr/local/envs/my_env/bin/python3
cachedir: .pytest_cache
metadata: {'Python': '3.9.0', 'Platform': 'macOS-10.14.6-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.1'}, 'Plugins': {'subtests': '0.5.0', 'pylint': '0.18.0'}
rootdir: /Users/<user>/exercism/python, configfile: pytest.ini
plugins: subtests-0.5.0, pylint-0.18.0
collected 5 items
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_one FAILED [ 20%]
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_two FAILED
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_three PASSED [ 40%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_four FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_five PASSED [ 60%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_six FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_seven PASSED [ 80%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_eight FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_nine PASSED [100%]
================================================ FAILURES ======================================================
# Failed tests are then individually printed out below
.......
-x]Прапорець -x запускає тести як звичайно, але зупиняє запуск після першої невдачі.
Це допомагає, коли потрібно налагоджувати по одній задачі чи невдалому тесту за раз:
$(my_venv) python3 -m pytest -o markers=task -x exercises/<exercise_name>/<test_file_test.py>
=================== FAILURES ====================
_______________ example_test_foo ________________
...
...
============ short test summary info ============
FAILED example_test.py::ExampleTest::example_test_foo
!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!
========== 1 failed, 5 passed in 0.28s ==========
--ff]Плагін pytest-cache запамʼятовує, які тести не пройшли під час останнього запуску pytest, тож прапорець --ff змусить pytest запустити раніше невдалі тести першими, а потім перейти до решти.
Це може пришвидшити тестування, якщо робити багато дрібних виправлень навколо однієї задачі чи набору вхідних даних.
$(my_venv) python3 -m pytest -o markers=task --ff <example_file_test.py>
==================== 7 passed in 503s ====================
Радимо використовувати такі команди, щоб налагодження було простішим і (можливо) швидшим:
Спершу перейдіть у теку вправи, яку хочете протестувати:
$(my_venv) cd path/to/exercise
Потім запустіть тести разом із поясненими вище аргументами -x та --ff:
$(my_venv) python3 -m pytest -o markers=task -x --ff <example_file_test.py>
Це запустить тести для рішення.
Коли pytest натрапляє на невдалий тест, програма зупиняється й повідомляє, який тест не пройшов.
Коли ми вносимо виправлення й запускаємо тести знову, pytest спершу виконає попередній невдалий тест, а потім перейде до решти.
Якщо хочеться «налагоджувати як професіонал», додайте аргумент --pdb після команди pytest і потрапите у вбудований налагоджувач Python, PDB.
$(my_venv) python3 -m pytest -o markers=task -x --ff --pdb <example_file_test.py>
=============== 4 passed in 0.15s ===============
Коли тест не проходить, потрапляння в PDB дає змогу покроково виконувати код, бачити поточну область видимості, а також перевіряти значення змінних і сигнатури різних функцій.
Більше про модуль PDB можна дізнатися з документації Python щодо PDB.
Крім того, надзвичайно корисними будуть документація pytest щодо PDB і цей посібник від Real Python.
Якщо хочеться розширити IDE інструментами, які допоможуть тестувати й покращувати код, зазирніть на сторінку інструментів. Там ми розглядаємо різні IDE, редактори та корисні розширення для лінтування й налагодження.
Примітка: Якщо Python на Windows встановлено через PSF Installer, команда буде py, а не python3.
Набирати python3 -m щоразу, коли потрібно запустити модуль, може трохи дратувати.
Щоб цього уникнути, можна додати теку Scripts зі встановленого Python до свого PATH.
Якщо невідомо, куди встановлено Python, виконайте таку команду в терміналі:
$ python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
<python_directory>
Повернена тека вказує, куди встановлено поточну активну версію Python; у цьому розділі вона позначена як <python_directory>.
Натисніть кнопку Windows Start, знайдіть Edit the system environment variables і натисніть Enter.
Далі натисніть Environment Variables...:

Знайдіть змінну Path у розділі User variables, виділіть її й натисніть Edit...:

Потім додайте новий рядок, як показано на малюнку, замінивши <python_directory> на теку встановлення Python:

Наведене нижче має працювати для більшості варіантів Linux і MacOS з оболонкою bash.
Команди можуть відрізнятися залежно від дистрибутива Linux і від того, яку оболонку використано, fish чи zsh.
Замініть <python_directory> на результат виконання python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
export PATH="$PATH:<python_directory>"