No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Flask

Curso de Flask

Bernardo Cassina

Bernardo Cassina

Pruebas básicas con Flask-testing

20/36
Recursos

La etapa de pruebas se denomina testing y se trata de una investigación exhaustiva, no solo técnica sino también empírica, que busca reunir información objetiva sobre la calidad de un proyecto de software, por ejemplo, una aplicación móvil o un sitio web.

El objetivo del testing no solo es encontrar fallas sino también aumentar la confianza en la calidad del producto, facilitar información para la toma de decisiones y detectar oportunidades de mejora.

Aportes 45

Preguntas 24

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Para probar si un mensaje fue flasheado pueden usar el método assert_message_flashed()

def test_user_registered_flashed_message(self):
    fake_form = {
        'username': 'vijoin',
        'password': '123456'
    }
    self.client.post(url_for('index'), data=fake_form)
    message = 'User registered successfully'
    self.assert_message_flashed(message)

Este método solo recibe el mensaje que quieres validar. Los mensajes flasheados ya están en el atributo self.flashed_messages luego de realizar el request

No se si a alguien le sucedió el mismo error que a mí.

La función self.assertRedirects extrae el atributo location del primer parámetro (“response”) , y del segundo revisa el netloc, que seria para ambos parámetros
localhost

Para esto usa la función urlparse, pero no toma el netloc, solo el path ‘/’ en index y ‘/hello’ .

Como no encuentra el netloc en el segundo parametro, le añade ‘localhost’, por lo que la comparación queda mal.

Posiblemente esto no ocurría en las versiones anteriores de Flask-Testing.

Así que modifique la función del modulo. Ya que en Visual Code se puede acceder a la función directamente ubicando el puntero en esta y presionando CTRL.

Aquí esta el código corregido. Sé que el código puede ser más prolijo pero priorice claridad de uso sobre limpieza.

Aquí esta el repositorio original:

jarus/flask-testing

https://pastebin.com/7CLNGK0h

La verdad nunca llegué a programar para una página web, empecé con Inteligencia artificial y ahora quise seguir con este mundo para ver como me va

Esto es lo que sucede cuando no se usa un control de versiones, para que tiene su requirements.txt si tiene version infinita? para saver que version de werkzeug tiene el prof 😕

Para correr pruebas desde Visual Studio Code solo haría falta agregar en el documento launch.json la siguiente configuración:

        {
            "name": "Python: Flask-testing",
            "type": "python",
            "request": "launch",
            "module": "flask",
            "env": {
                "FLASK_APP": "main.py",
                "FLASK_ENV": "development",
                "FLASK_DEBUG": "1"
            },
            "args": [
                "test"
            ],
            "jinja": true
        },

Y solo bastaría correr desde esta nueva configuración. Espero les sirva de algo 😉.

Hago las clases suponiendo entender algo de lo que hago pero no es el caso, en resumen, ni siquiera se si vaya a seguir esto, sería inútil…

Esta clase deberia de estar realizada con pytest y no con flask-testing. Quizá no tan conveniente en algunas cosas pero definitavamente más standar y future proof

Hola, no se si alguien me pueda ayudar, en el test del POST me sale el siguiente error:

FAIL: test_hello_post (test_base.MainTest)

Traceback (most recent call last):
File “/home/andresm/Escritorio/platzi-flask/tests/test_base.py”, line 33, in test_hello_post
self.assertRedirects(response, url_for(‘index’))
File “/home/andresm/Escritorio/platzi-flask/venv/lib/python3.6/site-packages/flask_testing/utils.py”, line 308, in assertRedirects
self.assertTrue(response.status_code in valid_status_codes, message or not_redirect)
AssertionError: False is not true : HTTP Status 301, 302, 303, 305, 307 expected but got 200

No se si sea porque cuando se hace el post luego se hace un get del index… este es el comportamiento del servidor cuando se hace el post:

127.0.0.1 - - [06/May/2020 17:05:50] “POST /hello HTTP/1.1” 302 -
127.0.0.1 - - [06/May/2020 17:05:50] “GET / HTTP/1.1” 302 -
Pepe
127.0.0.1 - - [06/May/2020 17:05:50] “GET /hello HTTP/1.1” 200 -
127.0.0.1 - - [06/May/2020 17:05:50] “GET /favicon.ico HTTP/1.1” 200 -

No se si a alguno le ha pasado.

sino me está redirigiendo a index, cómo puedo saber a donde me está mandando?

AssertionError: False is not true : HTTP Status 301, 302, 303, 305, 307 expected but got 200 obtuve este error corriendo el ultimo test.

Para quienes tengan al inicio, el siguiente error
TypeError: discover() missing 1 required positional argument: ‘start_dir’
Para el uso de la función discover se les realizan, los cambios en el código fueron los siguientes:
loader = unittest.TestLoader()
tests= loader.discover(’.’)
u=unittest.TextTestRunner()
u.run(tests)

