diff --git a/test/fixtures/setup-py/README.rst b/test/fixtures/setup-py/README.rst
new file mode 100644
index 0000000000000000000000000000000000000000..357c3da23035c966961c138d1f302683ed4e4d67
--- /dev/null
+++ b/test/fixtures/setup-py/README.rst
@@ -0,0 +1,114 @@
+Maya: Datetime for Humansâ„¢
+==========================
+
+.. image:: https://img.shields.io/pypi/v/maya.svg
+    :target: https://pypi.python.org/pypi/maya
+
+.. image:: https://travis-ci.org/kennethreitz/maya.svg?branch=master
+    :target: https://travis-ci.org/kennethreitz/maya
+
+.. image:: https://img.shields.io/badge/SayThanks.io-☼-1EAEDB.svg
+    :target: https://saythanks.io/to/kennethreitz
+
+
+Datetimes are very frustrating to work with in Python, especially when dealing
+with different locales on different systems. This library exists to make the
+simple things **much** easier, while admitting that time is an illusion
+(timezones doubly so).
+
+Datetimes should be interacted with via an API written for humans.
+
+Maya is mostly built around the headaches and use-cases around parsing datetime data from websites.
+
+
+☤ Basic Usage of Maya
+---------------------
+
+Behold, datetimes for humans!
+
+.. code-block:: pycon
+
+    >>> now = maya.now()
+    <MayaDT epoch=1481850660.9>
+
+    >>> tomorrow = maya.when('tomorrow')
+    <MayaDT epoch=1481919067.23>
+
+    >>> tomorrow.slang_date()
+    'tomorrow'
+
+    >>> tomorrow.slang_time()
+    '23 hours from now'
+
+    >>> tomorrow.iso8601()
+    '2016-12-16T15:11:30.263350Z'
+
+    >>> tomorrow.rfc2822()
+    'Fri, 16 Dec 2016 20:11:30 -0000'
+
+    >>> tomorrow.datetime()
+    datetime.datetime(2016, 12, 16, 15, 11, 30, 263350, tzinfo=<UTC>)
+
+    # Automatically parse datetime strings and generate naive datetimes.
+    >>> scraped = '2016-12-16 18:23:45.423992+00:00'
+    >>> maya.parse(scraped).datetime(to_timezone='US/Eastern', naive=True)
+    datetime.datetime(2016, 12, 16, 13, 23, 45, 423992)
+
+    >>> rand_day = maya.when('2011-02-07', timezone='US/Eastern')
+    <MayaDT epoch=1297036800.0>
+
+    # Note how this is the 6th, not the 7th.
+    >>> rand_day.day
+    6
+
+    # Always.
+    >>> rand_day.timezone
+    UTC
+
+☤ Why is this useful?
+---------------------
+
+- All timezone algebra will behave identically on all machines, regardless of system locale.
+- Complete symmetric import and export of both ISO 8601 and RFC 2822 datetime stamps.
+- Fantastic parsing of both dates written for/by humans and machines (``maya.when()`` vs ``maya.parse()``).
+- Support for human slang, both import and export (e.g. `an hour ago`).
+- Datetimes can very easily be generated, with or without tzinfo attached.
+- This library is based around epoch time, but dates before Jan 1 1970 are indeed supported, via negative integers.
+- Maya never panics, and always carries a towel.
+
+
+☤ What about Delorean, Arrow, & Pendulum?
+-----------------------------------------
+
+Arrow, for example, is a fantastic library, but isn't what I wanted in a datetime library. In many ways, it's better than Maya for certain things. In some ways, in my opinion, it's not.
+
+I simply desire a sane API for datetimes that made sense to me for all the things I'd ever want to do—especially when dealing with timezone algebra. Arrow doesn't do all of the things I need (but it does a lot more!). Maya does do exactly what I need.
+
+I think these projects complement each-other, personally. Maya is great for parsing websites. For example- Arrow supports floors and ceilings and spans of dates, which Maya does not at all.
+
+
+☤ Installing Maya
+-----------------
+
+Installation is easy, with pip::
+
+    $ pip install maya
+
+✨🍰✨
+
+☤ Like it?
+----------
+
+`Say Thanks <https://saythanks.io/to/kennethreitz>`_!
+
+
+How to Contribute
+-----------------
+
+#. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.
+#. Fork `the repository`_ on GitHub to start making your changes to the **master** branch (or branch off of it).
+#. Write a test which shows that the bug was fixed or that the feature works as expected.
+#. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to AUTHORS_.
+
+.. _`the repository`: http://github.com/kennethreitz/maya
+.. _AUTHORS: https://github.com/kennethreitz/maya/blob/master/AUTHORS.rst
diff --git a/test/fixtures/setup-py/maya.py b/test/fixtures/setup-py/maya.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7323b089e618f0d38e5d341cfb10fd16ef3b860
--- /dev/null
+++ b/test/fixtures/setup-py/maya.py
@@ -0,0 +1,273 @@
+
+# ___  __  ___  _  _  ___
+# || \/ | ||=|| \\// ||=||
+# ||    | || ||  //  || ||
+
+# Ignore warnings for yaml usage.
+import warnings
+import ruamel.yaml
+warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)
+
+
+import email.utils
+import time
+from datetime import datetime as Datetime
+
+import pytz
+import humanize
+import dateparser
+import iso8601
+import dateutil.parser
+from tzlocal import get_localzone
+
+_EPOCH_START = (1970, 1, 1)
+
+
+def validate_class_type_arguments(operator):
+    """
+    Decorator to validate all the arguments to function
+    are of the type of calling class
+    """
+
+    def inner(function):
+        def wrapper(self, *args, **kwargs):
+            for arg in args + tuple(kwargs.values()):
+                if not isinstance(arg, self.__class__):
+                    raise TypeError('unorderable types: {}() {} {}()'.format(
+                        type(self).__name__, operator, type(arg).__name__))
+            return function(self, *args, **kwargs)
+
+        return wrapper
+
+    return inner
+
+
+
+class MayaDT(object):
+    """The Maya Datetime object."""
+
+    def __init__(self, epoch):
+        super(MayaDT, self).__init__()
+        self._epoch = epoch
+
+    def __repr__(self):
+        return '<MayaDT epoch={}>'.format(self._epoch)
+
+    def __str__(self):
+        return self.rfc2822()
+
+    def __format__(self, *args, **kwargs):
+        """Return's the datetime's format"""
+        return format(self.datetime(), *args, **kwargs)
+
+
+    @validate_class_type_arguments('==')
+    def __eq__(self, maya_dt):
+        return self._epoch == maya_dt._epoch
+
+    @validate_class_type_arguments('!=')
+    def __ne__(self, maya_dt):
+        return self._epoch != maya_dt._epoch
+
+    @validate_class_type_arguments('<')
+    def __lt__(self, maya_dt):
+        return self._epoch < maya_dt._epoch
+
+    @validate_class_type_arguments('<=')
+    def __le__(self, maya_dt):
+        return self._epoch <= maya_dt._epoch
+
+    @validate_class_type_arguments('>')
+    def __gt__(self, maya_dt):
+        return self._epoch > maya_dt._epoch
+
+    @validate_class_type_arguments('>=')
+    def __ge__(self, maya_dt):
+        return self._epoch >= maya_dt._epoch
+
+
+    # Timezone Crap
+    # -------------
+
+    @property
+    def timezone(self):
+        """Returns the UTC tzinfo name. It's always UTC. Always."""
+        return 'UTC'
+
+    @property
+    def _tz(self):
+        """Returns the UTC tzinfo object."""
+        return pytz.timezone(self.timezone)
+
+    @property
+    def local_timezone(self):
+        """Returns the name of the local timezone, for informational purposes."""
+        return self._local_tz.zone
+
+    @property
+    def _local_tz(self):
+        """Returns the local timezone."""
+        return get_localzone()
+
+    @staticmethod
+    def __dt_to_epoch(dt):
+        """Converts a datetime into an epoch."""
+
+        # Assume UTC if no datetime is provided.
+        if dt.tzinfo is None:
+            dt = dt.replace(tzinfo=pytz.utc)
+
+        epoch_start = Datetime(*_EPOCH_START, tzinfo=pytz.timezone('UTC'))
+        return (dt - epoch_start).total_seconds()
+
+    # Importers
+    # ---------
+
+    @classmethod
+    def from_datetime(klass, dt):
+        """Returns MayaDT instance from datetime."""
+        return klass(klass.__dt_to_epoch(dt))
+
+    @classmethod
+    def from_iso8601(klass, string):
+        """Returns MayaDT instance from iso8601 string."""
+        dt = iso8601.parse_date(string)
+        return klass.from_datetime(dt)
+
+    @staticmethod
+    def from_rfc2822(string):
+        """Returns MayaDT instance from rfc2822 string."""
+        return parse(string)
+
+    # Exporters
+    # ---------
+
+    def datetime(self, to_timezone=None, naive=False):
+        """Returns a timezone-aware datetime...
+        Defaulting to UTC (as it should).
+
+        Keyword Arguments:
+            to_timezone {string} -- timezone to convert to (default: None/UTC)
+            naive {boolean} -- if True, the tzinfo is simply dropped (default: False)
+        """
+        if to_timezone:
+            dt = self.datetime().astimezone(pytz.timezone(to_timezone))
+        else:
+            dt = Datetime.utcfromtimestamp(self._epoch)
+            dt.replace(tzinfo=self._tz)
+
+        # Strip the timezone info if requested to do so.
+        if naive:
+            return dt.replace(tzinfo=None)
+        else:
+            if dt.tzinfo is None:
+                dt = dt.replace(tzinfo=self._tz)
+
+        return dt
+
+    def iso8601(self):
+        """Returns an ISO 8601 representation of the MayaDT."""
+        # Get a timezone-naive datetime.
+        dt = self.datetime(naive=True)
+        return '{}Z'.format(dt.isoformat())
+
+    def rfc2822(self):
+        """Returns an RFC 2822 representation of the MayaDT."""
+        return email.utils.formatdate(self.epoch, usegmt=True)
+
+    # Properties
+    # ----------
+
+    @property
+    def year(self):
+        return self.datetime().year
+
+    @property
+    def month(self):
+        return self.datetime().month
+
+    @property
+    def day(self):
+        return self.datetime().day
+
+    @property
+    def week(self):
+        return self.datetime().isocalendar()[1]
+
+    @property
+    def weekday(self):
+        """Return the day of the week as an integer. Monday is 1 and Sunday is 7"""
+        return self.datetime().isoweekday()
+
+    @property
+    def hour(self):
+        return self.datetime().hour
+
+    @property
+    def minute(self):
+        return self.datetime().minute
+
+    @property
+    def second(self):
+        return self.datetime().second
+
+    @property
+    def microsecond(self):
+        return self.datetime().microsecond
+
+    @property
+    def epoch(self):
+        return self._epoch
+
+    # Human Slang Extras
+    # ------------------
+
+    def slang_date(self):
+        """"Returns human slang representation of date."""
+        dt = self.datetime(naive=True, to_timezone=self.local_timezone)
+        return humanize.naturaldate(dt)
+
+    def slang_time(self):
+        """"Returns human slang representation of time."""
+        dt = self.datetime(naive=True, to_timezone=self.local_timezone)
+        return humanize.naturaltime(dt)
+
+
+
+
+def now():
+    """Returns a MayaDT instance for this exact moment."""
+    epoch = time.time()
+    return MayaDT(epoch=epoch)
+
+def when(string, timezone='UTC'):
+    """"Returns a MayaDT instance for the human moment specified.
+
+    Powered by dateparser. Useful for scraping websites.
+
+    Examples:
+        'next week', 'now', 'tomorrow', '300 years ago', 'August 14, 2015'
+
+    Keyword Arguments:
+        string -- string to be parsed
+        timezone -- timezone referenced from (default: 'UTC')
+
+    """
+    dt = dateparser.parse(string, settings={'TIMEZONE': timezone, 'RETURN_AS_TIMEZONE_AWARE': True, 'TO_TIMEZONE': 'UTC'})
+
+    if dt is None:
+        raise ValueError('invalid datetime input specified.')
+
+    return MayaDT.from_datetime(dt)
+
+def parse(string, day_first=False):
+    """"Returns a MayaDT instance for the machine-produced moment specified.
+
+    Powered by dateutil. Accepts most known formats. Useful for working with data.
+
+    Keyword Arguments:
+        string -- string to be parsed
+        day_first -- if true, the first value (e.g. 01/05/2016) is parsed as day (default: False)
+    """
+    dt = dateutil.parser.parse(string, dayfirst=day_first)
+    return MayaDT.from_datetime(dt)
diff --git a/test/fixtures/setup-py/setup.py b/test/fixtures/setup-py/setup.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..38389c1d8c0c5bf4d423d1b08195c3fcd22a6ede 100644
--- a/test/fixtures/setup-py/setup.py
+++ b/test/fixtures/setup-py/setup.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import codecs
+
+from setuptools import setup
+
+try:
+    # Python 3
+    from os import dirname
+except ImportError:
+    # Python 2
+    from os.path import dirname
+
+here = os.path.abspath(dirname(__file__))
+
+with codecs.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
+    long_description = '\n' + f.read()
+
+
+if sys.argv[-1] == "publish":
+    os.system("python setup.py sdist bdist_wheel upload")
+    sys.exit()
+
+required = [
+    'humanize',
+    'pytz',
+    'dateparser',
+    'iso8601',
+    'python-dateutil',
+    'ruamel.yaml',
+    'tzlocal'
+]
+
+setup(
+    name='maya',
+    version='0.1.6',
+    description='Datetimes for Humans.',
+    long_description=long_description,
+    author='Kenneth Reitz',
+    author_email='me@kennethreitz.com',
+    url='https://github.com/kennethreitz/maya',
+    py_modules=['maya'],
+    install_requires=required,
+    license='MIT',
+    classifiers=(
+
+    ),
+)
diff --git a/test/run b/test/run
index c650ea79c94495777b5bff0d25afdab5c8807975..8876e4e61a1d2d030ee61fdfc8d0142a13455bba 100755
--- a/test/run
+++ b/test/run
@@ -1,5 +1,17 @@
 #!/usr/bin/env bash
-# See README.md for info on running these tests.
+
+testNoRequirements() {
+  compile "no-requirements"
+  assertCapturedError
+}
+
+
+testSetupPy() {
+  compile "setup-py"
+  assertCaptured "maya"
+  assertCapturedSuccess
+}
+
 
 testStandardRequirements() {
   compile "requirements-standard"
@@ -26,6 +38,8 @@ testPython3() {
 }
 
 
+
+
 pushd $(dirname 0) >/dev/null
 popd >/dev/null
 
diff --git a/test/utils b/test/utils
index c30544b14474d309e90f380930d77865ce227bd0..c46d242264cc629affbe14dc8aaf90803eb7436e 100644
--- a/test/utils
+++ b/test/utils
@@ -147,6 +147,11 @@ _assertContains()
   fi
 }
 
+debug()
+{
+  cat $STD_OUT
+}
+
 assertContains()
 {
   _assertContains "$@" 0 "text"