Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> python

Tutorial de PyTest:Qué es, Cómo instalar, Framework, Aserciones

¿Qué es PyTest?

PyTest es un marco de prueba que permite a los usuarios escribir códigos de prueba utilizando el lenguaje de programación Python. Le ayuda a escribir casos de prueba simples y escalables para bases de datos, API o UI. PyTest se utiliza principalmente para escribir pruebas para API. Ayuda a escribir pruebas desde pruebas unitarias simples hasta pruebas funcionales complejas.

¿Por qué usar PyTest?

Algunas de las ventajas de pytest son

En este tutorial de Python PyTest, aprenderá:

Cómo instalar PyTest

El siguiente es un proceso sobre cómo instalar PyTest:

Paso 1) Puede instalar pytest por

pip install pytest==2.9.1

Una vez completada la instalación, puede confirmarla con por

py.test -h

Esto mostrará la ayuda

Primer PyTest básico

Ahora, aprenderemos a usar Pytest con un ejemplo básico de PyTest.

Cree una carpeta study_pytest. Vamos a crear nuestros archivos de prueba dentro de esta carpeta.

Navegue a esa carpeta en su línea de comando.

Cree un archivo llamado test_sample1.py dentro de la carpeta

Agregue el siguiente código y guárdelo

import pytest
def test_file1_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed"
def test_file1_method2():
	x=5
	y=6
	assert x+1 == y,"test failed" 

Ejecute la prueba usando el comando

py.test

Obtendrá resultados como

test_sample1.py F.
============================================== FAILURES ========================================
____________________________________________ test_sample1 ______________________________________
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed"
E       AssertionError: test failed
E       assert 5 == 6
test_sample1.py:6: AssertionError

Aquí en test_sample1.py F.

F dice fracaso

Punto(.) dice éxito.

En la sección de fallas, puede ver los métodos fallidos y la línea de falla. Aquí x==y significa 5==6 que es falso.

A continuación, en este tutorial de PyTest, aprenderemos sobre la aserción en PyTest.

Afirmaciones en PyTest

Las aserciones de Pytest son comprobaciones que devuelven el estado Verdadero o Falso. En Python Pytest, si una aserción falla en un método de prueba, entonces la ejecución del método se detiene allí. El código restante en ese método de prueba no se ejecuta y las afirmaciones de Pytest continuarán con el siguiente método de prueba.

Ejemplos de afirmaciones de Pytest:

assert "hello" == "Hai" is an assertion failure.
assert 4==4 is a successful assertion
assert True is a successful assertion
assert False is an assertion failure.

Considere

assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

Coloque este código en test_file1_method1() en lugar de la afirmación

assert x == y,"test failed"

Ejecutar la prueba arrojará el error como AssertionError:prueba fallida x=5 y=6

Cómo identifica PyTest los archivos de prueba y los métodos de prueba

Por defecto, pytest solo identifica los nombres de archivo que comienzan con test_ o terminando en _test como los archivos de prueba. Sin embargo, podemos mencionar explícitamente otros nombres de archivo (explicado más adelante). Pytest requiere que los nombres de los métodos de prueba comiencen con “test .” Todos los demás nombres de métodos serán ignorados incluso si solicitamos explícitamente ejecutar esos métodos.

Vea algunos ejemplos de nombres de archivo pytest válidos y no válidos

test_login.py - valid
login_test.py - valid
testlogin.py -invalid
logintest.py -invalid

Nota:Sí, podemos pedirle explícitamente a pytest que elija testlogin.py y logintest.py

Vea algunos ejemplos de métodos de prueba de pytest válidos e inválidos

def test_file1_method1(): - valid
def testfile1_method1(): - valid
def file1_method1(): - invalid	

Nota:Incluso si mencionamos explícitamente file1_method1(), pytest no ejecutará este método.

Ejecute varias pruebas desde un archivo específico y varios archivos

