Brought the rest of the Django client tests up to passing

This commit is contained in:
David Cramer 2011-10-07 12:12:54 -04:00
parent 16854905e7
commit bf731f6899
9 changed files with 189 additions and 232 deletions

View File

@ -4,7 +4,9 @@ import sys
from os.path import dirname, abspath, join
from optparse import OptionParser
sys.path.insert(0, dirname(abspath(__file__)))
where_am_i = dirname(abspath(__file__))
sys.path.insert(0, where_am_i)
logging.getLogger('sentry').addHandler(logging.StreamHandler())
@ -45,6 +47,7 @@ if not settings.configured:
BROKER_VHOST="/",
CELERY_ALWAYS_EAGER=True,
TEMPLATE_DEBUG=True,
TEMPLATE_DIRS=[join(where_am_i, 'tests', 'contrib', 'django', 'templates')],
)
import djcelery
djcelery.setup_loader()

View File

@ -48,7 +48,9 @@ class SentryClient(object):
kwargs.setdefault('level', logging.ERROR)
kwargs.setdefault('server_name', settings.NAME)
versions = get_versions()
modules = settings.INCLUDE_PATHS
versions = get_versions(modules)
kwargs['data']['__sentry__']['versions'] = versions
# Shorten lists/strings
@ -59,9 +61,6 @@ class SentryClient(object):
# if we've passed frames, lets try to fetch the culprit
if not kwargs.get('view') and kwargs['data']['__sentry__'].get('frames'):
# This should be cached
modules = settings.INCLUDE_PATHS
# We iterate through each frame looking for an app in INSTALLED_APPS
# When one is found, we mark it as last "best guess" (best_guess) and then
# check it against SENTRY_EXCLUDE_PATHS. If it isnt listed, then we
@ -104,7 +103,7 @@ class SentryClient(object):
})
if 'checksum' not in kwargs:
checksum = construct_checksum(**kwargs)
kwargs['checksum'] = checksum = construct_checksum(**kwargs)
else:
checksum = kwargs['checksum']

View File

@ -29,6 +29,9 @@ class DjangoClient(SentryClient):
else:
post_data = request.POST
if 'data' not in kwargs:
kwargs['data'] = {}
kwargs['data'].update(dict(
META=request.META,
POST=post_data,
@ -77,6 +80,9 @@ class DjangoClient(SentryClient):
data = kwargs.pop('data', {}) or {}
if '__sentry__' not in data:
data['__sentry__'] = {}
try:
exc_type, exc_value, exc_traceback = exc_info

View File

@ -33,7 +33,7 @@ class SentryResponseErrorIdMiddleware(object):
def process_response(self, request, response):
if not getattr(request, 'sentry', None):
return response
response['X-Sentry-ID'] = request.sentry['id']
response['X-Sentry-ID'] = '$'.join(request.sentry['id'])
return response
class SentryLogMiddleware(object):

View File

@ -69,7 +69,10 @@ def get_versions(module_list=None):
versions = {}
for module_name in ext_module_list:
if module_name not in _VERSION_CACHE:
__import__(module_name)
try:
__import__(module_name)
except ImportError:
continue
app = sys.modules[module_name]
if hasattr(app, 'get_version'):
get_version = app.get_version

View File

@ -0,0 +1 @@
{% invalid template tag %}

View File

@ -3,6 +3,7 @@
from __future__ import absolute_import
import logging
from pprint import pformat
from django.conf import settings as django_settings
from django.contrib.auth.models import User
@ -14,6 +15,7 @@ from django.test import TestCase
from django.utils.encoding import smart_unicode
from sentry_client.conf import settings
from sentry_client.conf import defaults
from sentry_client.contrib.django import DjangoClient
from sentry_client.contrib.django.models import get_client
@ -26,13 +28,45 @@ class TempStoreClient(DjangoClient):
def send(self, **kwargs):
self.events.append(kwargs)
class Settings(object):
"""
Allows you to define settings that are required for this function to work.
>>> with Settings(SENTRY_LOGIN_URL='foo'): #doctest: +SKIP
>>> print settings.SENTRY_LOGIN_URL #doctest: +SKIP
"""
NotDefined = object()
def __init__(self, **overrides):
self.overrides = overrides
self._orig = {}
def __enter__(self):
for k, v in self.overrides.iteritems():
self._orig[k] = getattr(django_settings, k, self.NotDefined)
setattr(django_settings, k, v)
if k.startswith('SENTRY_'):
setattr(settings, k.split('SENTRY_', 1)[1], v)
def __exit__(self, exc_type, exc_value, traceback):
for k, v in self._orig.iteritems():
if v is self.NotDefined:
delattr(django_settings, k)
if k.startswith('SENTRY_'):
k = k.split('SENTRY_', 1)[1]
setattr(settings, k, getattr(defaults, k, None))
else:
setattr(django_settings, k, v)
if k.startswith('SENTRY_'):
setattr(settings, k.split('SENTRY_', 1)[1], v)
class DjangoClientTest(TestCase):
## Fixture setup/teardown
urls = 'tests.contrib.django.urls'
def setUp(self):
self.sentry_client = get_client()
django_settings.MIDDLEWARE_CLASSES = []
def test_signal_integration(self):
try:
@ -59,51 +93,48 @@ class DjangoClientTest(TestCase):
self.assertEquals(event['message'], 'view exception')
self.assertEquals(event['view'], 'tests.contrib.django.views.raise_exc')
# def test_user_info(self):
# user = User(username='admin', email='admin@example.com')
# user.set_password('admin')
# user.save()
def test_user_info(self):
user = User(username='admin', email='admin@example.com')
user.set_password('admin')
user.save()
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
# self.assertEquals(GroupedMessage.objects.count(), 1)
# self.assertEquals(Message.objects.count(), 1)
# last = Message.objects.get()
# self.assertTrue('user' in last.data['__sentry__'])
# user_info = last.data['__sentry__']['user']
# self.assertTrue('is_authenticated' in user_info)
# self.assertFalse(user_info['is_authenticated'])
# self.assertFalse('username' in user_info)
# self.assertFalse('email' in user_info)
# self.assertTrue(self.client.login(username='admin', password='admin'))
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
# self.assertEquals(GroupedMessage.objects.count(), 1)
# self.assertEquals(Message.objects.count(), 2)
# last = Message.objects.order_by('-id')[0]
# self.assertTrue('user' in last.data['__sentry__'])
# user_info = last.data['__sentry__']['user']
# self.assertTrue('is_authenticated' in user_info)
# self.assertTrue(user_info['is_authenticated'])
# self.assertTrue('username' in user_info)
# self.assertEquals(user_info['username'], 'admin')
# self.assertTrue('email' in user_info)
# self.assertEquals(user_info['email'], 'admin@example.com')
def test_request_middleware_exception(self):
django_settings.MIDDLEWARE_CLASSES = ['tests.contrib.django.middleware.BrokenRequestMiddleware']
self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc'))
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertTrue('user' in event['data']['__sentry__'])
user_info = event['data']['__sentry__']['user']
self.assertTrue('is_authenticated' in user_info)
self.assertFalse(user_info['is_authenticated'])
self.assertFalse('username' in user_info)
self.assertFalse('email' in user_info)
self.assertEquals(event['class_name'], 'ImportError')
self.assertEquals(event['level'], logging.ERROR)
self.assertEquals(event['message'], 'request')
self.assertEquals(event['view'], 'tests.contrib.django.middleware.process_request')
self.assertTrue(self.client.login(username='admin', password='admin'))
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertTrue('user' in event['data']['__sentry__'])
user_info = event['data']['__sentry__']['user']
self.assertTrue('is_authenticated' in user_info)
self.assertTrue(user_info['is_authenticated'])
self.assertTrue('username' in user_info)
self.assertEquals(user_info['username'], 'admin')
self.assertTrue('email' in user_info)
self.assertEquals(user_info['email'], 'admin@example.com')
def test_request_middleware_exception(self):
with Settings(MIDDLEWARE_CLASSES=['tests.contrib.django.middleware.BrokenRequestMiddleware']):
self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals(event['class_name'], 'ImportError')
self.assertEquals(event['level'], logging.ERROR)
self.assertEquals(event['message'], 'request')
self.assertEquals(event['view'], 'tests.contrib.django.middleware.process_request')
# XXX: Django doesn't handle response middleware exceptions (yet)
# def test_response_middlware_exception(self):
@ -123,208 +154,122 @@ class DjangoClientTest(TestCase):
# django_settings.MIDDLEWARE_CLASSES = orig
def test_view_middleware_exception(self):
django_settings.MIDDLEWARE_CLASSES = ['tests.contrib.django.middleware.BrokenViewMiddleware']
with Settings(MIDDLEWARE_CLASSES=['tests.contrib.django.middleware.BrokenViewMiddleware']):
self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc'))
self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals(event['class_name'], 'ImportError')
self.assertEquals(event['level'], logging.ERROR)
self.assertEquals(event['message'], 'view')
self.assertEquals(event['view'], 'tests.contrib.django.middleware.process_view')
def test_exclude_modules_view(self):
with Settings(SENTRY_EXCLUDE_PATHS=['tests.views.decorated_raise_exc']):
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc-decor'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals(event['view'], 'tests.contrib.django.views.raise_exc')
def test_include_modules(self):
with Settings(SENTRY_INCLUDE_PATHS=['django.shortcuts.get_object_or_404']):
self.assertRaises(Exception, self.client.get, reverse('sentry-django-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals(event['view'], 'django.shortcuts.get_object_or_404')
def test_template_name_as_view(self):
self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc'))
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals(event['class_name'], 'ImportError')
self.assertEquals(event['level'], logging.ERROR)
self.assertEquals(event['message'], 'view')
self.assertEquals(event['view'], 'tests.contrib.django.middleware.process_view')
self.assertEquals(event['view'], 'error.html')
# def test_exclusion_view_path(self):
# try: Message.objects.get(pk=1341324)
# except: get_client().create_from_exception()
# def test_request_in_logging(self):
# resp = self.client.get(reverse('sentry-log-request-exc'))
# self.assertEquals(resp.status_code, 200)
# self.assertEquals(len(self.client.events), 1)
# event = self.client.events.pop(0)
# self.assertEquals(len(self.sentry_client.events), 1)
# event = self.sentry_client.events.pop(0)
# self.assertEquals(last.view, 'tests.tests.test_exclusion_view_path')
# self.assertEquals(event['view'], 'tests.contrib.django.views.logging_request_exc')
# self.assertEquals(event['data']['META']['REMOTE_ADDR'], '127.0.0.1')
# def test_best_guess_view(self):
# settings.EXCLUDE_PATHS = ['tests.tests']
def test_create_from_record_none_exc_info(self):
# sys.exc_info can return (None, None, None) if no exception is being
# handled anywhere on the stack. See:
# http://docs.python.org/library/sys.html#sys.exc_info
record = logging.LogRecord(
'foo',
logging.INFO,
pathname=None,
lineno=None,
msg='test',
args=(),
exc_info=(None, None, None),
)
self.sentry_client.create_from_record(record)
# try: Message.objects.get(pk=1341324)
# except: get_client().create_from_exception()
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
# last = Message.objects.get()
self.assertEquals(event['message'], 'test')
# self.assertEquals(last.view, 'tests.tests.test_best_guess_view')
def test_versions(self):
import sentry_client
with Settings(SENTRY_INCLUDE_PATHS=['sentry_client', 'tests']):
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
# settings.EXCLUDE_PATHS = []
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
# def test_exclude_modules_view(self):
# settings.EXCLUDE_PATHS = ['tests.views.decorated_raise_exc']
self.assertTrue('versions' in event['data']['__sentry__'])
self.assertTrue('sentry_client' in event['data']['__sentry__']['versions'])
self.assertEquals(event['data']['__sentry__']['versions']['sentry_client'], sentry_client.VERSION)
self.assertTrue('module' in event['data']['__sentry__'])
self.assertEquals(event['data']['__sentry__']['module'], 'tests')
self.assertTrue('version' in event['data']['__sentry__'])
self.assertEquals(event['data']['__sentry__']['version'], '1.0')
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc-decor'))
def test_404_middleware(self):
with Settings(MIDDLEWARE_CLASSES=['sentry_client.contrib.django.middleware.Sentry404CatchMiddleware']):
resp = self.client.get('/non-existant-page')
self.assertEquals(resp.status_code, 404)
# last = Message.objects.get()
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
# self.assertEquals(last.view, 'tests.views.raise_exc')
self.assertEquals(event['url'], u'http://testserver/non-existant-page')
self.assertEquals(event['level'], logging.INFO)
self.assertEquals(event['logger'], 'http404')
# settings.EXCLUDE_PATHS = []
def test_response_error_id_middleware(self):
# TODO: test with 500s
with Settings(MIDDLEWARE_CLASSES=['sentry_client.contrib.django.middleware.SentryResponseErrorIdMiddleware', 'sentry_client.contrib.django.middleware.Sentry404CatchMiddleware']):
resp = self.client.get('/non-existant-page')
self.assertEquals(resp.status_code, 404)
headers = dict(resp.items())
self.assertTrue('X-Sentry-ID' in headers)
self.assertEquals(len(self.sentry_client.events), 1)
event = self.sentry_client.events.pop(0)
self.assertEquals('$'.join([event['message_id'], event['checksum']]), headers['X-Sentry-ID'])
# def test_varying_messages(self):
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc') + '?message=foo')
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc') + '?message=bar')
# self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc') + '?message=gra')
# def test_get_client(self):
# from sentry.client.log import LoggingSentryClient
# self.assertEquals(GroupedMessage.objects.count(), 1)
# self.assertEquals(get_client().__class__, SentryClient)
# self.assertEquals(get_client(), get_client())
# def test_include_modules(self):
# settings.INCLUDE_PATHS = ['django.shortcuts.get_object_or_404']
# settings.CLIENT = 'sentry.client.log.LoggingSentryClient'
# self.assertRaises(Exception, self.client.get, reverse('sentry-django-exc'))
# self.assertEquals(get_client().__class__, LoggingSentryClient)
# self.assertEquals(get_client(), get_client())
# last = Message.objects.get()
# self.assertEquals(last.view, 'django.shortcuts.get_object_or_404')
# settings.INCLUDE_PATHS = []
# def test_template_name_as_view(self):
# self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc'))
# last = Message.objects.get()
# self.assertEquals(last.view, 'sentry-tests/error.html')
# def test_request_in_logging(self):
# resp = self.client.get(reverse('sentry-log-request-exc'))
# self.assertEquals(resp.status_code, 200)
# last = Message.objects.get()
# self.assertEquals(last.view, 'tests.views.logging_request_exc')
# self.assertEquals(last.data['META']['REMOTE_ADDR'], '127.0.0.1')
# def test_create_from_record_none_exc_info(self):
# # sys.exc_info can return (None, None, None) if no exception is being
# # handled anywhere on the stack. See:
# # http://docs.python.org/library/sys.html#sys.exc_info
# client = get_client()
# record = logging.LogRecord(
# 'foo',
# logging.INFO,
# pathname=None,
# lineno=None,
# msg='test',
# args=(),
# exc_info=(None, None, None),
# )
# message_id = client.create_from_record(record)
# message = Message.objects.get(message_id=message_id)
# self.assertEquals('test', message.message)
# def test_versions(self):
# import sentry
# resp = self.client.get(reverse('sentry-log-request-exc'))
# self.assertEquals(resp.status_code, 200)
# self.assertEquals(Message.objects.count(), 1)
# self.assertEquals(GroupedMessage.objects.count(), 1)
# last = Message.objects.get()
# self.assertTrue('versions' in last.data['__sentry__'], last.data['__sentry__'])
# self.assertTrue('sentry' in last.data['__sentry__']['versions'], last.data['__sentry__'])
# self.assertEquals(last.data['__sentry__']['versions']['sentry'], sentry.VERSION)
# self.assertTrue('module' in last.data['__sentry__'], last.data['__sentry__'])
# self.assertEquals(last.data['__sentry__']['module'], 'tests')
# self.assertTrue('version' in last.data['__sentry__'], last.data['__sentry__'])
# self.assertEquals(last.data['__sentry__']['version'], '1.0')
# last = GroupedMessage.objects.get()
# self.assertTrue('module' in last.data)
# self.assertEquals(last.data['module'], 'tests')
# self.assertTrue('version' in last.data)
# self.assertEquals(last.data['version'], '1.0')
# def test_404_middleware(self):
# existing = django_settings.MIDDLEWARE_CLASSES
# django_settings.MIDDLEWARE_CLASSES = (
# 'sentry.client.middleware.Sentry404CatchMiddleware',
# ) + django_settings.MIDDLEWARE_CLASSES
# resp = self.client.get('/non-existant-page')
# self.assertEquals(resp.status_code, 404)
# self.assertEquals(Message.objects.count(), 1)
# self.assertEquals(GroupedMessage.objects.count(), 1)
# last = Message.objects.get()
# self.assertEquals(last.url, u'http://testserver/non-existant-page')
# self.assertEquals(last.level, logging.INFO)
# self.assertEquals(last.logger, 'http404')
# django_settings.MIDDLEWARE_CLASSES = existing
# def test_response_error_id_middleware(self):
# # TODO: test with 500s
# existing = django_settings.MIDDLEWARE_CLASSES
# django_settings.MIDDLEWARE_CLASSES = (
# 'sentry.client.middleware.SentryResponseErrorIdMiddleware',
# 'sentry.client.middleware.Sentry404CatchMiddleware',
# ) + django_settings.MIDDLEWARE_CLASSES
# resp = self.client.get('/non-existant-page')
# self.assertEquals(resp.status_code, 404)
# headers = dict(resp.items())
# self.assertTrue(headers.get('X-Sentry-ID'))
# self.assertTrue(Message.objects.filter(message_id=headers['X-Sentry-ID']).exists())
# django_settings.MIDDLEWARE_CLASSES = existing
# def test_extra_storage(self):
# from sentry.utils import MockDjangoRequest
# request = MockDjangoRequest(
# META = {'foo': 'bar'},
# )
# logger = logging.getLogger()
# self.setUpHandler()
# logger.error('This is a test %s', 'error', extra={
# 'request': request,
# 'data': {
# 'baz': 'bar',
# }
# })
# self.assertEquals(Message.objects.count(), 1)
# self.assertEquals(GroupedMessage.objects.count(), 1)
# last = Message.objects.get()
# self.assertEquals(last.logger, 'root')
# self.assertEquals(last.level, logging.ERROR)
# self.assertEquals(last.message, 'This is a test error')
# self.assertTrue('META' in last.data)
# self.assertTrue('foo' in last.data['META'])
# self.assertEquals(last.data['META']['foo'], 'bar')
# self.assertTrue('baz' in last.data)
# self.assertEquals(last.data['baz'], 'bar')
# class SentryClientTest(TestCase):
# def setUp(self):
# self._client = settings.CLIENT
# def tearDown(self):
# settings.CLIENT = self._client
# def test_get_client(self):
# from sentry.client.log import LoggingSentryClient
# self.assertEquals(get_client().__class__, SentryClient)
# self.assertEquals(get_client(), get_client())
# settings.CLIENT = 'sentry.client.log.LoggingSentryClient'
# self.assertEquals(get_client().__class__, LoggingSentryClient)
# self.assertEquals(get_client(), get_client())
# settings.CLIENT = 'sentry.client.base.SentryClient'
# settings.CLIENT = 'sentry.client.base.SentryClient'

View File

@ -16,10 +16,10 @@ def decorated_raise_exc(request):
return raise_exc(request)
def template_exc(request):
return render_to_response('sentry-tests/error.html')
return render_to_response('error.html')
def logging_request_exc(request):
logger = logging.getLogger('sentry.test')
logger = logging.getLogger(__name__)
try:
raise Exception(request.GET.get('message', 'view exception'))
except Exception, e: