# HG changeset patch # User Victor Ng # Date 1219931083 14400 # Node ID ff263bdd455e142133f0e49541ba2b4fbbbfe788 initial checkin diff -r 000000000000 -r ff263bdd455e .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,6 @@ +syntax: glob + +*.pyc +*.egg-info +build +dist diff -r 000000000000 -r ff263bdd455e AUTHORS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AUTHORS Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,3 @@ +Jason Pellerin +Bjorn Stabell +Victor Ng diff -r 000000000000 -r ff263bdd455e Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,7 @@ +pypi: + python setup.py sdist bdist_egg upload -s + +clean: + rm -rf dist build *egg-info + find . -name "*.pyc" | xargs rm + diff -r 000000000000 -r ff263bdd455e README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.txt Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,18 @@ +Nose django helper plugin +========================= + +nosetests -v --with-django --with-doctest --doctest-tests + +This is a rewrite of Jason Pellerin's original nose-django plugin. + +This plugin will work with Django trunk (0.97-pre SVN revision 6669) + +Features: + + * automatic settings.py detection in current or parent directory + * fixture support + * database setup/teardown + +Contact: + Victor Ng + diff -r 000000000000 -r ff263bdd455e examples/project/manage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/manage.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff -r 000000000000 -r ff263bdd455e examples/project/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/settings.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,74 @@ +# Django settings for dtt project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'sqlite3' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. +DATABASE_NAME = ':memory:' # Or path to database file if using sqlite3. +#DATABASE_USER = '' # Not used with sqlite3. +#DATABASE_PASSWORD = '' # Not used with sqlite3. +#DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +#DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + + +# Local time zone for this installation. All choices can be found here: +# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://blogs.law.harvard.edu/tech/stories/storyReader$15 +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. +# Example: "http://media.lawrence.com" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'gl6%_ew1u)@)4#^blbji7(25urbdmr82jtov=%i$crckk^t%y@' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.doc.XViewMiddleware', +) + +ROOT_URLCONF = 'dtt.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates". + # Always use forward slashes, even on Windows. +) + +INSTALLED_APPS = ( + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sessions', + 'django.contrib.sites', + 'project.zoo' +) diff -r 000000000000 -r ff263bdd455e examples/project/tests/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/tests/__init__.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,1 @@ +pass diff -r 000000000000 -r ff263bdd455e examples/project/tests/test_views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/tests/test_views.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,6 @@ +from django.http import HttpRequest +from project.zoo import views + +def test_view_index(): + r = views.index(HttpRequest()) + assert r diff -r 000000000000 -r ff263bdd455e examples/project/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/urls.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + # Example: + # (r'^dtt/', include('dtt.apps.foo.urls.foo')), + + # Uncomment this for admin: +# (r'^admin/', include('django.contrib.admin.urls')), +) diff -r 000000000000 -r ff263bdd455e examples/project/zoo/models.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/zoo/models.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,45 @@ +""" +Module-level doctest. + + >>> Zoo + + >>> 1 + 1 + 2 +""" +from django.db import models + +# Create your models here. +class Zoo(models.Model): + """ + Class-level doctest + + >>> Zoo + + >>> 1 + 1 + 2 + >>> Zoo.objects.all() + [] + >>> z = Zoo(name='Bronx') + >>> z.save() + >>> z + + >>> Zoo.objects.all() + [] + """ + name = models.CharField(max_length=100) + + def __str__(self): + """ + Function in class test + >>> 1 + 2 + 3 + """ + return self.name + +def func(): + """ + Function-level test + >>> 1+3 + 4 + """ + pass diff -r 000000000000 -r ff263bdd455e examples/project/zoo/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/project/zoo/views.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,4 @@ +# Create your views here. + +def index(request): + return 1 diff -r 000000000000 -r ff263bdd455e nosedjango/nosedjango.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nosedjango/nosedjango.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,118 @@ +""" +nose plugin for easy testing of django projects and apps. Sets up a test +database (or schema) and installs apps from test settings file before tests +are run, and tears the test database (or schema) down after all tests are run. +""" +__author = 'Jason Pellerin' +__version__ = '0.1' + +import atexit +import logging +import os, sys +import re + +from nose.plugins import Plugin +import nose.case + +# Force settings.py pointer +# search the current working directory and all parent directories to find +# the settings file +from nose.importer import add_path +os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +def get_SETTINGS_PATH(): + cwd = os.getcwd() + while cwd: + if 'settings.py' in os.listdir(cwd): + break + cwd = os.path.split(cwd)[0] + if cwd == '/': + return None + return cwd +SETTINGS_PATH = get_SETTINGS_PATH() + +log = logging.getLogger('nose.plugins.nosedjango') + +class NoseDjango(Plugin): + """ + Enable to set up django test environment before running all tests, and + tear it down after all tests. If the django database engine in use is not + sqlite3, one or both of --django-test-db or django-test-schema must be + specified. + + Note that your django project must be on PYTHONPATH for the settings file + to be loaded. The plugin will help out by placing the nose working dir + into sys.path if it isn't already there, unless the -P + (--no-path-adjustment) argument is set. + """ + name = 'django' + + def configure(self, options, conf): + Plugin.configure(self, options, conf) + self.verbosity = conf.verbosity + + def begin(self): + """Create the test database and schema, if needed, and switch the + connection over to that database. Then call install() to install + all apps listed in the loaded settings module. + """ + # Add the working directory (and any package parents) to sys.path + # before trying to import django modules; otherwise, they won't be + # able to find project.settings if the working dir is project/ or + # project/.. + + if not SETTINGS_PATH: + sys.stderr.write("Can't find Django settings file!\n") + # short circuit if no settings file can be found + return + + if self.conf.addPaths: + map(add_path, self.conf.where) + + add_path(SETTINGS_PATH) + sys.path.append(SETTINGS_PATH) + import settings + settings.DEBUG = False # I have no idea why Django does this, but it does + from django.core import mail + self.mail = mail + from django.conf import settings + from django.core import management + from django.test.utils import setup_test_environment + from django.db import connection + + self.old_db = settings.DATABASE_NAME + + # setup the test env for each test case + setup_test_environment() + connection.creation.create_test_db(verbosity=self.verbosity) + + # exit the setup phase and let nose do it's thing + + def beforeTest(self, test): + + if not SETTINGS_PATH: + # short circuit if no settings file can be found + return + + from django.core.management import call_command + call_command('flush', verbosity=0, interactive=False) + + if isinstance(test, nose.case.Test) and \ + isinstance(test.test, nose.case.MethodTestCase) and \ + hasattr(test.context, 'fixtures'): + # We have to use this slightly awkward syntax due to the fact + # that we're using *args and **kwargs together. + call_command('loaddata', *test.context.fixtures, **{'verbosity': 0}) + self.mail.outbox = [] + + def finalize(self, result=None): + """ + Clean up any created database and schema. + """ + if not SETTINGS_PATH: + # short circuit if no settings file can be found + return + + from django.test.utils import teardown_test_environment + from django.db import connection + connection.creation.destroy_test_db(self.old_db, verbosity=self.verbosity) + teardown_test_environment() diff -r 000000000000 -r ff263bdd455e setup.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.cfg Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,5 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff -r 000000000000 -r ff263bdd455e setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Thu Aug 28 09:44:43 2008 -0400 @@ -0,0 +1,24 @@ +from setuptools import setup, find_packages + +setup( + name='NoseDjango', + version='0.5', + author='Victor Ng', + author_email = 'victor.ng@monkeybeanonline.com', + description = 'nose plugin for easy testing of django projects ' \ + 'and apps. Sets up a test database (or schema) and installs apps ' \ + 'from test settings file before tests are run, and tears the test ' \ + 'database (or schema) down after all tests are run.', + install_requires='nose>=0.10', + url = "http://poli-cms.googlecode.com/svn/nose-django/", + license = 'GNU LGPL', + packages = find_packages(exclude=['tests']), + zip_safe = False, + include_package_data = True, + entry_points = { + 'nose.plugins': [ + 'django = nosedjango.nosedjango:NoseDjango', + ] + } + ) +