¿Cómo puedo afirmar la igualdad de listas con pytest?

6 minutos de lectura

Estoy tratando de hacer algunas pruebas unitarias con pytest.

Estaba pensando en hacer cosas como esa:

actual = b_manager.get_b(complete_set)
assert actual is not None
assert actual.columns == ['bl', 'direction', 'day']

La primera afirmación está bien, pero con la segunda tengo un error de valor.

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Supongo que no es la forma correcta de afirmar la igualdad de dos listas diferentes con pytest.

¿Cómo puedo afirmar que las columnas del marco de datos (una lista) son iguales a las esperadas?

Gracias

  • El rastreo incluye una pista… Usar a.any() o a.all(). POR CIERTO assert no es la forma ‘normal’ de hacer unittesting

    – Chris_Rands

    24 de octubre de 2017 a las 15:28

  • @Chris_Rands assert es LA manera de probar los valores bajo pytest. pytest reescribe internamente el código de bytes de asserts y llama a su propia función de comparación.

    – Doctor

    24/10/2017 a las 16:25


  • Es actual.columns ¿una lista? El rastreo sugiere que es un bool.

    – Doctor

    24 de octubre de 2017 a las 16:29

  • real.columns es una lista de hecho. Después de investigar un poco, me di cuenta de que la comparación devuelve otra lista con valores booleanos para verificar si el contenido es diferente o no. [True, False, True, True ..].Y es por eso que tengo que usar .All() .. Para poder darle a Assert un booleano único, no una lista de booleanos

    – Ban

    25 de octubre de 2017 a las 8:46


  • @Chris_Rands Estoy usando pytest, no el marco de prueba de unidad incorporado. Entonces, ¿cuál debería ser una forma normal de hacer unittest?

    – Ban

    25 de octubre de 2017 a las 8:48

Ver este:

Nota:

Simplemente puede utilizar el assert declaración para afirmar las expectativas de la prueba. pytest Introspección de afirmación avanzada informará de forma inteligente los valores intermedios de la expresión de afirmación, liberándolo de la necesidad de aprender los muchos nombres de Métodos heredados de JUnit.

Y este:

Se realizan comparaciones especiales para una serie de casos:

  • comparando cadenas largas: se muestra una diferencia de contexto
  • comparación de secuencias largas: primeros índices fallidos
  • comparando dictados: diferentes entradas

Y el demostración de informes:

failure_demo.py:59: AssertionError
_______ TestSpecialisedExplanations.test_eq_list ________

self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>

    def test_eq_list(self):
>       assert [0, 1, 2] == [0, 1, 3]
E       assert [0, 1, 2] == [0, 1, 3]
E         At index 2 diff: 2 != 3
E         Use -v to get the full diff

Ver la afirmación de igualdad de listas con literal == ¿Por ahí? pytest ha hecho el trabajo duro por usted.

  • Buena respuesta. Debe ser el aceptado. Traiga ejemplos de código reales a la respuesta para que quede más claro.

    –Maxim Veksler

    1 de febrero de 2018 a las 8:55


  • Por alguna razón, recibo el mensaje de error de ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() aunque estoy usando pytest versión 4.3.0

    –Allen Wang

    5 de marzo de 2019 a las 0:19

  • @AllenWang es probable que uno o ambos valores para comparar sean matrices numpy. Parece que, en ese caso, pytest probaría el valor real de la matriz numpy resultante de la comparación, que es una matriz numpy de valores booleanos, y numpy generaría la advertencia anterior. Intenta envolver ambos valores con list().

    – Pomin Wu

    21 de marzo de 2019 a las 4:29

avatar de usuario
ritchie46

Podría hacer una lista de comprensión para verificar la igualdad de todos los valores. si llamas all en el resultado de las comprensiones de la lista, devolverá True si todos los parámetros son iguales.

actual = ['bl', 'direction', 'day']
expected = ['bl', 'direction', 'day']

assert len(actual) == len(expected)
assert all([a == b for a, b in zip(actual, expected)])

print(all([a == b for a, b in zip(actual, expected)]))

>>> True

  • @smerlung all() toma un iterable, la comparación de la lista devolvería un bool.

    – Tomas T.

    23 de febrero de 2018 a las 15:48

  • Se olvidó de la verificación de la longitud de la lista. La función zip () corta la salida por lista con un tamaño mínimo. reescriba real y configúrelo en [‘bl’, ‘direction’, ‘day’, ‘MYAHAHA’] o incluso [] y obtenga True también: P Intentaré reescribir su muestra.

    – Denis Barmenkov

    8 de octubre de 2020 a las 17:08


avatar de usuario
ggguser

Hay dos claves para responder a esta respuesta aparentemente simple:
Condiciones de igualdad y utilidad del error de afirmación.

Las condiciones de igualdad dependen de restricciones y requisitos dados. El error de aserción debe señalar la violación de esas condiciones.

Responde las siguientes preguntas:

  1. ¿Es importante el orden de las listas?

    son [1, 2] y [2, 1] ¿igual?

  2. ¿Pueden las listas tener duplicados?

    son [1, 2] y [1, 1, 2] ¿igual?

  3. ¿Hay elementos que no se pueden deshacer?

    ¿Hay algún tipo mutable?

  4. ¿Debe el error de aserción ser informativo y útil?

No, No, No, No: diferencia simétrica entre conjuntos

def test_nnnn():
    expected = [1, 2, 3]
    actual = [4, 3, 2, 1]
    difference = set(a) ^ set(b)
    assert not difference

E assert not {4, 5}

Es útil usar este método en listas grandes, porque es rápido y difference contendrá solo hm de diferencia entre ellos, por lo que AssertionError será compacto, sin embargo no informativo.

No, No, No, Sí: diferencia entre conjuntos con mensaje personalizado

def test_nnny():
    expected = [1, 2, 3, 4]
    actual = [5, 3, 2, 1]
    lacks = set(expected) - set(actual)
    extra = set(actual) - set(expected)
    message = f"Lacks elements {lacks} " if lacks else ''
    message += f"Extra elements {extra}" if extra else ''
    assert not message

E AssertionError: assert not 'Lacks elements {4} Extra elements {5}'

No, Sí, No, Sí: verifique si hay duplicados, que diferencia en conjuntos

Porque set() elimina los duplicados, debe verificarlos con anticipación usando esta respuesta:

def test_nyny():
    expected = [1, 2, 3, 4]
    actual = [1, 2, 3, 3, 5]

    seen = set()
    duplicates = list()
    for x in actual:
        if x in seen:
            duplicates.append(x)
        else:
            seen.add(x)

    lacks = set(expected) - set(actual)
    extra = set(actual) - set(expected)
    message = f"Lacks elements {lacks} " if lacks else ''
    message += f"Extra elements {extra} " if extra else ''
    message += f"Duplicate elements {duplicates}" if duplicates else ''
    assert not message

E AssertionError: assert not 'Lacks elements {4} Extra elements {5} Duplicate elements [3]'

Sí, Sí, Sí, No: comparar listas

def test_yyyn():
    expected = [1, 2, 3, 3, 3, {'a': 1}]
    actual = [3, 3, 2, 1, {'a': 1}]
    assert expected == actual

E AssertionError: assert [1, 2, 3, 3, 3, {'a': 1}] == [3, 3, 2, 1, {'a': 1}]

Sí, sí, sí, sí: bibliotecas adicionales

Echa un vistazo a DeepDiff

  • Esto no funciona para casos como a = [1,1,2] and b = [1, 2, 2]

    – Sixtyfootersdude

    9 de noviembre de 2020 a las 22:40

  • He actualizado mi respuesta. Depende de usted decidir qué parámetros de las listas tomar en comparación.

    – ggguser

    12 de noviembre de 2020 a las 9:03


  • sorted([1, {'a': 1}, 2, 3]) → “TypeError: ‘<' no soportado entre instancias de 'dict' e 'int'". sorted([{‘a’: 2}, {‘a’: 1}]) → “TypeError: ‘<' no soportado entre instancias de 'dict' y 'dict'".

    – l0b0

    27 de enero de 2021 a las 3:09


  • Gran respuesta. Muchísimas gracias.

    – EugZol

    10 de febrero de 2021 a las 17:20

  • @ l0b0: para ordenar podrías usar sorted(..., key=id)

    – Gerardo

    26 oct 2021 a las 6:46

avatar de usuario
adam erickson

En Python 3.9, esto debería funcionar ahora:

def test_arrays_equal():
    a = [1, 2, 3]
    b = [1, 2, 4]
    assert a == b

O bien, puede analizar las listas para numpy arrays y función de uso array_equal:

import numpy as np

def test_arrays_equal():
    a = [1, 2, 3]
    b = [1, 2, 4]
    ar = np.array(a)
    br = np.array(b)
    assert np.array_equal(ar, br)

  • Estoy usando pytest, no el paquete unittest integrado. Es por eso que no estoy usando assertListEqual..

    – Ban

    25 de octubre de 2017 a las 8:48


  • Vocación unittest.TestCase().assertCountEqual(first, second) en un caso de prueba pytest funciona bien. Obtendrá un mensaje de error algo peor (con rastreo desde dentro del método assertCountEqual) si la afirmación falla, pero de lo contrario no hay problema con eso.

    – usuario7610

    29 de julio de 2018 a las 21:05

  • Esta es la mejor respuesta para el caso general con orden sin sentido, posibles duplicados, registros de datos potencialmente no clasificables, tipos de datos potencialmente diferentes pero comparables pero no clasificables. Consulte también stackoverflow.com/a/45946306/11715259

    – N1ngu

    3 de febrero a las 11:46

convierta las matrices numpy en listas de python y obtendrá una mejor respuesta que simplemente usando all o any. De esta manera, si la prueba falla, verá cómo difieren lo esperado y lo real

avatar de usuario
AdityaS

También podrías usar https://github.com/AdityaSavara/UnitTesterSG que se puede obtener por pip UnitTesterSG

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad