[TIP] Struggling with pymock

Rod Hyde rod.hyde at gmail.com
Tue Sep 18 23:53:54 PDT 2007


Having decided to give pymock a try, I've run into a problem with
expectAndRaise(). My tests that use it keep failing with
RecordedCallsWereNotReplayedCorrectly and I'm beginning to wonder if
I'm doing something fundamentally wrong.

For example, I have a piece of code that attempts to make an FTP
connection to a server and retries if it isn't available. I wanted to
test the fact that it retries, so I wrote a test that uses
expectAndRaise().


Here's the test. The idea is that the connection isn't available on
the first attempt, but is available on the second attempt.

def test_do_work_retries_when_connection_down():
    HOST = 'host at somewhere.com'
    USER = 'user'
    PASSWORD = 'password'
    worker = ProblemWorker(HOST, USER, PASSWORD)
    controller = pymock.Controller()
    worker.make_ftp = controller.mock()
    controller.expectAndRaise(worker.make_ftp(HOST, USER, PASSWORD),
                              socket.error(10060, 'timed out'))
    conn = controller.mock()
    controller.expectAndReturn(worker.make_ftp(HOST, USER, PASSWORD),
                               conn)
    conn.set_pasv(True)
    conn.quit()
    controller.replay()
    worker.do_work()
    controller.verify()


And here's the cut-down piece of code that it is testing...

class ProblemWorker(object):

    def __init__(self, host, user, password):
        self.host = host
        self.user = user
        self.password = password
        self.make_ftp = ftplib.FTP

    def make_connection(self):
        while True:
            try:
                conn = self.make_ftp(self.host, self.user, self.password)
                conn.set_pasv(True)
                return conn
            except socket.error, e:
                if e.args[0] not in (10060, 10061):
                    raise
                # sleep(60)

    def do_work(self):
        conn = self.make_connection()
        # Do something useful here.
        conn.quit()


When I run the test, it fails as follows...

C:>nosetests test\test_hack_ftp.py
E
======================================================================
ERROR: test_hack_ftp.test_do_work_retries_when_connection_down
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\python25\lib\site-packages\nose-0.10.0b1-py2.5.egg\nose\case.py", lin
e 177, in runTest
    self.test(*self.arg)
  File "B:\python\WBI\StopWBI\test\test_hack_ftp.py", line 25, in test_do_work_r
etries_when_connection_down
    worker.do_work()
  File "B:\python\WBI\StopWBI\hack_ftp.py", line 24, in do_work
    conn = self.make_connection()
  File "B:\python\WBI\StopWBI\hack_ftp.py", line 15, in make_connection
    conn = self.make_ftp(self.host, self.user, self.password)
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 263, in __call__
    return self.__controller.recordOrPlayback(functionCall)
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 137, in recordOrPl
ayback
    return self.playback(action)
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 149, in playback
    exprValue = recordedAction.playback()
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 408, in playback
    super(FunctionCallAction, self).playback()
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 328, in playback
    self.playbackPolicy.playback()
  File "c:\python25\lib\site-packages\pymock\pymock.py", line 484, in playback
    raise RecordedCallsWereNotReplayedCorrectly()
RecordedCallsWereNotReplayedCorrectly

----------------------------------------------------------------------
Ran 1 test in 0.010s

FAILED (errors=1)


All my other test code which doesn't use expectAndRaise() works just
fine. Am I doing something fundamentally wrong here?

--- Rod



More information about the testing-in-python mailing list