From 3d6a087e0cbff4dfc987457d9797eb25441e7cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Sat, 9 Oct 2021 17:39:37 +0200 Subject: [PATCH 1/6] Add initial integration tests and codecov integration --- .github/workflows/test.yml | 40 +++++++++++++++++++++------------ setup.cfg | 9 +++++++- tests/functional/test_sync.py | 26 +++++++++++++++++++++ tests/manage.py | 21 +++++++++++++++++ tests/testapp/__init__.py | 0 tests/testapp/settings.py | 35 +++++++++++++++++++++++++++++ tests/testapp/urls.py | 8 +++++++ tests/testapp/utils.py | 8 +++++++ tests/testapp/views/__init__.py | 0 tests/testapp/views/sync.py | 7 ++++++ tests/testapp/wsgi.py | 7 ++++++ 11 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 tests/functional/test_sync.py create mode 100755 tests/manage.py create mode 100644 tests/testapp/__init__.py create mode 100644 tests/testapp/settings.py create mode 100644 tests/testapp/urls.py create mode 100644 tests/testapp/utils.py create mode 100644 tests/testapp/views/__init__.py create mode 100644 tests/testapp/views/sync.py create mode 100644 tests/testapp/wsgi.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 849a16b..8fd358d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,15 +1,21 @@ -name: Run linter +name: Tests on: [push, pull_request] jobs: - test: + build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python-version: - - "3.8" - + python-version: [ '3.6', '3.7', '3.8', 'pypy3'] + django-version: [ '2.2', '3.0', '3.1', '3.2'] + pytest-version: ['pytest'] + pytest-django-version: ['pytest-django'] + include: + - python-version: '3.6' + django-version: '2.1' + pytest-version: 'pytest==4.0' + pytest-django-version: 'pytest-django==3.10.0' steps: - uses: actions/checkout@v2 @@ -18,14 +24,20 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 + - name: Install CI dependencies + run: pip install codecov ${{ matrix.pytest-version }} ${{ matrix.pytest-django-version }} + + - name: Install Django ${{ matrix.django-version }} + run: pip install 'Django==${{ matrix.django-version }}' - - name: Lint with flake8 + - name: Install Request Cache + run: pip install . + + - name: Run tests with coverage run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + # run tests with coverage + coverage run -m pytest tests + coverage xml + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 diff --git a/setup.cfg b/setup.cfg index 11e9ec4..2df317e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,9 @@ [metadata] -description-file = README.rst \ No newline at end of file +description-file = README.rst + +[tool:pytest] +python_files = tests.py test_*.py *_tests.py +DJANGO_SETTINGS_MODULE = testapp.settings + +[coverage:run] +source = ./django_request_cache diff --git a/tests/functional/test_sync.py b/tests/functional/test_sync.py new file mode 100644 index 0000000..ca12347 --- /dev/null +++ b/tests/functional/test_sync.py @@ -0,0 +1,26 @@ +from unittest import mock + +from django.test import TestCase + +from django_request_cache import cache_for_request + + +class RequestCacheMiddlewareTest(TestCase): + + + @mock.patch("testapp.views.sync.retrieve_time", spec_set=["__call__"]) + def test_sync_one_request(self, mock_func): + cached_func = mock.MagicMock(spec_set=["__call__", "__name__"]) + mock_func.side_effect = cache_for_request(cached_func) + self.client.get('/') + self.assertEqual(mock_func.call_count, 2) + self.assertEqual(cached_func.call_count, 1) + + @mock.patch("testapp.views.sync.retrieve_time", spec_set=["__call__"]) + def test_sync_two_requests(self, mock_func): + cached_func = mock.MagicMock(spec_set=["__call__", "__name__"]) + mock_func.side_effect = cache_for_request(cached_func) + self.client.get('/') + self.client.get('/') + self.assertEqual(mock_func.call_count, 4) + self.assertEqual(cached_func.call_count, 2) diff --git a/tests/manage.py b/tests/manage.py new file mode 100755 index 0000000..a02195b --- /dev/null +++ b/tests/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapp.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + 'available on your PYTHONPATH environment variable? Did you ' + 'forget to activate a virtual environment?' + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/tests/testapp/__init__.py b/tests/testapp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py new file mode 100644 index 0000000..84fd65d --- /dev/null +++ b/tests/testapp/settings.py @@ -0,0 +1,35 @@ +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SECRET_KEY = 'secret' +DEBUG = True +ALLOWED_HOSTS = [] + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django_request_cache', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django_userforeignkey.middleware.UserForeignKeyMiddleware', + 'django_request_cache.middleware.RequestCacheMiddleware', +] + +ROOT_URLCONF = 'testapp.urls' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} \ No newline at end of file diff --git a/tests/testapp/urls.py b/tests/testapp/urls.py new file mode 100644 index 0000000..41ba3df --- /dev/null +++ b/tests/testapp/urls.py @@ -0,0 +1,8 @@ + +from django.urls import path + +from testapp.views.sync import index_view + +urlpatterns = [ + path('', index_view, name='index'), +] \ No newline at end of file diff --git a/tests/testapp/utils.py b/tests/testapp/utils.py new file mode 100644 index 0000000..5652686 --- /dev/null +++ b/tests/testapp/utils.py @@ -0,0 +1,8 @@ +from datetime import datetime + +from django_request_cache import cache_for_request + + +@cache_for_request +def retrieve_time(): + return datetime.now() diff --git a/tests/testapp/views/__init__.py b/tests/testapp/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/testapp/views/sync.py b/tests/testapp/views/sync.py new file mode 100644 index 0000000..f8b5262 --- /dev/null +++ b/tests/testapp/views/sync.py @@ -0,0 +1,7 @@ +from django.http import HttpResponse +from testapp.utils import retrieve_time + +def index_view(request): + retrieve_time() + retrieve_time() + return HttpResponse() diff --git a/tests/testapp/wsgi.py b/tests/testapp/wsgi.py new file mode 100644 index 0000000..aa17590 --- /dev/null +++ b/tests/testapp/wsgi.py @@ -0,0 +1,7 @@ +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapp.settings') + +application = get_wsgi_application() From aa89e2a01f467c0b915e8bfcef7d40f4d83ee608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 15 Oct 2021 12:01:29 +0200 Subject: [PATCH 2/6] Add flake8 configuration and fix linter errors --- .flake8 | 9 +++++++++ .github/workflows/test.yml | 6 ++++++ tests/functional/test_sync.py | 1 - tests/manage.py | 3 ++- tests/testapp/settings.py | 2 +- tests/testapp/urls.py | 3 +-- tests/testapp/views/sync.py | 1 + 7 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..280c745 --- /dev/null +++ b/.flake8 @@ -0,0 +1,9 @@ +[flake8] +count = True +max-line-length = 127 +max-complecity = 10 +exclude = + .git, + .tox, + .venv +statistics = True diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8fd358d..c93cc9b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,12 @@ jobs: - name: Install Request Cache run: pip install . + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --select=E9,F63,F7,F82 + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --exit-zero - name: Run tests with coverage run: | diff --git a/tests/functional/test_sync.py b/tests/functional/test_sync.py index ca12347..22b4794 100644 --- a/tests/functional/test_sync.py +++ b/tests/functional/test_sync.py @@ -7,7 +7,6 @@ class RequestCacheMiddlewareTest(TestCase): - @mock.patch("testapp.views.sync.retrieve_time", spec_set=["__call__"]) def test_sync_one_request(self, mock_func): cached_func = mock.MagicMock(spec_set=["__call__", "__name__"]) diff --git a/tests/manage.py b/tests/manage.py index a02195b..6c75a82 100755 --- a/tests/manage.py +++ b/tests/manage.py @@ -1,4 +1,5 @@ #!/usr/bin/env python + """Django's command-line utility for administrative tasks.""" import os import sys @@ -18,4 +19,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py index 84fd65d..0a7601c 100644 --- a/tests/testapp/settings.py +++ b/tests/testapp/settings.py @@ -32,4 +32,4 @@ 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', } -} \ No newline at end of file +} diff --git a/tests/testapp/urls.py b/tests/testapp/urls.py index 41ba3df..ba88d50 100644 --- a/tests/testapp/urls.py +++ b/tests/testapp/urls.py @@ -1,8 +1,7 @@ - from django.urls import path from testapp.views.sync import index_view urlpatterns = [ path('', index_view, name='index'), -] \ No newline at end of file +] diff --git a/tests/testapp/views/sync.py b/tests/testapp/views/sync.py index f8b5262..81532e1 100644 --- a/tests/testapp/views/sync.py +++ b/tests/testapp/views/sync.py @@ -1,6 +1,7 @@ from django.http import HttpResponse from testapp.utils import retrieve_time + def index_view(request): retrieve_time() retrieve_time() From 5626e50bfa17201b16ac9e38fdab04f15748460c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 15 Oct 2021 12:04:15 +0200 Subject: [PATCH 3/6] Remove unsupported Dango and Python versions from test matrix --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c93cc9b..4777f1e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,8 +7,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ '3.6', '3.7', '3.8', 'pypy3'] - django-version: [ '2.2', '3.0', '3.1', '3.2'] + python-version: ['3.7', '3.8', 'pypy3'] + django-version: ['2.2', '3.1', '3.2'] pytest-version: ['pytest'] pytest-django-version: ['pytest-django'] include: From 5d6ed6bed20b006ea8c710827e88d46918f9b81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 15 Oct 2021 12:16:39 +0200 Subject: [PATCH 4/6] Fix syntax error in workflow --- .github/workflows/test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4777f1e..190a7d9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,11 +33,11 @@ jobs: - name: Install Request Cache run: pip install . - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --select=E9,F63,F7,F82 - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --exit-zero + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --select=E9,F63,F7,F82 + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --exit-zero - name: Run tests with coverage run: | From 954bad33342b22270eb13642e835c8608a0eace6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 15 Oct 2021 12:42:18 +0200 Subject: [PATCH 5/6] Remove unsupported django version from workflow --- .github/workflows/test.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 190a7d9..80f0b77 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,11 +11,6 @@ jobs: django-version: ['2.2', '3.1', '3.2'] pytest-version: ['pytest'] pytest-django-version: ['pytest-django'] - include: - - python-version: '3.6' - django-version: '2.1' - pytest-version: 'pytest==4.0' - pytest-django-version: 'pytest-django==3.10.0' steps: - uses: actions/checkout@v2 From e72520414a1b46d3d40f473787dbc433f95e0b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 15 Oct 2021 13:48:50 +0200 Subject: [PATCH 6/6] Fix CI dependencies --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80f0b77..f21adb1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install CI dependencies - run: pip install codecov ${{ matrix.pytest-version }} ${{ matrix.pytest-django-version }} + run: pip install flake8 codecov ${{ matrix.pytest-version }} ${{ matrix.pytest-django-version }} - name: Install Django ${{ matrix.django-version }} run: pip install 'Django==${{ matrix.django-version }}'