Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
sudo: false
language: python
addons:
firefox: "39.0"
services:
- memcached
- mysql
Expand Down Expand Up @@ -27,6 +29,7 @@ env:
- PIP_DISABLE_PIP_VERSION_CHECK=on
- SENTRY_LIGHT_BUILD=1
- SENTRY_SKIP_BACKEND_VALIDATION=1
- SELENIUM_DRIVER=firefox
install:
- make travis-install-$TEST_SUITE
script:
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ python_files = test*.py
addopts = --tb=native -p no:doctest
norecursedirs = bin dist docs htmlcov script hooks node_modules .* {args}
looponfailroots = src/sentry tests
selenium_driver = phantomjs

[flake8]
ignore = F999,E501,E128,E124,E402,W503,E731,C901
Expand Down
6 changes: 6 additions & 0 deletions src/sentry/utils/pytest/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from __future__ import absolute_import

pytest_plugins = [
'sentry.utils.pytest.sentry',
'sentry.utils.pytest.selenium',
]
193 changes: 38 additions & 155 deletions src/sentry/utils/pytest.py → src/sentry/utils/pytest/selenium.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import

import mock
# TODO(dcramer): this heavily inspired by pytest-selenium, and it's possible
# we could simply inherit from the plugin at this point

import os
import pytest
import signal
Expand Down Expand Up @@ -110,156 +112,23 @@ def save_cookie(self, name, value, path='/',
))


def pytest_configure(config):
# HACK: Only needed for testing!
os.environ.setdefault('_SENTRY_SKIP_CONFIGURATION', '1')

os.environ.setdefault('RECAPTCHA_TESTING', 'True')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sentry.conf.server')

if not settings.configured:
# only configure the db if its not already done
test_db = os.environ.get('DB', 'postgres')
if test_db == 'mysql':
settings.DATABASES['default'].update({
'ENGINE': 'django.db.backends.mysql',
'NAME': 'sentry',
'USER': 'root',
'HOST': '127.0.0.1',
})
# mysql requires running full migration all the time
settings.SOUTH_TESTS_MIGRATE = True
elif test_db == 'postgres':
settings.DATABASES['default'].update({
'ENGINE': 'sentry.db.postgres',
'USER': 'postgres',
'NAME': 'sentry',
})
# postgres requires running full migration all the time
# since it has to install stored functions which come from
# an actual migration.
settings.SOUTH_TESTS_MIGRATE = True
elif test_db == 'sqlite':
settings.DATABASES['default'].update({
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
})
settings.SOUTH_TESTS_MIGRATE = os.environ.get('SENTRY_SOUTH_TESTS_MIGRATE', '1') == '1'
else:
raise RuntimeError('oops, wrong database: %r' % test_db)

settings.TEMPLATE_DEBUG = True

# Disable static compiling in tests
settings.STATIC_BUNDLES = {}

# override a few things with our test specifics
settings.INSTALLED_APPS = tuple(settings.INSTALLED_APPS) + (
'tests',
)
# Need a predictable key for tests that involve checking signatures
settings.SENTRY_PUBLIC = False

if not settings.SENTRY_CACHE:
settings.SENTRY_CACHE = 'sentry.cache.django.DjangoCache'
settings.SENTRY_CACHE_OPTIONS = {}

# This speeds up the tests considerably, pbkdf2 is by design, slow.
settings.PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]

# Replace real sudo middleware with our mock sudo middleware
# to assert that the user is always in sudo mode
middleware = list(settings.MIDDLEWARE_CLASSES)
sudo = middleware.index('sentry.middleware.sudo.SudoMiddleware')
middleware[sudo] = 'sentry.testutils.middleware.SudoMiddleware'
settings.MIDDLEWARE_CLASSES = tuple(middleware)

# enable draft features
settings.SENTRY_OPTIONS['mail.enable-replies'] = True

settings.SENTRY_ALLOW_ORIGIN = '*'

