Hello community,
here is the log from the commit of package python-parameterized for
openSUSE:Factory checked in at 2020-06-05 20:00:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-parameterized (Old)
and /work/SRC/openSUSE:Factory/.python-parameterized.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-parameterized"
Fri Jun 5 20:00:19 2020 rev:7 rq:811024 version:0.7.4
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-parameterized/python-parameterized.changes
2019-12-11 12:11:00.036592066 +0100
+++
/work/SRC/openSUSE:Factory/.python-parameterized.new.3606/python-parameterized.changes
2020-06-05 20:00:28.731992702 +0200
@@ -1,0 +2,20 @@
+Tue Jun 2 14:26:24 UTC 2020 - [email protected]
+
+- version update to 0.7.4
+ * Add ``class_name_func`` option to ``@parameterized_class``
+ * Fix arguments being passed to skip_on_empty_helper (thanks @gaf3;
+ https://github.com/wolever/parameterized/issues/57)
+ * Fix tests on Python 3.8.2 (thanks @Ikke;
+ https://github.com/wolever/parameterized/pull/99)
+ * Fix some typos (thanks @LWprogramming, @jinnovation;
+ https://github.com/wolever/parameterized/pull/77,
+ https://github.com/wolever/parameterized/pull/80)
+ * Fix unicode handling in setup.py (thanks @sliwinski-milosz;
+ https://github.com/wolever/parameterized/pull/89)
+ * Fix Python 3.9 compat (thanks @vstinner;
+ https://github.com/wolever/parameterized/pull/94)
+ * Add `@parameterized_class` name function callback support (thanks
+ @duncwebb et al; https://github.com/wolever/parameterized/pull/74)
+- drop dependency on unittest2
+
+-------------------------------------------------------------------
Old:
----
parameterized-0.7.1.tar.gz
New:
----
parameterized-0.7.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-parameterized.spec ++++++
--- /var/tmp/diff_new_pack.XqZum8/_old 2020-06-05 20:00:30.795999472 +0200
+++ /var/tmp/diff_new_pack.XqZum8/_new 2020-06-05 20:00:30.799999485 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-parameterized
#
-# Copyright (c) 2019 SUSE LLC
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-parameterized
-Version: 0.7.1
+Version: 0.7.4
Release: 0
Summary: Parameterized testing
License: BSD-2-Clause
@@ -31,12 +31,10 @@
BuildRequires: %{python_module nose2}
BuildRequires: %{python_module nose}
BuildRequires: %{python_module setuptools}
-BuildRequires: %{python_module unittest2}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Suggests: python-nose
Suggests: python-nose2
-Suggests: python-unittest2
BuildArch: noarch
%python_subpackages
@@ -58,10 +56,8 @@
%check
export LANG=en_US.UTF8
-# gh#wolever/parameterized#84
%{python_expand nosetests-%$python_version}
%{python_expand nose2-%$python_version}
-%{python_expand unit2-%$python_version}
%python_exec -m unittest parameterized.test
%files %{python_files}
++++++ parameterized-0.7.1.tar.gz -> parameterized-0.7.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/.travis.yml
new/parameterized-0.7.4/.travis.yml
--- old/parameterized-0.7.1/.travis.yml 2019-11-19 22:04:40.000000000 +0100
+++ new/parameterized-0.7.4/.travis.yml 2020-04-12 23:07:48.000000000 +0200
@@ -1,71 +0,0 @@
-# !!! WARNING !!!
-# This file is automatically generated by ./rebuild-travis-yaml
-# !!! WARNING !!!
-language: python
-sudo: false
-matrix:
- include:
- - env: "TOXENV=py27-nose"
- python: "2.7"
- - env: "TOXENV=py27-nose2"
- python: "2.7"
- - env: "TOXENV=py27-pytest2"
- python: "2.7"
- - env: "TOXENV=py27-pytest3"
- python: "2.7"
- - env: "TOXENV=py27-unit"
- python: "2.7"
- - env: "TOXENV=py27-unit2"
- python: "2.7"
- - env: "TOXENV=py35-nose"
- python: "3.5"
- - env: "TOXENV=py35-nose2"
- python: "3.5"
- - env: "TOXENV=py35-pytest2"
- python: "3.5"
- - env: "TOXENV=py35-pytest3"
- python: "3.5"
- - env: "TOXENV=py35-unit"
- python: "3.5"
- - env: "TOXENV=py35-unit2"
- python: "3.5"
- - env: "TOXENV=py36-nose"
- python: "3.6"
- - env: "TOXENV=py36-nose2"
- python: "3.6"
- - env: "TOXENV=py36-pytest2"
- python: "3.6"
- - env: "TOXENV=py36-pytest3"
- python: "3.6"
- - env: "TOXENV=py36-unit"
- python: "3.6"
- - env: "TOXENV=py36-unit2"
- python: "3.6"
- - env: "TOXENV=pypy-nose"
- python: "pypy"
- - env: "TOXENV=pypy-nose2"
- python: "pypy"
- - env: "TOXENV=pypy-pytest2"
- python: "pypy"
- - env: "TOXENV=pypy-pytest3"
- python: "pypy"
- - env: "TOXENV=pypy-unit"
- python: "pypy"
- - env: "TOXENV=pypy-unit2"
- python: "pypy"
- - env: "TOXENV=py37-nose"
- python: "3.7"
- - env: "TOXENV=py37-nose2"
- python: "3.7"
- - env: "TOXENV=py37-pytest3"
- python: "3.7"
- - env: "TOXENV=py37-unit"
- python: "3.7"
- - env: "TOXENV=py37-unit2"
- python: "3.7"
-
-install: pip install tox
-script: tox
-# !!! WARNING !!!
-# This file is automatically generated by ./rebuild-travis-yaml
-# !!! WARNING !!!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/CHANGELOG.txt
new/parameterized-0.7.4/CHANGELOG.txt
--- old/parameterized-0.7.1/CHANGELOG.txt 2019-11-19 23:04:03.000000000
+0100
+++ new/parameterized-0.7.4/CHANGELOG.txt 2020-04-14 19:58:58.000000000
+0200
@@ -1,3 +1,23 @@
+0.7.4 (2020-04-14)
+ * Add ``class_name_func`` option to ``@parameterized_class``
+ * Fix arguments being passed to skip_on_empty_helper (thanks @gaf3;
+ https://github.com/wolever/parameterized/issues/57)
+ * Fix tests on Python 3.8.2 (thanks @Ikke;
+ https://github.com/wolever/parameterized/pull/99)
+
+0.7.3 (2020-04-12)
+ * Fix some typos (thanks @LWprogramming, @jinnovation;
+ https://github.com/wolever/parameterized/pull/77,
+ https://github.com/wolever/parameterized/pull/80)
+ * Fix unicode handling in setup.py (thanks @sliwinski-milosz;
+ https://github.com/wolever/parameterized/pull/89)
+ * Fix Python 3.9 compat (thanks @vstinner;
+ https://github.com/wolever/parameterized/pull/94)
+
+0.7.2 (2020-04-12)
+ * Add `@parameterized_class` name function callback support (thanks
+ @duncwebb et al; https://github.com/wolever/parameterized/pull/74)
+
0.7.1 (2019-11-19)
* Fix #73: calling `setUp` and `tearDown` in parameterized classes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/LICENSE.txt
new/parameterized-0.7.4/LICENSE.txt
--- old/parameterized-0.7.1/LICENSE.txt 2019-11-19 21:17:12.000000000 +0100
+++ new/parameterized-0.7.4/LICENSE.txt 2020-04-12 23:37:30.000000000 +0200
@@ -1,5 +1,3 @@
-tl;dr: all code code is licensed under simplified BSD.
-
Unless stated otherwise in the source files, all code is copyright 2010 David
Wolever <[email protected]>. All rights reserved.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/PKG-INFO
new/parameterized-0.7.4/PKG-INFO
--- old/parameterized-0.7.1/PKG-INFO 2019-11-19 23:04:22.000000000 +0100
+++ new/parameterized-0.7.4/PKG-INFO 2020-04-14 19:59:42.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
Name: parameterized
-Version: 0.7.1
+Version: 0.7.4
Summary: Parameterized testing with any Python test framework
Home-page: https://github.com/wolever/parameterized
Author: David Wolever
@@ -9,15 +9,14 @@
Description: Parameterized testing with any Python test framework
====================================================
- |pypi| |travis|
-
- .. |pypi| image:: https://img.shields.io/pypi/v/parameterized.svg
+ .. image:: https://img.shields.io/pypi/v/parameterized.svg
:alt: PyPI
:target: https://pypi.org/project/parameterized/
- .. |travis| image::
https://travis-ci.org/wolever/parameterized.svg?branch=master
- :alt: Travis CI
- :target: https://travis-ci.org/wolever/parameterized
+ .. image:: https://circleci.com/gh/wolever/parameterized.svg?style=svg
+ :alt: Circle CI
+ :target: https://circleci.com/gh/wolever/parameterized
+
Parameterized testing in Python sucks.
@@ -197,6 +196,8 @@
- Py3.5
- Py3.6
- Py3.7
+ - Py3.8
+ - Py3.9
- PyPy
- ``@mock.patch``
* - nose
@@ -208,6 +209,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - nose2
- yes
- yes
@@ -217,6 +220,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 2
- yes
- yes
@@ -226,6 +231,8 @@
- no*
- yes
- yes
+ - yes
+ - yes
* - py.test 3
- yes
- yes
@@ -235,6 +242,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 4
- no**
- no**
@@ -244,6 +253,8 @@
- no**
- no**
- no**
+ - no**
+ - no**
* - py.test fixtures
- no†
- no†
@@ -253,6 +264,8 @@
- no†
- no†
- no†
+ - no†
+ - no†
* - | unittest
| (``@parameterized.expand``)
- yes
@@ -263,6 +276,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - | unittest2
| (``@parameterized.expand``)
- yes
@@ -273,6 +288,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
\*: py.test 2 does `does not appear to work (#71)`__ under Python 3.
Please comment on the related issues if you are affected.
@@ -397,7 +414,7 @@
``test_add_0_2_and_3`` and ``test_add_1_3_and_5``.
The names of the test cases generated by ``@parameterized.expand`` can
be
- customized using the ``testcase_func_name`` keyword argument. The
value should
+ customized using the ``name_func`` keyword argument. The value should
be a function which accepts three arguments: ``testcase_func``,
``param_num``,
and ``params``, and it should return the name of the test case.
``testcase_func`` will be the function to be tested, ``param_num``
will be the
@@ -419,7 +436,7 @@
@parameterized.expand([
(2, 3, 5),
(2, 3, 5),
- ], testcase_func_name=custom_name_func)
+ ], name_func=custom_name_func)
def test_add(self, a, b, expected):
assert_equal(a + b, expected)
@@ -495,41 +512,77 @@
.. code:: python
- from yourapp.models import User
- from parameterized import parameterized_class
+ from yourapp.models import User
+ from parameterized import parameterized_class
- @parameterized_class(("username", "access_level",
"expected_status_code"), [
- ("user_1", 1, 200),
- ("user_2", 2, 404)
- ])
- class TestUserAccessLevel(TestCase):
- def setUp(self):
-
self.client.force_login(User.objects.get(username=self.username)[0])
-
- def test_url_a(self):
- response = self.client.get("/url")
- self.assertEqual(response.status_code,
self.expected_status_code)
+ @parameterized_class([
+ { "username": "user_1", "access_level": 1 },
+ { "username": "user_2", "access_level": 2,
"expected_status_code": 404 },
+ ])
+ class TestUserAccessLevel(TestCase):
+ expected_status_code = 200
- def tearDown(self):
- self.client.logout()
+ def setUp(self):
+
self.client.force_login(User.objects.get(username=self.username)[0])
+ def test_url_a(self):
+ response = self.client.get('/url')
+ self.assertEqual(response.status_code,
self.expected_status_code)
- @parameterized_class([
- { "username": "user_1", "access_level": 1 },
- { "username": "user_2", "access_level": 2,
"expected_status_code": 404 },
- ])
- class TestUserAccessLevel(TestCase):
- expected_status_code = 200
+ def tearDown(self):
+ self.client.logout()
+
+
+ @parameterized_class(("username", "access_level",
"expected_status_code"), [
+ ("user_1", 1, 200),
+ ("user_2", 2, 404)
+ ])
+ class TestUserAccessLevel(TestCase):
+ def setUp(self):
+
self.client.force_login(User.objects.get(username=self.username)[0])
+
+ def test_url_a(self):
+ response = self.client.get("/url")
+ self.assertEqual(response.status_code,
self.expected_status_code)
+
+ def tearDown(self):
+ self.client.logout()
+
+
+ The ``@parameterized_class`` decorator accepts a ``class_name_func``
argument,
+ which controls the name of the parameterized classes generated by
+ ``@parameterized_class``:
- def setUp(self):
-
self.client.force_login(User.objects.get(username=self.username)[0])
+ .. code:: python
+
+ from parameterized import parameterized, parameterized_class
+
+ def get_class_name(cls, num, params_dict):
+ # By default the generated class named includes either the
"name"
+ # parameter (if present), or the first string value. This
example shows
+ # multiple parameters being included in the generated class
name:
+ return "%s_%s_%s%s" %(
+ cls.__name__,
+ num,
+ parameterized.to_safe_name(params_dict['a']),
+ parameterized.to_safe_name(params_dict['b']),
+ )
+
+ @parameterized_class([
+ { "a": "hello", "b": " world!", "expected": "hello world!" },
+ { "a": "say ", "b": " cheese :)", "expected": "say cheese :)" },
+ ], class_name_func=get_class_name)
+ class TestConcatenation(TestCase):
+ def test_concat(self):
+ self.assertEqual(self.a + self.b, self.expected)
+
+ ::
+
+ $ nosetests -v test_math.py
+ test_concat (test_concat.TestConcatenation_0_hello_world_) ... ok
+ test_concat (test_concat.TestConcatenation_0_say_cheese__) ... ok
- def test_url_a(self):
- response = self.client.get('/url')
- self.assertEqual(response.status_code,
self.expected_status_code)
- def tearDown(self):
- self.client.logout()
Using with Single Parameters
............................
@@ -624,3 +677,4 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: BSD License
+Provides-Extra: dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/README.rst
new/parameterized-0.7.4/README.rst
--- old/parameterized-0.7.1/README.rst 2019-11-19 23:04:05.000000000 +0100
+++ new/parameterized-0.7.4/README.rst 2020-04-14 19:27:29.000000000 +0200
@@ -1,15 +1,14 @@
Parameterized testing with any Python test framework
====================================================
-|pypi| |travis|
-
-.. |pypi| image:: https://img.shields.io/pypi/v/parameterized.svg
+.. image:: https://img.shields.io/pypi/v/parameterized.svg
:alt: PyPI
:target: https://pypi.org/project/parameterized/
-.. |travis| image::
https://travis-ci.org/wolever/parameterized.svg?branch=master
- :alt: Travis CI
- :target: https://travis-ci.org/wolever/parameterized
+.. image:: https://circleci.com/gh/wolever/parameterized.svg?style=svg
+ :alt: Circle CI
+ :target: https://circleci.com/gh/wolever/parameterized
+
Parameterized testing in Python sucks.
@@ -189,6 +188,8 @@
- Py3.5
- Py3.6
- Py3.7
+ - Py3.8
+ - Py3.9
- PyPy
- ``@mock.patch``
* - nose
@@ -200,6 +201,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - nose2
- yes
- yes
@@ -209,6 +212,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 2
- yes
- yes
@@ -218,6 +223,8 @@
- no*
- yes
- yes
+ - yes
+ - yes
* - py.test 3
- yes
- yes
@@ -227,6 +234,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 4
- no**
- no**
@@ -236,6 +245,8 @@
- no**
- no**
- no**
+ - no**
+ - no**
* - py.test fixtures
- no†
- no†
@@ -245,6 +256,8 @@
- no†
- no†
- no†
+ - no†
+ - no†
* - | unittest
| (``@parameterized.expand``)
- yes
@@ -255,6 +268,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - | unittest2
| (``@parameterized.expand``)
- yes
@@ -265,6 +280,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
\*: py.test 2 does `does not appear to work (#71)`__ under Python 3. Please
comment on the related issues if you are affected.
@@ -389,7 +406,7 @@
``test_add_0_2_and_3`` and ``test_add_1_3_and_5``.
The names of the test cases generated by ``@parameterized.expand`` can be
-customized using the ``testcase_func_name`` keyword argument. The value should
+customized using the ``name_func`` keyword argument. The value should
be a function which accepts three arguments: ``testcase_func``, ``param_num``,
and ``params``, and it should return the name of the test case.
``testcase_func`` will be the function to be tested, ``param_num`` will be the
@@ -411,7 +428,7 @@
@parameterized.expand([
(2, 3, 5),
(2, 3, 5),
- ], testcase_func_name=custom_name_func)
+ ], name_func=custom_name_func)
def test_add(self, a, b, expected):
assert_equal(a + b, expected)
@@ -487,41 +504,77 @@
.. code:: python
- from yourapp.models import User
- from parameterized import parameterized_class
+ from yourapp.models import User
+ from parameterized import parameterized_class
- @parameterized_class(("username", "access_level", "expected_status_code"), [
- ("user_1", 1, 200),
- ("user_2", 2, 404)
- ])
- class TestUserAccessLevel(TestCase):
- def setUp(self):
- self.client.force_login(User.objects.get(username=self.username)[0])
-
- def test_url_a(self):
- response = self.client.get("/url")
- self.assertEqual(response.status_code, self.expected_status_code)
+ @parameterized_class([
+ { "username": "user_1", "access_level": 1 },
+ { "username": "user_2", "access_level": 2, "expected_status_code": 404
},
+ ])
+ class TestUserAccessLevel(TestCase):
+ expected_status_code = 200
- def tearDown(self):
- self.client.logout()
+ def setUp(self):
+ self.client.force_login(User.objects.get(username=self.username)[0])
+ def test_url_a(self):
+ response = self.client.get('/url')
+ self.assertEqual(response.status_code, self.expected_status_code)
- @parameterized_class([
- { "username": "user_1", "access_level": 1 },
- { "username": "user_2", "access_level": 2, "expected_status_code": 404 },
- ])
- class TestUserAccessLevel(TestCase):
- expected_status_code = 200
+ def tearDown(self):
+ self.client.logout()
+
+
+ @parameterized_class(("username", "access_level", "expected_status_code"),
[
+ ("user_1", 1, 200),
+ ("user_2", 2, 404)
+ ])
+ class TestUserAccessLevel(TestCase):
+ def setUp(self):
+ self.client.force_login(User.objects.get(username=self.username)[0])
+
+ def test_url_a(self):
+ response = self.client.get("/url")
+ self.assertEqual(response.status_code, self.expected_status_code)
+
+ def tearDown(self):
+ self.client.logout()
+
+
+The ``@parameterized_class`` decorator accepts a ``class_name_func`` argument,
+which controls the name of the parameterized classes generated by
+``@parameterized_class``:
- def setUp(self):
- self.client.force_login(User.objects.get(username=self.username)[0])
+.. code:: python
+
+ from parameterized import parameterized, parameterized_class
+
+ def get_class_name(cls, num, params_dict):
+ # By default the generated class named includes either the "name"
+ # parameter (if present), or the first string value. This example shows
+ # multiple parameters being included in the generated class name:
+ return "%s_%s_%s%s" %(
+ cls.__name__,
+ num,
+ parameterized.to_safe_name(params_dict['a']),
+ parameterized.to_safe_name(params_dict['b']),
+ )
+
+ @parameterized_class([
+ { "a": "hello", "b": " world!", "expected": "hello world!" },
+ { "a": "say ", "b": " cheese :)", "expected": "say cheese :)" },
+ ], class_name_func=get_class_name)
+ class TestConcatenation(TestCase):
+ def test_concat(self):
+ self.assertEqual(self.a + self.b, self.expected)
+
+::
+
+ $ nosetests -v test_math.py
+ test_concat (test_concat.TestConcatenation_0_hello_world_) ... ok
+ test_concat (test_concat.TestConcatenation_0_say_cheese__) ... ok
- def test_url_a(self):
- response = self.client.get('/url')
- self.assertEqual(response.status_code, self.expected_status_code)
- def tearDown(self):
- self.client.logout()
Using with Single Parameters
............................
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/parameterized/parameterized.py
new/parameterized-0.7.4/parameterized/parameterized.py
--- old/parameterized-0.7.1/parameterized/parameterized.py 2019-11-19
23:04:03.000000000 +0100
+++ new/parameterized-0.7.4/parameterized/parameterized.py 2020-04-14
19:33:58.000000000 +0200
@@ -44,7 +44,10 @@
def make_method(func, instance, type):
return MethodType(func, instance, type)
+
CompatArgSpec = namedtuple("CompatArgSpec", "args varargs keywords defaults")
+
+
def getargspec(func):
if PY2:
return CompatArgSpec(*inspect.getargspec(func))
@@ -58,11 +61,11 @@
) %(func, ))
return CompatArgSpec(*args[:4])
-_param = namedtuple("param", "args kwargs")
def skip_on_empty_helper(*a, **kw):
raise SkipTest("parameterized input is empty")
+
def reapply_patches_if_need(func):
def dummy_wrapper(orgfunc):
@@ -79,11 +82,14 @@
func = patch_obj.decorate_callable(func)
return func
+
def delete_patches_if_need(func):
if hasattr(func, 'patchings'):
func.patchings[:] = []
+_param = namedtuple("param", "args kwargs")
+
class param(_param):
""" Represents a single parameter to a test case.
@@ -217,6 +223,7 @@
return result
+
def short_repr(x, n=64):
""" A shortened repr of ``x`` which is guaranteed to be ``unicode``::
@@ -236,6 +243,7 @@
x_repr = x_repr[:n//2] + "..." + x_repr[len(x_repr) - n//2:]
return x_repr
+
def default_doc_func(func, num, p):
if func.__doc__ is None:
return None
@@ -256,9 +264,11 @@
args = "%s[with %s]" %(len(first) and " " or "", ", ".join(descs))
return "".join([first.rstrip(), args, suffix, nl, rest])
+
def default_name_func(func, num, p):
base_name = func.__name__
name_suffix = "_%s" %(num, )
+
if len(p.args) > 0 and isinstance(p.args[0], string_types):
name_suffix += "_" + parameterized.to_safe_name(p.args[0])
return base_name + name_suffix
@@ -271,6 +281,7 @@
"_pytest": "pytest",
}
+
def set_test_runner(name):
global _test_runner_override
if name not in _test_runners:
@@ -280,6 +291,7 @@
)
_test_runner_override = name
+
def detect_runner():
""" Guess which test runner we're using by traversing the stack and looking
for the first matching module. This *should* be reasonably safe, as
@@ -375,7 +387,7 @@
"`parameterized([], skip_on_empty=True)` to skip "
"this test when the input is empty)"
)
- wrapper = wraps(test_func)(lambda: skip_on_empty_helper())
+ wrapper = wraps(test_func)(skip_on_empty_helper)
wrapper.parameterized_input = input
wrapper.parameterized_func = test_func
@@ -482,9 +494,9 @@
frame = stack[1]
frame_locals = frame[0].f_locals
- paramters = cls.input_as_callable(input)()
+ parameters = cls.input_as_callable(input)()
- if not paramters:
+ if not parameters:
if not skip_on_empty:
raise ValueError(
"Parameters iterable is empty (hint: use "
@@ -493,8 +505,8 @@
)
return wraps(f)(lambda: skip_on_empty_helper())
- digits = len(str(len(paramters) - 1))
- for num, p in enumerate(paramters):
+ digits = len(str(len(parameters) - 1))
+ for num, p in enumerate(parameters):
name = name_func(f, "{num:0>{digits}}".format(digits=digits,
num=num), p)
# If the original function has patches applied by 'mock.patch',
# re-construct all patches on the just former decoration layer
@@ -536,7 +548,7 @@
return str(re.sub("[^a-zA-Z0-9_]+", "_", s))
-def parameterized_class(attrs, input_values=None):
+def parameterized_class(attrs, input_values=None, class_name_func=None,
classname_func=None):
""" Parameterizes a test class by setting attributes on the class.
Can be used in two ways:
@@ -569,25 +581,24 @@
[dict(zip(attrs, vals)) for vals in input_values]
)
+ class_name_func = class_name_func or default_class_name_func
+
+ if classname_func:
+ warnings.warn(
+ "classname_func= is deprecated; use class_name_func= instead. "
+ "See:
https://github.com/wolever/parameterized/pull/74#issuecomment-613577057",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ class_name_func = lambda cls, idx, input: classname_func(cls, idx,
input_dicts)
+
def decorator(base_class):
test_class_module = sys.modules[base_class.__module__].__dict__
for idx, input_dict in enumerate(input_dicts):
test_class_dict = dict(base_class.__dict__)
test_class_dict.update(input_dict)
- name_suffix = input_values and input_values[idx]
- if isinstance(name_suffix, (list, tuple)) and len(input_values) >
0:
- name_suffix = name_suffix[0]
- name_suffix = (
- "_%s" %(name_suffix, ) if isinstance(name_suffix,
string_types) else
- ""
- )
-
- name = "%s_%s%s" %(
- base_class.__name__,
- idx,
- name_suffix,
- )
+ name = class_name_func(base_class, idx, input_dict)
test_class_module[name] = type(name, (base_class, ),
test_class_dict)
@@ -603,3 +614,26 @@
return base_class
return decorator
+
+
+def get_class_name_suffix(params_dict):
+ if "name" in params_dict:
+ return parameterized.to_safe_name(params_dict["name"])
+
+ params_vals = (
+ params_dict.values() if PY3 else
+ (v for (_, v) in sorted(params_dict.items()))
+ )
+ return parameterized.to_safe_name(next((
+ v for v in params_vals
+ if isinstance(v, string_types)
+ ), ""))
+
+
+def default_class_name_func(cls, num, params_dict):
+ suffix = get_class_name_suffix(params_dict)
+ return "%s_%s%s" %(
+ cls.__name__,
+ num,
+ suffix and "_" + suffix,
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/parameterized/test.py
new/parameterized-0.7.4/parameterized/test.py
--- old/parameterized-0.7.1/parameterized/test.py 2019-11-19
23:04:03.000000000 +0100
+++ new/parameterized-0.7.4/parameterized/test.py 2020-04-14
19:26:48.000000000 +0200
@@ -249,7 +249,10 @@
f_locals = stack[3][0].f_locals
test_method = (
f_locals.get("testMethod") or # Py27
- f_locals.get("function") # Py33
+ f_locals.get("function") or # Py33
+ f_locals.get("method") or # Py38
+ f_locals.get("testfunction") or # Py382
+ None
)
if test_method is None:
raise AssertionError("uh oh, unittest changed a local variable
name")
@@ -444,17 +447,14 @@
@parameterized_class(("a", "b", "c"), [
("foo", 1, 2),
- ("bar", 3, 0),
(0, 1, 2),
])
class TestParameterizedClass(TestCase):
expect([
"TestParameterizedClass_0_foo:test_method_a('foo', 1, 2)",
"TestParameterizedClass_0_foo:test_method_b('foo', 1, 2)",
- "TestParameterizedClass_1_bar:test_method_a('bar', 3, 0)",
- "TestParameterizedClass_1_bar:test_method_b('bar', 3, 0)",
- "TestParameterizedClass_2:test_method_a(0, 1, 2)",
- "TestParameterizedClass_2:test_method_b(0, 1, 2)",
+ "TestParameterizedClass_1:test_method_a(0, 1, 2)",
+ "TestParameterizedClass_1:test_method_b(0, 1, 2)",
])
def _assertions(self, test_name):
@@ -475,22 +475,43 @@
self._assertions("test_method_b")
+@parameterized_class(("a", ), [
+ (1, ),
+ (2, ),
+], class_name_func=lambda cls, idx, attrs: "%s_custom_func_%s" %(cls.__name__,
attrs["a"]))
+class TestNamedParameterizedClass(TestCase):
+ expect([
+ "TestNamedParameterizedClass_custom_func_1:test_method(1)",
+ "TestNamedParameterizedClass_custom_func_2:test_method(2)",
+ ])
+
+ def test_method(self):
+ missing_tests.remove("%s:test_method(%r)" %(
+ self.__class__.__name__,
+ self.a,
+ ))
+
+
@parameterized_class([
- {"foo": 1},
- {"bar": 1},
+ {"foo": 42},
+ {"bar": "some stuff"},
+ {"bar": "other stuff", "name": "some name", "foo": 12},
])
class TestParameterizedClassDict(TestCase):
expect([
- "TestParameterizedClassDict_0:setUp(1, 0)",
- "TestParameterizedClassDict_0:tearDown(1, 0)",
- "TestParameterizedClassDict_0:test_method(1, 0)",
- "TestParameterizedClassDict_1:test_method(0, 1)",
- "TestParameterizedClassDict_1:setUp(0, 1)",
- "TestParameterizedClassDict_1:tearDown(0, 1)",
+ "TestParameterizedClassDict_0:setUp(42, 'empty')",
+ "TestParameterizedClassDict_0:test_method(42, 'empty')",
+ "TestParameterizedClassDict_0:tearDown(42, 'empty')",
+ "TestParameterizedClassDict_1_some_stuff:setUp(0, 'some stuff')",
+ "TestParameterizedClassDict_1_some_stuff:test_method(0, 'some stuff')",
+ "TestParameterizedClassDict_1_some_stuff:tearDown(0, 'some stuff')",
+ "TestParameterizedClassDict_2_some_name:setUp(12, 'other stuff')",
+ "TestParameterizedClassDict_2_some_name:test_method(12, 'other
stuff')",
+ "TestParameterizedClassDict_2_some_name:tearDown(12, 'other stuff')",
])
foo = 0
- bar = 0
+ bar = 'empty'
def setUp(self):
# Ensure that super() works (issue #73)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/parameterized.egg-info/PKG-INFO
new/parameterized-0.7.4/parameterized.egg-info/PKG-INFO
--- old/parameterized-0.7.1/parameterized.egg-info/PKG-INFO 2019-11-19
23:04:22.000000000 +0100
+++ new/parameterized-0.7.4/parameterized.egg-info/PKG-INFO 2020-04-14
19:59:42.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
Name: parameterized
-Version: 0.7.1
+Version: 0.7.4
Summary: Parameterized testing with any Python test framework
Home-page: https://github.com/wolever/parameterized
Author: David Wolever
@@ -9,15 +9,14 @@
Description: Parameterized testing with any Python test framework
====================================================
- |pypi| |travis|
-
- .. |pypi| image:: https://img.shields.io/pypi/v/parameterized.svg
+ .. image:: https://img.shields.io/pypi/v/parameterized.svg
:alt: PyPI
:target: https://pypi.org/project/parameterized/
- .. |travis| image::
https://travis-ci.org/wolever/parameterized.svg?branch=master
- :alt: Travis CI
- :target: https://travis-ci.org/wolever/parameterized
+ .. image:: https://circleci.com/gh/wolever/parameterized.svg?style=svg
+ :alt: Circle CI
+ :target: https://circleci.com/gh/wolever/parameterized
+
Parameterized testing in Python sucks.
@@ -197,6 +196,8 @@
- Py3.5
- Py3.6
- Py3.7
+ - Py3.8
+ - Py3.9
- PyPy
- ``@mock.patch``
* - nose
@@ -208,6 +209,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - nose2
- yes
- yes
@@ -217,6 +220,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 2
- yes
- yes
@@ -226,6 +231,8 @@
- no*
- yes
- yes
+ - yes
+ - yes
* - py.test 3
- yes
- yes
@@ -235,6 +242,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - py.test 4
- no**
- no**
@@ -244,6 +253,8 @@
- no**
- no**
- no**
+ - no**
+ - no**
* - py.test fixtures
- no†
- no†
@@ -253,6 +264,8 @@
- no†
- no†
- no†
+ - no†
+ - no†
* - | unittest
| (``@parameterized.expand``)
- yes
@@ -263,6 +276,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
* - | unittest2
| (``@parameterized.expand``)
- yes
@@ -273,6 +288,8 @@
- yes
- yes
- yes
+ - yes
+ - yes
\*: py.test 2 does `does not appear to work (#71)`__ under Python 3.
Please comment on the related issues if you are affected.
@@ -397,7 +414,7 @@
``test_add_0_2_and_3`` and ``test_add_1_3_and_5``.
The names of the test cases generated by ``@parameterized.expand`` can
be
- customized using the ``testcase_func_name`` keyword argument. The
value should
+ customized using the ``name_func`` keyword argument. The value should
be a function which accepts three arguments: ``testcase_func``,
``param_num``,
and ``params``, and it should return the name of the test case.
``testcase_func`` will be the function to be tested, ``param_num``
will be the
@@ -419,7 +436,7 @@
@parameterized.expand([
(2, 3, 5),
(2, 3, 5),
- ], testcase_func_name=custom_name_func)
+ ], name_func=custom_name_func)
def test_add(self, a, b, expected):
assert_equal(a + b, expected)
@@ -495,41 +512,77 @@
.. code:: python
- from yourapp.models import User
- from parameterized import parameterized_class
+ from yourapp.models import User
+ from parameterized import parameterized_class
- @parameterized_class(("username", "access_level",
"expected_status_code"), [
- ("user_1", 1, 200),
- ("user_2", 2, 404)
- ])
- class TestUserAccessLevel(TestCase):
- def setUp(self):
-
self.client.force_login(User.objects.get(username=self.username)[0])
-
- def test_url_a(self):
- response = self.client.get("/url")
- self.assertEqual(response.status_code,
self.expected_status_code)
+ @parameterized_class([
+ { "username": "user_1", "access_level": 1 },
+ { "username": "user_2", "access_level": 2,
"expected_status_code": 404 },
+ ])
+ class TestUserAccessLevel(TestCase):
+ expected_status_code = 200
- def tearDown(self):
- self.client.logout()
+ def setUp(self):
+
self.client.force_login(User.objects.get(username=self.username)[0])
+ def test_url_a(self):
+ response = self.client.get('/url')
+ self.assertEqual(response.status_code,
self.expected_status_code)
- @parameterized_class([
- { "username": "user_1", "access_level": 1 },
- { "username": "user_2", "access_level": 2,
"expected_status_code": 404 },
- ])
- class TestUserAccessLevel(TestCase):
- expected_status_code = 200
+ def tearDown(self):
+ self.client.logout()
+
+
+ @parameterized_class(("username", "access_level",
"expected_status_code"), [
+ ("user_1", 1, 200),
+ ("user_2", 2, 404)
+ ])
+ class TestUserAccessLevel(TestCase):
+ def setUp(self):
+
self.client.force_login(User.objects.get(username=self.username)[0])
+
+ def test_url_a(self):
+ response = self.client.get("/url")
+ self.assertEqual(response.status_code,
self.expected_status_code)
+
+ def tearDown(self):
+ self.client.logout()
+
+
+ The ``@parameterized_class`` decorator accepts a ``class_name_func``
argument,
+ which controls the name of the parameterized classes generated by
+ ``@parameterized_class``:
- def setUp(self):
-
self.client.force_login(User.objects.get(username=self.username)[0])
+ .. code:: python
+
+ from parameterized import parameterized, parameterized_class
+
+ def get_class_name(cls, num, params_dict):
+ # By default the generated class named includes either the
"name"
+ # parameter (if present), or the first string value. This
example shows
+ # multiple parameters being included in the generated class
name:
+ return "%s_%s_%s%s" %(
+ cls.__name__,
+ num,
+ parameterized.to_safe_name(params_dict['a']),
+ parameterized.to_safe_name(params_dict['b']),
+ )
+
+ @parameterized_class([
+ { "a": "hello", "b": " world!", "expected": "hello world!" },
+ { "a": "say ", "b": " cheese :)", "expected": "say cheese :)" },
+ ], class_name_func=get_class_name)
+ class TestConcatenation(TestCase):
+ def test_concat(self):
+ self.assertEqual(self.a + self.b, self.expected)
+
+ ::
+
+ $ nosetests -v test_math.py
+ test_concat (test_concat.TestConcatenation_0_hello_world_) ... ok
+ test_concat (test_concat.TestConcatenation_0_say_cheese__) ... ok
- def test_url_a(self):
- response = self.client.get('/url')
- self.assertEqual(response.status_code,
self.expected_status_code)
- def tearDown(self):
- self.client.logout()
Using with Single Parameters
............................
@@ -624,3 +677,4 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: BSD License
+Provides-Extra: dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/parameterized-0.7.1/parameterized.egg-info/SOURCES.txt
new/parameterized-0.7.4/parameterized.egg-info/SOURCES.txt
--- old/parameterized-0.7.1/parameterized.egg-info/SOURCES.txt 2019-11-19
23:04:22.000000000 +0100
+++ new/parameterized-0.7.4/parameterized.egg-info/SOURCES.txt 2020-04-14
19:59:42.000000000 +0200
@@ -16,4 +16,5 @@
parameterized.egg-info/SOURCES.txt
parameterized.egg-info/dependency_links.txt
parameterized.egg-info/pbr.json
+parameterized.egg-info/requires.txt
parameterized.egg-info/top_level.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/parameterized.egg-info/pbr.json
new/parameterized-0.7.4/parameterized.egg-info/pbr.json
--- old/parameterized-0.7.1/parameterized.egg-info/pbr.json 2019-11-19
23:04:22.000000000 +0100
+++ new/parameterized-0.7.4/parameterized.egg-info/pbr.json 2020-04-14
19:59:42.000000000 +0200
@@ -1 +1 @@
-{"is_release": false, "git_version": "4d73fbe"}
\ No newline at end of file
+{"is_release": false, "git_version": "ff5a1da"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/parameterized-0.7.1/parameterized.egg-info/requires.txt
new/parameterized-0.7.4/parameterized.egg-info/requires.txt
--- old/parameterized-0.7.1/parameterized.egg-info/requires.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/parameterized-0.7.4/parameterized.egg-info/requires.txt 2020-04-14
19:59:42.000000000 +0200
@@ -0,0 +1,3 @@
+
+[dev]
+jinja2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/setup.py
new/parameterized-0.7.4/setup.py
--- old/parameterized-0.7.1/setup.py 2019-11-19 23:04:03.000000000 +0100
+++ new/parameterized-0.7.4/setup.py 2020-04-14 19:59:14.000000000 +0200
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+import io
import os
import sys
@@ -8,13 +9,13 @@
os.chdir(os.path.dirname(sys.argv[0]) or ".")
try:
- long_description = open("README.rst", "U").read()
+ long_description = io.open("README.rst", encoding="utf-8").read()
except IOError:
long_description = "See https://github.com/wolever/parameterized"
setup(
name="parameterized",
- version="0.7.1",
+ version="0.7.4",
url="https://github.com/wolever/parameterized",
license="FreeBSD",
author="David Wolever",
@@ -26,5 +27,10 @@
'License :: OSI Approved :: BSD License',
],
packages=find_packages(),
+ extras_require={
+ 'dev': [
+ 'jinja2',
+ ]
+ },
long_description=long_description,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/parameterized-0.7.1/tox.ini
new/parameterized-0.7.4/tox.ini
--- old/parameterized-0.7.1/tox.ini 2019-11-19 21:26:37.000000000 +0100
+++ new/parameterized-0.7.4/tox.ini 2020-04-12 23:07:48.000000000 +0200
@@ -1,5 +1,5 @@
[tox]
-envlist=py{27,35,36,py}-{nose,nose2,pytest2,pytest3,unit,unit2},py37-{nose,nose2,pytest3,unit,unit2}
+envlist=py{27,35,36,py}-{nose,nose2,pytest2,pytest3,unit,unit2},py{37,38,39}-{nose,nose2,pytest3,unit,unit2}
[testenv]
deps=
nose