Cómo probar en el track de Python

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.

Instalar pytest

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.

Windows

PS C:\Users\foobar> py -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...

Linux / MacOS

$ 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

Ejecutar los tests

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>

Note

<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 ====================

Solucionar las advertencias

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

Fallos en los tests

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 ==========

Argumentos adicionales

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.

Mostrar todos los detalles [-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

.......

Detenerse tras el primer fallo [-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 ==========

Los tests fallidos primero [--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 ====================

Flujo de trabajo recomendado

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.

Usar PDB, el depurador de Python, con pytest

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.

Ampliar tu IDE

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.

Información adicional

Añadir Python a tu PATH

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>.

Windows

Haz clic en el botón Windows Start y busca Edit the system environment variables y pulsa Intro. A continuación, pulsa Environment Variables...:

Pulsa el botón azul, jaja

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

Selección de la variable Path

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:

Añadir Python a la ruta

MacOS/Linux

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>"