settings.SENTRY_TSDB = 'sentry.tsdb.inmemory.InMemoryTSDB'
settings.SENTRY_TSDB_OPTIONS = {}

settings.RECAPTCHA_PUBLIC_KEY = 'a' * 40
settings.RECAPTCHA_PRIVATE_KEY = 'b' * 40

settings.BROKER_BACKEND = 'memory'
settings.BROKER_URL = None
settings.CELERY_ALWAYS_EAGER = False
settings.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True

settings.DEBUG_VIEWS = True

settings.DISABLE_RAVEN = True

settings.CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}

if not hasattr(settings, 'SENTRY_OPTIONS'):
settings.SENTRY_OPTIONS = {}

settings.SENTRY_OPTIONS.update({
'redis.clusters': {
'default': {
'hosts': {
0: {
'db': 9,
},
},
},
},
'mail.backend': 'django.core.mail.backends.locmem.EmailBackend',
'system.url-prefix': 'http://testserver',
})
def pytest_addoption(parser):
parser.addini('selenium_driver',
help='selenium driver (phantomjs or firefox)')

# django mail uses socket.getfqdn which doesn't play nice if our
# networking isn't stable
patcher = mock.patch('socket.getfqdn', return_value='localhost')
patcher.start()
group = parser.getgroup('selenium', 'selenium')
group._addoption('--selenium-driver',
dest='selenium_driver',
help='selenium driver (phantomjs or firefox)')

from sentry.runner.initializer import (
bootstrap_options, configure_structlog, initialize_receivers, fix_south,
bind_cache_to_option_store)

bootstrap_options(settings)
configure_structlog()
fix_south(settings)

bind_cache_to_option_store()

initialize_receivers()

from sentry.utils.redis import clusters

with clusters.get('default').all() as client:
client.flushdb()

# force celery registration
from sentry.celery import app # NOQA

# disable DISALLOWED_IPS
from sentry import http
http.DISALLOWED_IPS = set()


def pytest_runtest_teardown(item):
from sentry.app import tsdb
tsdb.flush()

from sentry.utils.redis import clusters

with clusters.get('default').all() as client:
client.flushdb()
def pytest_configure(config):
if hasattr(config, 'slaveinput'):
return # xdist slave

from celery.task.control import discard_all
discard_all()
config.option.selenium_driver = config.getoption('selenium_driver') or \
config.getini('selenium_driver') or \
os.getenv('SELENIUM_DRIVER')


@pytest.fixture(scope='session')
Expand All @@ -281,13 +150,19 @@ def percy(request):

@pytest.fixture(scope='function')
def browser(request, percy, live_server):
phantomjs_path = os.path.join(
settings.NODE_MODULES_ROOT,
'phantomjs-prebuilt',
'bin',
'phantomjs',
)
driver = webdriver.PhantomJS(executable_path=phantomjs_path)
driver_type = request.config.getoption('selenium_driver')
if driver_type == 'firefox':
driver = webdriver.Firefox()
elif driver_type == 'phantomjs':
phantomjs_path = os.path.join(
settings.NODE_MODULES_ROOT,
'phantomjs-prebuilt',
'bin',
'phantomjs',
)
driver = webdriver.PhantomJS(executable_path=phantomjs_path)
else:
raise pytest.UsageError('--driver must be specified')

def fin():
# Teardown Selenium.
Expand All @@ -296,7 +171,8 @@ def fin():
except Exception:
pass
# TODO: remove this when fixed in: https://github.com/seleniumhq/selenium/issues/767
driver.service.process.send_signal(signal.SIGTERM)
if hasattr(driver, 'service'):
driver.service.process.send_signal(signal.SIGTERM)
driver.quit()

request.node._driver = driver
Expand All @@ -314,6 +190,13 @@ def fin():
return driver


@pytest.fixture(scope='session', autouse=True)
def _environment(request):
config = request.config
# add environment details to the pytest-html plugin
config._environment.append(('Driver', config.option.selenium_driver))


@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call, __multicall__):
report = __multicall__.execute()
Expand Down
Loading