Skip to content

Commit

Permalink
improve test coverage (django-import-export#1372)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewhegarty committed Dec 26, 2021
1 parent 0d4340f commit f0a9b81
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 67 deletions.
77 changes: 24 additions & 53 deletions .github/workflows/django-import-export-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,61 +13,27 @@ jobs:
runs-on: ubuntu-latest
env:
USERNAME: testuser
PASSWD: ${{ secrets.TEST_PASSWD }}
PASSWD: somepass
DB_NAME: import_export
MYSQL_USER: root
MYSQL_PASS: root
strategy:
max-parallel: 4
matrix:
db: [ sqlite, postgres, mysql ]
python-version: [ 3.6, 3.7, 3.8, 3.9, "3.10" ]
django-version: [ 2.2, 3.0, 3.1, 3.2, 4.0, main ]
db: [ postgres, mysql ]
python-version: [ "3.10" ]
django-version: [ main ]
include:
- db: postgres
db_port: 5432
test_type: postgres
- db: mysql
db_port: 3306
exclude:
- django-version: main
python-version: 3.6
- django-version: main
python-version: 3.7
- django-version: 4.0
python-version: 3.6
- django-version: 4.0
python-version: 3.7
- django-version: 2.2
python-version: "3.10"
- django-version: 3.0
python-version: "3.10"
- django-version: 3.1
python-version: "3.10"
- django-version: 3.2
python-version: "3.10"
test_type: mysql-innodb
services:
mysql:
image: mysql:8.0
env:
IMPORT_EXPORT_TEST_TYPE: mysql-innodb
IMPORT_EXPORT_MYSQL_USER: ${{ env.TESTUSER }}
IMPORT_EXPORT_MYSQL_PASSWORD: ${{ env.PASSWD }}
MYSQL_USER: ${{ env.TESTUSER }}
MYSQL_PASSWORD: ${{ env.IMPORT_EXPORT_MYSQL_PASSWORD }}
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: import_export
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
postgres:
image: postgres
env:
IMPORT_EXPORT_TEST_TYPE: postgres
IMPORT_EXPORT_POSTGRESQL_USER: postgres
IMPORT_EXPORT_POSTGRESQL_PASSWORD: ${{ env.PASSWD }}
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_PASSWORD: ${{ env.PASSWD }}
POSTGRES_DB: import_export
ports:
- 5432:5432
Expand All @@ -78,6 +44,10 @@ jobs:
--health-retries 5
steps:
- name: Set up MySQL
run: |
sudo /etc/init.d/mysql start
mysql -e 'CREATE DATABASE ${{ env.DB_NAME }};' -u${{ env.MYSQL_USER }} -p${{ env.MYSQL_PASS }}
- name: Check out repository code
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -109,15 +79,16 @@ jobs:
echo "Django `django-admin --version`"
- name: Run Tests
env:
DB: ${{ matrix.db }}
DB_HOST: 127.0.0.1
DB_PORT: ${{ matrix.db_port }}
DB_PASSWORD: ${{ env.PASSWD }}
run: >-
PYTHONPATH=".:tests:$PYTHONPATH" python
-W error::DeprecationWarning -W error::PendingDeprecationWarning
-m coverage run --omit='setup.py,./tests/*,./import_export/locale/*'
--source=. tests/manage.py test core --settings=
IMPORT_EXPORT_TEST_TYPE: ${{ matrix.test_type }}
IMPORT_EXPORT_POSTGRESQL_USER: postgres
IMPORT_EXPORT_POSTGRESQL_PASSWORD: ${{ env.PASSWD }}
IMPORT_EXPORT_MYSQL_USER: ${{ env.MYSQL_USER }}
IMPORT_EXPORT_MYSQL_PASSWORD: ${{ env.MYSQL_PASS }}
run: >
PYTHONPATH=".:tests:$PYTHONPATH" python -W error::DeprecationWarning -W error::PendingDeprecationWarning
-m coverage run tests/manage.py test core --settings=
coverage combine
- name: Upload coverage data to coveralls.io
run: coveralls --service=github
env:
Expand Down
4 changes: 4 additions & 0 deletions import_export/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import warnings
warnings.warn("the exceptions module is deprecated and will be removed in a future release", DeprecationWarning)


class ImportExportError(Exception):
"""A generic exception for all others to extend."""
pass
Expand Down
21 changes: 11 additions & 10 deletions import_export/formats/base_formats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from importlib import import_module

import tablib
from tablib.formats import registry


class Format:
Expand Down Expand Up @@ -61,14 +60,16 @@ def get_format(self):
"""
Import and returns tablib module.
"""
try:
# Available since tablib 1.0
from tablib.formats import registry
except ImportError:
return import_module(self.TABLIB_MODULE)
else:
key = self.TABLIB_MODULE.split('.')[-1].replace('_', '')
return registry.get_format(key)
# try:
# # Available since tablib 1.0
# from tablib.formats import registry
# except ImportError:
# return import_module(self.TABLIB_MODULE)
# else:
if not self.TABLIB_MODULE:
raise AttributeError("TABLIB_MODULE must be defined")
key = self.TABLIB_MODULE.split('.')[-1].replace('_', '')
return registry.get_format(key)

@classmethod
def is_available(cls):
Expand Down
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ python-file-with-version = import_export/__init__.py

[isort]
profile = black

[coverage:run]
parallel = true
source = import_export
10 changes: 10 additions & 0 deletions tests/core/tests/test_base_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ def test_can_import_default(self):
def test_can_export_default(self):
self.assertFalse(self.format.can_export())


class TablibFormatTest(TestCase):
def setUp(self):
self.format = base_formats.TablibFormat()

def test_get_format_for_undefined_TABLIB_MODULE_raises_AttributeError(self):
with self.assertRaises(AttributeError):
self.format.get_format()


class XLSTest(TestCase):

def setUp(self):
Expand Down
10 changes: 10 additions & 0 deletions tests/core/tests/test_import_export_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from unittest import TestCase

from import_export.templatetags import import_export_tags


class TagsTest(TestCase):

def test_compare_values(self):
target = '<del style="background:#ffe6e6;">a</del><ins style="background:#e6ffe6;">b</ins>'
self.assertEqual(target, import_export_tags.compare_values("a", "b"))
13 changes: 13 additions & 0 deletions tests/core/tests/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import date
from decimal import Decimal, InvalidOperation
from unittest import mock, skip, skipIf, skipUnless
from unittest.mock import patch

import django
import tablib
Expand Down Expand Up @@ -159,6 +160,18 @@ def test_init_instance_raises_NotImplementedError(self):
with self.assertRaises(NotImplementedError):
self.my_resource.init_instance([])

@patch("core.models.Book.full_clean")
def test_validate_instance_called_with_import_validation_errors_as_None_creates_empty_dict(self, full_clean_mock):
# validate_instance() import_validation_errors is an optional kwarg
# If not provided, it defaults to an empty dict
# this tests that scenario by ensuring that an empty dict is passed
# to the model instance full_clean() method.
book = Book()
self.my_resource._meta.clean_model_instances = True
self.my_resource.validate_instance(book)
target = dict()
full_clean_mock.assert_called_once_with(exclude=target.keys(), validate_unique=True)


class AuthorResource(resources.ModelResource):

Expand Down
19 changes: 17 additions & 2 deletions tests/core/tests/test_widgets.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from datetime import date, datetime, time, timedelta
from decimal import Decimal
from unittest import mock
from unittest import mock, skipUnless

import django
import pytz
from core.models import Author, Category
from django.test import TestCase
from django.test.utils import override_settings
from django.utils import timezone

from core.models import Author, Category
from import_export import widgets


Expand Down Expand Up @@ -42,6 +43,20 @@ def test_render(self):
self.assertEqual(self.widget.render(None), "")


class FormatDatetimeTest(TestCase):
date = date(10, 8, 2)
target_dt = "02.08.0010"
format = "%d.%m.%Y"

@skipUnless(django.VERSION[0] < 4, f"skipping django {django.VERSION} version specific test")
def test_format_datetime_lt_django4(self):
self.assertEqual(self.target_dt, widgets.format_datetime(self.date, self.format))

@skipUnless(django.VERSION[0] >= 4, f"skipping django {django.VERSION} version specific test")
def test_format_datetime_gte_django4(self):
self.assertEqual(self.target_dt, widgets.format_datetime(self.date, self.format))


class DateWidgetTest(TestCase):

def setUp(self):
Expand Down
4 changes: 2 additions & 2 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'import_export',
'USER': os.environ.get('IMPORT_EXPORT_MYSQL_USER', 'root'),
'PASSWORD': os.environ.get('IMPORT_EXPORT_MYSQL_PASSWORD', 'password'),
'USER': os.environ.get('IMPORT_EXPORT_MYSQL_USER'),
'PASSWORD': os.environ.get('IMPORT_EXPORT_MYSQL_PASSWORD'),
'HOST': '127.0.0.1',
'PORT': 3306,
'TEST': {
Expand Down

0 comments on commit f0a9b81

Please sign in to comment.