enables seamless replacement of fake objects in unit tests
Project description
Fakeable - Transparently Use Fake Objects in Unit Tests
Fakeable is a Python library that allows seamlessly replacing “real” objects with “fake” objects during unit testing. “Faking out” objects is a generally-accepted practice in unit testing to make it easy to traverse every code path of a method or function without having to set up a real environment to make that happen. Fakeable works at the class level and any class that wants to be fakeable during unit tests need only add a single line to its class definition to make this dream a reality.
Fakeable is supported in Python 2.7 and Python 3.3, and also has been confirmed to work in PyPy 2.1 and PyPy3 2.1-beta1.
Example
This section shows a simple, contrived example of how Fakeable can be used to test otherwise difficult to create scenarios.
Suppose you have a class named HttpDownloader that downloads files from the Internet using the HTTP protocol:
import urllib2 class HttpDownloader(object): # download the contents of the given URL and return it; # return None if the given URL is invalid def download(self, url): try: f = urllib2.urlopen(url) except urllib2.URLError: return None else: data = f.read() f.close() return data
Now suppose that you want to test another function called download_urls() that uses HttpDownloader in its implementation:
def download_urls(urls): downloader = HttpDownloader() datas = [] for url in urls: data = downloader.download(url) datas.append(data) return datas
In order to test this function properly you would have to start a real HTTP server, presumaby on localhost, and have it return some pre-canned responses. This seems reasonable.
But what about testing the error conditions? What would you specify for an invalid URL? A bit of experimentation would give some good sample data but there is no guarantee that the same failures would occur on another computer, another operating system, or another Python implementation. This is where faking comes in handy.
Let’s create a fake version of HttpDownloader that simply returns None, simulating the URLError being handled:
class FakeHttpDownloader(object): def download(self, url): return None
Next, make the real HttpDownloader class fakeable:
import fakeable import urllib2 class HttpDownloader(object): __metaclass__ = fakeable.Fakeable def download(self, url): ...
Finally, write the unit test that uses the fake version of HttpDownloader:
import unittest class TestHttpDownloader(unittest.TestCase): def test_InvalidUrl(self): with fakeable.set_fake_class("HttpDownloader", FakeHttpDownloader): retval = download_urls(["foo", "bar"]) self.assertListEqual(retval, [None, None])
This unit test can be further simplified by using the fakeable.FakeableCleanupMixin class to automatically unregister the fakes:
import unittest class TestHttpDownloader(fakeable.FakeableCleanupMixin, unittest.TestCase): def test_InvalidUrl(self): fakeable.set_fake_class("HttpDownloader", FakeHttpDownloader) retval = download_urls(["foo", "bar"]) self.assertListEqual(retval, [None, None])
Bug Reports and Feature Requests
Please report issues and feature requests on the GitHub issue tracker: https://github.com/sleepydragonsw/fakeable/issues.
Alternately, fork the repository on GitHub and issue a pull request.
Contact Information
Fakeable was written and is maintained by Denver Coneybeare. Version 1.0.0 was released in August 2013. Denver can be contacted at denver@sleepydragon.org.
The source code for Fakeable is freely available at https://github.com/sleepydragonsw/fakeable.
The documentation for Fakeable is published at https://fakeable.readthedocs.org
License
Fakeable is free and open-source software, released under the Apache License version 2.0. The text of the license is available in the file named LICENSE.txt in the source distribution and is also available on the Internet at http://www.apache.org/licenses/LICENSE-2.0.html
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.