Aprende a probar tus ejercicios de Python en Exercism.
Usamos pytest como ejecutor de tests de nuestro sitio web.
Tendrás que instalar pytest en tu ordenador de desarrollo si quieres descargar y ejecutar los tests de los ejercicios de la pista de Python en local.
También deberías instalar los siguientes complementos de pytest:
También recomendamos usar el programa de linting de código pylint, ya que forma parte de nuestro feedback automatizado en el sitio web y puede ser una herramienta de análisis estático de código muy útil.
Por comodidad, el complemento pytest-pylint de pytest te permitirá ejecutar pylint a través de pytest en la línea de comandos.
La configuración de Pylint puede ser un poco abrumadora, así que este tutorial de pylint.readthedocs.io puede ayudarte a empezar, igual que este resumen de Calidad del código: herramientas y buenas prácticas de Real Python.
Pytest se puede instalar y actualizar con la utilidad integrada de Python pip.
Para obtener más consejos, Brett Cannon tiene una buena guía rápida y sencilla sobre cómo instalar paquetes para Python, junto con una excelente explicación de por qué deberías usar python -m pip.
Para obtener más información sobre los argumentos de línea de comandos de Python, consulta línea de comandos y entorno en la documentación de Python.
Nota: Es posible que Python3 y py sean o no alias de Python en tu sistema.
Ajusta los comandos de instalación que aparecen a continuación en consecuencia.
Para instalar pytest en un entorno virtual, asegúrate de que el entorno esté activado antes de ejecutar los comandos.
De lo contrario, la instalación de pytest será global.
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 ...
Para comprobar si la instalación se ha realizado correctamente:
$ python3 -m pytest --version
pytest 8.3.3
Para ejecutar los tests, ve a la carpeta donde está guardado el ejercicio usando cd en tu terminal (sustituye <exercise-folder-location> a continuación por tu ruta).
$ cd <exercise-folder-location>
<exercise-folder-location> o la mayoría de las cosas entre corchetes angulares indican un valor de marcador de posición.
Una ruta o un nombre de fichero normal debe escribirse sin ningún corchete angular.
Por ejemplo: /Users/janedoe/exercism/python/exercises/concept/chaitanas-colossal-coaster (en sistemas *nix), C:\Users\janedoe\exercism\python\exercises\practice\hello-world\ (en Windows), myFolder o my_file.py.
El fichero que querrás ejecutar suele terminar en _test.py.
Este fichero contiene los tests de la solución del ejercicio y son los mismos tests que se ejecutan en el sitio web cuando se sube una solución.
A continuación, ejecuta el siguiente comando en tu terminal, sustituyendo <exercise_test.py> por la ubicación o el nombre del fichero de tests:
$ python3 -m pytest -o markers=task <exercise_test.py>
==================== 7 passed in 0.08s ====================
Si no usas pytest -o markers=task en el comando anterior, es posible que recibas warnings sobre «unknown markers» al ejecutar un test que usa nuestra sintaxis nueva.
Para evitar escribir pytest -o markers=task en cada test que ejecutes, puedes usar un fichero de configuración pytest.ini, que puedes descargar desde el nivel superior del directorio de la pista de Python: pytest.ini.
También puedes crear tu propio fichero pytest.ini con el siguiente contenido:
[pytest]
markers =
task: A concept exercise task.
Si colocas este fichero en el directorio raíz o de trabajo de los ejercicios de Exercism, se registrarán las marcas y se detendrán las advertencias.
Puedes encontrar más información sobre las marcas de pytest en la documentación de pytest sobre marcar funciones de test y en la documentación de pytest sobre trabajar con marcas personalizadas.
Puedes encontrar más información sobre cómo personalizar las configuraciones de pytest en la documentación de pytest sobre formatos de fichero de configuración
Cuando fallan los tests, pytest imprime en la terminal el texto de cada test fallido, junto con los valores return esperados y reales de cada uno.
A continuación tienes un ejemplo genérico de un test fallido:
$(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 ==========
Si realmente quieres ser específico sobre lo que pytest muestra en tu pantalla, aquí tienes algunos argumentos de línea de comandos útiles que te permiten configurar su comportamiento.
-v]Añadir el flag -v (verbose) devolverá tanto información del entorno como un resumen de los tests, además de los tests fallidos:
$(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]Usar el flag -x ejecutará los tests con normalidad, pero detendrá la ejecución en el primer fallo de test.
Esto ayuda cuando quieres depurar una sola tarea o un solo fallo de test cada vez:
$(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]El complemento pytest-cache recuerda qué tests fallaron la última vez que ejecutaste pytest, así que usar el flag --ff le indicará a pytest que ejecute primero los tests que fallaron antes y, después, continúe con el resto de los tests.
Esto puede acelerar tus pruebas si estás haciendo muchos arreglos pequeños en torno a una tarea concreta o a un conjunto de entradas.
$(my_venv) python3 -m pytest -o markers=task --ff <example_file_test.py>
==================== 7 passed in 503s ====================
Recomendamos usar los siguientes comandos para que tu depuración sea más fácil y (posiblemente) más rápida:
Primero, cambia tu directorio de trabajo al directorio del ejercicio que quieres probar:
$(my_venv) cd path/to/exercise
Después, ejecuta los tests junto con los argumentos -x y --ff explicados anteriormente:
$(my_venv) python3 -m pytest -o markers=task -x --ff <example_file_test.py>
Esto probará tu solución.
Cuando pytest se encuentre con un test fallido, el programa se detendrá y te dirá qué test ha fallado.
Cuando hagas arreglos y vuelvas a ejecutar el test, pytest ejecutará primero el test que falló antes y, después, continuará con el resto de los tests.
Si quieres «depurar como un profesional», puedes usar el argumento --pdb después del comando pytest y pasar al depurador de Python integrado, PDB.
$(my_venv) python3 -m pytest -o markers=task -x --ff --pdb <example_file_test.py>
=============== 4 passed in 0.15s ===============
Cuando falla un test, pasar a PDB te permitirá recorrer tu código paso a paso viendo el scope actual, además de comprobar el valor de las variables y la firma de distintas funciones.
Puedes encontrar más detalles sobre el módulo PDB en la documentación de Python sobre PDB.
Además, la documentación de pytest sobre PDB y esta guía de Real Python son muy útiles.
Si quieres ampliar tu IDE con algunas herramientas que te ayuden a probar y mejorar tu código, consulta la página de herramientas. Allí exploramos varios IDE, editores y algunas extensiones útiles para el linting y la depuración.
Nota: Si has instalado Python en Windows mediante el instalador de la PSF, el comando será py en lugar de python3.
Escribir python3 -m cada vez que quieres ejecutar un módulo puede resultar un poco molesto.
Para evitarlo, puedes añadir la carpeta Scripts de tu instalación de Python a tu PATH.
Si no sabes dónde has instalado Python, ejecuta el siguiente comando en tu terminal:
$ python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
<python_directory>
El directorio devuelto es donde está instalada tu versión de Python activa actual; en esta sección se hace referencia a él como <python_directory>.
Haz clic en el botón Windows Start y busca Edit the system environment variables y pulsa Intro.
A continuación, pulsa Environment Variables...:

Después, busca la variable Path en tus variables de usuario, selecciónala y haz clic en Edit...:

A continuación, añade una nueva línea, como se muestra en la imagen, sustituyendo <python_directory> por el directorio de tu instalación de Python:

Lo siguiente debería funcionar en la mayoría de las distribuciones de Linux y MacOS con un shell bash.
Los comandos pueden variar según la distribución de Linux y según se use un shell fish o zsh.
Sustituye <python_directory> por la salida de python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
export PATH="$PATH:<python_directory>"