una que propias procedimientos por pasar parametros parametro omision metodos lista funciones como argumentos python unit-testing python-unittest python-unittest.mock

que - parametros por omision python



Python simulacro call_args_list desempaquetando tuplas para afirmar en argumentos (2)

Creo que muchas de las dificultades aquí están envueltas en el tratamiento del objeto "llamado". Se puede considerar como una tupla con 2 miembros (args, kwargs) y, por lo tanto, con frecuencia es agradable descomprimirlo:

args, kwargs = call

Una vez desempaquetado, puede hacer sus afirmaciones por separado para args y kwargs (ya que una es una tupla y la otra es un dict)

def test_foo(self): def foo(fn): fn(''PASS and some other stuff'') f = Mock() foo(f) foo(f) foo(f) for call in f.call_args_list: args, kwargs = call self.assertTrue(all(a.startswith(''PASS'') for a in args))

Tenga en cuenta que a veces la tersidad no es útil (por ejemplo, si hay un error):

for call in f.call_args_list: args, kwargs = call for a in args: self.assertTrue(a.startswith(''PASS''), msg="%s doesn''t start with PASS" % a)

Tengo algunos problemas para lidiar con la tupla anidada que devuelve Mock.call_args_list .

def test_foo(self): def foo(fn): fn(''PASS and some other stuff'') f = Mock() foo(f) foo(f) foo(f) for call in f.call_args_list: for args in call: for arg in args: self.assertTrue(arg.startswith(''PASS''))

Me gustaría saber si hay una mejor manera de desempaquetar esa call_args_list en el objeto simulado para poder hacer mi afirmación. Este bucle funciona, pero parece que debe haber un camino más directo.


Una mejor manera podría ser construir las llamadas esperadas y luego usar una afirmación directa:

>>> from mock import call, Mock >>> f = Mock() >>> f(''first call'') <Mock name=''mock()'' id=''31270416''> >>> f(''second call'') <Mock name=''mock()'' id=''31270416''> >>> expected_calls = [call(s + '' call'') for s in (''first'', ''second'')] >>> f.assert_has_calls(expected_calls)

Tenga en cuenta que las llamadas deben ser secuenciales, si no desea eso, entonces anule el any_order any_order a la aserción.

También tenga en cuenta que está permitido que haya llamadas adicionales antes o después de las llamadas especificadas. Si no quieres eso, deberás agregar otra aserción:

>>> assert f.call_count == len(expected_calls)

Abordando el comentario de mgilson, aquí hay un ejemplo de cómo crear un objeto ficticio que puede usar para las comparaciones de igualdad de comodines:

>>> class AnySuffix(object): ... def __eq__(self, other): ... try: ... return other.startswith(''PASS'') ... except Exception: ... return False ... >>> f = Mock() >>> f(''PASS and some other stuff'') <Mock name=''mock()'' id=''28717456''> >>> f(''PASS more stuff'') <Mock name=''mock()'' id=''28717456''> >>> f("PASS blah blah don''t care") <Mock name=''mock()'' id=''28717456''> >>> expected_calls = [call(AnySuffix())]*3 >>> f.assert_has_calls(expected_calls)

Y un ejemplo del modo de fallo:

>>> Mock().assert_has_calls(expected_calls) AssertionError: Calls not found. Expected: [call(<__main__.AnySuffix object at 0x1f6d750>), call(<__main__.AnySuffix object at 0x1f6d750>), call(<__main__.AnySuffix object at 0x1f6d750>)] Actual: []