Monday, October 1, 2018

Temporary ftp server for testing

Leave a Comment

I want to write a test for my code which uses a ftp library and does upload data via ftp.

I would like to avoid the need for a real ftp server in my test.

What is the most simple way to test my code?

There are several edge-cases which I would like to test.

For example: my code tries to create a directory which already exists.

I want to catch the exception and do appropriate error handling.

I know that I could use the mocking library. I used it before. But maybe there is a better solution for this use case?

Update Why I don't want to do mocking: I know that I could use mocking to solve this. I could mock the library I use (I use ftputil from Stefan Schwarzer) and test my code this way. But what happens if I change my code and use a different ftp library in the future? Then I would need to re-write my testing code, too. I am lazy. I want to be able to rewrite the real code I am testing without touching the test code. But maybe I am still missing a cool way to use mocking.

2 Answers

Answers 1

Firstly to hey this or of the way. You aren't asking about Mocking, your question is about Faking.

  • Fake, an implementation of an interface, which expresses correct behaviour, but cannot be used in production.

  • Mock, an implementation of an interface that responds to interactions based on a scripted (script as in movie script, not uncompiled code) response.

  • Stub, an implementation of an interface lacking any real implementation. Usually used in mcguffin style tests.

Notice that in every case the word "interface" is used.

Your question asks how to Fake a TCP port such that the behaviour is a FTP server, with STATE of a rw filesystem underneath.

This is hard.

It is much easier to MOCK an internal interface that throws when you call the mkdir function.

If you must FAKE a FTP server. I suggest creating a docker container with the server in the state you want and use docker to handle the repeatability and lifecycle of the FTP server.

Answers 2

ContextManager:

class FTPServerContext(object):      banner = 'FTPServerContext ready'      def __init__(self, directory_to_serve):         self.directory_to_serve = directory_to_serve      def __enter__(self):         cmd = ['serve_directory_via_ftp']         self.pipe = subprocess.Popen(cmd, cwd=self.directory_to_serve)         time.sleep(2) # TODO check banner via https://stackoverflow.com/a/4896288/633961      def __exit__(self, *args):         self.pipe.kill() 

console_script:

def serve_directory_via_ftp():     # https://pyftpdlib.readthedocs.io/en/latest/tutorial.html     authorizer = DummyAuthorizer()     authorizer.add_user('testuser-ftp', 'testuser-ftp-pwd', '.', perm='elradfmwMT')     handler = FTPHandler     handler.authorizer = authorizer     handler.banner = testutils.FTPServerContext.banner     address = ('localhost', 2121)     server = FTPServer(address, handler)     server.serve_forever() 

Usage in test:

def test_execute_job_and_create_log(self):     temp_dir = tempfile.mkdtemp()     with testutils.FTPServerContext(temp_dir) as ftp_context:         execute_job_and_create_log(...) 

Code is in the public domain under any license you want. It would great if you make this a pip installable package at pypi.org.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment