From c54131db6edf3b23d9e067ab46b97866aed37ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Bryon?= Date: Fri, 12 Jun 2015 15:42:50 +0200 Subject: [PATCH] Refs #98 - Moved tests outside django-downloadview package, i.e. in tests/ folder at project root. --- django_downloadview/tests/__init__.py | 2 - django_downloadview/tests/views.py | 302 ------------------ {django_downloadview/tests => tests}/api.py | 0 .../tests => tests}/response.py | 0 tests/sendfile.py | 42 +++ tests/views.py | 270 +++++++++++++++- tox.ini | 4 +- 7 files changed, 299 insertions(+), 321 deletions(-) delete mode 100644 django_downloadview/tests/__init__.py delete mode 100644 django_downloadview/tests/views.py rename {django_downloadview/tests => tests}/api.py (100%) rename {django_downloadview/tests => tests}/response.py (100%) create mode 100644 tests/sendfile.py diff --git a/django_downloadview/tests/__init__.py b/django_downloadview/tests/__init__.py deleted file mode 100644 index 0f38c3e..0000000 --- a/django_downloadview/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -"""Unit tests.""" diff --git a/django_downloadview/tests/views.py b/django_downloadview/tests/views.py deleted file mode 100644 index 5ccfb20..0000000 --- a/django_downloadview/tests/views.py +++ /dev/null @@ -1,302 +0,0 @@ -# -*- coding: utf-8 -*- -"""Unit tests around views.""" -import os -import unittest -try: - from unittest import mock -except ImportError: - import mock - -from django.core.files import File -from django.http import Http404 -from django.http.response import HttpResponseNotModified -import django.test - -from django_downloadview import exceptions -from django_downloadview.test import setup_view -from django_downloadview.response import DownloadResponse -from django_downloadview import views -from django_downloadview.shortcuts import sendfile - - -class DownloadMixinTestCase(unittest.TestCase): - """Tests around :class:`django_downloadviews.views.base.DownloadMixin`.""" - def test_get_file(self): - """DownloadMixin.get_file() raise NotImplementedError. - - Subclasses must implement it! - - """ - mixin = views.DownloadMixin() - with self.assertRaises(NotImplementedError): - mixin.get_file() - - def test_get_basename(self): - """DownloadMixin.get_basename() returns basename attribute.""" - mixin = views.DownloadMixin() - self.assertEqual(mixin.get_basename(), None) - mixin.basename = 'fake' - self.assertEqual(mixin.get_basename(), 'fake') - - def test_was_modified_since_file(self): - """DownloadMixin.was_modified_since() tries (1) file's implementation. - - :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` - first tries to delegate computations to file wrapper's implementation. - - """ - file_wrapper = mock.Mock() - file_wrapper.was_modified_since = mock.Mock( - return_value=mock.sentinel.was_modified) - mixin = views.DownloadMixin() - self.assertIs( - mixin.was_modified_since(file_wrapper, mock.sentinel.since), - mock.sentinel.was_modified) - file_wrapper.was_modified_since.assertCalledOnceWith( - mock.sentinel.since) - - def test_was_modified_since_django(self): - """DownloadMixin.was_modified_since() tries (2) files attributes. - - When calling file wrapper's ``was_modified_since()`` raises - ``NotImplementedError`` or ``AttributeError``, - :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` - tries to pass file wrapper's ``size`` and ``modified_time`` to - :func:`django.views.static import was_modified_since`. - - """ - file_wrapper = mock.Mock() - file_wrapper.was_modified_since = mock.Mock( - side_effect=AttributeError) - file_wrapper.size = mock.sentinel.size - file_wrapper.modified_time = mock.sentinel.modified_time - was_modified_since_mock = mock.Mock( - return_value=mock.sentinel.was_modified) - mixin = views.DownloadMixin() - with mock.patch('django_downloadview.views.base.was_modified_since', - new=was_modified_since_mock): - self.assertIs( - mixin.was_modified_since(file_wrapper, mock.sentinel.since), - mock.sentinel.was_modified) - was_modified_since_mock.assertCalledOnceWith( - mock.sentinel.size, - mock.sentinel.modified_time) - - def test_was_modified_since_fallback(self): - """DownloadMixin.was_modified_since() fallbacks to `True`. - - When: - - * calling file wrapper's ``was_modified_since()`` raises - ``NotImplementedError`` or ``AttributeError``; - - * and accessing ``size`` and ``modified_time`` from file wrapper raises - ``NotImplementedError`` or ``AttributeError``... - - ... then - :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` - returns ``True``. - - """ - file_wrapper = mock.Mock() - file_wrapper.was_modified_since = mock.Mock( - side_effect=NotImplementedError) - type(file_wrapper).modified_time = mock.PropertyMock( - side_effect=NotImplementedError) - mixin = views.DownloadMixin() - self.assertIs( - mixin.was_modified_since(file_wrapper, 'fake since'), - True) - - def test_not_modified_response(self): - "DownloadMixin.not_modified_response returns HttpResponseNotModified." - mixin = views.DownloadMixin() - response = mixin.not_modified_response() - self.assertTrue(isinstance(response, HttpResponseNotModified)) - - def test_download_response(self): - "DownloadMixin.download_response() returns download response instance." - mixin = views.DownloadMixin() - mixin.file_instance = mock.sentinel.file_wrapper - response_factory = mock.Mock(return_value=mock.sentinel.response) - mixin.response_class = response_factory - response_kwargs = {'dummy': 'value', - 'file_instance': mock.sentinel.file_wrapper, - 'attachment': True, - 'basename': None, - 'file_mimetype': None, - 'file_encoding': None} - response = mixin.download_response(**response_kwargs) - self.assertIs(response, mock.sentinel.response) - response_factory.assert_called_once_with(**response_kwargs) # Not args - - def test_render_to_response_not_modified(self): - """DownloadMixin.render_to_response() respects HTTP_IF_MODIFIED_SINCE - header (calls ``not_modified_response()``).""" - # Setup. - mixin = views.DownloadMixin() - mixin.request = django.test.RequestFactory().get( - '/dummy-url', - HTTP_IF_MODIFIED_SINCE=mock.sentinel.http_if_modified_since) - mixin.was_modified_since = mock.Mock(return_value=False) - mixin.not_modified_response = mock.Mock( - return_value=mock.sentinel.http_not_modified_response) - mixin.get_file = mock.Mock(return_value=mock.sentinel.file_wrapper) - # Run. - response = mixin.render_to_response() - # Check. - self.assertIs(response, mock.sentinel.http_not_modified_response) - mixin.get_file.assert_called_once_with() - mixin.was_modified_since.assert_called_once_with( - mock.sentinel.file_wrapper, - mock.sentinel.http_if_modified_since) - mixin.not_modified_response.assert_called_once_with() - - def test_render_to_response_modified(self): - """DownloadMixin.render_to_response() calls download_response().""" - # Setup. - mixin = views.DownloadMixin() - mixin.request = django.test.RequestFactory().get( - '/dummy-url', - HTTP_IF_MODIFIED_SINCE=None) - mixin.was_modified_since = mock.Mock() - mixin.download_response = mock.Mock( - return_value=mock.sentinel.download_response) - mixin.get_file = mock.Mock(return_value=mock.sentinel.file_wrapper) - # Run. - response = mixin.render_to_response() - # Check. - self.assertIs(response, mock.sentinel.download_response) - mixin.get_file.assert_called_once_with() - self.assertEqual(mixin.was_modified_since.call_count, 0) - mixin.download_response.assert_called_once_with() - - def test_render_to_response_file_not_found(self): - "DownloadMixin.render_to_response() calls file_not_found_response()." - # Setup. - mixin = views.DownloadMixin() - mixin.request = django.test.RequestFactory().get('/dummy-url') - mixin.get_file = mock.Mock(side_effect=exceptions.FileNotFound) - mixin.file_not_found_response = mock.Mock() - # Run. - mixin.render_to_response() - # Check. - mixin.file_not_found_response.assert_called_once_with() - - def test_file_not_found_response(self): - """DownloadMixin.file_not_found_response() raises Http404.""" - mixin = views.DownloadMixin() - with self.assertRaises(Http404): - mixin.file_not_found_response() - - -class BaseDownloadViewTestCase(unittest.TestCase): - "Tests around :class:`django_downloadviews.views.base.BaseDownloadView`." - def test_get(self): - """BaseDownloadView.get() calls render_to_response().""" - request = django.test.RequestFactory().get('/dummy-url') - args = ['dummy-arg'] - kwargs = {'dummy': 'kwarg'} - view = setup_view(views.BaseDownloadView(), request, *args, **kwargs) - view.render_to_response = mock.Mock( - return_value=mock.sentinel.response) - response = view.get(request, *args, **kwargs) - self.assertIs(response, mock.sentinel.response) - view.render_to_response.assert_called_once_with() - - -class PathDownloadViewTestCase(unittest.TestCase): - "Tests for :class:`django_downloadviews.views.path.PathDownloadView`." - def test_get_file_ok(self): - "PathDownloadView.get_file() returns ``File`` instance." - view = setup_view(views.PathDownloadView(path=__file__), - 'fake request') - file_wrapper = view.get_file() - self.assertTrue(isinstance(file_wrapper, File)) - - def test_get_file_does_not_exist(self): - """PathDownloadView.get_file() raises FileNotFound if field does not - exist. - - """ - view = setup_view(views.PathDownloadView(path='i-do-no-exist'), - 'fake request') - with self.assertRaises(exceptions.FileNotFound): - view.get_file() - - def test_get_file_is_directory(self): - """PathDownloadView.get_file() raises FileNotFound if file is a - directory.""" - view = setup_view( - views.PathDownloadView(path=os.path.dirname(__file__)), - 'fake request') - with self.assertRaises(exceptions.FileNotFound): - view.get_file() - - -class ObjectDownloadViewTestCase(unittest.TestCase): - "Tests for :class:`django_downloadviews.views.object.ObjectDownloadView`." - def test_get_file_ok(self): - "ObjectDownloadView.get_file() returns ``file`` field by default." - view = setup_view(views.ObjectDownloadView(), 'fake request') - view.object = mock.Mock(spec=['file']) - view.get_file() - - def test_get_file_wrong_field(self): - """ObjectDownloadView.get_file() raises AttributeError if field does - not exist. - - ``AttributeError`` is expected because this is a configuration error, - i.e. it is related to Python code. - - """ - view = setup_view(views.ObjectDownloadView(file_field='other_field'), - 'fake request') - view.object = mock.Mock(spec=['file']) - with self.assertRaises(AttributeError): - view.get_file() - - def test_get_file_empty_field(self): - """ObjectDownloadView.get_file() raises FileNotFound if field does not - exist.""" - view = setup_view(views.ObjectDownloadView(file_field='other_field'), - 'fake request') - view.object = mock.Mock() - view.object.other_field = None - with self.assertRaises(exceptions.FileNotFound): - view.get_file() - - -class SendfileTestCase(django.test.TestCase): - """Tests around :func:`django_downloadview.sendfile.sendfile`.""" - def test_defaults(self): - """sendfile() takes at least request and filename.""" - request = django.test.RequestFactory().get('/fake-url') - filename = __file__ - response = sendfile(request, filename) - self.assertTrue(isinstance(response, DownloadResponse)) - self.assertFalse(response.attachment) - - def test_custom(self): - """sendfile() accepts various arguments for response tuning.""" - request = django.test.RequestFactory().get('/fake-url') - filename = __file__ - response = sendfile(request, - filename, - attachment=True, - attachment_filename='toto.txt', - mimetype='test/octet-stream', - encoding='gzip') - self.assertTrue(isinstance(response, DownloadResponse)) - self.assertTrue(response.attachment) - self.assertEqual(response.basename, 'toto.txt') - self.assertEqual(response['Content-Type'], - 'test/octet-stream; charset=utf-8') - self.assertEqual(response.get_encoding(), 'gzip') - - def test_404(self): - """sendfile() raises Http404 if file does not exists.""" - request = django.test.RequestFactory().get('/fake-url') - filename = 'i-do-no-exist' - with self.assertRaises(Http404): - sendfile(request, filename) diff --git a/django_downloadview/tests/api.py b/tests/api.py similarity index 100% rename from django_downloadview/tests/api.py rename to tests/api.py diff --git a/django_downloadview/tests/response.py b/tests/response.py similarity index 100% rename from django_downloadview/tests/response.py rename to tests/response.py diff --git a/tests/sendfile.py b/tests/sendfile.py new file mode 100644 index 0000000..370a5a9 --- /dev/null +++ b/tests/sendfile.py @@ -0,0 +1,42 @@ +# coding=utf-8 +"""Tests around :py:mod:`django_downloadview.sendfile`.""" +from django.http import Http404 +import django.test + +from django_downloadview.response import DownloadResponse +from django_downloadview.shortcuts import sendfile + + +class SendfileTestCase(django.test.TestCase): + """Tests around :func:`django_downloadview.sendfile.sendfile`.""" + def test_defaults(self): + """sendfile() takes at least request and filename.""" + request = django.test.RequestFactory().get('/fake-url') + filename = __file__ + response = sendfile(request, filename) + self.assertTrue(isinstance(response, DownloadResponse)) + self.assertFalse(response.attachment) + + def test_custom(self): + """sendfile() accepts various arguments for response tuning.""" + request = django.test.RequestFactory().get('/fake-url') + filename = __file__ + response = sendfile(request, + filename, + attachment=True, + attachment_filename='toto.txt', + mimetype='test/octet-stream', + encoding='gzip') + self.assertTrue(isinstance(response, DownloadResponse)) + self.assertTrue(response.attachment) + self.assertEqual(response.basename, 'toto.txt') + self.assertEqual(response['Content-Type'], + 'test/octet-stream; charset=utf-8') + self.assertEqual(response.get_encoding(), 'gzip') + + def test_404(self): + """sendfile() raises Http404 if file does not exists.""" + request = django.test.RequestFactory().get('/fake-url') + filename = 'i-do-no-exist' + with self.assertRaises(Http404): + sendfile(request, filename) diff --git a/tests/views.py b/tests/views.py index a98e2a9..c6c9517 100644 --- a/tests/views.py +++ b/tests/views.py @@ -1,29 +1,41 @@ # coding=utf-8 -"""Tests around :py:mod:`django_downloadview.views`.""" +"""Tests around :mod:`django_downloadview.views`.""" +import os import unittest try: from unittest import mock except ImportError: import mock +from django.core.files import File +from django.http import Http404 +from django.http.response import HttpResponseNotModified +import django.test + +from django_downloadview import exceptions +from django_downloadview.test import setup_view from django_downloadview import views -def setup_view(view, request, *args, **kwargs): - """Mimic as_view() returned callable, but returns view instance. - - ``*args`` and ``**kwargs`` are the same you would pass to ``reverse()`` - - """ - view.request = request - view.args = args - view.kwargs = kwargs - return view - - class DownloadMixinTestCase(unittest.TestCase): - """Test suite around :py:class:`django_downloadview.views.DownloadMixin`. - """ + """Test suite around :class:`django_downloadview.views.DownloadMixin`.""" + def test_get_file(self): + """DownloadMixin.get_file() raise NotImplementedError. + + Subclasses must implement it! + + """ + mixin = views.DownloadMixin() + with self.assertRaises(NotImplementedError): + mixin.get_file() + + def test_get_basename(self): + """DownloadMixin.get_basename() returns basename attribute.""" + mixin = views.DownloadMixin() + self.assertEqual(mixin.get_basename(), None) + mixin.basename = 'fake' + self.assertEqual(mixin.get_basename(), 'fake') + def test_was_modified_since_specific(self): """DownloadMixin.was_modified_since() delegates to file wrapper.""" file_wrapper = mock.Mock() @@ -49,6 +61,234 @@ class DownloadMixinTestCase(unittest.TestCase): since = mock.sentinel.since self.assertTrue(mixin.was_modified_since(file_wrapper, since)) + def test_was_modified_since_file(self): + """DownloadMixin.was_modified_since() tries (1) file's implementation. + + :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` + first tries to delegate computations to file wrapper's implementation. + + """ + file_wrapper = mock.Mock() + file_wrapper.was_modified_since = mock.Mock( + return_value=mock.sentinel.was_modified) + mixin = views.DownloadMixin() + self.assertIs( + mixin.was_modified_since(file_wrapper, mock.sentinel.since), + mock.sentinel.was_modified) + file_wrapper.was_modified_since.assertCalledOnceWith( + mock.sentinel.since) + + def test_was_modified_since_django(self): + """DownloadMixin.was_modified_since() tries (2) files attributes. + + When calling file wrapper's ``was_modified_since()`` raises + ``NotImplementedError`` or ``AttributeError``, + :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` + tries to pass file wrapper's ``size`` and ``modified_time`` to + :func:`django.views.static import was_modified_since`. + + """ + file_wrapper = mock.Mock() + file_wrapper.was_modified_since = mock.Mock( + side_effect=AttributeError) + file_wrapper.size = mock.sentinel.size + file_wrapper.modified_time = mock.sentinel.modified_time + was_modified_since_mock = mock.Mock( + return_value=mock.sentinel.was_modified) + mixin = views.DownloadMixin() + with mock.patch('django_downloadview.views.base.was_modified_since', + new=was_modified_since_mock): + self.assertIs( + mixin.was_modified_since(file_wrapper, mock.sentinel.since), + mock.sentinel.was_modified) + was_modified_since_mock.assertCalledOnceWith( + mock.sentinel.size, + mock.sentinel.modified_time) + + def test_was_modified_since_fallback(self): + """DownloadMixin.was_modified_since() fallbacks to `True`. + + When: + + * calling file wrapper's ``was_modified_since()`` raises + ``NotImplementedError`` or ``AttributeError``; + + * and accessing ``size`` and ``modified_time`` from file wrapper raises + ``NotImplementedError`` or ``AttributeError``... + + ... then + :meth:`django_downloadview.views.base.DownloadMixin.was_modified_since` + returns ``True``. + + """ + file_wrapper = mock.Mock() + file_wrapper.was_modified_since = mock.Mock( + side_effect=NotImplementedError) + type(file_wrapper).modified_time = mock.PropertyMock( + side_effect=NotImplementedError) + mixin = views.DownloadMixin() + self.assertIs( + mixin.was_modified_since(file_wrapper, 'fake since'), + True) + + def test_not_modified_response(self): + "DownloadMixin.not_modified_response returns HttpResponseNotModified." + mixin = views.DownloadMixin() + response = mixin.not_modified_response() + self.assertTrue(isinstance(response, HttpResponseNotModified)) + + def test_download_response(self): + "DownloadMixin.download_response() returns download response instance." + mixin = views.DownloadMixin() + mixin.file_instance = mock.sentinel.file_wrapper + response_factory = mock.Mock(return_value=mock.sentinel.response) + mixin.response_class = response_factory + response_kwargs = {'dummy': 'value', + 'file_instance': mock.sentinel.file_wrapper, + 'attachment': True, + 'basename': None, + 'file_mimetype': None, + 'file_encoding': None} + response = mixin.download_response(**response_kwargs) + self.assertIs(response, mock.sentinel.response) + response_factory.assert_called_once_with(**response_kwargs) # Not args + + def test_render_to_response_not_modified(self): + """DownloadMixin.render_to_response() respects HTTP_IF_MODIFIED_SINCE + header (calls ``not_modified_response()``).""" + # Setup. + mixin = views.DownloadMixin() + mixin.request = django.test.RequestFactory().get( + '/dummy-url', + HTTP_IF_MODIFIED_SINCE=mock.sentinel.http_if_modified_since) + mixin.was_modified_since = mock.Mock(return_value=False) + mixin.not_modified_response = mock.Mock( + return_value=mock.sentinel.http_not_modified_response) + mixin.get_file = mock.Mock(return_value=mock.sentinel.file_wrapper) + # Run. + response = mixin.render_to_response() + # Check. + self.assertIs(response, mock.sentinel.http_not_modified_response) + mixin.get_file.assert_called_once_with() + mixin.was_modified_since.assert_called_once_with( + mock.sentinel.file_wrapper, + mock.sentinel.http_if_modified_since) + mixin.not_modified_response.assert_called_once_with() + + def test_render_to_response_modified(self): + """DownloadMixin.render_to_response() calls download_response().""" + # Setup. + mixin = views.DownloadMixin() + mixin.request = django.test.RequestFactory().get( + '/dummy-url', + HTTP_IF_MODIFIED_SINCE=None) + mixin.was_modified_since = mock.Mock() + mixin.download_response = mock.Mock( + return_value=mock.sentinel.download_response) + mixin.get_file = mock.Mock(return_value=mock.sentinel.file_wrapper) + # Run. + response = mixin.render_to_response() + # Check. + self.assertIs(response, mock.sentinel.download_response) + mixin.get_file.assert_called_once_with() + self.assertEqual(mixin.was_modified_since.call_count, 0) + mixin.download_response.assert_called_once_with() + + def test_render_to_response_file_not_found(self): + "DownloadMixin.render_to_response() calls file_not_found_response()." + # Setup. + mixin = views.DownloadMixin() + mixin.request = django.test.RequestFactory().get('/dummy-url') + mixin.get_file = mock.Mock(side_effect=exceptions.FileNotFound) + mixin.file_not_found_response = mock.Mock() + # Run. + mixin.render_to_response() + # Check. + mixin.file_not_found_response.assert_called_once_with() + + def test_file_not_found_response(self): + """DownloadMixin.file_not_found_response() raises Http404.""" + mixin = views.DownloadMixin() + with self.assertRaises(Http404): + mixin.file_not_found_response() + + +class BaseDownloadViewTestCase(unittest.TestCase): + "Tests around :class:`django_downloadviews.views.base.BaseDownloadView`." + def test_get(self): + """BaseDownloadView.get() calls render_to_response().""" + request = django.test.RequestFactory().get('/dummy-url') + args = ['dummy-arg'] + kwargs = {'dummy': 'kwarg'} + view = setup_view(views.BaseDownloadView(), request, *args, **kwargs) + view.render_to_response = mock.Mock( + return_value=mock.sentinel.response) + response = view.get(request, *args, **kwargs) + self.assertIs(response, mock.sentinel.response) + view.render_to_response.assert_called_once_with() + + +class PathDownloadViewTestCase(unittest.TestCase): + "Tests for :class:`django_downloadviews.views.path.PathDownloadView`." + def test_get_file_ok(self): + "PathDownloadView.get_file() returns ``File`` instance." + view = setup_view(views.PathDownloadView(path=__file__), + 'fake request') + file_wrapper = view.get_file() + self.assertTrue(isinstance(file_wrapper, File)) + + def test_get_file_does_not_exist(self): + """PathDownloadView.get_file() raises FileNotFound if field does not + exist. + + """ + view = setup_view(views.PathDownloadView(path='i-do-no-exist'), + 'fake request') + with self.assertRaises(exceptions.FileNotFound): + view.get_file() + + def test_get_file_is_directory(self): + """PathDownloadView.get_file() raises FileNotFound if file is a + directory.""" + view = setup_view( + views.PathDownloadView(path=os.path.dirname(__file__)), + 'fake request') + with self.assertRaises(exceptions.FileNotFound): + view.get_file() + + +class ObjectDownloadViewTestCase(unittest.TestCase): + "Tests for :class:`django_downloadviews.views.object.ObjectDownloadView`." + def test_get_file_ok(self): + "ObjectDownloadView.get_file() returns ``file`` field by default." + view = setup_view(views.ObjectDownloadView(), 'fake request') + view.object = mock.Mock(spec=['file']) + view.get_file() + + def test_get_file_wrong_field(self): + """ObjectDownloadView.get_file() raises AttributeError if field does + not exist. + + ``AttributeError`` is expected because this is a configuration error, + i.e. it is related to Python code. + + """ + view = setup_view(views.ObjectDownloadView(file_field='other_field'), + 'fake request') + view.object = mock.Mock(spec=['file']) + with self.assertRaises(AttributeError): + view.get_file() + + def test_get_file_empty_field(self): + """ObjectDownloadView.get_file() raises FileNotFound if field does not + exist.""" + view = setup_view(views.ObjectDownloadView(file_field='other_field'), + 'fake request') + view.object = mock.Mock() + view.object.other_field = None + with self.assertRaises(exceptions.FileNotFound): + view.get_file() + class VirtualDownloadViewTestCase(unittest.TestCase): """Test suite around diff --git a/tox.ini b/tox.ini index bf63543..91a58c9 100644 --- a/tox.ini +++ b/tox.ini @@ -16,8 +16,8 @@ deps = commands = pip install -e . pip install -e demo - demo test --cover-package=django_downloadview {posargs: django_downloadview demoproject} - cover erase + demo test --cover-package=django_downloadview --cover-package=demoproject {posargs: tests demoproject} + coverage erase pip freeze [testenv:flake8]