Actualmente, dentro de la carpeta study_pytest, tenemos un archivo test_sample1.py. Supongamos que tenemos varios archivos, digamos test_sample2.py, test_sample3.py. Para ejecutar todas las pruebas de todos los archivos en la carpeta y subcarpetas, solo necesitamos ejecutar el comando pytest.

py.test

Esto ejecutará todos los nombres de archivo que comienzan con test_ y los nombres de archivo que terminan con _test en esa carpeta y subcarpetas debajo de esa carpeta.

Para ejecutar pruebas solo desde un archivo específico, podemos usar py.test

py.test test_sample1.py

Ejecutar un subconjunto de la prueba completa con PyTest

A veces no queremos ejecutar todo el conjunto de pruebas. Pytest nos permite ejecutar pruebas específicas. Podemos hacerlo de 2 maneras

Ya tenemos test_sample1.py. Cree un archivo test_sample2.py y agréguele el siguiente código

def test_file2_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
def test_file2_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

Así que tenemos actualmente

  • test_sample1.py
    • test_file1_method1()
    • test_file1_method2()
  • test_sample2.py
    • test_file2_method1()
    • test_file2_method2()

Opción 1) Ejecutar pruebas por coincidencia de subcadenas

Aquí, para ejecutar todas las pruebas que tienen el método 1 en su nombre, tenemos que ejecutar

py.test -k method1 -v
-k <expression> is used to represent the substring to match
-v increases the verbosity

Entonces ejecutar py.test -k method1 -v le dará el siguiente resultado

test_sample2.py::test_file2_method1 FAILED
test_sample1.py::test_file1_method1 FAILED

============================================== FAILURES ==============================================
_________________________________________ test_file2_method1 _________________________________________
    def test_file2_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
test_sample2.py:5: AssertionError

_________________________________________ test_file1_method1 _________________________________________
    @pytest.mark.only
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
test_sample1.py:8: AssertionError

================================= 2 tests deselected by '-kmethod1' ==================================
=============================== 2 failed, 2 deselected in 0.02 seconds ===============================

Aquí puede ver hacia el final 2 pruebas deseleccionadas por '-kmethod1' que son test_file1_method2 y test_file2_method2

Intenta correr con varias combinaciones como:-

py.test -k method -v - will run all the four methods
py.test -k methods -v – will not run any test as there is no test name matches the substring 'methods'

Opción 2) Ejecutar pruebas por marcadores

Pytest nos permite establecer varios atributos para los métodos de prueba usando marcadores de pytest, @pytest.mark. Para usar marcadores en el archivo de prueba, necesitamos importar pytest en los archivos de prueba.

Aquí aplicaremos diferentes nombres de marcadores a los métodos de prueba y ejecutaremos pruebas específicas basadas en los nombres de los marcadores. Podemos definir los marcadores en cada nombre de prueba usando

@pytest.mark.<name>.			

Estamos definiendo los marcadores set1 y set2 en los métodos de prueba y ejecutaremos la prueba usando los nombres de los marcadores. Actualice los archivos de prueba con el siguiente código

prueba_muestra1.py

import pytest
@pytest.mark.set1
def test_file1_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

@pytest.mark.set2
def test_file1_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

prueba_muestra2.py

import pytest
@pytest.mark.set1
def test_file2_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

@pytest.mark.set1
def test_file2_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

Podemos ejecutar la prueba marcada por

py.test -m <name>
-m <name> mentions the marker name

Ejecute py.test -m set1. Esto ejecutará los métodos test_file1_method1, test_file2_method1, test_file2_method2.

Ejecutar py.test -m set2 ejecutará test_file1_method2.

Ejecutar pruebas en paralelo con Pytest

Por lo general, un conjunto de pruebas tendrá múltiples archivos de prueba y cientos de métodos de prueba que llevarán una cantidad considerable de tiempo para ejecutarse. Pytest nos permite ejecutar pruebas en paralelo.

Para eso, primero debemos instalar pytest-xdist ejecutando

pip install pytest-xdist

