python unit-testing mox

python - Mocking abierto(file_name) en pruebas unitarias



unit-testing mox (7)

Me tomé la libertad de volver a escribir tu función de muestra:

Suponga que su función se encuentra en un archivo llamado code.py

# code.py import csv import logging def ParseCsvFile(source): """Parse the csv file. Args: source: file to be parsed Returns: the list of dictionary entities; each dictionary contains attribute to value mapping or its equivalent. """ global rack_file rack_file = source attributes_list = [] try: rack_type_file = open(rack_file) except IOError, (errno, strerror): logging.error("I/O error(%s): %s", errno, strerror) else: reader = csv.DictReader(rack_type_file, delimiter='','') attributes_list = [line for line in reader] # list of dictionaries rack_type_file.close() return attributes_list

Un caso de prueba simple sería:

# your test file import __builtin__ import unittest import contextlib from StringIO import StringIO import mox import code @contextlib.contextmanager def mox_replayer(mox_instance): mox_instance.ReplayAll() yield mox_instance.VerifyAll() class TestParseCSVFile(unittest.TestCase): def setUp(self): self.mox = mox.Mox() def tearDown(self): self.mox.UnsetStubs() def test_parse_csv_file_returns_list_of_dicts(self): TEST_FILE_NAME = ''foo.csv'' self.mox.StubOutWithMock(__builtin__, ''open'') open(TEST_FILE_NAME).AndReturn(StringIO("name,age/nfoo,13")) with mox_replayer(self.mox): result = code.ParseCsvFile(TEST_FILE_NAME) self.assertEqual(result, [{''age'': ''13'', ''name'': ''foo''}]) # works! if __name__ == ''__main__'': unittest.main()

EDITAR:

% /usr/bin/python2.6 Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import __builtin__ >>> import mox >>> mock = mox.Mox() >>> mock.StubOutWithMock(__builtin__, ''open'') >>> mock.UnsetStubs()

Funciona bien en 2.6 usando mox 0.53

Tengo un código fuente que abre un archivo csv y configura un encabezado para valorar la asociación. El código fuente se da a continuación:

def ParseCsvFile(source): """Parse the csv file. Args: source: file to be parsed Returns: the list of dictionary entities; each dictionary contains attribute to value mapping or its equivalent. """ global rack_file rack_type_file = None try: rack_file = source rack_type_file = open(rack_file) # Need to mock this line. headers = rack_type_file.readline().split('','') length = len(headers) reader = csv.reader(rack_type_file, delimiter='','') attributes_list=[] # list of dictionaries. for line in reader: # More process to happeng. Converting the rack name to sequence. attributes_list.append(dict((headers[i], line[i]) for i in range(length))) return attributes_list except IOError, (errno, strerror): logging.error("I/O error(%s): %s" % (errno, strerror)) except IndexError, (errno, strerror): logging.error(''Index Error(%s), %s'' %(errno, strerror)) finally: rack_type_file.close()

Estoy tratando de burlarme de la siguiente declaración rack_type_file = open (rack_file) ¿Cómo me burlo de la función open (...)? Cualquier ayuda sería apreciada


>>> class A(object): ... def __init__(self): ... self.x = open(''test.py'') ... >>> old_open = open >>> def open(s): ... return "test/n" ... >>> a = A() >>> a.x ''test/n'' >>> open = old_open >>> a = A() >>> a.x <open file ''test.py'', mode ''r'' at 0xb7736230>


Para __builtin__ función incorporada abierta con mox use el módulo __builtin__ :

import __builtin__ # unlike __builtins__ this must be imported m = mox.Mox() m.StubOutWithMock(__builtin__, ''open'') open(''ftphelp.yml'', ''rb'').AndReturn(StringIO("fake file content")) m.ReplayAll() # call the code you want to test that calls `open` m.VerifyAll() m.UnsetStubs()

Tenga en cuenta que __builtins__ no es siempre un módulo, puede ser de tipo dict, por favor utilice el __builtin__ (sin "s") para referirse a los métodos integrados del sistema.

Más sobre el módulo __builtin__ : http://docs.python.org/library/ builtin .html


Hay dos formas en que me gusta hacer esto, dependiendo de la situación.

Si su prueba unitaria va a llamar a ParseCsvFile directamente, agregaría un nuevo kwarg a ParseCsvFile:

def ParseCsvFile(source, open=open): # ... rack_type_file = open(rack_file) # Need to mock this line.

Entonces su prueba unitaria puede pasar un open_func diferente para lograr la burla.

Si la prueba de su unidad llama a alguna otra función que a su vez llame a ParseCsvFile, pasar alrededor de open_func solo para las pruebas es feo. En ese caso, usaría el módulo simulado . Esto le permite modificar una función por nombre y reemplazarla por un objeto Mock.

# code.py def open_func(name): return open(name) def ParseCsvFile(source): # ... rack_type_file = open_func(rack_file) # Need to mock this line. # test.py import unittest import mock from StringIO import StringIO @mock.patch(''code.open_func'') class ParseCsvTest(unittest.TestCase): def test_parse(self, open_mock): open_mock.return_value = StringIO("my,example,input") # ...


Hola, estaba teniendo un problema similar, y me estaba arrancando el pelo moviéndome entre diferentes bibliotecas de burlas. Finalmente encontré una solución con la que estoy contento, ¿y quizás te pueda ayudar? Al final fui con la biblioteca de Mocker http://labix.org/mocker y aquí está el código para la burla abierta:

from mocker import Mocker from StringIO import StringIO import __builtin__ mocker = Mocker() sourceFile = ''myTestFile.txt'' __builtin__.open = mocker.mock() __builtin__.open(sourceFile) mocker.result(StringIO(''this,is,a,test,file'')) <the rest of your test setup goes here> mocker.replay() ParseCsvFile(sourceFile) mocker.restore() mocker.verify()

Incidentalmente, la razón por la que fui con Mocker es porque estaba probando una función que usaba abierta para leer un archivo, y luego la usé para sobrescribir el mismo archivo con nuevos datos. Lo que tenía que hacer era probar el caso en el que el archivo inicial no existía, así que configuró un simulacro, que lanzó un IOError la primera vez, y luego funcionó la segunda vez. La configuración para la cual se veía así:

from mocker import Mocker import __builtin__ mocker = Mocker() mockFileObject = mocker.mock() __builtin__.open = mocker.mock() __builtin__.open(''previousState.pkl'', ''r'') mocker.throw(IOError(''Boom'')) __builtin__.open(''previousState.pkl'',''w'') mocker.result(mockFileObject) <rest of test setup > mocker.replay() <test> mocker.restore() #required to restore the open method mocker.verify()

¡Espero que esto ayude!


Esta es ciertamente una vieja pregunta, por lo tanto, algunas de las respuestas están desactualizadas.

En la versión actual de la biblioteca mock hay una función de conveniencia diseñada precisamente para este propósito . Así es como funciona:

>>> from mock import mock_open >>> m = mock_open() >>> with patch(''__main__.open'', m, create=True): ... with open(''foo'', ''w'') as h: ... h.write(''some stuff'') ... >>> m.mock_calls [call(''foo'', ''w''), call().__enter__(), call().write(''some stuff''), call().__exit__(None, None, None)] >>> m.assert_called_once_with(''foo'', ''w'') >>> handle = m() >>> handle.write.assert_called_once_with(''some stuff'')

La documentación está aquí .


Es simple con el decorador (Python3):

def my_method(): with open(file="/1.txt", mode=''r'', encoding=''utf-8'') as file: return file.read().strip() @mock.patch("builtins.open", create=True) def test_my_method(mock_open): mock_open.side_effect = [ mock.mock_open(read_data="A").return_value ] resA = my_method() assert resA == "A" mock_open.mock_calls == [mock.call(file="/1.txt", mode=''r'', encoding=''utf-8'')]