Ciao, sto cercando di capire come fare il mock di urlopen, in modo da testare il comportamento di una funzione, vorrei capire:
cosa sto sbagliando come rendere il codice testabile sia su python3 che su python2 il codice è il seguente: #!/usr/bin/env python # -*- coding: utf-8 -*- import tempfile import os try: # Python 3.x from unittest import mock from urllib.request import urlopen from urllib.error import URLError URLOPEN_MOCKPATH = 'urllib.request.urlopen' except ImportError: # Python 2.x import mock from urllib2 import urlopen from urllib2 import URLError URLOPEN_MOCKPATH = 'urllib2.urlopen' import pytest from pytest import raises def myfunc(url, filename): try: chkret = urlopen(url) except URLError: chkret = "" if chkret: result = chkret.read() with open(filename, mode='w') as wfile: wfile.write(result) else: with open(filename, mode='r') as rfile: result = rfile.read() return result @mock.patch(URLOPEN_MOCKPATH, autospec=True) def test_myfunc(mock_urlopen): # create a temp file tmp_dir = tempfile.mkdtemp() filename = os.path.join(tmp_dir, 'mycache.txt') with open(filename, mode='w') as w: w.write("Success! (from file)") # =========================================== mock_chkret = mock.Mock() mock_chkret.read.return_value = "Success! (from urlopen)" mock_urlopen.return_value = mock_chkret result = myfunc("http://myulr.it", filename) mock_urlopen.assert_called() mock_chkret.read.assert_called() assert result == "Success! (from urlopen)" # =========================================== mock_urlopen.return_value = URLError result = myfunc("http://myulr.it", filename) mock_urlopen.assert_called() assert result == "Success! (from file)" # remove temporary file and directory os.rm(filename) os.rmdir(tmp_dir) Quando eseguo i test ottengo: $ pytest tests/test_urlopen_mock.py ======================= test session starts ================================= platform linux -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 rootdir: /home/pietro/docdat/synapsees/src/synapsees-raspberry-git, inifile: collected 1 item tests/test_urlopen_mock.py F ======================= FAILURES ====================================== __________________________ test_myfunc _________________________________________ mock_urlopen = <function urlopen at 0x7ff54690c0d0> @mock.patch(URLOPEN_MOCKPATH, autospec=True) def test_myfunc(mock_urlopen): # create a temp file tmp_dir = tempfile.mkdtemp() filename = os.path.join(tmp_dir, 'mycache.txt') with open(filename, mode='w') as w: w.write("Success! (from file)") # =========================================== mock_chkret = mock.Mock() mock_chkret.read.return_value = "Success! (from urlopen)" mock_urlopen.return_value = mock_chkret result = myfunc("http://myulr.it", filename) > mock_urlopen.assert_called() tests/test_urlopen_mock.py:55: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.6/unittest/mock.py:197: in assert_called return mock.assert_called(*args, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _mock_self = <MagicMock name='urlopen' spec='function' id='140691438470928'> def assert_called(_mock_self): """assert that the mock was called at least once """ self = _mock_self if self.call_count == 0: msg = ("Expected '%s' to have been called." % self._mock_name or 'mock') > raise AssertionError(msg) E AssertionError: Expected 'urlopen' to have been called. /usr/lib/python3.6/unittest/mock.py:786: AssertionError ==================== 1 failed in 0.13 seconds =================== In sostanza sta ignorando il mio mock, e continua ad usare la funzione urlopen, infatti se commento le righe: mock_urlopen.assert_called() mock_chkret.read.assert_called() pytest fallisce perché restituisce il valore dal file e non da urlopen: $ pytest tests/test_urlopen_mock.py ==================== test session starts ============================ platform linux -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 rootdir: /home/pietro/docdat/synapsees/src/synapsees-raspberry-git, inifile: collected 1 item tests/test_urlopen_mock.py F ========================= FAILURES ============================= ____________________________ test_myfunc ________________________________ mock_urlopen = <function urlopen at 0x7f958ce380d0> @mock.patch(URLOPEN_MOCKPATH, autospec=True) def test_myfunc(mock_urlopen): # create a temp file tmp_dir = tempfile.mkdtemp() filename = os.path.join(tmp_dir, 'mycache.txt') with open(filename, mode='w') as w: w.write("Success! (from file)") # =========================================== mock_chkret = mock.Mock() mock_chkret.read.return_value = "Success! (from urlopen)" mock_urlopen.return_value = mock_chkret result = myfunc("http://myulr.it", filename) #mock_urlopen.assert_called() #mock_chkret.read.assert_called() > assert result == "Success! (from urlopen)" E AssertionError: assert 'Success! (from file)' == 'Success! (from urlopen)' E - Success! (from file) E ? ^^ E + Success! (from urlopen) E ? ^^ ++ + tests/test_urlopen_mock.py:58: AssertionError ================== 1 failed in 0.06 seconds ======================== Cosa sto sbagliando? come fare a far si che usi mock_urlopen? Al momento mi interessa far funzionare i test solo su python3, ma non sarebbe male riuscire a farli girare anche sotto python2, voi come fate di solito? Suggerimenti? Grazie Pietro _______________________________________________ Python mailing list Python@lists.python.it https://lists.python.it/mailman/listinfo/python