Commits

Anonymous committed c5176c8

[gsoc2009-testing] Creating initial docs files. Windmill multi-module naming workaround implemented in regression suite. Added tests for admin_widgets. Implemented a tests to ensure fresh session state at end of windmill test.

Comments (0)

Files changed (11)

django/core/management/commands/test_windmill.py

 from time import sleep
 import types
 import logging
+import threading
 
 class ServerContainer(object):
     start_test_server = djangotest.start_test_server
     stop_test_server = djangotest.stop_test_server
 
 def attempt_import(name, suffix):
-        try:
-            mod = __import__(name+'.'+suffix)
-        except ImportError:
-            mod = None
-        if mod is not None:
-            s = name.split('.')
-            mod = __import__(s.pop(0))
-            for x in s+[suffix]:
-                try:
-                    mod = getattr(mod, x)
-                except Exception, e:
-                    pass
-        return mod
+    try:
+        mod = __import__(name+'.'+suffix)
+    except ImportError:
+        mod = None
+    if mod is not None:
+        s = name.split('.')
+        mod = __import__(s.pop(0))
+        for x in s+[suffix]:
+            try:
+                mod = getattr(mod, x)
+            except Exception, e:
+                pass
+    return mod
 
 class Command(BaseCommand):
 
             sys.argv.remove('manage.py')
         if 'test_windmill' in sys.argv:
             sys.argv.remove('test_windmill')
-        server_container = ServerContainer()
-        server_container.start_test_server()
-
-        global_settings.TEST_URL = 'http://localhost:%d' % server_container.server_thread.port
-
-        # import windmill
-        # windmill.stdout, windmill.stdin = sys.stdout, sys.stdin
-        from windmill.authoring import setup_module, teardown_module
 
         from django.conf import settings
         tests = []
             for suffix in ['tests', 'wmtests', 'windmilltests']:
                 x = attempt_import(name, suffix)
                 if x is not None: tests.append((suffix,x,));
-
+                wmfixs = []
         wmtests = []
         for (ttype, mod,) in tests:
             if ttype == 'tests':
                     wmtests.append(os.path.join(*os.path.split(os.path.abspath(mod.__file__))[:-1]))
                 else:
                     wmtests.append(os.path.abspath(mod.__file__))
+			# Look for any attribute named fixtures and try to load it.
+            if hasattr(mod, 'fixtures'):
+                for fixture in getattr(mod, 'fixtures'):
+                    wmfixs.append(fixture)
+
+        # Create the threaded server.
+        server_container = ServerContainer()
+        # Set the server's 'fixtures' attribute so they can be loaded in-thread if using sqlite's memory backend.
+        server_container.__setattr__('fixtures', wmfixs)
+        # Start the server thread.
+        started = server_container.start_test_server()
+
+        print 'Waiting for threaded server to come online.'
+        started.wait()
+        print 'DB Ready, Server online.'
+
+        global_settings.TEST_URL = 'http://localhost:%d' % server_container.server_thread.port
+
+        # import windmill
+        # windmill.stdout, windmill.stdin = sys.stdout, sys.stdin
+        from windmill.authoring import setup_module, teardown_module
+
 
         if len(wmtests) is 0:
             print 'Sorry, no windmill tests found.'

docs/howto/index.txt

    outputting-csv
    outputting-pdf
    static-files
+   windmill-tests
 
 .. seealso::
 

docs/howto/windmill-tests.txt

+.. _howto-windmill-tests:
+
+Writing a Functional Tests with Windmill
+=======================================
+
+.. currentmodule:: django.test
+
+If you need to provide custom file storage -- a common example is storing files
+on some remote system -- you can do so by defining a custom storage class.
+You'll need to follow these steps:
+
+#. Your custom storage system must be a subclass of
+   ``django.core.files.storage.Storage``::
+
+        from django.core.files.storage import Storage
+
+        class MyStorage(Storage):
+            ...
+
+#. Django must be able to instantiate your storage system without any arguments.
+   This means that any settings should be taken from ``django.conf.settings``::
+
+        from django.conf import settings
+        from django.core.files.storage import Storage
+
+        class MyStorage(Storage):
+            def __init__(self, option=None):
+                if not option:
+                    option = settings.CUSTOM_STORAGE_OPTIONS
+                ...
+
+#. Your storage class must implement the ``_open()`` and ``_save()`` methods,
+   along with any other methods appropriate to your storage class. See below for
+   more on these methods.
+
+   In addition, if your class provides local file storage, it must override
+   the ``path()`` method.
+
+Your custom storage system may override any of the storage methods explained in
+:ref:`ref-files-storage`, but you **must** implement the following methods:
+
+    * :meth:`Storage.delete`
+    * :meth:`Storage.exists`
+    * :meth:`Storage.listdir`
+    * :meth:`Storage.size`
+    * :meth:`Storage.url`
+
+You'll also usually want to use hooks specifically designed for custom storage
+objects. These are:
+
+``_open(name, mode='rb')``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Required**.
+
+Called by ``Storage.open()``, this is the actual mechanism the storage class
+uses to open the file. This must return a ``File`` object, though in most cases,
+you'll want to return some subclass here that implements logic specific to the
+backend storage system.
+
+``_save(name, content)``
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Called by ``Storage.save()``. The ``name`` will already have gone through
+``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
+``File`` object itself. 
+
+Should return the actual name of name of the file saved (usually the ``name``
+passed in, but if the storage needs to change the file name return the new name
+instead).
+
+``get_valid_name(name)``
+------------------------
+
+Returns a filename suitable for use with the underlying storage system. The
+``name`` argument passed to this method is the original filename sent to the
+server, after having any path information removed. Override this to customize
+how non-standard characters are converted to safe filenames.
+
+The code provided on ``Storage`` retains only alpha-numeric characters, periods
+and underscores from the original filename, removing everything else.
+
+``get_available_name(name)``
+----------------------------
+
+Returns a filename that is available in the storage mechanism, possibly taking
+the provided filename into account. The ``name`` argument passed to this method
+will have already cleaned to a filename valid for the storage system, according
+to the ``get_valid_name()`` method described above.
+
+The code provided on ``Storage`` simply appends underscores to the filename
+until it finds one that's available in the destination directory.
       :ref:`Overview <ref-django-admin>` |
       :ref:`Adding custom commands <howto-custom-management-commands>`
 
-    * **Testing:**  :ref:`Overview <topics-testing>`
+    * **Testing:** 
+      :ref:`Overview <topics-testing>` |
+      :ref:`Windmill <howto-windmill-tests>`
 
     * **Deployment:**
       :ref:`Overview <howto-deployment-index>` |

docs/ref/index.txt

    signals
    templates/index
    unicode
-

docs/topics/testing.txt

       a template context that contains certain values.
 
 Note that the test client is not intended to be a replacement for Twill_,
-Selenium_, or other "in-browser" frameworks. Django's test client has
+Windmill_, or other "in-browser" frameworks. Django's test client has
 a different focus. In short:
 
     * Use Django's test client to establish that the correct view is being
     * Use in-browser frameworks such as Twill and Selenium to test *rendered*
       HTML and the *behavior* of Web pages, namely JavaScript functionality.
 
-A comprehensive test suite should use a combination of both test types.
+A comprehensive test suite should use a combination of both test types. Which 
+is why Django makes it easy to integrate with 3rd party test runners via the 
+:setting:`TEST_RUNNER` setting. For convenience, Django ships a runner for
+the framework used in testing the :ref:`admin interface, <ref-contrib-admin>`
+Windmill_. Details on integrating Windmill tests with Django are available 
+:ref:`here. <howto-windmill-test>`
 
 .. _Twill: http://twill.idyll.org/
-.. _Selenium: http://www.openqa.org/selenium/
+.. _Windmill: http://www.getwindmill.com/
 
 Overview and a quick example
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tests/regressiontests/admin_views/tests.py

         self.failUnlessEqual(FancyDoodad.objects.count(), 1)
         self.failUnlessEqual(FancyDoodad.objects.all()[0].name, "Fancy Doodad 1 Updated")
 
-import os
-#from django.test import windmill_tests as djangotest
-#from windmill.authoring import djangotest
-#from windmill.conf import global_settings
-
+# import os
+# from django.test import windmill_tests as djangotest
+# #from windmill.authoring import djangotest
+# #from windmill.conf import global_settings
+# 
 # class TestProjectWindmillTest(djangotest.WindmillDjangoUnitTest):
 #     fixtures = ['admin-views-users.xml', 'admin-views-colors.xml', 'admin-views-fabrics.xml', 'admin-views-unicode.xml',
-#         'multiple-child-classes', 'admin-views-actions.xml', 'string-primary-key.xml', 'admin-views-person.xml']
+#      'multiple-child-classes', 'admin-views-actions.xml', 'string-primary-key.xml', 'admin-views-person.xml']
 #     test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'windmilltests')
 #     #test_dir = os.path.dirname(os.path.abspath(__file__))
 #     #test_dir = os.path.dirname(os.path.abspath(__file__))
 #     browser = 'firefox'
 #     test_url = 'http://localhost:8000/test_admin/admin/'
-#     global_settings.TEST_URL = test_url
+#     #global_settings.TEST_URL = test_url
+# 
+#     # def test_tryout(self):
+#     #     pass
 
-    # def test_tryout(self):
-    #     pass
 
 
-

tests/regressiontests/admin_views/windmilltests/__init__.py

+fixtures = ['admin-views-users.xml',
+    'admin-views-colors.xml',
+    'admin-views-fabrics.xml',
+    'admin-views-unicode.xml',
+    'multiple-child-classes',
+    'admin-views-actions.xml',
+    'string-primary-key.xml',
+    'admin-views-person.xml']
+
 # import os
 # from django.test import windmill_tests as djangotest
 # #from windmill.authoring import djangotest
 from windmill.conf import global_settings
 ADMIN_URL =  "%s/test_admin/admin" % global_settings.TEST_URL
 #ADMIN_URL = 'http://localhost:8000/test_admin/admin/'
+#['regressiontests/admin_views/fixtures/%s' % fix for fix in ]
 
 #
 # class TestProjectWindmillTest(djangotest.WindmillDjangoUnitTest):
 #     #     pass
 #
 from windmill.authoring import WindmillTestClient
-#from django.test.windmill_tests import calling_func_name
+from django.test.utils import calling_func_name
+
+# import functest
+# functest.modules_passed = []
+# functest.modules_failed = []
 
 def test_loginAndSetup():
     '''Mostly just a proof of concept to test working order of tests.'''
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     # print dir(client)
     #    print dir(client.open)
 
 def test_changeListNamingLinkingHistory():
     '''Creating a Model with strings for pk, and checking history.'''
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     # client.open(url=ADMIN_URL)
 
 def test_filtersSearchOnChangeList():
     '''Testing Updates and Filters/Search on Person Models'''
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
 
 def test_defaultDeleteAdminAction():
     '''Admin Actions test. Test the default delete action.'''
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     client.asserts.assertNode(link=u'Horizontal')
 
 def test_dateTimeModelsandWidgets():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     client.waits.forPageLoad(timeout=u'20000')
 
 def test_inlineEditandCreate():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
 
 
 def test_adminActionEmptyModels():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     client.waits.forPageLoad(timeout=u'20000')
 
 def test_parentChildRelationship():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     client.waits.forPageLoad(timeout=u'20000')
 
 def test_AdminAuthContrib():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
 
 
 def test_contribFlatSitesRedirect():
-    client = WindmillTestClient(__name__)
+    client = WindmillTestClient(calling_func_name())
 
     client.open(url=ADMIN_URL)
     client.waits.forPageLoad(timeout=u'20000')
     client.asserts.assertText(xpath=u'/html/body', validator=u'\nThis is some unique test content.\n')
     client.open(url=u'http://localhost:8000/test_admin/admin/')
     client.waits.forPageLoad(timeout=u'8000')
+    client.click(link=u'Log out')
+    client.waits.forPageLoad(timeout=u'20000')
+
+
+def test_ensureLogout():
+    client = WindmillTestClient(calling_func_name())
+
+    client.open(url=ADMIN_URL)
+    client.waits.forPageLoad(timeout=u'20000')
+    client.open(url="%s/accounts/logout"% global_settings.TEST_URL)
+    client.waits.forPageLoad(timeout=u'20000')
+    client.asserts.assertText(xpath=u"//div[@id='content']/h1", validator=u'Logged out')
+    client.asserts.assertText(xpath=u"//div[@id='content']/p", validator=u'Thanks for spending some quality time with the Web site today.')
+    client.asserts.assertNode(link=u'Log in again')

tests/regressiontests/admin_widgets/tests.py

     def test_changelist_foreignkey(self):
         response = self.client.get('/widget_admin/admin_widgets/car/')
         self.failUnless('/widget_admin/auth/user/add/' in response.content)
+
+
+
+# import os
+# from django.test import windmill_tests as djangotest
+# #from windmill.authoring import djangotest
+# #from windmill.conf import global_settings
+# 
+# class TestProjectWindmillTest(djangotest.WindmillDjangoUnitTest):
+#     fixtures = ['admin-views-users.xml', 'admin-views-colors.xml', 'admin-views-fabrics.xml', 'admin-views-unicode.xml',
+#      'multiple-child-classes', 'admin-views-actions.xml', 'string-primary-key.xml', 'admin-views-person.xml']
+#     test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'windmilltests')
+#     #test_dir = os.path.dirname(os.path.abspath(__file__))
+#     #test_dir = os.path.dirname(os.path.abspath(__file__))
+#     browser = 'firefox'
+#     test_url = 'http://localhost:8000/test_admin/admin/'
+#     #global_settings.TEST_URL = test_url
+# 
+#     # def test_tryout(self):
+#     #     pass

tests/regressiontests/admin_widgets/wmtests/__init__.py

+
+from windmill.conf import global_settings
+ADMIN_WIDGET_URL =  "%s/widget_admin/" % global_settings.TEST_URL
+from windmill.authoring import WindmillTestClient
+from django.test.utils import calling_func_name
+
+
+def test_baseWidgetTestCars():
+    client = WindmillTestClient("A second module")
+    
+    client.open(url=ADMIN_WIDGET_URL)
+    client.waits.forPageLoad(timeout=u'20000')
+    client.type(text=u'super', id=u'id_username')
+    client.type(text=u'secret', id=u'id_password')
+    client.click(value=u'Log in')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'Car tires', timeout=u'8000')
+    client.click(link=u'Car tires')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'              Add car tire             ', timeout=u'8000')
+    client.click(link=u'              Add car tire             ')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(timeout=u'8000', id=u'id_car')
+    client.click(id=u'id_car')
+    client.click(xpath=u"//a[@id='add_id_car']/img")
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(xpath=u"//form[@id='car_form']/div/fieldset/div[2]/div", timeout=u'8000')
+    client.click(xpath=u"//form[@id='car_form']/div/fieldset/div[2]/div")
+    client.click(id=u'id_owner')
+    client.select(option=u'super', id=u'id_owner')
+    client.click(value=u'100')
+    client.click(id=u'id_make')
+    client.type(text=u'Ferrari', id=u'id_make')
+    client.type(text=u'F-xx', id=u'id_model')
+    client.click(xpath=u"//form[@id='car_form']/div/fieldset/div[2]")
+    client.click(name=u'_save')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.closeWindow()
+    client.click(link=u'Home')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'Car tires', timeout=u'8000')
+    client.click(link=u'Car tires')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'              Add car tire             ', timeout=u'8000')
+    client.click(link=u'              Add car tire             ')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.select(option=u'Ferrari F-xx', id=u'id_car')
+    client.click(value=u'1')
+    client.click(name=u'_save')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'CarTire object', timeout=u'8000')
+    client.click(link=u'CarTire object')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.asserts.assertImageLoaded(xpath=u"//a[@id='add_id_car']/img")
+    client.asserts.assertNode(id=u'id_car')
+    client.asserts.assertNode(link=u'Delete')
+    client.click(xpath=u"//form[@id='cartire_form']/div/fieldset/div/div")
+    client.click(link=u'Home')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(link=u'Cars', timeout=u'8000')
+    client.click(link=u'Cars')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.asserts.assertImageLoaded(xpath=u"//a[@id='add_id_form-0-owner']/img")
+    client.asserts.assertNode(link=u'Ferrari')
+    client.asserts.assertNode(id=u'id_form-0-owner')
+    #client.asserts.assertSelected(xpath=u"//select[@id='id_form-0-owner']/option[3]", validator=u'')
+    client.click(link=u'        Home       ')
+    client.waits.forPageLoad(timeout=u'20000')
+    client.waits.forElement(timeout=u'8000', id=u'user-tools')
+    client.click(id=u'user-tools')
+    client.click(link=u'Log out')
+    client.waits.forPageLoad(timeout=u'20000')
+    
+def test_loginWidgetAdmin():
+    '''Mostly just a proof of concept to test working order of tests.'''
+    client = WindmillTestClient("freebie test")
+
+    # print dir(client)
+    #    print dir(client.open)
+    #    print dir(client.commands)
+    #    print client.commands()
+
+    # client.open(url=ADMIN_URL)
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.type(text=u'super', id=u'id_username')
+    #   client.type(text=u'secret', id=u'id_password')
+    #   client.click(value=u'Log in')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.asserts.assertNode(xpath=u"//div[@id='content-main']/div/table/tbody/tr[1]/th")
+    #   client.asserts.assertNode(link=u'Articles')
+    #   client.asserts.assertNode(link=u'Add')
+    #   client.asserts.assertNode(link=u'Change')
+    #   client.asserts.assertNode(link=u'Admin_Views')
+    #   client.asserts.assertNode(xpath=u"//div[@id='user-tools']/strong")
+    #   client.click(xpath=u"//div[@id='content-main']/div/table/tbody/tr[22]/td/a")
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.type(text=u'Test Section', id=u'id_name')
+    #   client.click(name=u'_save')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.asserts.assertNode(link=u'Section object')
+    #   client.click(link=u'         Admin_views       ')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.waits.forElement(link=u'Add', timeout=u'8000')
+    #   client.click(link=u'Add')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.type(text=u'Test 1', id=u'id_title')
+    #   client.type(text=u'This is test content.', id=u'id_content')
+    #   client.click(link=u'Today')
+    #   client.click(link=u'Now')
+    #   client.click(id=u'id_section')
+    #   client.select(option=u'Section object', id=u'id_section')
+    #   client.click(value=u'1')
+    #   #client.asserts.assertValue(validator=u'2009-06-16', id=u'id_date_0')
+    #   #client.asserts.assertValue(validator=u'13:31:21', id=u'id_date_1')
+    #   client.asserts.assertNode(id=u'id_section')
+    #   client.click(name=u'_save')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.asserts.assertNode(link=u'This is test content.')
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/td[2]")
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/td[3]")
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/td[4]")
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/td[5]")
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/th")
+    #   client.click(link=u'Today')
+    #   client.waits.forPageLoad(timeout=u'20000')
+    #   client.asserts.assertNode(xpath=u"//div[@id='changelist']/form/table/tbody/tr/th")
+    #   client.click(link=u'        Home       ')
+    #   client.waits.forPageLoad(timeout=u'20000')

tests/runtests.py

     'django.contrib.admin',
 ]
 
-WINDMILL_FIXTURES = ['regressiontests/admin_views/fixtures/%s' % fix for fix in ['admin-views-users.xml',
-    'admin-views-colors.xml',
-    'admin-views-fabrics.xml',
-    'admin-views-unicode.xml',
-    'multiple-child-classes',
-    'admin-views-actions.xml',
-    'string-primary-key.xml',
-    'admin-views-person.xml']]
+# WINDMILL_FIXTURES = ['regressiontests/admin_views/fixtures/%s' % fix for fix in ['admin-views-users.xml',
+#     'admin-views-colors.xml',
+#     'admin-views-fabrics.xml',
+#     'admin-views-unicode.xml',
+#     'multiple-child-classes',
+#     'admin-views-actions.xml',
+#     'string-primary-key.xml',
+#     'admin-views-person.xml']]
 
 
 def get_test_models():
     if not hasattr(settings, 'TEST_RUNNER'):
         settings.TEST_RUNNER = 'django.test.simple.run_tests'
     #establish coverage settings for the regression suite
-    settings.COVERAGE_MODULE_EXCLUDES = ['modeltests*', 'regressiontests*']
+    settings.COVERAGE_MODULE_EXCLUDES = ['modeltests*', 'regressiontests*', 'from .* import .*', 'import .*',]
     settings.COVERAGE_CODE_EXCLUDES = ['def __unicode__\(self\):', 'def get_absolute_url\(self\):']
     # depending on how this is run, we might need to tell the coverage libraries to consider django.*
     settings.COVERAGE_ADDITIONAL_MODULES = ['django']
         else:
             global_settings.START_FIREFOX = True
 
-
-        # Create the threaded server.
-        server_container = ServerContainer()
-        # Set the server's 'fixtures' attribute so they can be loaded in-thread if using sqlite's memory backend.
-        server_container.__setattr__('fixtures', WINDMILL_FIXTURES)
-        # Start the server thread.
-        started = server_container.start_test_server()
-
-        print 'Waiting for threaded server to come online.'
-        started.wait()
-        print 'DB Ready, Server online.'
-
-        # These 2 unit tests can't be used while running our admin. Explicitly remove.
-        if 'regressiontests.bug8245' in settings.INSTALLED_APPS:
-            settings.INSTALLED_APPS.remove('regressiontests.bug8245')
-        if 'django.contrib.gis' in settings.INSTALLED_APPS:
-            settings.INSTALLED_APPS.remove('django.contrib.gis')
-
-        # Set the testing URL based on what available port we get.
-        global_settings.TEST_URL = 'http://localhost:%d' % server_container.server_thread.port
-
-
+            #
         # Find which of our INSTALLED_APPS have tests.
         tests = []
         for name in [app for app in settings.INSTALLED_APPS if not('invalid' in app)]:
             for suffix in ['tests', 'wmtests', 'windmilltests']:
                 x = attempt_import(name, suffix)
                 if x is not None:
+                    print "Adding %s %s to tests" % (suffix, x, )
                     tests.append((suffix, x, ))
 
         # Collect the WindmillDjangoUnitTest from tests.py and any 'wmtests' or 'windmilltests' modules.
+        wmfixs = []
         wmtests = []
         for (ttype, mod, ) in tests:
             if ttype == 'tests':
                     wmtests.append(os.path.join(*os.path.split(os.path.abspath(mod.__file__))[:-1]))
                 else:
                     wmtests.append(os.path.abspath(mod.__file__))
+            # Look for any attribute named fixtures and try to load it.
+            if hasattr(mod, 'fixtures'):
+                for fixture in getattr(mod, 'fixtures'):
+                    wmfixs.append(fixture)
+
+        # Create the threaded server.
+        server_container = ServerContainer()
+        # Set the server's 'fixtures' attribute so they can be loaded in-thread if using sqlite's memory backend.
+        server_container.__setattr__('fixtures', wmfixs)
+        # Start the server thread.
+        started = server_container.start_test_server()
+                # These 2 unit tests can't be used while running our admin. Explicitly remove.
+        if 'regressiontests.bug8245' in settings.INSTALLED_APPS:
+            settings.INSTALLED_APPS.remove('regressiontests.bug8245')
+        if 'django.contrib.gis' in settings.INSTALLED_APPS:
+            settings.INSTALLED_APPS.remove('django.contrib.gis')
+
+        print 'Waiting for threaded server to come online.'
+        started.wait()
+        print 'DB Ready, Server online.'
+
+
+
+        # Set the testing URL based on what available port we get.
+        global_settings.TEST_URL = 'http://localhost:%d' % server_container.server_thread.port
+
+
 
         # Make sure we even need to run tests.
         if len(wmtests) is 0:
             # Setup and run unittests.
             testtotals = {}
             x = logging.getLogger()
-            x.setLevel(0)
+            x.setLevel(logging.DEBUG)
             from windmill.server.proxy import logger
-            from functest import bin
-            from functest import runner
-            runner.CLIRunner.final = classmethod(lambda self, totals: testtotals.update(totals))
-            import windmill
+            #from functest import bin
+            #from functest import runner
+            #runner.CLIRunner.final = classmethod(lambda self, totals: testtotals.update(totals))
+            #import windmill
+            #count = 0
+            #print wmtests
+            #for wmt in wmtests:
+                #print wmt
+                #print tests[count][1]
+                #count = count + 1
+            #count = 0
+            bin = None
+            runner = None
             setup_module(tests[0][1])
-            sys.argv = wmtests
-            bin.cli()
+            for wmt in wmtests:
+                print sys.argv
+                sys.argv = [wmt,]
+                print sys.argv
+                for k in (k for k in sys.modules.keys() if k.startswith('functest')):
+                    del(sys.modules[k])
+                #dbin)
+                #del(runner)
+                import functest
+                from functest import bin
+                from functest import runner
+                runner.CLIRunner.final = classmethod(lambda self, totals: testtotals.update(totals) )
+                bin.cli()
+                bin = None
+                runner = None
+                print sys.argv
+                # import functest
+                #                 functest.modules_passed = []
+                #                 functest.modules_failed = []
+                #                 from functest import frame
+                #                 frame.totals = {'pass':0, 'fail':0, 'skip':0}
+                #teardown_module(tests[count][1])
+                #sleep(.5)
+                #count = count + 1
+                #setup_module(tests[count][1])
             teardown_module(tests[0][1])
+            # sys.argv = [wmtests[0],]
+            #             bin.cli()
+            
             if testtotals['fail'] is not 0:
                 sleep(.5)
                 sys.exit(1)
     do_std = options.standard
     wm_browser = options.wmbrowser
     django_tests(int(options.verbosity), options.interactive, args)
+