Switch test_app generation over to use py.test fixtures.
authorChristopher Allan Webber <cwebber@dustycloud.org>
Fri, 5 Apr 2013 00:23:04 +0000 (19:23 -0500)
committerChristopher Allan Webber <cwebber@dustycloud.org>
Fri, 5 Apr 2013 00:23:04 +0000 (19:23 -0500)
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

18 files changed:
mediagoblin/tests/conftest.py [new file with mode: 0644]
mediagoblin/tests/pytest.ini [new file with mode: 0644]
mediagoblin/tests/test_api.py
mediagoblin/tests/test_auth.py
mediagoblin/tests/test_cache.py
mediagoblin/tests/test_collections.py
mediagoblin/tests/test_csrf_middleware.py
mediagoblin/tests/test_edit.py
mediagoblin/tests/test_http_callback.py
mediagoblin/tests/test_messages.py
mediagoblin/tests/test_misc.py
mediagoblin/tests/test_modelmethods.py
mediagoblin/tests/test_oauth.py
mediagoblin/tests/test_paste.ini
mediagoblin/tests/test_submission.py
mediagoblin/tests/test_tags.py
mediagoblin/tests/test_tests.py [deleted file]
mediagoblin/tests/tools.py

diff --git a/mediagoblin/tests/conftest.py b/mediagoblin/tests/conftest.py
new file mode 100644 (file)
index 0000000..25f495d
--- /dev/null
@@ -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)
diff --git a/mediagoblin/tests/pytest.ini b/mediagoblin/tests/pytest.ini
new file mode 100644 (file)
index 0000000..d4aa2d6
--- /dev/null
@@ -0,0 +1,2 @@
+[pytest]
+usefixtures = tmpdir
\ No newline at end of file
index 294cc4ef5a682aaa393ec0b90a8969590813b6b0..25ce852ba3c3f9bd6f9fdf0ec78551591aa4660f 100644 (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
index a59a319c8c29c3f4cf254b7b6e76c1d3476efbb9..f9fe8ed1685adb74bd717f066b42326d3a66686c 100644 (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)
 
index 48fa138608368e7efbcd2a3beb319d0b47a16e36..403173cd0bb4bf9dcc16685a93eb9776783eb91e 100644 (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')
index b19f63627297d9251e9a2ba529de0ff50d109f0a..d4d3af71f54024838a3211a8fbf76b6a697cc253 100644 (file)
 # 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:
index e720264cb6a146f676ff25d4b63e9c50eec15103..a272caf69997d2d21035328d6dd23419488b3429 100644 (file)
 # 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
index a1657cef3bf5e019b1cb7a92f049d25818469721..f1f0baba4fe31e219948ef527a1c618dac76dfc0 100644 (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,
index f724922916391e66b55a1d1bf331e427f4974e88..e2c85d0da7c825d72a88fe88fa0d6f082e83e477 100644 (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,
index 4c0f3e2e0579e25a6fc99df40dcd94f2a2ede12f..3ac917b0086276abdca8233f5cb9e9bfc537d722 100644 (file)
 # 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']
index b20262cf422fd79554a0db6f81e181df4148c9e3..7143938e9ed3ae252729956b973518e8ff7e8a7f 100644 (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)
index 808aa9f21967c44476c1fe2356ada094d0ed6767..a5739ed51532e1db9952197db534d1134d1ee67b 100644 (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):
-        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_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"
-
-    @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")
-
-        # 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"
+        assert entry.slug == u"beware-i-exist-9000"
 
-    def test_garbage_slug(self):
+    def test_existing_slug_cant_use_id(self, test_app):
+        self._setup()
+
+        # 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")
+
+            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()
+
+    def test_existing_slug_cant_use_id_extra_junk(self, test_app):
+        self._setup()
+
+        # 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")
+
+            # 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()
index 518d1bb170abc2981b003a05406576cd437f3072..901556fe229b945dcf32108ae04876b437d6f4a3 100644 (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
index d7c186422d5cd30b95cb88f291916878cebc4d45..875b4f653a4e6bdae53d9e43c067e2ecf99a29b3 100644 (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
index b61227bc9debe0ef0b7e90d802c0f1bfebe9fd95..ddb8cefd51e03fdcbedd1fe59b2b4c7a5ad9c10a 100644 (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
index ccb930854047fe71b77621eec5ba802fb4457656..e25cc283fe1184b19d9c53dd8c0dd940384e2f70 100644 (file)
 # 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'},
diff --git a/mediagoblin/tests/test_tests.py b/mediagoblin/tests/test_tests.py
deleted file mode 100644 (file)
index d539f1e..0000000
+++ /dev/null
@@ -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
index efe562c75058c24d565453abbf9d694463d41d56..2e47cb5c234d69db109519a183cc27ce8223d29a 100644 (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