diff --git a/chcemvediet/apps/accounts/tests/__init__.py b/chcemvediet/apps/accounts/tests/__init__.py index d2f8e730a..e69de29bb 100644 --- a/chcemvediet/apps/accounts/tests/__init__.py +++ b/chcemvediet/apps/accounts/tests/__init__.py @@ -1,18 +0,0 @@ -# vim: expandtab -# -*- coding: utf-8 -*- -from django.test import TestCase -from django.test.utils import override_settings - - -class AccountsTestCaseMixin(TestCase): - - def _pre_setup(self): - super(AccountsTestCaseMixin, self)._pre_setup() - self.settings_override = override_settings( - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), - ) - self.settings_override.enable() - - def _post_teardown(self): - self.settings_override.disable() - super(AccountsTestCaseMixin, self)._post_teardown() diff --git a/chcemvediet/apps/accounts/tests/test_forms.py b/chcemvediet/apps/accounts/tests/test_forms.py index 89f0a6f25..f6c0151bb 100644 --- a/chcemvediet/apps/accounts/tests/test_forms.py +++ b/chcemvediet/apps/accounts/tests/test_forms.py @@ -1,17 +1,13 @@ # vim: expandtab # -*- coding: utf-8 -*- -import os - import lxml.html from django.contrib.auth.models import User from django.test import TestCase from poleno.utils.urls import reverse -from . import AccountsTestCaseMixin - -class LoginFormTest(AccountsTestCaseMixin, TestCase): +class LoginFormTest(TestCase): u""" Tests ``allauth`` ``account_login`` view using ``LoginForm`` form registered as "account_login". Does not check ``account_login`` functionality, only checks functionality @@ -51,7 +47,7 @@ def test_recaptcha_field_is_required(self): response = self.client.post(reverse(u'account_login'), data, follow=True) self.assertFormError(response, u'form', u'recaptcha', u'This field is required.') -class SignupFormTest(AccountsTestCaseMixin, TestCase): +class SignupFormTest(TestCase): u""" Tests ``allauth`` ``account_signup`` view using ``SignupForm`` form registered as "account_signup". Does not check ``account_signup`` functionality, only checks functionality @@ -207,7 +203,7 @@ def test_recaptcha_field_is_required(self): response = self.client.post(reverse(u'account_signup'), data, follow=True) self.assertFormError(response, u'form', u'recaptcha', u'This field is required.') -class ResetPasswordFormTest(AccountsTestCaseMixin, TestCase): +class ResetPasswordFormTest(TestCase): u""" Tests ``allauth`` ``password_reset`` view using ``ResetPasswordForm`` form registered as "password_reset". Does not check ``password_reset`` functionality, only checks functionality diff --git a/chcemvediet/apps/accounts/tests/test_models.py b/chcemvediet/apps/accounts/tests/test_models.py index 53b6fce56..c32b4055a 100644 --- a/chcemvediet/apps/accounts/tests/test_models.py +++ b/chcemvediet/apps/accounts/tests/test_models.py @@ -4,12 +4,11 @@ from django.contrib.auth.models import User from django.test import TestCase -from . import AccountsTestCaseMixin from ..models import Profile from ..signals import create_profile_on_user_post_save -class ProfileModelTest(AccountsTestCaseMixin, TestCase): +class ProfileModelTest(TestCase): u""" Tests ``Profile`` model. """ diff --git a/chcemvediet/apps/accounts/tests/test_views.py b/chcemvediet/apps/accounts/tests/test_views.py index 392c6e96d..9613ad3eb 100644 --- a/chcemvediet/apps/accounts/tests/test_views.py +++ b/chcemvediet/apps/accounts/tests/test_views.py @@ -1,18 +1,13 @@ # vim: expandtab # -*- coding: utf-8 -*- -import functools -import mock - from django.contrib.auth.models import User from django.test import TestCase from poleno.utils.test import ViewTestCaseMixin from poleno.utils.urls import reverse -from . import AccountsTestCaseMixin - -class ProfileViewTest(AccountsTestCaseMixin, ViewTestCaseMixin, TestCase): +class ProfileViewTest(ViewTestCaseMixin, TestCase): u""" Tests ``profile()`` view registered as "accounts:profile". """ diff --git a/chcemvediet/apps/inforequests/tests/__init__.py b/chcemvediet/apps/inforequests/tests/__init__.py index faabf39d7..e7cea54f5 100644 --- a/chcemvediet/apps/inforequests/tests/__init__.py +++ b/chcemvediet/apps/inforequests/tests/__init__.py @@ -39,15 +39,16 @@ def mock_render(*args, **kwargs): return res def mock_render_to_string(*args, **kwargs): if pre_mock_render_to_string: # pragma: no cover - self.pre_mock_render_to_string(*args, **kwargs) + pre_mock_render_to_string(*args, **kwargs) with CaptureQueriesContext(connection) as captured: res = render_to_string(*args, **kwargs) queries.append(captured) return res - with mock.patch(u'chcemvediet.apps.inforequests.views.render', mock_render): - with mock.patch(u'chcemvediet.apps.inforequests.views.render_to_string', mock_render_to_string): - yield + with mock.patch(u'chcemvediet.apps.inforequests.views.inforequest.render', mock_render): + with mock.patch(u'chcemvediet.apps.inforequests.views.shortcuts.render', mock_render): + with mock.patch(u'chcemvediet.apps.inforequests.views.shortcuts.render_to_string', mock_render_to_string): + yield self.assertEqual(len(queries), len(patterns), u'%d renders executed, %d expected' % (len(queries), len(patterns))) for render_queries, render_patterns in zip(queries, patterns): @@ -70,16 +71,9 @@ def _pre_setup(self): self.settings_override = override_settings( MEDIA_ROOT=self.tempdir.path, EMAIL_BACKEND=u'poleno.mail.backend.EmailBackend', - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), ) self.settings_override.enable() - self.user1 = self._create_user() - self.user2 = self._create_user() - self.obligee1 = self._create_obligee() - self.obligee2 = self._create_obligee() - self.obligee3 = self._create_obligee() - def _post_teardown(self): self.settings_override.disable() self.tempdir.cleanup() diff --git a/chcemvediet/apps/inforequests/tests/test_views/skip_test_mine.py b/chcemvediet/apps/inforequests/tests/test_views/skip_test_mine.py deleted file mode 100644 index a84160615..000000000 --- a/chcemvediet/apps/inforequests/tests/test_views/skip_test_mine.py +++ /dev/null @@ -1,70 +0,0 @@ -# vim: expandtab -# -*- coding: utf-8 -*- -from django.test import TestCase - -from poleno.utils.test import ViewTestCaseMixin -from poleno.utils.urls import reverse - -from .. import InforequestsTestCaseMixin - - -class MineViewTest(InforequestsTestCaseMixin, ViewTestCaseMixin, TestCase): - u""" - Tests ``mine()`` view registered as "inforequests:mine". - """ - - def test_allowed_http_methods(self): - allowed = [u'HEAD', u'GET'] - self.assert_allowed_http_methods(allowed, reverse(u'inforequests:mine')) - - def test_anonymous_user_is_redirected(self): - self.assert_anonymous_user_is_redirected(reverse(u'inforequests:mine')) - - def test_authenticated_user_gets_inforequest_mine(self): - self._login_user() - response = self.client.get(reverse(u'inforequests:mine')) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, u'inforequests/mine.html') - - def test_user_gets_only_his_inforequests_and_drafts(self): - drafts1 = [self._create_inforequest_draft(applicant=self.user1) for i in range(5)] - drafts2 = [self._create_inforequest_draft(applicant=self.user2) for i in range(3)] - inforequests1 = [self._create_inforequest(applicant=self.user1) for i in range(4)] - inforequests2 = [self._create_inforequest(applicant=self.user2) for i in range(5)] - closed1 = [self._create_inforequest(applicant=self.user1, closed=True) for i in range(3)] - closed2 = [self._create_inforequest(applicant=self.user2, closed=True) for i in range(3)] - - self._login_user(self.user1) - response = self.client.get(reverse(u'inforequests:mine')) - self.assertEqual(response.status_code, 200) - self.assertItemsEqual(response.context[u'inforequests'], inforequests1) - self.assertItemsEqual(response.context[u'drafts'], drafts1) - self.assertItemsEqual(response.context[u'closed_inforequests'], closed1) - - def test_with_user_with_no_his_inforequests_nor_drafts(self): - drafts2 = [self._create_inforequest_draft(applicant=self.user2) for i in range(3)] - inforequests2 = [self._create_inforequest(applicant=self.user2) for i in range(5)] - closed2 = [self._create_inforequest(applicant=self.user2, closed=True) for i in range(3)] - - self._login_user(self.user1) - response = self.client.get(reverse(u'inforequests:mine')) - self.assertEqual(response.status_code, 200) - self.assertItemsEqual(response.context[u'inforequests'], []) - self.assertItemsEqual(response.context[u'drafts'], []) - self.assertItemsEqual(response.context[u'closed_inforequests'], []) - - def test_related_models_are_prefetched_before_render(self): - drafts1 = [self._create_inforequest_draft(applicant=self.user1) for i in range(5)] - inforequests1 = [self._create_inforequest(applicant=self.user1) for i in range(4)] - closed1 = [self._create_inforequest(applicant=self.user1, closed=True) for i in range(3)] - - # Force view querysets to evaluate before calling render - def pre_mock_render(request, temaplate, context): - list(context[u'inforequests']) - list(context[u'drafts']) - list(context[u'closed_inforequests']) - - self._login_user(self.user1) - with self.assertQueriesDuringRender([], pre_mock_render=pre_mock_render): - response = self.client.get(reverse(u'inforequests:mine')) - self.assertEqual(response.status_code, 200) diff --git a/chcemvediet/apps/inforequests/tests/test_views/test_mine.py b/chcemvediet/apps/inforequests/tests/test_views/test_mine.py new file mode 100644 index 000000000..863114f2a --- /dev/null +++ b/chcemvediet/apps/inforequests/tests/test_views/test_mine.py @@ -0,0 +1,155 @@ +# vim: expandtab +# -*- coding: utf-8 -*- +from django.test import TestCase + +from poleno.utils.misc import squeeze +from poleno.utils.test import ViewTestCaseMixin +from poleno.utils.urls import reverse + +from .. import InforequestsTestCaseMixin +from ...models import Action + + +class MineViewTest(InforequestsTestCaseMixin, ViewTestCaseMixin, TestCase): + u""" + Tests ``mine()`` view registered as "inforequests:mine". + """ + + def _create_pending_inforequest(self, applicant): + return self._create_inforequest(applicant=applicant) + + def _create_successful_inforequest(self, applicant): + inforequest, _, _ = self._create_inforequest_scenario(applicant, {u'closed': True}, + (u'disclosure', dict(disclosure_level=Action.DISCLOSURE_LEVELS.PARTIAL))) + return inforequest + + def _create_unsuccessful_inforequest(self, applicant): + return self._create_inforequest(applicant=applicant, closed=True) + + def test_allowed_http_methods(self): + allowed = [u'HEAD', u'GET'] + self.assert_allowed_http_methods(allowed, reverse(u'inforequests:mine')) + + def test_anonymous_user_is_redirected(self): + self.assert_anonymous_user_is_redirected(reverse(u'inforequests:mine')) + + def test_authenticated_user_gets_inforequest_mine(self): + self._login_user(self.user1) + response = self.client.get(reverse(u'inforequests:mine')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, u'inforequests/mine/mine.html') + + def test_user_gets_only_his_inforequests_and_drafts(self): + drafts1 = [self._create_inforequest_draft(applicant=self.user1) for i in range(5)] + drafts2 = [self._create_inforequest_draft(applicant=self.user2) for i in range(3)] + pending_inforequests1 = [self._create_pending_inforequest(applicant=self.user1) for i in range(4)] + pending_inforequests2 = [self._create_pending_inforequest(applicant=self.user2) for i in range(5)] + successful_inforequests1 = [self._create_successful_inforequest(applicant=self.user1) for i in range(3)] + successful_inforequests2 = [self._create_successful_inforequest(applicant=self.user2) for i in range(3)] + unsuccessful_inforequests1 = [self._create_unsuccessful_inforequest(applicant=self.user1) for i in range(3)] + unsuccessful_inforequests2 = [self._create_unsuccessful_inforequest(applicant=self.user2) for i in range(3)] + + self._login_user(self.user1) + response = self.client.get(reverse(u'inforequests:mine')) + self.assertEqual(response.status_code, 200) + self.assertItemsEqual(response.context[u'pending_inforequests'], pending_inforequests1) + self.assertItemsEqual(response.context[u'drafts'], drafts1) + self.assertItemsEqual(response.context[u'successful_inforequests'], successful_inforequests1) + self.assertItemsEqual(response.context[u'unsuccessful_inforequests'], unsuccessful_inforequests1) + + def test_with_user_with_no_his_inforequests_nor_drafts(self): + drafts2 = [self._create_inforequest_draft(applicant=self.user2) for i in range(3)] + pending_inforequests2 = [self._create_pending_inforequest(applicant=self.user2) for i in range(5)] + successful_inforequests2 = [self._create_successful_inforequest(applicant=self.user2) for i in range(3)] + unsuccessful_inforequests2 = [self._create_unsuccessful_inforequest(applicant=self.user2) for i in range(3)] + + self._login_user(self.user1) + response = self.client.get(reverse(u'inforequests:mine')) + self.assertEqual(response.status_code, 200) + self.assertItemsEqual(response.context[u'pending_inforequests'], []) + self.assertItemsEqual(response.context[u'drafts'], []) + self.assertItemsEqual(response.context[u'successful_inforequests'], []) + self.assertItemsEqual(response.context[u'unsuccessful_inforequests'], []) + + def test_related_models_are_prefetched_before_render(self): + drafts1 = [self._create_inforequest_draft(applicant=self.user1) for i in range(5)] + pending_inforequests1 = [self._create_pending_inforequest(applicant=self.user1) for i in range(4)] + successful_inforequests1 = [self._create_successful_inforequest(applicant=self.user1) for i in range(3)] + unsuccessful_inforequests1 = [self._create_unsuccessful_inforequest(applicant=self.user1) for i in range(3)] + + # Force view querysets to evaluate before calling render + def pre_mock_render(request, template, context): + list(context[u'pending_inforequests']) + list(context[u'drafts']) + list(context[u'successful_inforequests']) + list(context[u'unsuccessful_inforequests']) + + self._login_user(self.user1) + patterns_single_column = [ + u'FROM "accounts_profile" WHERE "accounts_profile"."user_id" = %s LIMIT 21', + squeeze(u""" + SELECT COUNT\(\*\) FROM "mail_message" + INNER JOIN "inforequests_inforequestemail" ON \( "mail_message"."id" = "inforequests_inforequestemail"."email_id" \) + INNER JOIN "inforequests_inforequest" ON \( "inforequests_inforequestemail"."inforequest_id" = "inforequests_inforequest"."id" \) + WHERE \("inforequests_inforequestemail"."type" = %s + AND "inforequests_inforequest"."applicant_id" = %s + AND "inforequests_inforequest"."closed" = %s\) + """), + u'FROM "invitations_invitationsupply" WHERE "invitations_invitationsupply"."user_id" = %s LIMIT 21', + ] + # TODO: Optimize N+1 queries in #419 + patterns_pending_inforequests = [ + squeeze(u""" + FROM "inforequests_action" + INNER JOIN "inforequests_branch" ON \( "inforequests_action"."branch_id" = "inforequests_branch"."id" \) + WHERE "inforequests_branch"."inforequest_id" = %s + ORDER BY "inforequests_action"."created" DESC, "inforequests_action"."id" DESC + LIMIT 1 + """) + ] * 4 + patterns_successful_inforequests = [ + squeeze(u""" + FROM "inforequests_action" WHERE "inforequests_action"."branch_id" = %s + ORDER BY "inforequests_action"."created" ASC, "inforequests_action"."id" ASC + """), + squeeze(u""" + FROM "inforequests_branch" WHERE "inforequests_branch"."inforequest_id" = %s + ORDER BY "inforequests_branch"."id" ASC"""), + squeeze(u""" + FROM "inforequests_action" + INNER JOIN "inforequests_branch" ON \( "inforequests_action"."branch_id" = "inforequests_branch"."id" \) + WHERE "inforequests_branch"."inforequest_id" = %s + ORDER BY "inforequests_action"."created" DESC, "inforequests_action"."id" DESC + LIMIT 1 + """), + squeeze(u""" + SELECT MAX\("inforequests_action"."disclosure_level"\) AS "disclosure_level__max" + FROM "inforequests_action" + INNER JOIN "inforequests_branch" ON \( "inforequests_action"."branch_id" = "inforequests_branch"."id" \) + WHERE "inforequests_branch"."inforequest_id" = %s + """), + ] * 3 + patterns_unsuccessful_inforequests = [ + squeeze(u""" + FROM "inforequests_action" + INNER JOIN "inforequests_branch" ON \( "inforequests_action"."branch_id" = "inforequests_branch"."id" \) + WHERE "inforequests_branch"."inforequest_id" = %s + ORDER BY "inforequests_action"."created" DESC, "inforequests_action"."id" DESC + LIMIT 1 + """), + squeeze(u""" + SELECT MAX\("inforequests_action"."disclosure_level"\) AS "disclosure_level__max" + FROM "inforequests_action" + INNER JOIN "inforequests_branch" ON \( "inforequests_action"."branch_id" = "inforequests_branch"."id" \) + WHERE "inforequests_branch"."inforequest_id" = %s + """), + ] * 3 + patterns = list( + patterns_single_column + + patterns_pending_inforequests + + patterns_successful_inforequests + + patterns_unsuccessful_inforequests + ) + with self.assertQueriesDuringRender(patterns, pre_mock_render=pre_mock_render): + response = self.client.get(reverse(u'inforequests:mine')) + self.assertEqual(response.status_code, 200) diff --git a/chcemvediet/tests/__init__.py b/chcemvediet/tests/__init__.py index 3671d7d75..1c399e149 100644 --- a/chcemvediet/tests/__init__.py +++ b/chcemvediet/tests/__init__.py @@ -27,6 +27,7 @@ class CustomTestRunner(DiscoverRunner): -- Disabled logging while testing. Source: http://stackoverflow.com/questions/5255657/how-can-i-disable-logging-while-running-unit-tests-in-python-django -- Forced language code 'en' + -- Used MD5 password hasher, it's much faster then the production hasher. -- Mocked google recaptcha. Source: https://pypi.org/project/django-recaptcha/1.0.6/#unit-testing """ @@ -34,6 +35,7 @@ class CustomTestRunner(DiscoverRunner): def setup_test_environment(self, **kwargs): super(CustomTestRunner, self).setup_test_environment(**kwargs) settings.LANGUAGE_CODE = u'en' + settings.PASSWORD_HASHERS = [u'django.contrib.auth.hashers.MD5PasswordHasher'] os.environ[u'RECAPTCHA_TESTING'] = u'True' def teardown_test_environment(self, **kwargs): @@ -50,6 +52,8 @@ def _pre_setup(self): super(ChcemvedietTestCaseMixin, self)._pre_setup() self.counter = itertools.count() self.user = self._create_user() + self.user1 = self._create_user() + self.user2 = self._create_user() self.message = self._create_message() self.recipient = self._create_recipient() self.region = self._create_region() @@ -57,6 +61,9 @@ def _pre_setup(self): self.municipality = self._create_municipality() self.neighbourhood = self._create_neighbourhood() self.obligee = self._create_obligee() + self.obligee1 = self._create_obligee() + self.obligee2 = self._create_obligee() + self.obligee3 = self._create_obligee() self.tag = self._create_obligee_tag() self.group = self._create_obligee_group() self.inforequest = self._create_inforequest() @@ -101,7 +108,10 @@ def _create_user(self, **kwargs): def _login_user(self, user=None, password=u'default_testing_secret'): if user is None: user = self.user - self.client.login(username=user.username, password=password) + logged_in = self.client.login(username=user.username, password=password) + self.assertTrue(logged_in, u'The provided credentials are incorrect:\nusername: {} password: {}.'.format( + user.username, password + )) def _logout_user(self): self.client.logout() diff --git a/chcemvediet/tests/test_cron.py b/chcemvediet/tests/test_cron.py index caf124a8d..3d1baeb3d 100644 --- a/chcemvediet/tests/test_cron.py +++ b/chcemvediet/tests/test_cron.py @@ -3,7 +3,6 @@ from django.contrib.auth.models import User from django.contrib.sessions.models import Session from django.test import TestCase -from django.test.utils import override_settings from poleno.timewarp import timewarp from poleno.utils.date import utc_datetime_from_local @@ -20,13 +19,8 @@ def _pre_setup(self): super(ClearExpiredSessionsCronjobTest, self)._pre_setup() timewarp.enable() timewarp.reset() - self.settings_override = override_settings( - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), - ) - self.settings_override.enable() def _post_teardown(self): - self.settings_override.disable() timewarp.reset() super(ClearExpiredSessionsCronjobTest, self)._post_teardown() diff --git a/poleno/attachments/tests/test_forms.py b/poleno/attachments/tests/test_forms.py index 764a1485c..71ff939be 100644 --- a/poleno/attachments/tests/test_forms.py +++ b/poleno/attachments/tests/test_forms.py @@ -38,7 +38,6 @@ def setUp(self): self.settings_override = override_settings( MEDIA_ROOT=self.tempdir.path, - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), ) self.settings_override.enable() diff --git a/poleno/attachments/tests/test_models.py b/poleno/attachments/tests/test_models.py index 282805f39..12ed8b2f4 100644 --- a/poleno/attachments/tests/test_models.py +++ b/poleno/attachments/tests/test_models.py @@ -30,7 +30,6 @@ def setUp(self): self.settings_override = override_settings( MEDIA_ROOT=self.tempdir.path, - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), ) self.settings_override.enable() diff --git a/poleno/attachments/tests/test_views.py b/poleno/attachments/tests/test_views.py index 3da57bbf1..e0b9a8543 100644 --- a/poleno/attachments/tests/test_views.py +++ b/poleno/attachments/tests/test_views.py @@ -42,7 +42,6 @@ def setUp(self): self.settings_override = override_settings( MEDIA_ROOT=self.tempdir.path, - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), ) self.settings_override.enable() diff --git a/poleno/timewarp/tests/test_admin.py b/poleno/timewarp/tests/test_admin.py index cccc90971..c1ec5bf12 100644 --- a/poleno/timewarp/tests/test_admin.py +++ b/poleno/timewarp/tests/test_admin.py @@ -5,7 +5,6 @@ from django.http import HttpResponse from django.contrib.auth.models import User from django.test import TestCase -from django.test.utils import override_settings from poleno.utils.urls import reverse @@ -21,20 +20,12 @@ class TimewarpAdminTest(TestCase): def setUp(self): timewarp.enable() timewarp.reset() - - self.settings_override = override_settings( - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), - ) - self.settings_override.enable() - self.admin = User.objects.create_superuser(username=u'admin', email=u'admin@example.com', password=u'top_secret') self.client.login(username=u'admin', password=u'top_secret') def tearDown(self): timewarp.reset() - self.settings_override.disable() - def _parse_dt(self, value): dt = datetime.datetime.strptime(value, u'%Y-%m-%d %H:%M:%S') diff --git a/poleno/utils/tests/test_views.py b/poleno/utils/tests/test_views.py index 99eeb32d7..4542598b1 100644 --- a/poleno/utils/tests/test_views.py +++ b/poleno/utils/tests/test_views.py @@ -66,7 +66,6 @@ def login_required_with_exception_view(request): def setUp(self): self.settings_override = override_settings( - PASSWORD_HASHERS=(u'django.contrib.auth.hashers.MD5PasswordHasher',), TEMPLATE_LOADERS=(u'django.template.loaders.filesystem.Loader',), ) self.settings_override.enable()