Hi Stefan,
thank you for the nice ftputil library.
Please provide some docs how to test an application which does ftp transfer. It would be very nice if you could test the code without installing a real ftp server. This makes automated testing much easier.
Something like this:
ftp_host = MockedFTPHost(path_to_directory)
This way ftputil users can test the code without the need for a real ftp server.
Or do you have a different or better solution?
Thomas Güttler
Thanks for the thanks, you're welcome. :-)
From your description, I guess you want to run your code against the
MockFTPHost
instead of the normalFTPHost
. The interesting part is: how do you wantMockFTPHost
to behave? Do you imagine something like a virtual in-memory FTP server? IfMockFTPHost
was implemented this way, the following example should work:host = ftputil.MockFTPHost("some_host", "some_user", "the_password") host.mkdir("test_directory") with host.open("test_directory/remote_file", "w") as fobj: fobj.write("Content") host.chdir("test_directory") print(host.stat("remote_file")) # (33188, None, None, 1, '0', '0', 641, None, 1248213600.0, None) with host.open("remote_file", "r") as fobj: print(fobj.read()) # "Content"
So
MockFTPHost
would need to keep all the file system state (directory structure including files, stat information and file contents), so that you can still navigate the directory structure and the files you created.Even though this would be a "perfect" "imitation" of the
FTPHost
class, it would still not allow you to test a few things:
- login failures
- directories/files owned by other users
- existing, but unreadable directories/files
- ...
So if you wanted to test things like this, this would require API extensions to "tell" the mock host to behave in these "anomal" ways.
A simpler approach could be to mock the session factory you pass into the
FTPHost
constructor. I use this approach in many of my unit tests. Have a look at test/mock_ftplib.py. But although this contains a lot of functionality, it probably doesn't have a good API and may be too low-level for your taste. Also, in the current form you would need to monkey-patch the module to use your own directory contents.Another approach to mock
FTPHost
instances might be to use the mock library, which is included in Python 3.3 and up, but can also be used with Python versions 2.5, 2.6, 2.7, 3.1 and 3.2. I've used the library in other projects and like it. Actually, I've thought of rewriting a good part of the mock tests in ftputil by using the mentioned mock library. (It wasn't around when I started the ftputil project over ten years ago. :-) ) If you haven't already, I suggest you have a look at it, too.What do you think?
Hi Stefan,
we use the mock library a lot (with Python 2.7).
I think the most basic FTP features (upload, download, stat) should be implemented. Special stuff like login failures and files owned by other users need not to be implemented.
In-memory would be a solution, but I would just take an existing directory. The MockedFTPHost should serve this local directory like a remote directory.
This would make it much easier to test applications which use ftputil.
What do you think?
Thomas Güttler
Replying to ftputiluser:
we use the mock library a lot (with Python 2.7).
Did you try it for mocking
FTPHost
?I think the most basic FTP features (upload, download, stat) should be implemented. Special stuff like login failures and files owned by other users need not to be implemented.
Um, I have the odd feeling that different people will consider different things "basic" or "special". ;-/
I think it would depend on which level you're testing. If you want to test the layer that speaks directly to
FTPHost
, I'd think that the features you call "special" would be rather important, especially the things you can't easily do even with a real FTP server (e. g. simulate an unreachable host).From our conversation so far I have the impression you want the
MockFTPHost
rather to test the higher levels so they have a "virtual back end" to "speak with".In-memory would be a solution, but I would just take an existing directory. The MockedFTPHost should serve this local directory like a remote directory.
I'm not sure if this would be actually easier to implement than an in-memory data structure, but I wouldn't necessarily need an API for preparing the mock environment (the FTP directory). On the other hand, by using a directory, this becomes less of a mock implementation. For example, if you have a real directory, you can't create a file owned by another user unless you can create new users or have a colleague nearby.
This would make it much easier to test applications which use ftputil.
If I implemented a
MockFTPHost
, it would probably use the in-memory approach. Using a directory would reduce the things you can mock seriously (depending on what you want/need to test). There are things you can't easily mock with an in-memory approach (like huge files that would fill the computer's memory), but I think these situations are less important as probably a "semi-huge" file would do.I think implementing the
MockFTPHost
could well amount to a lot of work and I wonder if this time shouldn't be put into other features.On the other hand, I've wanted to clean up the ftputil unit tests for quite some time and I'll think about whether there are synergies and how I would design the
MockFTPHost
.If a
MockFTPHost
gets implemented, it will certainly take some time, so for now I suggest you
- try the
mock
library if you want to test a layer close to ftputil, or- set up a real FTP server if you want to test higher levels (I'm aware this is work, but maybe it's less difficult than you might think. I'm using PureFTPd for some tests, but I also heard good things about pyftpdlib, implemented in Python.
For the use case of testing higher application levels, before I even start implementing a
MockFTPHost
, I'd download pyftpdlib and give it a try. If it's really easy to set up, a wiki page on this setup could be a reasonable alternative to implementing aMockFTPHost
.
Hi Stefan,
the subject of this ticket is "Provide Docs for Mocking an FTP Server". A MockFTPHost was just one solution I thought about.
I heard good things about pyftpdlib, too. I guess this is better than my initial idea of a MockFTPHost.
I guess this should make it possible to do automated testing (for example continuous integration) without a complicated and platform specific dependency on a running ftp server.
I suppose there should be some advice on mock testing in the documentation. I had gotten another question on this topic recently and can well imagine there's a real need for this. (Continuous integration is a good point.)
Replying to schwa:
I suppose there should be some advice on mock testing in the documentation.
Or maybe it should be a wiki page and a link to it in the documentation.