Puede ejecutar pruebas ahora

py.test -n 4

-n ejecuta las pruebas utilizando varios trabajadores. En el comando anterior, habrá 4 trabajadores para ejecutar la prueba.

Accesorios Pytest

Los accesorios se utilizan cuando queremos ejecutar algún código antes de cada método de prueba. Entonces, en lugar de repetir el mismo código en cada prueba, definimos accesorios. Por lo general, los accesorios se utilizan para inicializar las conexiones de la base de datos, pasar la base, etc.

Un método se marca como un accesorio Pytest al marcarlo con

@pytest.fixture

Un método de prueba puede usar un dispositivo Pytest mencionando el dispositivo como un parámetro de entrada.

Cree un nuevo archivo test_basic_fixture.py con el siguiente código

import pytest
@pytest.fixture
def supply_AA_BB_CC():
	aa=25
	bb =35
	cc=45
	return [aa,bb,cc]

def test_comparewithAA(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

Aquí

Cada una de las funciones de prueba tiene un argumento de entrada cuyo nombre coincide con un dispositivo disponible. Pytest luego invoca el método de fijación correspondiente y los valores devueltos se almacenarán en el argumento de entrada, aquí la lista [25,35,45]. Ahora los elementos de la lista se están utilizando en los métodos de prueba para la comparación.

Ahora ejecute la prueba y vea el resultado

 py.test test_basic_fixture
test_basic_fixture.py::test_comparewithAA FAILED                                                                                                                                                                                       
test_basic_fixture.py::test_comparewithBB PASSED                                                                                                                                                                                       
test_basic_fixture.py::test_comparewithCC FAILED
                                                                                                                                                                                       
============================================== FAILURES ==============================================
_________________________________________ test_comparewithAA _________________________________________
supply_AA_BB_CC = [25, 35, 45]
    def test_comparewithAA(supply_AA_BB_CC):
    	zz=35
>   	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"
E    AssertionError: aa and zz comparison failed
E    assert 25 == 35
test_basic_fixture.py:10: AssertionError

_________________________________________ test_comparewithCC _________________________________________
supply_AA_BB_CC = [25, 35, 45]
    def test_comparewithCC(supply_AA_BB_CC):
    	zz=35
>   	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
E    AssertionError: cc and zz comparison failed
E    assert 45 == 35
test_basic_fixture.py:16: AssertionError
================================= 2 failed, 1 passed in 0.05 seconds =================================

La prueba test_comparewithBB se pasa desde zz=BB=35, y las 2 pruebas restantes fallan.

El método fixture tiene un alcance solo dentro de ese archivo de prueba en el que está definido. Si tratamos de acceder al accesorio en algún otro archivo de prueba, obtendremos un error que dice que el accesorio ‘supply_AA_BB_CC’ no se encuentra para los métodos de prueba en otros archivos.

Para usar el mismo dispositivo en varios archivos de prueba, crearemos métodos de dispositivo en un archivo llamado conftest.py.

Veamos esto con el siguiente ejemplo de PyTest. Cree 3 archivos conftest.py, test_basic_fixture.py, test_basic_fixture2.py con el siguiente código

concurso.py

import pytest
@pytest.fixture
def supply_AA_BB_CC():
	aa=25
	bb =35
	cc=45
	return [aa,bb,cc]

test_basic_fixture.py

import pytest
def test_comparewithAA(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

test_basic_fixture2.py

import pytest
def test_comparewithAA_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

pytest primero buscará el accesorio en el archivo de prueba y, si no lo encuentra, lo buscará en conftest.py

Ejecute la prueba con py.test -k test_comparewith -v para obtener el resultado que se muestra a continuación

test_basic_fixture.py::test_comparewithAA FAILED  
test_basic_fixture.py::test_comparewithBB PASSED 
test_basic_fixture.py::test_comparewithCC FAILED 
test_basic_fixture2.py::test_comparewithAA_file2 PASSED 
test_basic_fixture2.py::test_comparewithBB_file2 FAILED 
test_basic_fixture2.py::test_comparewithCC_file2 FAILED

Prueba parametrizada de Pytest

El propósito de parametrizar una prueba es ejecutar una prueba contra múltiples conjuntos de argumentos. Podemos hacer esto con @pytest.mark.parametrize.

Veremos esto con el siguiente ejemplo de PyTest. Aquí pasaremos 3 argumentos a un método de prueba. Este método de prueba agregará los primeros 2 argumentos y los comparará con el tercer argumento.

Cree el archivo de prueba test_addition.py con el siguiente código

import pytest
@pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
def test_add(input1, input2, output):
	assert input1+input2 == output,"failed"

Aquí el método de prueba acepta 3 argumentos:entrada1, entrada2, salida. Agrega input1 y input2 y compara con la salida.

Ejecutemos la prueba con py.test -k test_add -v y veamos el resultado

test_addition.py::test_add[5-5-10] PASSED                                                                                                                                                                                              
test_addition.py::test_add[3-5-12] FAILED                                                                                                                                                                                              
============================================== FAILURES ==============================================
__________________________________________ test_add[3-5-12] __________________________________________
input1 = 3, input2 = 5, output = 12
    @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
    def test_add(input1, input2, output):
>   	assert input1+input2 == output,"failed"
E    AssertionError: failed
E    assert (3 + 5) == 12
test_addition.py:5: AssertionError

Puede ver que las pruebas se realizaron 2 veces:una comprobando 5+5 ==10 y otra comprobando 3+5 ==12

test_addition.py::test_add[5-5-10] APROBADO

test_addition.py::test_add[3-5-12] FALLIDO

Pytest Xfail/Omitir pruebas

Habrá algunas situaciones en las que no queremos ejecutar una prueba, o un caso de prueba no es relevante para un momento determinado. En esas situaciones, tenemos la opción de Xfail la prueba u omitir las pruebas

La prueba xfailed se ejecutará, pero no se contará como parte de las pruebas fallidas o aprobadas. No se mostrará ningún rastreo si esa prueba falla. Podemos xfail pruebas usando

@pytest.mark.xfail.

Omitir una prueba significa que la prueba no se ejecutará. Podemos omitir pruebas usando

@pytest.mark.skip.

Edite test_addition.py con el siguiente código

import pytest
@pytest.mark.skip
def test_add_1():
	assert 100+200 == 400,"failed"

@pytest.mark.skip
def test_add_2():
	assert 100+200 == 300,"failed"

@pytest.mark.xfail
def test_add_3():
	assert 15+13 == 28,"failed"

@pytest.mark.xfail
def test_add_4():
	assert 15+13 == 100,"failed"

def test_add_5():
	assert 3+2 == 5,"failed"

def test_add_6():
	assert 3+2 == 6,"failed"

Aquí

Ejecute la prueba con py.test test_addition.py -v y vea el resultado

test_addition.py::test_add_1 SKIPPED
test_addition.py::test_add_2 SKIPPED
test_addition.py::test_add_3 XPASS
test_addition.py::test_add_4 xfail
test_addition.py::test_add_5 PASSED
test_addition.py::test_add_6 FAILED

============================================== FAILURES ==============================================
_____________________________________________ test_add_6 _____________________________________________
    def test_add_6():
>   	assert 3+2 == 6,"failed"
E    AssertionError: failed
E    assert (3 + 2) == 6
test_addition.py:24: AssertionError

================ 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.07 seconds =================

XML de resultados

Podemos crear resultados de prueba en formato XML que podemos enviar a los servidores de integración continua para su posterior procesamiento, etc. Esto se puede hacer por

py.test prueba_muestra1.py -v –junitxml=”resultado.xml”

El result.xml registrará el resultado de la ejecución de la prueba. Encuentre un resultado de muestra.xml a continuación

<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" failures="1" name="pytest" skips="0" tests="2" time="0.046">
   <testcase classname="test_sample1" file="test_sample1.py" line="3" name="test_file1_method1" time="0.001384973526">
     <failure message="AssertionError:test failed because x=5 y=6 assert 5 ==6">
    @pytest.mark.set1
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
         test_sample1.py:9: AssertionError
    </failure>
   </testcase>
   <testcase classname="test_sample1" file="test_sample1.py" line="10" name="test_file1_method2" time="0.000830173492432" />
</testsuite>

De podemos ver un total de dos pruebas de las cuales una falla. Debajo puede ver los detalles de cada prueba ejecutada bajo la etiqueta .

Pytest Framework probando una API

Ahora crearemos un pequeño marco pytest para probar una API. La API utilizada aquí es gratuita de https://reqres.in/. Este sitio web es solo para proporcionar una API comprobable. Este sitio web no almacena nuestros datos.

Aquí escribiremos algunas pruebas para

Crea los siguientes archivos con el código dado

conftest.py:tenga un accesorio que proporcione la URL base para todos los métodos de prueba

import pytest
@pytest.fixture
def supply_url():
	return "https://reqres.in/api"

test_list_user.py:contiene los métodos de prueba para enumerar usuarios válidos e inválidos

import pytest
import requests
import json
@pytest.mark.parametrize("userid, firstname",[(1,"George"),(2,"Janet")])
def test_list_valid_user(supply_url,userid,firstname):
	url = supply_url + "/users/" + str(userid)
	resp = requests.get(url)
	j = json.loads(resp.text)
	assert resp.status_code == 200, resp.text
	assert j['data']['id'] == userid, resp.text
	assert j['data']['first_name'] == firstname, resp.text

def test_list_invaliduser(supply_url):
	url = supply_url + "/users/50"
	resp = requests.get(url)
	assert resp.status_code == 404, resp.text

test_login_user.py:contiene métodos de prueba para probar la funcionalidad de inicio de sesión.

import pytest
import requests
import json
def test_login_valid(supply_url):
	url = supply_url + "/login/" 
	data = {'email':'[email protected]','password':'something'}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 200, resp.text
	assert j['token'] == "QpwL5tke4Pnpja7X", resp.text

def test_login_no_password(supply_url):
	url = supply_url + "/login/" 
	data = {'email':'[email protected]'}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 400, resp.text
	assert j['error'] == "Missing password", resp.text

def test_login_no_email(supply_url):
	url = supply_url + "/login/" 
	data = {}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 400, resp.text
	assert j['error'] == "Missing email or username", resp.text

Ejecute la prueba usando py.test -v

Ver el resultado como

test_list_user.py::test_list_valid_user[1-George] PASSED                                                                                                                                                                               
test_list_user.py::test_list_valid_user[2-Janet] PASSED                                                                                                                                                                                
test_list_user.py::test_list_invaliduser PASSED                                                                                                                                                                                        
test_login_user.py::test_login_valid PASSED                                                                                                                                                                                            
test_login_user.py::test_login_no_password PASSED                                                                                                                                                                                      
test_login_user.py::test_login_no_email PASSED

Actualiza las pruebas y prueba varias salidas

Resumen

En este tutorial de PyTest, cubrimos


python

  1. Cómo instalar WordPress en Google Cloud
  2. Tutorial del marco de automatización de pruebas de IU codificadas
  3. ¿Qué es una llave de seguridad de red? ¿Cómo encontrarlo?
  4. ¿Qué son las llamadas WiFi? ¿Cómo funciona?
  5. ¿Qué es 6G y qué tan rápido será?
  6. Cómo instalar un nivelador de muelle
  7. Prueba de descarga parcial:qué es y cómo funciona
  8. ¿Qué es la cavitación de la bomba y cómo la evito?
  9. ¿Qué es la soldadura fuerte de cobre y cómo hacerla?
  10. ¿Qué es la acumulación de mantenimiento? ¿Cómo superarlo?
  11. ¿Qué es un probador de tubo de vacío?