Estoy escribiendo algunos casos de prueba para mi aplicación usando unittest de Python. Ahora necesito comparar una lista de objetos con una lista de otros objetos para verificar si los objetos de la primera lista son lo que estoy esperando.

¿Cómo puedo escribir un método personalizado .assertFoo()? Que debe hacer ¿Debería plantear una excepción en caso de fracaso? En caso afirmativo, ¿qué excepción? ¿Y cómo pasar el mensaje de error? ¿Debería el mensaje de error ser una cadena unicode o una cadena de bytes?

Desafortunadamente, la documentación oficial no explica cómo escribir métodos de afirmación personalizados.

Si necesita un ejemplo del mundo real para esto, continúe leyendo.


El código que estoy escribiendo es algo así:

def assert_object_list(self, objs, expected):
    for index, (item, values) in enumerate(zip(objs, expected)):
        self.assertEqual(
            item.foo, values[0],
            'Item {0}: {1} != {2}'.format(index, item.foo, values[0])
        )
        self.assertEqual(
            item.bar, values[1],
            'Item {0}: {1} != {2}'.format(index, item.bar, values[1])
        )

def test_foobar(self):
    objs = [...]  # Some processing here
    expected = [
        # Expected values for ".foo" and ".bar" for each object
        (1, 'something'),
        (2, 'nothing'),
    ]
    self.assert_object_list(objs, expected)

Este enfoque hace que sea extremadamente fácil describir los valores esperados de cada objeto de una manera muy compacta y sin necesidad de crear objetos completos.

Sin embargo ... Cuando un objeto falla la afirmación, no se comparan más objetos, y esto hace que la depuración sea un poco más difícil. Me gustaría escribir un método personalizado que compare incondicionalmente todos los objetos y luego muestre todos los objetos que fallaron, en lugar de solo el primero.

38
Denilson Sá Maia 11 jul. 2011 a las 23:54

3 respuestas

La mejor respuesta

Yo uso la herencia múltiple en estos casos. Por ejemplo:

Primero. Defino una clase con métodos que incorporarán.

import os

class CustomAssertions:
    def assertFileExists(self, path):
        if not os.path.lexists(path):
            raise AssertionError('File not exists in path "' + path + '".')

Ahora defino una clase que hereda de unittest.TestCase y CustomAssertion

import unittest

class MyTest(unittest.TestCase, CustomAssertions):
    def test_file_exists(self):
        self.assertFileExists('any/file/path')

if __name__ == '__main__':
    unittest.main()
36
Alan Cristhian 16 dic. 2013 a las 02:22

Debe crear su propia clase TestCase, derivada de unittest.TestCase. Luego ponga su método de afirmación personalizado en esa clase de caso de prueba. Si su prueba falla, genere un AssertionError. Tu mensaje debe ser una cadena. Si desea probar todos los objetos de la lista en lugar de detenerse ante una falla, recopile una lista de índices que fallan y, después del ciclo sobre todos los objetos, cree un mensaje de afirmación que resuma sus hallazgos.

18
Ned Batchelder 11 jul. 2011 a las 21:51

Solo un ejemplo para resumir con una prueba unitaria de comparación

import numpy as np
class CustomTestCase(unittest.TestCase):
    def npAssertAlmostEqual(self, first, second, rtol=1e-06, atol=1e-08):
        np.testing.assert_allclose(first, second, rtol=rtol, atol=atol)


class TestVector(CustomTestCase):
    def testFunction(self):
        vx = np.random.rand(size)
        vy = np.random.rand(size)
        self.npAssertAlmostEqual(vx, vy)
2
parisjohn 11 oct. 2017 a las 07:36