😃

Ejecute flask test y empezó a ejecutar una lista interminable de comprobaciones. Aún esta corriendo tras 20 minutos de ejecución, no era que no tenía que correr nada?

Un poco más de flask-testing: https://pythonhosted.org/Flask-Testing/

Me encanto esta clase la verdad con esto se defiende uno total con unit test.
Utilizando este modelo seria necesario crear mocks para probar con set de datos supuestos que vienen ejemplo de una DB .
Seria genial material sobre este tema.

Cuando ejecuto el comando, mi máquina empieza como analizar todo los archivos, la verdad no se que esta pasando. A alguien mas se le pasó?

es una lista interminable, pero esto es de lo primero

⚡ flask test              
struct.pack:  b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00'
DEPRECATION WARNING: The system version of Tk is deprecated and may be removed in a future release. Please don't rely on it. Set TK_SILENCE_DEPRECATION=1 to suppress this warning.
test_sqlite: testing with version '2.6.0', sqlite_version '3.30.1'
__phello__.foo
_bootlocale
_collections_abc
_compat_pickle
_compression
_dummy_thread
_markupbase
_osx_support
_py_abc
_pydecimal
_pyio
_sitebuiltins
_strptime
_sysconfigdata_m_darwin_darwin
_threading_local
_weakrefset
abc
aifc
from flask_testing import TestCase
from flask import current_app,url_for
from main import app

class MainTest(TestCase):
  def create_app(self):
    app.config['TESTING']=True
    app.config['WTF_CSRF_ENABLED']=False
    return app

  def test_app_exists(self): #app existe
    self.assertIsNotNone(current_app) 
  
  def test_app_in_test_mode(self): #app esta en testing
    self.assertTrue(current_app.config['TESTING'])
  
  def test_index_redirects(self):  #verificar que el index si redirige a hello
    response= self.client.get(url_for('index'))
    self.assertRedirects(response, url_for('hello'))

  def test_hello_get(self): #hello regresa 200 cuando se hace get
    response= self.client.get(url_for('hello'))
    self.assert200(response)
  
  def test_hello_post(self): #hello verificacion de  post
    fake_form={
      'username':'fake' ,
      'password': 'fake-passw'
    }
    response = self.client.post(url_for('hello'), data=fake_form)
    self.assertRedirects(response,url_for('index'))```

Muy contento con este apartado de testing en flask, saludos desde Py.

UnitTest Busca todos los archivos que comienza con la palabra test

El self.client que me permite hacer http_requests viene en el TestCase?

Por si les sale este error:

ERROR: test_base (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: test_base

Se puede solucionar agregando las siguientes líneas en el main.py:

import werkzeug
werkzeug.cached_property = werkzeug.utils.cached_property```

Realmente no sé cuál es el público objetivo del docente en este curso, empieza a hablar de cosas que no ha explicado y termina uno copiando código por inercia…
Muy mal preparado este curso.

No entiendo muy bien el tema de test. ¿Cuál es el objetivo? ¿Qué información y como utilizo la información en caso de no pasar un test?

A la hora de ejecutar los tests, vamos a crear una aplicación del mismo modo que se crea cuando se lanza el servidor de Flask. Esta aplicación tomará los parámetros de configuración definidos en el fichero config/testing.py. Ábrelo y comprueba si su contenido es este:

from .default import *
# Parámetros para activar el modo debug
TESTING = True
DEBUG = True
APP_ENV = APP_ENV_TESTING
WTF_CSRF_ENABLED = False

Si te falta algún parámetro, añádelo de manera que tu fichero quede similar al que te muestro arriba. El significado de cada uno de los parámetros es el siguiente:
TESTING Deshabilita la captura de errores durante el manejo de peticiones para obtener mejores informes de error en los tests
DEBUG Activa el modo debug
APP_ENV Nombre del entorno de ejecución. En este caso ‘testing’
WTF_CSRF_ENABLED Lo establecemos a False para deshabilitar la protección CSRF durante los tests

Por otro lado, para los tests vamos a utilizar una base de datos diferente a la de desarrollo. Esto lo haremos debido a que cada vez que se ejecuta un test, crearemos y borraremos las tablas de la base de datos (para asegurar la correcta ejecución de los tests). De este modo, usando una base de datos diferente, podremos tener siempre nuestros datos de prueba a salvo.

La cadena de conexión a la base de datos la definiremos en el fichero instance/config-testing.py. Abre este fichero y añade la cadena de conexión (con los datos de tu propia base de datos):

SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:[email protected]:5432/miniblog_test'

