summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Fladischer <FladischerMichael@fladi.at>2017-05-30 14:05:34 +0200
committerMichael Fladischer <FladischerMichael@fladi.at>2017-05-30 14:05:34 +0200
commit50ec3f8173a0bab6e2d6da3cd8a5739105a3641a (patch)
tree766c7165e8ef3a89bc5a2ba95d49693e7fb9ad06
parentd53380c5c4fb5eee56cf76a2a3df379c8a842556 (diff)
Import python-testfixtures_4.14.3.orig.tar.gz
-rw-r--r--.travis.yml8
-rw-r--r--docs/api.txt8
-rw-r--r--docs/changes.txt29
-rw-r--r--docs/comparing.txt2
-rwxr-xr-xdocs/components.txt6
-rw-r--r--docs/conf.py7
-rw-r--r--docs/description.txt18
-rwxr-xr-xdocs/django.txt54
-rw-r--r--docs/index.txt1
-rw-r--r--docs/mocking.txt4
-rw-r--r--setup.py8
-rw-r--r--testfixtures/comparison.py5
-rw-r--r--testfixtures/django.py24
-rw-r--r--testfixtures/shouldraise.py3
-rw-r--r--testfixtures/tests/compat.py9
-rw-r--r--testfixtures/tests/test_compare.py202
-rw-r--r--testfixtures/tests/test_components.py11
-rw-r--r--testfixtures/tests/test_django/__init__.py0
-rw-r--r--testfixtures/tests/test_django/models.py11
-rw-r--r--testfixtures/tests/test_django/settings.py4
-rw-r--r--testfixtures/tests/test_django/tests.py75
-rw-r--r--testfixtures/tests/test_should_raise.py6
-rw-r--r--testfixtures/tests/test_shouldwarn.py27
-rw-r--r--testfixtures/version.txt2
24 files changed, 375 insertions, 149 deletions
diff --git a/.travis.yml b/.travis.yml
index ad19bfb..150ede1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,14 +4,16 @@ language: python
sudo: false
python:
+ - "3.6"
- "3.5"
- "3.4"
- - "3.3"
- "2.7"
# command to install dependencies
-install: "pip install -Ue .[test,build]"
-
+install:
+- "pip install --upgrade pip setuptools"
+- "pip install -e .[test,build]"
+
# command to run tests, e.g. python setup.py test
script: nosetests --with-cov --cov=testfixtures
diff --git a/docs/api.txt b/docs/api.txt
index 463ec46..fbaea1f 100644
--- a/docs/api.txt
+++ b/docs/api.txt
@@ -306,3 +306,11 @@ API Reference
.. autoclass:: testfixtures.popen.MockPopen
:members:
+.. automodule:: testfixtures.django
+ :members:
+
+ .. function:: compare(x, y, prefix=None, suffix=None, raises=True, recursive=True, strict=False, comparers=None, **kw)
+
+ This is identical to :func:`compare`, but with ``ignore=True``
+ automatically set to make comparing django :class:`~django.db.models.Model`
+ instances easier.
diff --git a/docs/changes.txt b/docs/changes.txt
index 1a97f2a..f16dd4f 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -3,6 +3,27 @@ Changes
.. currentmodule:: testfixtures
+4.14.3 (15 May 2017)
+--------------------
+
+- Fix build environment bug in ``.travis.yml`` that caused bad tarballs.
+
+4.14.2 (15 May 2017)
+--------------------
+
+- New release as it looks like Travis mis-built the 4.14.1 tarball.
+
+4.14.1 (15 May 2017)
+--------------------
+
+- Fix mis-merge.
+
+4.14.0 (15 May 2017)
+--------------------
+
+- Added helpers for testing with :doc:`django <django>`
+ :class:`~django.db.models.Model` instances.
+
4.13.5 (1 March 2017)
-------------------------
@@ -50,7 +71,7 @@ Thanks to "mlabonte" for the bug report.
- Add support for recursive comparison of log messages with :class:`LogCapture`.
4.11.0 (12 October 2016)
--------------------------
+------------------------
- Allow the attributes returned in :meth:`LogCapture.actual` rows to be
specified.
@@ -115,7 +136,7 @@ Thanks to Wim Glenn for the suffix patch.
------------------------
- Add the ability to pass ``raises=False`` to :func:`compare` to just get
- and resulting message back rather than having an exception raised.
+ the resulting message back rather than having an exception raised.
4.6.0 (3 December 2015)
------------------------
@@ -222,7 +243,7 @@ Thanks to BATS Global Markets for donating the code for
Thanks to Daniel Fortunov for the documentation clarification.
4.1.1 (30 October 2014)
--------------------------
+-----------------------
- Fix bug that prevented logger propagation to be controlled by the
:class:`log_capture` decorator.
@@ -230,7 +251,7 @@ Thanks to Daniel Fortunov for the documentation clarification.
Thanks to John Kristensen for the fix.
4.1.0 (14 October 2014)
--------------------------
+-----------------------
- Fix :func:`compare` bug when :class:`dict` instances with
:class:`tuple` keys were not equal.
diff --git a/docs/comparing.txt b/docs/comparing.txt
index db70040..d930bc1 100644
--- a/docs/comparing.txt
+++ b/docs/comparing.txt
@@ -299,6 +299,8 @@ While comparing [1]['text']:
This also applies to any comparers you have provided, as can be seen
in the next section.
+.. _comparer-register:
+
Providing your own comparers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/components.txt b/docs/components.txt
index 3e706b0..fbf4ab3 100755
--- a/docs/components.txt
+++ b/docs/components.txt
@@ -3,11 +3,7 @@ Testing with zope.component
.. invisible-code-block: python
- from nose.plugins.skip import SkipTest
- try:
- from zope.component import getSiteManager
- except ImportError:
- raise SkipTest('zope.component unavailable')
+ from zope.component import getSiteManager
from testfixtures.components import TestComponents
.. currentmodule:: testfixtures
diff --git a/docs/conf.py b/docs/conf.py
index 3a340fd..7a3cef7 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,13 +14,16 @@ extensions = [
'sphinx.ext.intersphinx'
]
-intersphinx_mapping = {'http://docs.python.org': None}
+intersphinx_mapping = {
+ 'http://docs.python.org': None,
+ 'http://django.readthedocs.org/en/latest/': None,
+}
# General
source_suffix = '.txt'
master_doc = 'index'
project = pkg_info.name
-copyright = '2008-2015 Simplistix Ltd, %s Chris Withers' % build_date.year
+copyright = '2008-2015 Simplistix Ltd, 2016-%s Chris Withers' % build_date.year
version = release = pkg_info.version
exclude_trees = ['_build']
exclude_patterns = ['description.txt']
diff --git a/docs/description.txt b/docs/description.txt
index fd0f947..dcfab6e 100644
--- a/docs/description.txt
+++ b/docs/description.txt
@@ -41,7 +41,19 @@ statements, and making assertion about it.
Support for creating and checking files and directories in sandboxes
for both doc tests and unit tests.
-**Testing exceptions**
+**Testing exceptions and warnings**
-Easy to use ways of checking that a certain exception is raised, even
-down the to the parameters the exception is raised with.
+Easy to use ways of checking that a certain exception is raised,
+or a warning is issued, even down the to the parameters provided.
+
+**Testing subprocesses**
+
+A handy mock for testing code that uses subprocesses.
+
+**Testing when using django**
+
+Helpers for comparing instances of django models.
+
+**Testing when using zope.component**
+
+An easy to use sterile component registry.
diff --git a/docs/django.txt b/docs/django.txt
new file mode 100755
index 0000000..417a612
--- /dev/null
+++ b/docs/django.txt
@@ -0,0 +1,54 @@
+Testing when using django
+=========================
+
+Django's ORM has an unfortunate implementation choice to consider
+:class:`~django.db.models.Model` instances to be identical as long as their
+primary keys are the same:
+
+>>> from testfixtures.tests.test_django.models import SampleModel
+>>> SampleModel(id=1, value=1) == SampleModel(id=1, value=2)
+True
+
+To work around this, :mod:`testfixtures.django` :ref:`registers <comparer-register>`
+a comparer for the django :class:`~django.db.models.Model` class. However,
+for this to work, ``ignore_eq=True`` must be passed:
+
+>>> compare(SampleModel(id=1, value=1), SampleModel(id=1, value=2),
+... ignore_eq=True)
+Traceback (most recent call last):
+ ...
+AssertionError: SampleModel not as expected:
+<BLANKLINE>
+same:
+[u'id']
+<BLANKLINE>
+values differ:
+'value': 1 != 2
+
+Since the above can quickly become cumbersome, a django-specific version
+of :func:`~testfixtures.compare`, with ignoring ``__eq__`` built in, is provided:
+
+>>> from testfixtures.django import compare as django_compare
+>>> django_compare(SampleModel(id=1, value=1), SampleModel(id=1, value=2))
+Traceback (most recent call last):
+ ...
+AssertionError: SampleModel not as expected:
+<BLANKLINE>
+same:
+[u'id']
+<BLANKLINE>
+values differ:
+'value': 1 != 2
+
+It may also be that you want to ignore fields over which you have no control
+and cannot easily mock, such as created or modified times. For this, you
+can use the `ignore_fields` option:
+
+>>> compare(SampleModel(id=1, value=1), SampleModel(id=1, value=2),
+... ignore_eq=True, ignore_fields=['value'])
+
+.. note::
+
+ The implementation of the comparer for
+ :class:`~django.db.models.Model` instances ignores fields
+ that have ``editable`` set to ``False``.
diff --git a/docs/index.txt b/docs/index.txt
index cbd65e0..af85e1d 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -18,6 +18,7 @@ The sections below describe the use of the various tools included:
exceptions.txt
warnings.txt
popen.txt
+ django.txt
components.txt
utilities.txt
diff --git a/docs/mocking.txt b/docs/mocking.txt
index 761d949..42a1d5c 100644
--- a/docs/mocking.txt
+++ b/docs/mocking.txt
@@ -323,7 +323,7 @@ do so as follows:
.. code-block:: python
- from testfixtures import Replacer, not_there
+ from testfixtures import Replace, not_there
from testfixtures.tests.sample1 import someDict
def test_function():
@@ -345,7 +345,7 @@ duration of a test, you would do so as follows:
.. code-block:: python
- from testfixtures import Replacer, not_there
+ from testfixtures import Replace, not_there
from testfixtures.tests import sample1
def test_function():
diff --git a/setup.py b/setup.py
index b58625e..1e0d295 100644
--- a/setup.py
+++ b/setup.py
@@ -25,20 +25,18 @@ setup(
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.2',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
],
packages=find_packages(),
zip_safe=False,
include_package_data=True,
extras_require=dict(
- test=['nose', 'nose-fixes', 'nose-cov', 'mock', 'manuel',
- 'zope.component', 'coveralls'],
+ test=['nose', 'nose-fixes', 'nose-cov', 'mock', 'manuel', 'coveralls',
+ 'zope.component', 'django'],
build=['sphinx', 'pkginfo', 'setuptools-git', 'wheel', 'twine']
)
)
diff --git a/testfixtures/comparison.py b/testfixtures/comparison.py
index a30d474..cecd483 100644
--- a/testfixtures/comparison.py
+++ b/testfixtures/comparison.py
@@ -462,6 +462,9 @@ def compare(*args, **kw):
be added to the global comparer registry for the duration
of this call.
"""
+
+ __tracebackhide__ = True
+
prefix = kw.pop('prefix', None)
suffix = kw.pop('suffix', None)
raises = kw.pop('raises', True)
@@ -545,8 +548,6 @@ class Comparison(object):
if isinstance(other, BaseException):
v = dict(vars(other))
v['args'] = other.args
- if PY3 and '_not_found' in v:
- del v['_not_found']
else:
try:
v = vars(other)
diff --git a/testfixtures/django.py b/testfixtures/django.py
new file mode 100644
index 0000000..066a2bf
--- /dev/null
+++ b/testfixtures/django.py
@@ -0,0 +1,24 @@
+from __future__ import absolute_import
+from functools import partial
+
+from django.db.models import Model
+from django.forms import model_to_dict
+
+from .comparison import _compare_mapping, register
+from . import compare as base_compare
+
+
+def compare_model(x, y, context):
+ ignore_fields = context.get_option('ignore_fields', set())
+ args = []
+ for obj in x, y:
+ args.append({k: v for (k, v) in model_to_dict(obj).items()
+ if k not in ignore_fields})
+ args.append(context)
+ args.append(x)
+ return _compare_mapping(*args)
+
+register(Model, compare_model)
+
+
+compare = partial(base_compare, ignore_eq=True)
diff --git a/testfixtures/shouldraise.py b/testfixtures/shouldraise.py
index 9e7b49b..63ecbe2 100644
--- a/testfixtures/shouldraise.py
+++ b/testfixtures/shouldraise.py
@@ -44,6 +44,9 @@ class ShouldRaise(object):
return self
def __exit__(self, type, actual, traceback):
+
+ __tracebackhide__ = True
+
# bug in python :-(
if type is not None and not isinstance(actual, type):
# fixed in 2.7 onwards!
diff --git a/testfixtures/tests/compat.py b/testfixtures/tests/compat.py
index 112785f..4eb47dc 100644
--- a/testfixtures/tests/compat.py
+++ b/testfixtures/tests/compat.py
@@ -23,10 +23,12 @@ from ..compat import PY2 as py_2
py_33_plus = sys.version_info[:2] >= (3, 3)
py_34_plus = sys.version_info[:2] >= (3, 4)
py_35_plus = sys.version_info[:2] >= (3, 5)
+py_36_plus = sys.version_info[:2] >= (3, 6)
# Python 2.7 compatibility stuff
BYTE_LITERALS = re.compile("^b('.*')$", re.MULTILINE)
+UNICODE_LITERALS = re.compile("u('.*')", re.MULTILINE)
def find_code_blocks(document):
@@ -55,4 +57,9 @@ if py_2:
self, want, got, optionflags
)
else:
- DocTestChecker = doctest.OutputChecker
+ class DocTestChecker(doctest.OutputChecker):
+ def check_output(self, want, got, optionflags):
+ want = UNICODE_LITERALS.sub('\\1', want)
+ return doctest.OutputChecker.check_output(
+ self, want, got, optionflags
+ )
diff --git a/testfixtures/tests/test_compare.py b/testfixtures/tests/test_compare.py
index 30295cd..8e390c7 100644
--- a/testfixtures/tests/test_compare.py
+++ b/testfixtures/tests/test_compare.py
@@ -1,5 +1,3 @@
-# Copyright (c) 2008-2014 Simplistix Ltd
-# See license.txt for license details.
from datetime import date
from functools import partial
@@ -34,9 +32,10 @@ call_list_repr = repr(Mock().mock_calls.__class__)
marker = object()
-class TestCompare(TestCase):
+class CompareHelper(object):
- def checkRaises(self, x=marker, y=marker, message=None, regex=None, **kw):
+ def check_raises(self, x=marker, y=marker, message=None, regex=None,
+ compare=compare, **kw):
args = []
for value in x, y:
if value is not marker:
@@ -49,7 +48,7 @@ class TestCompare(TestCase):
actual = hexsub(e.args[0])
if message is not None:
# handy for debugging, but can't be relied on for tests!
- # compare(actual, message, show_whitespace=True)
+ compare(actual, expected=message, show_whitespace=True)
self.assertEqual(actual, message)
else:
if not regex.match(actual): # pragma: no cover
@@ -57,6 +56,9 @@ class TestCompare(TestCase):
else:
self.fail('No exception raised!')
+
+class TestCompare(CompareHelper, TestCase):
+
def test_object_same(self):
o = object()
compare(o, o)
@@ -64,23 +66,23 @@ class TestCompare(TestCase):
def test_object_diff(self):
o1 = object()
o2 = object()
- self.checkRaises(
+ self.check_raises(
o1, o2,
'<object object at ...> != <object object at ...>'
)
def test_different_types(self):
- self.checkRaises('x', 1, "'x' != 1")
+ self.check_raises('x', 1, "'x' != 1")
def test_number_same(self):
compare(1, 1)
def test_number_different(self):
- self.checkRaises(1, 2, '1 != 2')
+ self.check_raises(1, 2, '1 != 2')
def test_different_with_labels(self):
- self.checkRaises(1, 2, '1 (expected) != 2 (actual)',
- x_label='expected', y_label='actual')
+ self.check_raises(1, 2, '1 (expected) != 2 (actual)',
+ x_label='expected', y_label='actual')
def test_string_same(self):
compare('x', 'x')
@@ -90,31 +92,31 @@ class TestCompare(TestCase):
expected = "u'a' != 'b'"
else:
expected = "'a' != b'b'"
- self.checkRaises(
+ self.check_raises(
UnicodeLiteral('a'), BytesLiteral('b'),
expected
)
def test_string_diff_short(self):
- self.checkRaises(
+ self.check_raises(
'\n'+('x'*9), '\n'+('y'*9),
"'\\nxxxxxxxxx' != '\\nyyyyyyyyy'"
)
def test_string_diff_long(self):
- self.checkRaises(
+ self.check_raises(
'x'*11, 'y'*11,
"\n'xxxxxxxxxxx'\n!=\n'yyyyyyyyyyy'"
)
def test_string_diff_long_newlines(self):
- self.checkRaises(
+ self.check_raises(
'x'*5+'\n'+'y'*5, 'x'*5+'\n'+'z'*5,
"\n--- first\n+++ second\n@@ -1,2 +1,2 @@\n xxxxx\n-yyyyy\n+zzzzz"
)
def test_string_diff_short_labels(self):
- self.checkRaises(
+ self.check_raises(
'\n'+('x'*9), '\n'+('y'*9),
"'\\nxxxxxxxxx' (expected) != '\\nyyyyyyyyy' (actual)",
x_label='expected',
@@ -122,7 +124,7 @@ class TestCompare(TestCase):
)
def test_string_diff_long_labels(self):
- self.checkRaises(
+ self.check_raises(
'x'*11, 'y'*11,
"\n'xxxxxxxxxxx' (expected)\n!=\n'yyyyyyyyyyy' (actual)",
x_label='expected',
@@ -130,7 +132,7 @@ class TestCompare(TestCase):
)
def test_string_diff_long_newlines_labels(self):
- self.checkRaises(
+ self.check_raises(
'x'*5+'\n'+'y'*5, 'x'*5+'\n'+'z'*5,
"\n--- expected\n+++ actual\n"
"@@ -1,2 +1,2 @@\n xxxxx\n-yyyyy\n+zzzzz",
@@ -150,7 +152,7 @@ class TestCompare(TestCase):
def test_exception_different_object(self):
e1 = ValueError('some message')
e2 = ValueError('some message')
- self.checkRaises(
+ self.check_raises(
e1, e2,
"ValueError('some message',) != ValueError('some message',)"
)
@@ -163,7 +165,7 @@ class TestCompare(TestCase):
def test_exception_diff(self):
e1 = ValueError('some message')
e2 = ValueError('some other message')
- self.checkRaises(
+ self.check_raises(
e1, e2,
"ValueError('some message',) != ValueError('some other message',)"
)
@@ -171,7 +173,7 @@ class TestCompare(TestCase):
def test_exception_diff_c_wrapper(self):
e1 = ValueError('some message')
e2 = ValueError('some other message')
- self.checkRaises(
+ self.check_raises(
C(e1), e2,
("\n"
" <C(failed):{0}.ValueError>\n"
@@ -182,7 +184,7 @@ class TestCompare(TestCase):
).format(exception_module))
def test_sequence_long(self):
- self.checkRaises(
+ self.check_raises(
['quite a long string 1', 'quite a long string 2',
'quite a long string 3', 'quite a long string 4',
'quite a long string 5', 'quite a long string 6',
@@ -215,7 +217,7 @@ class TestCompare(TestCase):
)
def test_sequence_different_labels_supplied(self):
- self.checkRaises(
+ self.check_raises(
[1, 2, 3], [1, 2, 4],
"sequence not as expected:\n\n"
"same:\n"
@@ -232,7 +234,7 @@ class TestCompare(TestCase):
compare([1, 2, 3], [1, 2, 3])
def test_list_different(self):
- self.checkRaises(
+ self.check_raises(
[1, 2, 3], [1, 2, 4],
"sequence not as expected:\n\n"
"same:\n"
@@ -244,7 +246,7 @@ class TestCompare(TestCase):
)
def test_list_totally_different(self):
- self.checkRaises(
+ self.check_raises(
[1], [2],
"sequence not as expected:\n\n"
"same:\n"
@@ -256,7 +258,7 @@ class TestCompare(TestCase):
)
def test_list_first_shorter(self):
- self.checkRaises(
+ self.check_raises(
[1, 2], [1, 2, 3],
"sequence not as expected:\n\n"
"same:\n[1, 2]\n\n"
@@ -265,7 +267,7 @@ class TestCompare(TestCase):
)
def test_list_second_shorter(self):
- self.checkRaises(
+ self.check_raises(
[1, 2, 3], [1, 2],
"sequence not as expected:\n\n"
"same:\n[1, 2]\n\n"
@@ -277,7 +279,7 @@ class TestCompare(TestCase):
compare(dict(x=1), dict(x=1))
def test_dict_first_missing_keys(self):
- self.checkRaises(
+ self.check_raises(
dict(), dict(z=3),
"dict not as expected:\n"
"\n"
@@ -286,7 +288,7 @@ class TestCompare(TestCase):
)
def test_dict_second_missing_keys(self):
- self.checkRaises(
+ self.check_raises(
dict(z=3), dict(),
"dict not as expected:\n"
"\n"
@@ -295,7 +297,7 @@ class TestCompare(TestCase):
)
def test_dict_values_different(self):
- self.checkRaises(
+ self.check_raises(
dict(x=1), dict(x=2),
"dict not as expected:\n"
"\n"
@@ -304,7 +306,7 @@ class TestCompare(TestCase):
)
def test_dict_labels_specified(self):
- self.checkRaises(
+ self.check_raises(
dict(x=1, y=2), dict(x=2, z=3),
"dict not as expected:\n"
"\n"
@@ -324,7 +326,7 @@ class TestCompare(TestCase):
compare({(1, 2): None}, {(1, 2): None})
def test_dict_tuple_keys_different_value(self):
- self.checkRaises(
+ self.check_raises(
{(1, 2): 3},
{(1, 2): 42},
"dict not as expected:\n"
@@ -334,7 +336,7 @@ class TestCompare(TestCase):
)
def test_dict_full_diff(self):
- self.checkRaises(
+ self.check_raises(
dict(x=1, y=2, a=4), dict(x=1, z=3, a=5),
"dict not as expected:\n"
"\n"
@@ -352,7 +354,7 @@ class TestCompare(TestCase):
)
def test_dict_consistent_ordering(self):
- self.checkRaises(
+ self.check_raises(
dict(xa=1, xb=2, ya=1, yb=2, aa=3, ab=4),
dict(xa=1, xb=2, za=3, zb=4, aa=5, ab=5),
"dict not as expected:\n"
@@ -374,7 +376,7 @@ class TestCompare(TestCase):
)
def test_dict_consistent_ordering_types_same(self):
- self.checkRaises(
+ self.check_raises(
{None: 1, 6: 2, 1: 3},
{None: 1, 6: 2, 1: 4},
"dict not as expected:\n"
@@ -387,7 +389,7 @@ class TestCompare(TestCase):
)
def test_dict_consistent_ordering_types_x_not_y(self):
- self.checkRaises(
+ self.check_raises(
{None: 1, 3: 2},
{},
"dict not as expected:\n"
@@ -398,7 +400,7 @@ class TestCompare(TestCase):
)
def test_dict_consistent_ordering_types_y_not_x(self):
- self.checkRaises(
+ self.check_raises(
{},
{None: 1, 3: 2},
"dict not as expected:\n"
@@ -409,7 +411,7 @@ class TestCompare(TestCase):
)
def test_dict_consistent_ordering_types_value(self):
- self.checkRaises(
+ self.check_raises(
{None: 1, 6: 2},
{None: 3, 6: 4},
"dict not as expected:\n"
@@ -423,7 +425,7 @@ class TestCompare(TestCase):
compare(set([1]), set([1]))
def test_set_first_missing_keys(self):
- self.checkRaises(
+ self.check_raises(
set(), set([3]),
"set not as expected:\n"
"\n"
@@ -433,7 +435,7 @@ class TestCompare(TestCase):
)
def test_set_second_missing_keys(self):
- self.checkRaises(
+ self.check_raises(
set([3]), set(),
"set not as expected:\n"
"\n"
@@ -443,7 +445,7 @@ class TestCompare(TestCase):
)
def test_set_full_diff(self):
- self.checkRaises(
+ self.check_raises(
set([1, 2, 4]), set([1, 3, 5]),
"set not as expected:\n"
"\n"
@@ -456,7 +458,7 @@ class TestCompare(TestCase):
)
def test_set_type_ordering(self):
- self.checkRaises(
+ self.check_raises(
{None, 1}, {'', 2},
"set not as expected:\n"
"\n"
@@ -469,7 +471,7 @@ class TestCompare(TestCase):
)
def test_set_labels(self):
- self.checkRaises(
+ self.check_raises(
set([1, 2, 4]), set([1, 3, 5]),
"set not as expected:\n"
"\n"
@@ -487,7 +489,7 @@ class TestCompare(TestCase):
compare((1, 2, 3), (1, 2, 3))
def test_tuple_different(self):
- self.checkRaises(
+ self.check_raises(
(1, 2, 3), (1, 2, 4),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -496,7 +498,7 @@ class TestCompare(TestCase):
)
def test_tuple_totally_different(self):
- self.checkRaises(
+ self.check_raises(
(1, ), (2, ),
"sequence not as expected:\n\n"
"same:\n()\n\n"
@@ -505,7 +507,7 @@ class TestCompare(TestCase):
)
def test_tuple_first_shorter(self):
- self.checkRaises(
+ self.check_raises(
(1, 2), (1, 2, 3),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -514,7 +516,7 @@ class TestCompare(TestCase):
)
def test_tuple_second_shorter(self):
- self.checkRaises(
+ self.check_raises(
(1, 2, 3), (1, 2),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -526,7 +528,7 @@ class TestCompare(TestCase):
compare(generator(1, 2, 3), generator(1, 2, 3))
def test_generator_different(self):
- self.checkRaises(
+ self.check_raises(
generator(1, 2, 3), generator(1, 2, 4),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -535,7 +537,7 @@ class TestCompare(TestCase):
)
def test_generator_totally_different(self):
- self.checkRaises(
+ self.check_raises(
generator(1, ), generator(2, ),
"sequence not as expected:\n\n"
"same:\n()\n\n"
@@ -544,7 +546,7 @@ class TestCompare(TestCase):
)
def test_generator_first_shorter(self):
- self.checkRaises(
+ self.check_raises(
generator(1, 2), generator(1, 2, 3),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -553,7 +555,7 @@ class TestCompare(TestCase):
)
def test_generator_second_shorted(self):
- self.checkRaises(
+ self.check_raises(
generator(1, 2, 3), generator(1, 2),
"sequence not as expected:\n\n"
"same:\n(1, 2)\n\n"
@@ -562,7 +564,7 @@ class TestCompare(TestCase):
)
def test_nested_generator_different(self):
- self.checkRaises(
+ self.check_raises(
generator(1, 2, generator(3), 4),
generator(1, 2, generator(3), 5),
"sequence not as expected:\n"
@@ -598,7 +600,7 @@ class TestCompare(TestCase):
"<generator object (generator )?at... "
"\(<(class|type) 'generator'>\) \(actual\)"
)
- self.checkRaises(
+ self.check_raises(
(1, 2, 3), generator(1, 2, 3),
regex=expected,
strict=True,
@@ -613,7 +615,7 @@ class TestCompare(TestCase):
compare(xrange(1, 4), xrange(1, 4))
def test_iterable_with_iterable_different(self):
- self.checkRaises(
+ self.check_raises(
xrange(1, 4), xrange(1, 3),
"sequence not as expected:\n"
"\n"
@@ -636,7 +638,7 @@ class TestCompare(TestCase):
"<generator object (generator )?at... "
"\(<(class|type) 'generator'>\)"
)
- self.checkRaises(
+ self.check_raises(
xrange(1, 4), generator(1, 2, 3),
regex=expected,
strict=True,
@@ -656,7 +658,7 @@ class TestCompare(TestCase):
expected = ("(1, 2, 3) (<class 'tuple'>) != "
"[1, 2, 3] (<class 'list'>)")
- self.checkRaises(
+ self.check_raises(
(1, 2, 3), [1, 2, 3],
expected,
strict=True
@@ -693,18 +695,18 @@ class TestCompare(TestCase):
class Y:
pass
- self.checkRaises(X, Y, expected)
+ self.check_raises(X, Y, expected)
def test_show_whitespace(self):
# does nothing! ;-)
- self.checkRaises(
+ self.check_raises(
' x \n\r', ' x \n \t',
"' x \\n\\r' != ' x \\n \\t'",
show_whitespace=True
)
def test_show_whitespace_long(self):
- self.checkRaises(
+ self.check_raises(
"\t \n '", '\r \n ',
'\n--- first\n'
'+++ second\n'
@@ -720,7 +722,7 @@ class TestCompare(TestCase):
compare('x', 'x', show_whitespace=True)
def test_show_whitespace_not_used_because_of_other_difference(self):
- self.checkRaises(
+ self.check_raises(
(1, 'a'),
(2, 'b'),
"sequence not as expected:\n"
@@ -737,7 +739,7 @@ class TestCompare(TestCase):
)
def test_include_trailing_whitespace(self):
- self.checkRaises(
+ self.check_raises(
' x \n', ' x \n',
"' x \\n' != ' x \\n'"
)
@@ -746,7 +748,7 @@ class TestCompare(TestCase):
compare(' x \t\n', ' x\t \n', trailing_whitespace=False)
def test_ignore_trailing_whitespace_non_string(self):
- self.checkRaises(
+ self.check_raises(
1, '',
"1 != ''",
trailing_whitespace=False
@@ -755,7 +757,7 @@ class TestCompare(TestCase):
def test_ignore_trailing_whitespace_but_respect_leading_whitespace(self):
# NB: careful: this strips off the last newline too
# DON'T use if you care about that!
- self.checkRaises(
+ self.check_raises(
'a\n b\n c\n',
'a\nb\nc\n',
"'a\\n b\\n c' != 'a\\nb\\nc'",
@@ -763,7 +765,7 @@ class TestCompare(TestCase):
)
def test_include_blank_lines(self):
- self.checkRaises(
+ self.check_raises(
'\n \n', '\n ',
"'\\n \\n' != '\\n '"
)
@@ -778,7 +780,7 @@ b
' a\nb', blanklines=False)
def test_ignore_blank_lines_non_string(self):
- self.checkRaises(
+ self.check_raises(
1, '',
"1 != ''",
blanklines=False
@@ -818,7 +820,7 @@ b
r.replace('testfixtures.comparison._registry', {
list: compare_sequence,
})
- self.checkRaises(
+ self.check_raises(
[1, MyObject('foo')], [1, MyObject('bar')],
"sequence not as expected:\n"
"\n"
@@ -839,7 +841,7 @@ b
m = Mock()
m.aCall()
# Mock().method_calls is a list subclass
- self.checkRaises(
+ self.check_raises(
[call.bCall()], m.method_calls,
"sequence not as expected:\n\n"
"same:\n[]\n\n"
@@ -856,7 +858,7 @@ b
compare_obj = Mock()
compare_obj.return_value = 'not equal'
- self.checkRaises(
+ self.check_raises(
object(), object(),
"not equal",
strict=True,
@@ -867,7 +869,7 @@ b
class MyList(list):
pass
# default comparer used!
- self.checkRaises(
+ self.check_raises(
MyList((1, 2, 3)), MyList((1, 2, 4)),
"sequence not as expected:\n"
"\n"
@@ -885,7 +887,7 @@ b
def test_list_subclass_strict(self):
m = Mock()
m.aCall()
- self.checkRaises(
+ self.check_raises(
[call.aCall()], m.method_calls,
("[call.aCall()] (<{0} 'list'>) != [call.aCall()] "
"({1})").format(class_type_name, call_list_repr),
@@ -895,7 +897,7 @@ b
def test_list_subclass_long_strict(self):
m = Mock()
m.call('X'*20)
- self.checkRaises(
+ self.check_raises(
[call.call('Y'*20)], m.method_calls,
("[call.call('YYYYYYYYYYYYYYYYYY... "
"(<{0} 'list'>) != "
@@ -905,11 +907,11 @@ b
)
def test_prefix(self):
- self.checkRaises(1, 2, 'wrong number of orders: 1 != 2',
- prefix='wrong number of orders')
+ self.check_raises(1, 2, 'wrong number of orders: 1 != 2',
+ prefix='wrong number of orders')
def test_prefix_multiline(self):
- self.checkRaises(
+ self.check_raises(
'x'*5+'\n'+'y'*5, 'x'*5+'\n'+'z'*5,
"file content: \n--- first\n+++ second\n"
"@@ -1,2 +1,2 @@\n xxxxx\n-yyyyy\n+zzzzz",
@@ -917,7 +919,7 @@ b
)
def test_suffix(self):
- self.checkRaises(
+ self.check_raises(
1, 2,
'1 != 2\n'
'additional context',
@@ -925,7 +927,7 @@ b
)
def test_labels_multiline(self):
- self.checkRaises(
+ self.check_raises(
'x'*5+'\n'+'y'*5, 'x'*5+'\n'+'z'*5,
"\n--- expected\n+++ actual\n"
"@@ -1,2 +1,2 @@\n xxxxx\n-yyyyy\n+zzzzz",
@@ -934,7 +936,7 @@ b
)
def test_generator_with_non_generator(self):
- self.checkRaises(
+ self.check_raises(
generator(1, 2, 3), None,
'<generator object generator at ...> != None',
)
@@ -949,7 +951,7 @@ b
compare(generator(1, 2, 3), bad_gen())
def test_nested_dict_tuple_values_different(self):
- self.checkRaises(
+ self.check_raises(
dict(x=(1, 2, 3)), dict(x=(1, 2, 4)),
"dict not as expected:\n"
"\n"
@@ -969,7 +971,7 @@ b
)
def test_nested_dict_different(self):
- self.checkRaises(
+ self.check_raises(
dict(x=dict(y=1)), dict(x=dict(y=2)),
"dict not as expected:\n"
"\n"
@@ -989,7 +991,7 @@ b
compare(dict(x=dict(x=1)), dict(x=dict(x=1)), ignore_eq=True)
def test_tuple_list_different(self):
- self.checkRaises(
+ self.check_raises(
(1, [2, 3, 5]), (1, [2, 4, 5]),
"sequence not as expected:\n"
"\n"
@@ -1015,7 +1017,7 @@ b
)
def test_tuple_long_strings_different(self):
- self.checkRaises(
+ self.check_raises(
(1, 2, "foo\nbar\nbaz\n", 4),
(1, 2, "foo\nbob\nbaz\n", 4),
"sequence not as expected:\n"
@@ -1043,7 +1045,7 @@ b
)
def test_dict_multiple_differences(self):
- self.checkRaises(
+ self.check_raises(
dict(x=(1, 2, 3), y=(4, 5, 6, )),
dict(x=(1, 2, 4), y=(4, 5, 7, )),
"dict not as expected:\n"
@@ -1081,7 +1083,7 @@ b
gen1 = generator(obj1, obj2)
gen2 = generator(obj1, )
# dict -> list -> tuple -> generator
- self.checkRaises(
+ self.check_raises(
dict(x=[1, ('a', 'b', gen1), 3], y=[3, 4]),
dict(x=[1, ('a', 'b', gen2), 3], y=[3, 4]), (
"dict not as expected:\n"
@@ -1134,7 +1136,7 @@ b
gen1 = generator(obj1, obj2)
gen2 = generator(obj1, )
# dict -> list -> tuple -> generator
- self.checkRaises(
+ self.check_raises(
dict(x=[1, ('a', 'b', gen1), 3], y=[3, 4]),
dict(x=[1, ('a', 'b', gen2), 3], y=[3, 4]), (
"dict not as expected:\n"
@@ -1188,7 +1190,7 @@ b
MyTuple = namedtuple('MyTuple', 'x y z')
type_repr = repr(MyTuple)
tuple_repr = repr(tuple)
- self.checkRaises(
+ self.check_raises(
[MyTuple(1, 2, 3)],
[(1, 2, 3)],
("sequence not as expected:\n"
@@ -1215,7 +1217,7 @@ b
else:
expected = "[1, 2] (<class 'list'>) != (1, 3) (<class 'tuple'>)"
- self.checkRaises(
+ self.check_raises(
(1, 2, [1, 2]), (1, 2, (1, 3)),
"sequence not as expected:\n"
"\n"
@@ -1238,7 +1240,7 @@ b
def test_namedtuple_same_type(self):
class_ = namedtuple('Foo', 'x y')
- self.checkRaises(
+ self.check_raises(
class_(1, 2), class_(1, 3),
"Foo not as expected:\n\n"
"same:\n"
@@ -1250,7 +1252,7 @@ b
def test_namedtuple_different_type(self):
class_a = namedtuple('Foo', 'x y')
class_b = namedtuple('Bar', 'x y z')
- self.checkRaises(
+ self.check_raises(
class_a(1, 2), class_b(1, 2, 3),
"Foo(x=1, y=2) (<class 'testfixtures.tests.test_compare.Foo'>) != "
"Bar(x=1, y=2, z=3) "
@@ -1258,27 +1260,27 @@ b
)
def test_dict_with_list(self):
- self.checkRaises(
+ self.check_raises(
{1: 'one', 2: 'two'}, [1, 2],
"{1: 'one', 2: 'two'} != [1, 2]"
)
def test_explicit_expected(self):
- self.checkRaises('x', expected='y',
- message="'y' (expected) != 'x' (actual)")
+ self.check_raises('x', expected='y',
+ message="'y' (expected) != 'x' (actual)")
def test_explicit_actual(self):
- self.checkRaises('x', actual='y',
- message="'x' (expected) != 'y' (actual)")
+ self.check_raises('x', actual='y',
+ message="'x' (expected) != 'y' (actual)")
def test_explicit_both(self):
- self.checkRaises(message="'x' (expected) != 'y' (actual)",
- expected='x', actual='y')
+ self.check_raises(message="'x' (expected) != 'y' (actual)",
+ expected='x', actual='y')
def test_explicit_and_labels(self):
- self.checkRaises(message="'x' (x_label) != 'y' (y_label)",
- expected='x', actual='y',
- x_label='x_label', y_label='y_label')
+ self.check_raises(message="'x' (x_label) != 'y' (y_label)",
+ expected='x', actual='y',
+ x_label='x_label', y_label='y_label')
def test_invalid_two_args_expected(self):
with ShouldRaise(TypeError(
@@ -1333,7 +1335,7 @@ b
if x.a != y.a:
return 'OrmObj: %s != %s' % (x.a, y.a)
- self.checkRaises(
+ self.check_raises(
message=(
"sequence not as expected:\n\n"
"same:\n(OrmObj: 1,)\n\n"
@@ -1363,7 +1365,7 @@ b
self.OrmObj(date(2016, 1, 1)))
def test_django_orm_is_horrible_part_3(self):
- self.checkRaises(
+ self.check_raises(
message=(
"OrmObj: 1 (expected) != OrmObj: 1 (actual)"
),
@@ -1373,7 +1375,7 @@ b
)
def test_django_orm_is_horrible_part_4(self):
- self.checkRaises(
+ self.check_raises(
message='[1] (expected) != 2 (actual)',
expected=[1],
actual=2,
diff --git a/testfixtures/tests/test_components.py b/testfixtures/tests/test_components.py
index 3bdf0b5..29c2bf2 100644
--- a/testfixtures/tests/test_components.py
+++ b/testfixtures/tests/test_components.py
@@ -1,15 +1,6 @@
-# Copyright (c) 2011-2013 Simplistix Ltd
-# See license.txt for license details.
-
-from nose.plugins.skip import SkipTest
-
-try:
- from testfixtures.components import TestComponents
-except ImportError: # pragma: no cover
- raise SkipTest('zope.component is not available')
-
from mock import Mock, call
from testfixtures import Replacer, compare
+from testfixtures.components import TestComponents
from unittest import TestCase
from warnings import catch_warnings
diff --git a/testfixtures/tests/test_django/__init__.py b/testfixtures/tests/test_django/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testfixtures/tests/test_django/__init__.py
diff --git a/testfixtures/tests/test_django/models.py b/testfixtures/tests/test_django/models.py
new file mode 100644
index 0000000..ff67456
--- /dev/null
+++ b/testfixtures/tests/test_django/models.py
@@ -0,0 +1,11 @@
+from django.db import models
+
+
+class OtherModel(models.Model):
+ pass
+
+
+class SampleModel(models.Model):
+ value = models.IntegerField()
+ not_editable = models.IntegerField(editable=False)
+ created = models.DateTimeField(auto_now_add=True)
diff --git a/testfixtures/tests/test_django/settings.py b/testfixtures/tests/test_django/settings.py
new file mode 100644
index 0000000..c36f430
--- /dev/null
+++ b/testfixtures/tests/test_django/settings.py
@@ -0,0 +1,4 @@
+SECRET_KEY = 'fake-key'
+INSTALLED_APPS = [
+ "testfixtures.tests.test_django",
+]
diff --git a/testfixtures/tests/test_django/tests.py b/testfixtures/tests/test_django/tests.py
new file mode 100644
index 0000000..0a7eacc
--- /dev/null
+++ b/testfixtures/tests/test_django/tests.py
@@ -0,0 +1,75 @@
+import django
+import os
+from unittest import TestCase
+
+from testfixtures.compat import PY3
+from ... import compare
+from ...django import compare as django_compare
+from ..test_compare import CompareHelper
+
+os.environ['DJANGO_SETTINGS_MODULE'] = 'testfixtures.tests.test_django.settings'
+django.setup()
+
+from .models import SampleModel
+
+
+class CompareTests(CompareHelper, TestCase):
+
+ def test_simple_same(self):
+ django_compare(SampleModel(id=1), SampleModel(id=1))
+
+ def test_simple_diff(self):
+ if PY3:
+ expected = "'id': 1 != 2"
+ else:
+ expected = "u'id': 1 != 2"
+
+ self.check_raises(
+ SampleModel(id=1), SampleModel(id=2),
+ compare=django_compare,
+ message=(
+ 'SampleModel not as expected:\n'
+ '\n'
+ 'same:\n'
+ "['value']\n"
+ '\n'
+ 'values differ:\n'+
+ expected
+ )
+ )
+
+ def test_simple_ignore_fields(self):
+ django_compare(SampleModel(id=1), SampleModel(id=1),
+ ignore_fields=['id'])
+
+ def test_ignored_because_speshul(self):
+ # see http://stackoverflow.com/questions/21925671/convert-django-model-object-to-dict-with-all-of-the-fields-intact
+ django_compare(SampleModel(not_editable=1), SampleModel(not_editable=2))
+
+ def test_normal_compare_id_same(self):
+ # other diffs ignored
+ compare(SampleModel(id=1, value=1), SampleModel(id=1, value=2))
+
+ def test_normal_compare_id_diff(self):
+ if PY3:
+ expected = (
+ "'id': 3 != 4\n"
+ "'value': 1 != 2"
+ )
+
+ else:
+ expected = (
+ "'value': 1 != 2\n"
+ "u'id': 3 != 4"
+ )
+
+ self.check_raises(
+ SampleModel(id=3, value=1), SampleModel(id=4, value=2),
+ compare=django_compare,
+ message=(
+ 'SampleModel not as expected:\n'
+ '\n'
+ 'values differ:\n'+
+ expected
+ )
+ )
diff --git a/testfixtures/tests/test_should_raise.py b/testfixtures/tests/test_should_raise.py
index 58ecdc5..4f860e9 100644
--- a/testfixtures/tests/test_should_raise.py
+++ b/testfixtures/tests/test_should_raise.py
@@ -5,6 +5,7 @@ from testfixtures import Comparison as C, ShouldRaise, should_raise
from unittest import TestCase
from .compat import py_33_plus
+from .compat import py_36_plus
class TestShouldRaise(TestCase):
@@ -191,7 +192,10 @@ class TestShouldRaise(TestCase):
message = "No module named 'textfixtures'"
else:
message = 'No module named textfixtures.foo.bar'
- with ShouldRaise(ImportError(message)):
+
+ exception = ModuleNotFoundError if py_36_plus else ImportError
+
+ with ShouldRaise(exception(message)):
import textfixtures.foo.bar
def test_import_errors_2(self):
diff --git a/testfixtures/tests/test_shouldwarn.py b/testfixtures/tests/test_shouldwarn.py
index 3586a09..1e9b49c 100644
--- a/testfixtures/tests/test_shouldwarn.py
+++ b/testfixtures/tests/test_shouldwarn.py
@@ -13,6 +13,8 @@ if PY3:
else:
warn_module = 'exceptions'
+from .compat import py_36_plus
+
class ShouldWarnTests(TestCase):
@@ -106,14 +108,19 @@ class ShouldWarnTests(TestCase):
'foo', DeprecationWarning, 'bar.py', 42, 'bar_module'
)
compare(len(recorded), expected=1)
- compare(C(warnings.WarningMessage,
- _category_name='DeprecationWarning',
- category=DeprecationWarning,
- file=None,
- filename='bar.py',
- line=None,
- lineno=42,
- message=C(DeprecationWarning('foo'))
- ), recorded[0])
-
+ expected_attrs = dict(
+ _category_name='DeprecationWarning',
+ category=DeprecationWarning,
+ file=None,
+ filename='bar.py',
+ line=None,
+ lineno=42,
+ message=C(DeprecationWarning('foo')),
+ )
+
+ if py_36_plus:
+ expected_attrs['source'] = None
+
+ compare(expected=C(warnings.WarningMessage, **expected_attrs),
+ actual=recorded[0])
diff --git a/testfixtures/version.txt b/testfixtures/version.txt
index e0d9923..453b50f 100644
--- a/testfixtures/version.txt
+++ b/testfixtures/version.txt
@@ -1 +1 @@
-4.13.5
+4.14.3