Switch test_app generation over to use py.test fixtures.

By doing this, we can take advantage of py.test's ability to create
temporary directories that are then cleaned up later during testing.
This helps for sandboxing things.

This also involves a ton of changes:
 - Changing the get_app stuff appropriately, getting rid of the
   setup_fresh_app decorator
 - Making said fixture
 - Switching over a billion tests to use it
This commit is contained in:
Christopher Allan Webber 2013-04-04 19:23:04 -05:00
parent e11c62a0ef
commit 5c2ece7401
18 changed files with 243 additions and 246 deletions

View File

@ -0,0 +1,15 @@
from mediagoblin.tests import tools
import pytest
@pytest.fixture()
def test_app(request):
"""
py.test fixture to pass sandboxed mediagoblin applications into tests that
want them.
You could make a local version of this method for your own tests
to override the paste and config files being used by passing them
in differently to get_app.
"""
return tools.get_app(request)

View File

@ -0,0 +1,2 @@
[pytest]
usefixtures = tmpdir

View File

@ -20,9 +20,11 @@ import base64
from pkg_resources import resource_filename
import pytest
from mediagoblin import mg_globals
from mediagoblin.tools import template, pluginapi
from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
_log = logging.getLogger(__name__)
@ -42,16 +44,16 @@ EVIL_PNG = resource('evil.png')
BIG_BLUE = resource('bigblue.png')
@pytest.mark.usefixtures("test_app")
class TestAPI(object):
def setup(self):
self.app = get_app(dump_old_app=False)
self.db = mg_globals.database
self.user_password = u'4cc355_70k3N'
self.user = fixture_add_user(u'joapi', self.user_password)
def login(self):
self.app.post(
def login(self, test_app):
test_app.post(
'/auth/login/', {
'username': self.user.username,
'password': self.user_password})
@ -65,14 +67,14 @@ class TestAPI(object):
self.user.username,
self.user_password])))}
def do_post(self, data, **kwargs):
def do_post(self, data, test_app, **kwargs):
url = kwargs.pop('url', '/api/submit')
do_follow = kwargs.pop('do_follow', False)
if not 'headers' in kwargs.keys():
kwargs['headers'] = self.http_auth_headers()
response = self.app.post(url, data, **kwargs)
response = test_app.post(url, data, **kwargs)
if do_follow:
response.follow()
@ -82,21 +84,22 @@ class TestAPI(object):
def upload_data(self, filename):
return {'upload_files': [('file', filename)]}
def test_1_test_test_view(self):
self.login()
def test_1_test_test_view(self, test_app):
self.login(test_app)
response = self.app.get(
response = test_app.get(
'/api/test',
headers=self.http_auth_headers())
assert response.body == \
'{"username": "joapi", "email": "joapi@example.com"}'
def test_2_test_submission(self):
self.login()
def test_2_test_submission(self, test_app):
self.login(test_app)
response = self.do_post(
{'title': 'Great JPG!'},
test_app,
**self.upload_data(GOOD_JPG))
assert response.status_int == 200

View File

@ -22,7 +22,7 @@ from nose.tools import assert_equal
from mediagoblin import mg_globals
from mediagoblin.auth import lib as auth_lib
from mediagoblin.db.models import User
from mediagoblin.tests.tools import setup_fresh_app, get_app, fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
from mediagoblin.tools import template, mail
@ -65,7 +65,6 @@ def test_bcrypt_gen_password_hash():
'notthepassword', hashed_pw, '3><7R45417')
@setup_fresh_app
def test_register_views(test_app):
"""
Massive test function that all our registration-related views all work.
@ -300,11 +299,10 @@ def test_register_views(test_app):
assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
def test_authentication_views():
def test_authentication_views(test_app):
"""
Test logging in and logging out
"""
test_app = get_app(dump_old_app=False)
# Make a new user
test_user = fixture_add_user(active_user=False)

View File

@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tests.tools import setup_fresh_app
from mediagoblin import mg_globals
@ -37,7 +36,6 @@ def _get_some_data(key):
return value
@setup_fresh_app
def test_cache_working(test_app):
some_data_cache = mg_globals.cache.get_cache('sum_data')
assert not some_data_cache.has_key('herp')

View File

@ -14,17 +14,13 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tests.tools import fixture_add_collection, fixture_add_user, \
get_app
from mediagoblin.tests.tools import fixture_add_collection, fixture_add_user
from mediagoblin.db.models import Collection, User
from mediagoblin.db.base import Session
from nose.tools import assert_equal
def test_user_deletes_collection():
def test_user_deletes_collection(test_app):
# Setup db.
get_app(dump_old_app=False)
user = fixture_add_user()
coll = fixture_add_collection(user=user)
# Reload into session:

View File

@ -14,12 +14,10 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tests.tools import get_app
from mediagoblin import mg_globals
def test_csrf_cookie_set():
test_app = get_app(dump_old_app=False)
def test_csrf_cookie_set(test_app):
cookie_name = mg_globals.app_config['csrf_cookie_name']
# get login page
@ -33,11 +31,14 @@ def test_csrf_cookie_set():
assert response.headers.get('Vary', False) == 'Cookie'
def test_csrf_token_must_match():
# We need a fresh app for this test on webtest < 1.3.6.
# We do not understand why, but it fixes the tests.
# If we require webtest >= 1.3.6, we can switch to a non fresh app here.
test_app = get_app(dump_old_app=True)
# We need a fresh app for this test on webtest < 1.3.6.
# We do not understand why, but it fixes the tests.
# If we require webtest >= 1.3.6, we can switch to a non fresh app here.
#
# ... this comment might be irrelevant post-pytest-fixtures, but I'm not
# removing it yet in case we move to module-level tests :)
# -- cwebber
def test_csrf_token_must_match(test_app):
# construct a request with no cookie or form token
assert test_app.post('/auth/login/',
@ -67,8 +68,7 @@ def test_csrf_token_must_match():
extra_environ={'gmg.verify_csrf': True}).\
status_int == 200
def test_csrf_exempt():
test_app = get_app(dump_old_app=False)
def test_csrf_exempt(test_app):
# monkey with the views to decorate a known endpoint
import mediagoblin.auth.views
from mediagoblin.meddleware.csrf import csrf_exempt

View File

@ -18,31 +18,31 @@ from nose.tools import assert_equal
from mediagoblin import mg_globals
from mediagoblin.db.models import User
from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
from mediagoblin.tools import template
from mediagoblin.auth.lib import bcrypt_check_password
class TestUserEdit(object):
def setup(self):
self.app = get_app(dump_old_app=False)
# set up new user
self.user_password = u'toast'
self.user = fixture_add_user(password = self.user_password)
self.login()
def login(self):
self.app.post(
def login(self, test_app):
test_app.post(
'/auth/login/', {
'username': self.user.username,
'password': self.user_password})
def test_user_deletion(self):
def test_user_deletion(self, test_app):
"""Delete user via web interface"""
self.login(test_app)
# Make sure user exists
assert User.query.filter_by(username=u'chris').first()
res = self.app.post('/edit/account/delete/', {'confirmed': 'y'})
res = test_app.post('/edit/account/delete/', {'confirmed': 'y'})
# Make sure user has been deleted
assert User.query.filter_by(username=u'chris').first() == None
@ -52,14 +52,16 @@ class TestUserEdit(object):
#Restore user at end of test
self.user = fixture_add_user(password = self.user_password)
self.login()
self.login(test_app)
def test_change_password(self):
def test_change_password(self, test_app):
"""Test changing password correctly and incorrectly"""
self.login(test_app)
# test that the password can be changed
# template.clear_test_template_context()
res = self.app.post(
res = test_app.post(
'/edit/account/', {
'old_password': 'toast',
'new_password': '123456',
@ -76,7 +78,7 @@ class TestUserEdit(object):
# test that the password cannot be changed if the given
# old_password is wrong template.clear_test_template_context()
self.app.post(
test_app.post(
'/edit/account/', {
'old_password': 'toast',
'new_password': '098765',
@ -86,11 +88,12 @@ class TestUserEdit(object):
assert not bcrypt_check_password('098765', test_user.pw_hash)
def test_change_bio_url(self):
def test_change_bio_url(self, test_app):
"""Test changing bio and URL"""
self.login(test_app)
# Test if legacy profile editing URL redirects correctly
res = self.app.post(
res = test_app.post(
'/edit/profile/', {
'bio': u'I love toast!',
'url': u'http://dustycloud.org/'}, expect_errors=True)
@ -99,7 +102,7 @@ class TestUserEdit(object):
assert_equal (res.status_int, 302)
assert res.headers['Location'].endswith("/u/chris/edit/")
res = self.app.post(
res = test_app.post(
'/u/chris/edit/', {
'bio': u'I love toast!',
'url': u'http://dustycloud.org/'})
@ -110,7 +113,7 @@ class TestUserEdit(object):
# change a different user than the logged in (should fail with 403)
fixture_add_user(username=u"foo")
res = self.app.post(
res = test_app.post(
'/u/foo/edit/', {
'bio': u'I love toast!',
'url': u'http://dustycloud.org/'}, expect_errors=True)
@ -119,7 +122,7 @@ class TestUserEdit(object):
# test changing the bio and the URL inproperly
too_long_bio = 150 * 'T' + 150 * 'o' + 150 * 'a' + 150 * 's' + 150* 't'
self.app.post(
test_app.post(
'/u/chris/edit/', {
# more than 500 characters
'bio': too_long_bio,

View File

@ -20,28 +20,27 @@ from urlparse import urlparse, parse_qs
from mediagoblin import mg_globals
from mediagoblin.tools import processing
from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
from mediagoblin.tests.test_submission import GOOD_PNG
from mediagoblin.tests import test_oauth as oauth
class TestHTTPCallback(object):
def setup(self):
self.app = get_app(dump_old_app=False)
def _setup(self, test_app):
self.db = mg_globals.database
self.user_password = u'secret'
self.user = fixture_add_user(u'call_back', self.user_password)
self.login()
self.login(test_app)
def login(self):
self.app.post('/auth/login/', {
def login(self, testapp):
testapp.post('/auth/login/', {
'username': self.user.username,
'password': self.user_password})
def get_access_token(self, client_id, client_secret, code):
response = self.app.get('/oauth/access_token', {
def get_access_token(self, testapp, client_id, client_secret, code):
response = testapp.get('/oauth/access_token', {
'code': code,
'client_id': client_id,
'client_secret': client_secret})
@ -50,13 +49,15 @@ class TestHTTPCallback(object):
return response_data['access_token']
def test_callback(self):
def test_callback(self, test_app):
''' Test processing HTTP callback '''
self._setup(test_app)
self.oauth = oauth.TestOAuth()
self.oauth.setup()
self.oauth._setup(test_app)
redirect, client_id = self.oauth.test_4_authorize_confidential_client()
redirect, client_id = self.oauth.test_4_authorize_confidential_client(
test_app)
code = parse_qs(urlparse(redirect.location).query)['code'][0]
@ -65,11 +66,11 @@ class TestHTTPCallback(object):
client_secret = client.secret
access_token = self.get_access_token(client_id, client_secret, code)
access_token = self.get_access_token(test_app, client_id, client_secret, code)
callback_url = 'https://foo.example?secrettestmediagoblinparam'
res = self.app.post('/api/submit?client_id={0}&access_token={1}\
res = test_app.post('/api/submit?client_id={0}&access_token={1}\
&client_secret={2}'.format(
client_id,
access_token,

View File

@ -15,18 +15,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.messages import fetch_messages, add_message
from mediagoblin.tests.tools import get_app
from mediagoblin.tools import template
def test_messages():
def test_messages(test_app):
"""
Added messages should show up in the request.session,
fetched messages should be the same as the added ones,
and fetching should clear the message list.
"""
test_app = get_app(dump_old_app=False)
# Aquire a request object
test_app.get('/')
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']

View File

@ -18,18 +18,15 @@ from nose.tools import assert_equal
from mediagoblin.db.base import Session
from mediagoblin.db.models import User, MediaEntry, MediaComment
from mediagoblin.tests.tools import get_app, \
fixture_add_user, fixture_media_entry
from mediagoblin.tests.tools import fixture_add_user, fixture_media_entry
def test_404_for_non_existent():
test_app = get_app(dump_old_app=False)
def test_404_for_non_existent(test_app):
res = test_app.get('/does-not-exist/', expect_errors=True)
assert_equal(res.status_int, 404)
def test_user_deletes_other_comments():
get_app() # gotta init the db and etc
def test_user_deletes_other_comments(test_app):
user_a = fixture_add_user(u"chris_a")
user_b = fixture_add_user(u"chris_b")
@ -81,8 +78,7 @@ def test_user_deletes_other_comments():
assert_equal(cmt_cnt2, cmt_cnt1 - 4)
def test_media_deletes_broken_attachment():
get_app() # gotta init the db and etc
def test_media_deletes_broken_attachment(test_app):
user_a = fixture_add_user(u"chris_a")
media = fixture_media_entry(uploader=user_a.id, save=False)

View File

@ -22,8 +22,7 @@ from nose.tools import assert_equal
from mediagoblin.db.base import Session
from mediagoblin.db.models import MediaEntry
from mediagoblin.tests.tools import get_app, \
fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
import mock
@ -35,8 +34,7 @@ UUID_MOCK = mock.Mock(return_value=FakeUUID())
class TestMediaEntrySlugs(object):
def setup(self):
self.test_app = get_app(dump_old_app=True)
def _setup(self):
self.chris_user = fixture_add_user(u'chris')
self.emily_user = fixture_add_user(u'emily')
self.existing_entry = self._insert_media_entry_fixture(
@ -57,56 +55,78 @@ class TestMediaEntrySlugs(object):
return entry
def test_unique_slug_from_title(self):
def test_unique_slug_from_title(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(u"Totally unique slug!", save=False)
entry.generate_slug()
assert entry.slug == u'totally-unique-slug'
def test_old_good_unique_slug(self):
def test_old_good_unique_slug(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(
u"A title here", u"a-different-slug-there", save=False)
entry.generate_slug()
assert entry.slug == u"a-different-slug-there"
def test_old_weird_slug(self):
def test_old_weird_slug(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(
slug=u"wowee!!!!!", save=False)
entry.generate_slug()
assert entry.slug == u"wowee"
def test_existing_slug_use_id(self):
def test_existing_slug_use_id(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(
u"Beware, I exist!!", this_id=9000, save=False)
entry.generate_slug()
assert entry.slug == u"beware-i-exist-9000"
@mock.patch('uuid.uuid4', UUID_MOCK)
def test_existing_slug_cant_use_id(self):
# This one grabs the nine thousand slug
self._insert_media_entry_fixture(
slug=u"beware-i-exist-9000")
def test_existing_slug_cant_use_id(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(
u"Beware, I exist!!", this_id=9000, save=False)
entry.generate_slug()
assert entry.slug == u"beware-i-exist-test"
# Getting tired of dealing with test_app and this mock.patch
# thing conflicting, getting lazy.
@mock.patch('uuid.uuid4', UUID_MOCK)
def _real_test():
# This one grabs the nine thousand slug
self._insert_media_entry_fixture(
slug=u"beware-i-exist-9000")
@mock.patch('uuid.uuid4', UUID_MOCK)
def test_existing_slug_cant_use_id_extra_junk(self):
# This one grabs the nine thousand slug
self._insert_media_entry_fixture(
slug=u"beware-i-exist-9000")
entry = self._insert_media_entry_fixture(
u"Beware, I exist!!", this_id=9000, save=False)
entry.generate_slug()
assert entry.slug == u"beware-i-exist-test"
_real_test()
# This one grabs makes sure the annoyance doesn't stop
self._insert_media_entry_fixture(
slug=u"beware-i-exist-test")
def test_existing_slug_cant_use_id_extra_junk(self, test_app):
self._setup()
entry = self._insert_media_entry_fixture(
u"Beware, I exist!!", this_id=9000, save=False)
entry.generate_slug()
assert entry.slug == u"beware-i-exist-testtest"
# Getting tired of dealing with test_app and this mock.patch
# thing conflicting, getting lazy.
@mock.patch('uuid.uuid4', UUID_MOCK)
def _real_test():
# This one grabs the nine thousand slug
self._insert_media_entry_fixture(
slug=u"beware-i-exist-9000")
def test_garbage_slug(self):
# This one grabs makes sure the annoyance doesn't stop
self._insert_media_entry_fixture(
slug=u"beware-i-exist-test")
entry = self._insert_media_entry_fixture(
u"Beware, I exist!!", this_id=9000, save=False)
entry.generate_slug()
assert entry.slug == u"beware-i-exist-testtest"
_real_test()
def test_garbage_slug(self, test_app):
"""
Titles that sound totally like Q*Bert shouldn't have slugs at
all. We'll just reference them by id.
@ -126,14 +146,15 @@ class TestMediaEntrySlugs(object):
| |#| |#| |#| |#|
\|/ \|/ \|/ \|/
"""
self._setup()
qbert_entry = self._insert_media_entry_fixture(
u"@!#?@!", save=False)
qbert_entry.generate_slug()
assert qbert_entry.slug is None
def test_media_data_init():
get_app() # gotta init the db and etc
def test_media_data_init(test_app):
Session.rollback()
Session.remove()
media = MediaEntry()

View File

@ -21,15 +21,14 @@ from urlparse import parse_qs, urlparse
from mediagoblin import mg_globals
from mediagoblin.tools import template, pluginapi
from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
_log = logging.getLogger(__name__)
class TestOAuth(object):
def setup(self):
self.app = get_app()
def _setup(self, test_app):
self.db = mg_globals.database
self.pman = pluginapi.PluginManager()
@ -37,17 +36,17 @@ class TestOAuth(object):
self.user_password = u'4cc355_70k3N'
self.user = fixture_add_user(u'joauth', self.user_password)
self.login()
self.login(test_app)
def login(self):
self.app.post(
def login(self, test_app):
test_app.post(
'/auth/login/', {
'username': self.user.username,
'password': self.user_password})
def register_client(self, name, client_type, description=None,
def register_client(self, test_app, name, client_type, description=None,
redirect_uri=''):
return self.app.post(
return test_app.post(
'/oauth/client/register', {
'name': name,
'description': description,
@ -57,9 +56,11 @@ class TestOAuth(object):
def get_context(self, template_name):
return template.TEMPLATE_TEST_CONTEXT[template_name]
def test_1_public_client_registration_without_redirect_uri(self):
def test_1_public_client_registration_without_redirect_uri(self, test_app):
''' Test 'public' OAuth client registration without any redirect uri '''
response = self.register_client(u'OMGOMGOMG', 'public',
self._setup(test_app)
response = self.register_client(test_app, u'OMGOMGOMG', 'public',
'OMGOMG Apache License v2')
ctx = self.get_context('oauth/client/register.html')
@ -75,10 +76,10 @@ class TestOAuth(object):
# Should not pass through
assert not client
def test_2_successful_public_client_registration(self):
def test_2_successful_public_client_registration(self, test_app):
''' Successfully register a public client '''
self.login()
self.register_client(u'OMGOMG', 'public', 'OMG!',
self._setup(test_app)
self.register_client(test_app, u'OMGOMG', 'public', 'OMG!',
'http://foo.example')
client = self.db.OAuthClient.query.filter(
@ -87,9 +88,12 @@ class TestOAuth(object):
# Client should have been registered
assert client
def test_3_successful_confidential_client_reg(self):
def test_3_successful_confidential_client_reg(self, test_app):
''' Register a confidential OAuth client '''
response = self.register_client(u'GMOGMO', 'confidential', 'NO GMO!')
self._setup(test_app)
response = self.register_client(
test_app, u'GMOGMO', 'confidential', 'NO GMO!')
assert response.status_int == 302
@ -101,15 +105,16 @@ class TestOAuth(object):
return client
def test_4_authorize_confidential_client(self):
def test_4_authorize_confidential_client(self, test_app):
''' Authorize a confidential client as a logged in user '''
self._setup(test_app)
client = self.test_3_successful_confidential_client_reg()
client = self.test_3_successful_confidential_client_reg(test_app)
client_identifier = client.identifier
redirect_uri = 'https://foo.example'
response = self.app.get('/oauth/authorize', {
response = test_app.get('/oauth/authorize', {
'client_id': client.identifier,
'scope': 'admin',
'redirect_uri': redirect_uri})
@ -122,7 +127,7 @@ class TestOAuth(object):
form = ctx['form']
# Short for client authorization post reponse
capr = self.app.post(
capr = test_app.post(
'/oauth/client/authorize', {
'client_id': form.client_id.data,
'allow': 'Allow',
@ -139,16 +144,19 @@ class TestOAuth(object):
def get_code_from_redirect_uri(self, uri):
return parse_qs(urlparse(uri).query)['code'][0]
def test_token_endpoint_successful_confidential_request(self):
def test_token_endpoint_successful_confidential_request(self, test_app):
''' Successful request against token endpoint '''
code_redirect, client_id = self.test_4_authorize_confidential_client()
self._setup(test_app)
code_redirect, client_id = self.test_4_authorize_confidential_client(
test_app)
code = self.get_code_from_redirect_uri(code_redirect.location)
client = self.db.OAuthClient.query.filter(
self.db.OAuthClient.identifier == unicode(client_id)).first()
token_res = self.app.get('/oauth/access_token?client_id={0}&\
token_res = test_app.get('/oauth/access_token?client_id={0}&\
code={1}&client_secret={2}'.format(client_id, code, client.secret))
assert token_res.status_int == 200
@ -162,16 +170,19 @@ code={1}&client_secret={2}'.format(client_id, code, client.secret))
assert type(token_data['expires_in']) == int
assert token_data['expires_in'] > 0
def test_token_endpont_missing_id_confidential_request(self):
def test_token_endpont_missing_id_confidential_request(self, test_app):
''' Unsuccessful request against token endpoint, missing client_id '''
code_redirect, client_id = self.test_4_authorize_confidential_client()
self._setup(test_app)
code_redirect, client_id = self.test_4_authorize_confidential_client(
test_app)
code = self.get_code_from_redirect_uri(code_redirect.location)
client = self.db.OAuthClient.query.filter(
self.db.OAuthClient.identifier == unicode(client_id)).first()
token_res = self.app.get('/oauth/access_token?\
token_res = test_app.get('/oauth/access_token?\
code={0}&client_secret={1}'.format(code, client.secret))
assert token_res.status_int == 200

View File

@ -10,7 +10,7 @@ use = egg:Paste#urlmap
[app:mediagoblin]
use = egg:mediagoblin#app
filter-with = beaker
config = %(here)s/test_mgoblin_app.ini
config = %(here)s/mediagoblin.ini
[app:publicstore_serve]
use = egg:Paste#static

View File

@ -24,8 +24,7 @@ import os
from nose.tools import assert_equal, assert_true
from pkg_resources import resource_filename
from mediagoblin.tests.tools import get_app, \
fixture_add_user
from mediagoblin.tests.tools import fixture_add_user
from mediagoblin import mg_globals
from mediagoblin.db.models import MediaEntry
from mediagoblin.tools import template
@ -51,8 +50,8 @@ REQUEST_CONTEXT = ['mediagoblin/user_pages/user.html', 'request']
class TestSubmission:
def setup(self):
self.test_app = get_app(dump_old_app=False)
def _setup(self, test_app):
self.test_app = test_app
# TODO: Possibly abstract into a decorator like:
# @as_authenticated_user('chris')
@ -90,7 +89,9 @@ class TestSubmission:
comments = request.db.MediaComment.find({'media_entry': media_id})
assert_equal(count, len(list(comments)))
def test_missing_fields(self):
def test_missing_fields(self, test_app):
self._setup(test_app)
# Test blank form
# ---------------
response, form = self.do_post({}, *FORM_CONTEXT)
@ -117,10 +118,12 @@ class TestSubmission:
self.logout()
self.test_app.get(url)
def test_normal_jpg(self):
def test_normal_jpg(self, test_app):
self._setup(test_app)
self.check_normal_upload(u'Normal upload 1', GOOD_JPG)
def test_normal_png(self):
def test_normal_png(self, test_app):
self._setup(test_app)
self.check_normal_upload(u'Normal upload 2', GOOD_PNG)
def check_media(self, request, find_data, count=None):
@ -131,7 +134,9 @@ class TestSubmission:
return
return media[0]
def test_tags(self):
def test_tags(self, test_app):
self._setup(test_app)
# Good tag string
# --------
response, request = self.do_post({'title': u'Balanced Goblin 2',
@ -156,7 +161,9 @@ class TestSubmission:
'Tags that are too long: ' \
'ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu'])
def test_delete(self):
def test_delete(self, test_app):
self._setup(test_app)
response, request = self.do_post({'title': u'Balanced Goblin'},
*REQUEST_CONTEXT, do_follow=True,
**self.upload_data(GOOD_JPG))
@ -201,7 +208,9 @@ class TestSubmission:
self.check_media(request, {'id': media_id}, 0)
self.check_comments(request, media_id, 0)
def test_evil_file(self):
def test_evil_file(self, test_app):
self._setup(test_app)
# Test non-suppoerted file with non-supported extension
# -----------------------------------------------------
response, form = self.do_post({'title': u'Malicious Upload 1'},
@ -212,9 +221,11 @@ class TestSubmission:
str(form.file.errors[0])
def test_get_media_manager(self):
def test_get_media_manager(self, test_app):
"""Test if the get_media_manger function returns sensible things
"""
self._setup(test_app)
response, request = self.do_post({'title': u'Balanced Goblin'},
*REQUEST_CONTEXT, do_follow=True,
**self.upload_data(GOOD_JPG))
@ -224,10 +235,12 @@ class TestSubmission:
assert_equal(media.media_manager, img_MEDIA_MANAGER)
def test_sniffing(self):
def test_sniffing(self, test_app):
'''
Test sniffing mechanism to assert that regular uploads work as intended
'''
self._setup(test_app)
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
@ -257,22 +270,33 @@ class TestSubmission:
assert_equal(entry.state, 'failed')
assert_equal(entry.fail_error, u'mediagoblin.processing:BadMediaFail')
def test_evil_jpg(self):
def test_evil_jpg(self, test_app):
self._setup(test_app)
# Test non-supported file with .jpg extension
# -------------------------------------------
self.check_false_image(u'Malicious Upload 2', EVIL_JPG)
def test_evil_png(self):
def test_evil_png(self, test_app):
self._setup(test_app)
# Test non-supported file with .png extension
# -------------------------------------------
self.check_false_image(u'Malicious Upload 3', EVIL_PNG)
def test_media_data(self):
def test_media_data(self, test_app):
self._setup(test_app)
self.check_normal_upload(u"With GPS data", GPS_JPG)
media = self.check_media(None, {"title": u"With GPS data"}, 1)
assert_equal(media.media_data.gps_latitude, 59.336666666666666)
def test_processing(self):
def test_processing(self, test_app):
self._setup(test_app)
public_store_dir = mg_globals.global_config[
'storage:publicstore']['base_dir']
data = {'title': u'Big Blue'}
response, request = self.do_post(data, *REQUEST_CONTEXT, do_follow=True,
**self.upload_data(BIG_BLUE))
@ -282,10 +306,9 @@ class TestSubmission:
('medium', 'bigblue.medium.png'),
('thumb', 'bigblue.thumbnail.png')):
# Does the processed image have a good filename?
filename = resource_filename(
'mediagoblin.tests',
os.path.join('test_user_dev/media/public',
*media.media_files.get(key, [])))
filename = os.path.join(
public_store_dir,
*media.media_files.get(key, []))
assert_true(filename.endswith('_' + basename))
# Is it smaller than the last processed image we looked at?
size = os.stat(filename).st_size

View File

@ -14,17 +14,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tests.tools import get_app
from mediagoblin.tools import text
def test_list_of_dicts_conversion():
def test_list_of_dicts_conversion(test_app):
"""
When the user adds tags to a media entry, the string from the form is
converted into a list of tags, where each tag is stored in the database
as a dict. Each tag dict should contain the tag's name and slug. Another
function performs the reverse operation when populating a form to edit tags.
"""
test_app = get_app(dump_old_app=False)
# Leading, trailing, and internal whitespace should be removed and slugified
assert text.convert_to_tag_list_of_dicts('sleep , 6 AM, chainsaw! ') == [
{'name': u'sleep', 'slug': u'sleep'},

View File

@ -1,36 +0,0 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin import mg_globals
from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.db.models import User
def test_get_app_wipes_db():
"""
Make sure we get a fresh database on every wipe :)
"""
get_app(dump_old_app=True)
assert User.query.count() == 0
fixture_add_user()
assert User.query.count() == 1
get_app(dump_old_app=False)
assert User.query.count() == 1
get_app(dump_old_app=True)
assert User.query.count() == 0

View File

@ -43,8 +43,6 @@ TEST_APP_CONFIG = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_mgoblin_app.ini')
TEST_USER_DEV = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_user_dev')
MGOBLIN_APP = None
OLD_MGOBLIN_APP_CONFIGS = (None, None)
USER_DEV_DIRECTORIES_TO_SETUP = [
@ -105,10 +103,30 @@ def suicide_if_bad_celery_environ():
raise BadCeleryEnviron(BAD_CELERY_MESSAGE)
def get_app(paste_config=None, mgoblin_config=None, dump_old_app=True):
def get_app(request, paste_config=None, mgoblin_config=None):
"""Create a MediaGoblin app for testing.
Args:
- request: Not an http request, but a pytest fixture request. We
use this to make temporary directories that pytest
automatically cleans up as needed.
- paste_config: particular paste config used by this application.
- mgoblin_config: particular mediagoblin config used by this
application.
"""
paste_config = paste_config or TEST_SERVER_CONFIG
mgoblin_config = mgoblin_config or TEST_APP_CONFIG
# This is the directory we're copying the paste/mgoblin config stuff into
run_dir = request.config._tmpdirhandler.mktemp(
'mgoblin_app', numbered=True)
user_dev_dir = run_dir.mkdir('test_user_dev').strpath
new_paste_config = run_dir.join('paste.ini').strpath
new_mgoblin_config = run_dir.join('mediagoblin.ini').strpath
shutil.copyfile(paste_config, new_paste_config)
shutil.copyfile(mgoblin_config, new_mgoblin_config)
suicide_if_bad_celery_environ()
# Make sure we've turned on testing
@ -117,32 +135,16 @@ def get_app(paste_config=None, mgoblin_config=None, dump_old_app=True):
# Leave this imported as it sets up celery.
from mediagoblin.init.celery import from_tests
global MGOBLIN_APP
# Just return the old app if that exists and it's okay to set up
# and return
#
# ...Man I can't wait till we get rid of paste configs in tests.
global OLD_MGOBLIN_APP_CONFIGS
old_paste, old_mgoblin = OLD_MGOBLIN_APP_CONFIGS
if MGOBLIN_APP and not dump_old_app \
and old_paste == paste_config and old_mgoblin == mgoblin_config:
return MGOBLIN_APP
Session.rollback()
Session.remove()
# Remove and reinstall user_dev directories
if os.path.exists(TEST_USER_DEV):
shutil.rmtree(TEST_USER_DEV)
# install user_dev directories
for directory in USER_DEV_DIRECTORIES_TO_SETUP:
full_dir = os.path.join(TEST_USER_DEV, directory)
full_dir = os.path.join(user_dev_dir, directory)
os.makedirs(full_dir)
# Get app config
global_config, validation_result = read_mediagoblin_config(TEST_APP_CONFIG)
global_config, validation_result = read_mediagoblin_config(new_mgoblin_config)
app_config = global_config['mediagoblin']
# Run database setup/migrations
@ -150,7 +152,7 @@ def get_app(paste_config=None, mgoblin_config=None, dump_old_app=True):
# setup app and return
test_app = loadapp(
'config:' + TEST_SERVER_CONFIG)
'config:' + new_paste_config)
# Re-setup celery
setup_celery_app(app_config, global_config)
@ -162,41 +164,10 @@ def get_app(paste_config=None, mgoblin_config=None, dump_old_app=True):
mg_globals.app.meddleware.insert(0, TestingMeddleware(mg_globals.app))
app = TestApp(test_app)
MGOBLIN_APP = app
# Make sure we can see if this app matches the next app if not
# re-setting-up
OLD_MGOBLIN_APP_CONFIGS = (paste_config, mgoblin_config)
return app
class SetupFreshApp(object):
"""
Decorator to setup a fresh test application for this function.
Cleans out test buckets and passes in a new, fresh test_app.
"""
def __init__(self, paste_config, mgoblin_config, dump_old_app=True):
self.paste_config = paste_config
self.mgoblin_config = mgoblin_config
self.dump_old_app = dump_old_app
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
test_app = get_app(
paste_config=self.paste_config,
mgoblin_config=self.mgoblin_config,
dump_old_app=self.dump_old_app)
testing.clear_test_buckets()
return func(test_app, *args, **kwargs)
return wrapper
setup_fresh_app = SetupFreshApp(TEST_SERVER_CONFIG, TEST_APP_CONFIG)
def install_fixtures_simple(db, fixtures):
"""
Very simply install fixtures in the database