Tuve que devolverme a esta clase, sin entender por que al hacer el Test Driven Development en todas las clases subsiguientes, nunca me funcionaron los test. Para darme cuenta de la importancia que tiene exportar la variable export

FLASK_APP=main.py

Creo que la confusión parte de que en determinado momento exporte la variable

FLASK_APP=test_base.py 

Esta parte se me había complicado, por esta pequeña sutileza.

Este video me ayudó muchísimo a comprender un poco más los CLI, en realidad son un concepto sencillo: https://www.youtube.com/watch?v=7yJbMfQMvRQ&t=3030s&ab_channel=codigofacilito

Genial!!!

El último test me arrija un error.
Mi código es de de abajo. No encuentro qué debo arreglar.

    def test_hello_post(self):
        """Cuando enviamos un post con la forma, debemos obtener un index"""
        fake_form={
            'username': 'fake',
            'password': 'fake-password'
                }
        response = self.client.post(url_for('hello'), data=fake_form)

        self.assertRedirects(response, url_for('index'))

Y el error:

flask test
...F.
======================================================================
FAIL: test_hello_post (test_base.MainTest)
Cuando enviamos un post con la forma, debemos obtener un index
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\jorge\OneDrive\Documents\Platzi\Curso_de_Flask\tests\test_base.py", line 42, in test_hello_post
    self.assertRedirects(response, url_for('index'))
  File "c:\users\jorge\onedrive\documents\platzi\curso_de_flask\venv\lib\site-packages\flask_testing\utils.py", line 313, in assertRedirects
    self.assertTrue(response.status_code in valid_status_codes, message or not_redirect)
AssertionError: False is not true : HTTP Status 301, 302, 303, 305, 307 expected but got 200

----------------------------------------------------------------------
Ran 5 tests in 0.058s

FAILED (failures=1)

👍👍👍

Si tienes este Error:

ImportError: Start directory is not importable: 'tests’

Debes cambiar esto:

@app.cli.command()
def test():
    tests = unittest.TestLoader().discover('tests')
    unittest.TextTestRunner.run(tests)

Por esto:

@app.cli.command()
def test():
    tests = unittest.TestLoader().discover('tests')
    u = unittest.TextTestRunner() 
    u.run(tests)

Esto sucede porque primero debes inicializar una instancia de la clase TextTestRunner y luego ahí si correr su método Run()

Para que me funcionara el test tuve que crear el archivo

__init__.py

en la carpeta de test

hola tengo problema el implementar flask- test
mi código.

@app.cli.command()
def test():
    tests = unittest.TestLoader().discorver('tests')
    unittest.TextTestRunner().run(tests) ```
 
y ya e corrido el comando "export FLASK_APP=main" y me sigue arrojando este error.
 

Usage: flask [OPTIONS] COMMAND [ARGS]…
Try ‘flask --help’ for help.

Error: No such command ‘test’.```

ModuleNotFoundError: No module named ´flask_testing´

Dentro del directorio test, el archivo test_base.py:

from flask_testing import TestCase

Alguien sabe el por qué?

Tengo el siguiente error:

cli: command line interface

Excelente ya voy entendiendo el tema de los testing

Excelente la etapa de testing.

Todo perfecto hasta el momento

En windows tenia el error :

python - unittest - ImportError: Start directory is not importable

Lo solucione creando un init.py en la carpeta tests

Totalmente Hermoso !

¿el metodo url_for recibe el nombre de la funcion en la cual esta el decorador de app.route? Por ejemplo si el decorador es ‘@app.route(’/hello’)’ y la funcion es def hello_world(), ¿el url_for recibe ‘hello_world’?
Estoy un poco confundido por eso, gracias

Uff Excelso

Se me ejecutan 41 test con el primer uso de flask test

Corri el comando flask test por primera vez y ejecuto 41 tests:

para los que les da el error

AssertionError: False is not true : HTTP Status 301, 302, 303, 305, 307 expected but got 200

a mi me dio ese error porque en mi archivo main yo tenía:

if login_form.validate_on_submit():
        user_name = login_form.user_name.data
        session['user_name'] = user_name

        flash('Nombre de usuario registrado con éxito') #los flashes hay que renderearlos en el html

        return redirect(url_for('index'))

y en el test tenía:

def test_hello_post(self):
        fake_form = {

            'username':'fake',
            'password': 'fake-pasword',

        }
        response = self.client.post(url_for('hello'), data=fake_form)
        self.assertRedirects(response, url_for('index'))

es dificil de ver, pero el formulario tiene que ser identico en el archivo main como en el archivo testing:
la solución fue cambiar ‘username’ del archivo testing a ‘user_name’

El CSRF (del inglés Cross-site request forgery o falsificación de petición en sitios cruzados) es un tipo de exploit malicioso de un sitio web en el que comandos no autorizados son transmitidos por un usuario en el cual el sitio web confía.