Browse Source

Various test cleanup and organization

David Cramer 11 years ago
parent
commit
a9840f09b3

File diff suppressed because it is too large
+ 0 - 36
src/sentry/testutils.py


+ 11 - 0
src/sentry/testutils/__init__.py

@@ -0,0 +1,11 @@
+"""
+sentry.testutils
+~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+from .asserts import *  # NOQA
+from .cases import *  # NOQA
+from .skips import *  # NOQA

+ 12 - 0
src/sentry/testutils/asserts.py

@@ -0,0 +1,12 @@
+"""
+sentry.testutils.asserts
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+
+def assert_date_resembles(one, two):
+    # this is mostly intended to handle discrepencies between mysql/postgres
+    assert one.replace(microsecond=0) == two.replace(microsecond=0)

+ 175 - 0
src/sentry/testutils/cases.py

@@ -0,0 +1,175 @@
+"""
+sentry.testutils.cases
+~~~~~~~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+from __future__ import absolute_import
+
+__all__ = ('TestCase', 'TransactionTestCase', 'APITestCase')
+
+import base64
+import os.path
+
+from django.conf import settings
+from django.contrib.auth import login
+from django.core.cache import cache
+from django.core.management import call_command
+from django.core.urlresolvers import reverse
+from django.db import connections, DEFAULT_DB_ALIAS
+from django.http import HttpRequest
+from django.test import TestCase, TransactionTestCase
+from django.test.client import Client
+from django.utils.importlib import import_module
+from exam import Exam
+from rest_framework.test import APITestCase as BaseAPITestCase
+
+from sentry.constants import MODULE_ROOT
+from sentry.models import Option, ProjectOption
+from sentry.utils import json
+
+from .fixtures import Fixtures
+from .helpers import get_auth_header
+
+
+class BaseTestCase(Fixtures, Exam):
+    urls = 'tests.sentry.web.urls'
+
+    def assertRequiresAuthentication(self, path, method='GET'):
+        resp = getattr(self.client, method.lower())(path)
+        assert resp.status_code == 302
+        assert resp['Location'] == 'http://testserver' + reverse('sentry-login')
+
+    def login_as(self, user):
+        user.backend = settings.AUTHENTICATION_BACKENDS[0]
+
+        engine = import_module(settings.SESSION_ENGINE)
+
+        request = HttpRequest()
+        if self.client.session:
+            request.session = self.client.session
+        else:
+            request.session = engine.SessionStore()
+
+        login(request, user)
+
+        # Save the session values.
+        request.session.save()
+
+        # Set the cookie to represent the session.
+        session_cookie = settings.SESSION_COOKIE_NAME
+        self.client.cookies[session_cookie] = request.session.session_key
+        cookie_data = {
+            'max-age': None,
+            'path': '/',
+            'domain': settings.SESSION_COOKIE_DOMAIN,
+            'secure': settings.SESSION_COOKIE_SECURE or None,
+            'expires': None,
+        }
+        self.client.cookies[session_cookie].update(cookie_data)
+
+    def login(self):
+        self.login_as(self.user)
+
+    def load_fixture(self, filepath):
+        filepath = os.path.join(
+            MODULE_ROOT,
+            'tests',
+            'fixtures',
+            filepath,
+        )
+        with open(filepath, 'rb') as fp:
+            return fp.read()
+
+    def _pre_setup(self):
+        cache.clear()
+        ProjectOption.objects.clear_cache()
+        Option.objects.clear_cache()
+        super(BaseTestCase, self)._pre_setup()
+
+    def _makeMessage(self, data):
+        return base64.b64encode(json.dumps(data))
+
+    def _postWithKey(self, data, key=None):
+        resp = self.client.post(reverse('sentry-api-store'), {
+            'data': self._makeMessage(data),
+            'key': settings.SENTRY_KEY,
+        })
+        return resp
+
+    def _postWithHeader(self, data, key=None, secret=None):
+        if key is None:
+            key = self.projectkey.public_key
+            secret = self.projectkey.secret_key
+
+        message = self._makeMessage(data)
+        resp = self.client.post(
+            reverse('sentry-api-store'), message,
+            content_type='application/octet-stream',
+            HTTP_X_SENTRY_AUTH=get_auth_header('_postWithHeader', key, secret),
+        )
+        return resp
+
+    _postWithSignature = _postWithHeader
+    _postWithNewSignature = _postWithHeader
+
+
+class TestCase(BaseTestCase, TestCase):
+    pass
+
+
+class TransactionTestCase(BaseTestCase, TransactionTestCase):
+    """
+    Subclass of ``django.test.TransactionTestCase`` that quickly tears down
+    fixtures and doesn't `flush` on setup.  This enables tests to be run in
+    any order.
+    """
+    urls = 'tests.urls'
+
+    def __call__(self, result=None):
+        """
+        Wrapper around default __call__ method to perform common Django test
+        set up. This means that user-defined Test Cases aren't required to
+        include a call to super().setUp().
+        """
+        self.client = getattr(self, 'client_class', Client)()
+        try:
+            self._pre_setup()
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except Exception:
+            import sys
+            result.addError(self, sys.exc_info())
+            return
+        try:
+            super(TransactionTestCase, self).__call__(result)
+        finally:
+            try:
+                self._post_teardown()
+            except (KeyboardInterrupt, SystemExit):
+                raise
+            except Exception:
+                import sys
+                result.addError(self, sys.exc_info())
+
+    def _get_databases(self):
+        if getattr(self, 'multi_db', False):
+            return connections
+        return [DEFAULT_DB_ALIAS]
+
+    def _fixture_setup(self):
+        for db in self._get_databases():
+            if hasattr(self, 'fixtures') and self.fixtures:
+                # We have to use this slightly awkward syntax due to the fact
+                # that we're using *args and **kwargs together.
+                call_command('loaddata', *self.fixtures, **{'verbosity': 0, 'database': db})
+
+    def _fixture_teardown(self):
+        for db in self._get_databases():
+            call_command('flush', verbosity=0, interactive=False, database=db)
+
+
+class APITestCase(BaseTestCase, BaseAPITestCase):
+    pass

File diff suppressed because it is too large
+ 14 - 0
src/sentry/testutils/fixtures.py


+ 21 - 0
src/sentry/testutils/helpers.py

@@ -0,0 +1,21 @@
+"""
+sentry.testutils.helpers
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+
+def get_auth_header(client, api_key=None, secret_key=None):
+    header = [
+        ('sentry_client', client),
+        ('sentry_version', '5'),
+    ]
+
+    if api_key:
+        header.append(('sentry_key', api_key))
+    if secret_key:
+        header.append(('sentry_secret', secret_key))
+
+    return 'Sentry %s' % ', '.join('%s=%s' % (k, v) for k, v in header)

+ 39 - 0
src/sentry/testutils/skips.py

@@ -0,0 +1,39 @@
+"""
+sentry.testutils.skips
+~~~~~~~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+import pytest
+
+
+def riak_is_available():
+    import socket
+    try:
+        socket.create_connection(('127.0.0.1', 8098), 1.0)
+    except socket.error:
+        return False
+    else:
+        return True
+
+
+requires_riak = pytest.mark.skipif(
+    lambda x: not riak_is_available(),
+    reason="requires riak server running")
+
+
+def cassandra_is_available():
+    import socket
+    try:
+        socket.create_connection(('127.0.0.1', 9042), 1.0)
+    except socket.error:
+        return False
+    else:
+        return True
+
+
+requires_cassandra = pytest.mark.skipif(
+    lambda x: not cassandra_is_available(),
+    reason="requires cassandra server running")

+ 1 - 1
tests/integration/tests.py

@@ -216,7 +216,7 @@ class DepdendencyTest(TestCase):
 
         import_string.side_effect = self.raise_import_error(package)
 
-        with self.Settings(**{key: setting_value}):
+        with self.settings(**{key: setting_value}):
             with self.assertRaises(ConfigurationError):
                 validate_settings(django_settings)
 

+ 3 - 4
tests/sentry/api/endpoints/test_group_details.py

@@ -1,11 +1,10 @@
 from django.core.urlresolvers import reverse
-from rest_framework.test import APITestCase
 from sentry.constants import STATUS_RESOLVED
 from sentry.models import Group
-from sentry.testutils import BaseTestCase
+from sentry.testutils import APITestCase
 
 
-class GroupDetailsTest(BaseTestCase, APITestCase):
+class GroupDetailsTest(APITestCase):
     def test_simple(self):
         self.client.force_authenticate(user=self.user)
 
@@ -32,7 +31,7 @@ class GroupDetailsTest(BaseTestCase, APITestCase):
         }
 
 
-class GroupUpdateTest(BaseTestCase, APITestCase):
+class GroupUpdateTest(APITestCase):
     def test_simple(self):
         self.client.force_authenticate(user=self.user)
 

+ 2 - 3
tests/sentry/api/endpoints/test_group_index.py

@@ -1,9 +1,8 @@
 from django.core.urlresolvers import reverse
-from rest_framework.test import APITestCase
-from sentry.testutils import BaseTestCase
+from sentry.testutils import APITestCase
 
 
-class GroupIndexTest(BaseTestCase, APITestCase):
+class GroupIndexTest(APITestCase):
     def test_simple(self):
         self.create_group(checksum='a' * 32)
         self.create_group(checksum='b' * 32)

Some files were not shown because too many files changed in this diff