Parameterized testing with any Python test framework

Overview

Parameterized testing with any Python test framework

PyPI PyPI - Downloads Circle CI

Parameterized testing in Python sucks.

parameterized fixes that. For everything. Parameterized testing for nose, parameterized testing for py.test, parameterized testing for unittest.

# test_math.py
from nose.tools import assert_equal
from parameterized import parameterized, parameterized_class

import unittest
import math

@parameterized([
    (2, 2, 4),
    (2, 3, 8),
    (1, 9, 1),
    (0, 9, 0),
])
def test_pow(base, exponent, expected):
   assert_equal(math.pow(base, exponent), expected)

class TestMathUnitTest(unittest.TestCase):
   @parameterized.expand([
       ("negative", -1.5, -2.0),
       ("integer", 1, 1.0),
       ("large fraction", 1.6, 1),
   ])
   def test_floor(self, name, input, expected):
       assert_equal(math.floor(input), expected)

@parameterized_class(('a', 'b', 'expected_sum', 'expected_product'), [
   (1, 2, 3, 2),
   (5, 5, 10, 25),
])
class TestMathClass(unittest.TestCase):
   def test_add(self):
      assert_equal(self.a + self.b, self.expected_sum)

   def test_multiply(self):
      assert_equal(self.a * self.b, self.expected_product)

@parameterized_class([
   { "a": 3, "expected": 2 },
   { "b": 5, "expected": -4 },
])
class TestMathClassDict(unittest.TestCase):
   a = 1
   b = 1

   def test_subtract(self):
      assert_equal(self.a - self.b, self.expected)

With nose (and nose2):

$ nosetests -v test_math.py
test_floor_0_negative (test_math.TestMathUnitTest) ... ok
test_floor_1_integer (test_math.TestMathUnitTest) ... ok
test_floor_2_large_fraction (test_math.TestMathUnitTest) ... ok
test_math.test_pow(2, 2, 4, {}) ... ok
test_math.test_pow(2, 3, 8, {}) ... ok
test_math.test_pow(1, 9, 1, {}) ... ok
test_math.test_pow(0, 9, 0, {}) ... ok
test_add (test_math.TestMathClass_0) ... ok
test_multiply (test_math.TestMathClass_0) ... ok
test_add (test_math.TestMathClass_1) ... ok
test_multiply (test_math.TestMathClass_1) ... ok
test_subtract (test_math.TestMathClassDict_0) ... ok

----------------------------------------------------------------------
Ran 12 tests in 0.015s

OK

As the package name suggests, nose is best supported and will be used for all further examples.

With py.test (version 2.0 and above):

$ py.test -v test_math.py
============================= test session starts ==============================
platform darwin -- Python 3.6.1, pytest-3.1.3, py-1.4.34, pluggy-0.4.0
collecting ... collected 13 items

test_math.py::test_pow::[0] PASSED
test_math.py::test_pow::[1] PASSED
test_math.py::test_pow::[2] PASSED
test_math.py::test_pow::[3] PASSED
test_math.py::TestMathUnitTest::test_floor_0_negative PASSED
test_math.py::TestMathUnitTest::test_floor_1_integer PASSED
test_math.py::TestMathUnitTest::test_floor_2_large_fraction PASSED
test_math.py::TestMathClass_0::test_add PASSED
test_math.py::TestMathClass_0::test_multiply PASSED
test_math.py::TestMathClass_1::test_add PASSED
test_math.py::TestMathClass_1::test_multiply PASSED
test_math.py::TestMathClassDict_0::test_subtract PASSED
==================== 12 passed, 4 warnings in 0.16 seconds =====================

With unittest (and unittest2):

$ python -m unittest -v test_math
test_floor_0_negative (test_math.TestMathUnitTest) ... ok
test_floor_1_integer (test_math.TestMathUnitTest) ... ok
test_floor_2_large_fraction (test_math.TestMathUnitTest) ... ok
test_add (test_math.TestMathClass_0) ... ok
test_multiply (test_math.TestMathClass_0) ... ok
test_add (test_math.TestMathClass_1) ... ok
test_multiply (test_math.TestMathClass_1) ... ok
test_subtract (test_math.TestMathClassDict_0) ... ok

----------------------------------------------------------------------
Ran 8 tests in 0.001s

OK

(note: because unittest does not support test decorators, only tests created with @parameterized.expand will be executed)

With green:

$ green test_math.py -vvv
test_math
  TestMathClass_1
.   test_method_a
.   test_method_b
  TestMathClass_2
.   test_method_a
.   test_method_b
  TestMathClass_3
.   test_method_a
.   test_method_b
  TestMathUnitTest
.   test_floor_0_negative
.   test_floor_1_integer
.   test_floor_2_large_fraction
  TestMathClass_0
.   test_add
.   test_multiply
  TestMathClass_1
.   test_add
.   test_multiply
  TestMathClassDict_0
.   test_subtract

Ran 12 tests in 0.121s

OK (passes=9)

Installation

$ pip install parameterized

Compatibility

Yes (mostly).

  Py2.6 Py2.7 Py3.4 Py3.5 Py3.6 Py3.7 Py3.8 Py3.9 PyPy @mock.patch
nose yes yes yes yes yes yes yes yes yes yes
nose2 yes yes yes yes yes yes yes yes yes yes
py.test 2 yes yes no* no* no* no* yes yes yes yes
py.test 3 yes yes yes yes yes yes yes yes yes yes
py.test 4 no** no** no** no** no** no** no** no** no** no**
py.test fixtures no† no† no† no† no† no† no† no† no† no†
unittest
(@parameterized.expand)
yes yes yes yes yes yes yes yes yes yes
unittest2
(@parameterized.expand)
yes yes yes yes yes 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.

**: py.test 4 is not yet supported (but coming!) in issue #34

†: py.test fixture support is documented in issue #81

Dependencies

(this section left intentionally blank)

Exhaustive Usage Examples

The @parameterized and @parameterized.expand decorators accept a list or iterable of tuples or param(...), or a callable which returns a list or iterable:

from parameterized import parameterized, param

# A list of tuples
@parameterized([
    (2, 3, 5),
    (3, 5, 8),
])
def test_add(a, b, expected):
    assert_equal(a + b, expected)

# A list of params
@parameterized([
    param("10", 10),
    param("10", 16, base=16),
])
def test_int(str_val, expected, base=10):
    assert_equal(int(str_val, base=base), expected)

# An iterable of params
@parameterized(
    param.explicit(*json.loads(line))
    for line in open("testcases.jsons")
)
def test_from_json_file(...):
    ...

# A callable which returns a list of tuples
def load_test_cases():
    return [
        ("test1", ),
        ("test2", ),
    ]
@parameterized(load_test_cases)
def test_from_function(name):
    ...

Note that, when using an iterator or a generator, all the items will be loaded into memory before the start of the test run (we do this explicitly to ensure that generators are exhausted exactly once in multi-process or multi-threaded testing environments).

The @parameterized decorator can be used test class methods, and standalone functions:

from parameterized import parameterized

class AddTest(object):
    @parameterized([
        (2, 3, 5),
    ])
    def test_add(self, a, b, expected):
        assert_equal(a + b, expected)

@parameterized([
    (2, 3, 5),
])
def test_add(a, b, expected):
    assert_equal(a + b, expected)

And @parameterized.expand can be used to generate test methods in situations where test generators cannot be used (for example, when the test class is a subclass of unittest.TestCase):

import unittest
from parameterized import parameterized

class AddTestCase(unittest.TestCase):
    @parameterized.expand([
        ("2 and 3", 2, 3, 5),
        ("3 and 5", 2, 3, 5),
    ])
    def test_add(self, _, a, b, expected):
        assert_equal(a + b, expected)

Will create the test cases:

$ nosetests example.py
test_add_0_2_and_3 (example.AddTestCase) ... ok
test_add_1_3_and_5 (example.AddTestCase) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

Note that @parameterized.expand works by creating new methods on the test class. If the first parameter is a string, that string will be added to the end of the method name. For example, the test case above will generate the methods 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 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 index of the test case parameters in the list of parameters, and param (an instance of param) will be the parameters which will be used.

import unittest
from parameterized import parameterized

def custom_name_func(testcase_func, param_num, param):
    return "%s_%s" %(
        testcase_func.__name__,
        parameterized.to_safe_name("_".join(str(x) for x in param.args)),
    )

class AddTestCase(unittest.TestCase):
    @parameterized.expand([
        (2, 3, 5),
        (2, 3, 5),
    ], name_func=custom_name_func)
    def test_add(self, a, b, expected):
        assert_equal(a + b, expected)

Will create the test cases:

$ nosetests example.py
test_add_1_2_3 (example.AddTestCase) ... ok
test_add_2_3_5 (example.AddTestCase) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

The param(...) helper class stores the parameters for one specific test case. It can be used to pass keyword arguments to test cases:

from parameterized import parameterized, param

@parameterized([
    param("10", 10),
    param("10", 16, base=16),
])
def test_int(str_val, expected, base=10):
    assert_equal(int(str_val, base=base), expected)

If test cases have a docstring, the parameters for that test case will be appended to the first line of the docstring. This behavior can be controlled with the doc_func argument:

from parameterized import parameterized

@parameterized([
    (1, 2, 3),
    (4, 5, 9),
])
def test_add(a, b, expected):
    """ Test addition. """
    assert_equal(a + b, expected)

def my_doc_func(func, num, param):
    return "%s: %s with %s" %(num, func.__name__, param)

@parameterized([
    (5, 4, 1),
    (9, 6, 3),
], doc_func=my_doc_func)
def test_subtraction(a, b, expected):
    assert_equal(a - b, expected)
$ nosetests example.py
Test addition. [with a=1, b=2, expected=3] ... ok
Test addition. [with a=4, b=5, expected=9] ... ok
0: test_subtraction with param(*(5, 4, 1)) ... ok
1: test_subtraction with param(*(9, 6, 3)) ... ok

----------------------------------------------------------------------
Ran 4 tests in 0.001s

OK

Finally @parameterized_class parameterizes an entire class, using either a list of attributes, or a list of dicts that will be applied to the class:

from yourapp.models import User
from parameterized import parameterized_class

@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 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()


@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:

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

Using with Single Parameters

If a test function only accepts one parameter and the value is not iterable, then it is possible to supply a list of values without wrapping each one in a tuple:

@parameterized([1, 2, 3])
def test_greater_than_zero(value):
   assert value > 0

Note, however, that if the single parameter is iterable (such as a list or tuple), then it must be wrapped in a tuple, list, or the param(...) helper:

@parameterized([
   ([1, 2, 3], ),
   ([3, 3], ),
   ([6], ),
])
def test_sums_to_6(numbers):
   assert sum(numbers) == 6

(note, also, that Python requires single element tuples to be defined with a trailing comma: (foo, ))

Using with @mock.patch

parameterized can be used with mock.patch, but the argument ordering can be confusing. The @mock.patch(...) decorator must come below the @parameterized(...), and the mocked parameters must come last:

@mock.patch("os.getpid")
class TestOS(object):
   @parameterized(...)
   @mock.patch("os.fdopen")
   @mock.patch("os.umask")
   def test_method(self, param1, param2, ..., mock_umask, mock_fdopen, mock_getpid):
      ...

Note: the same holds true when using @parameterized.expand.

Migrating from nose-parameterized to parameterized

To migrate a codebase from nose-parameterized to parameterized:

  1. Update your requirements file, replacing nose-parameterized with parameterized.

  2. Replace all references to nose_parameterized with parameterized:

    $ perl -pi -e 's/nose_parameterized/parameterized/g' your-codebase/
    
  3. You're done!

FAQ

What happened to nose-parameterized?
Originally only nose was supported. But now everything is supported, and it only made sense to change the name!
What do you mean when you say "nose is best supported"?
There are small caveates with py.test and unittest: py.test does not show the parameter values (ex, it will show test_add[0] instead of test_add[1, 2, 3]), and unittest/unittest2 do not support test generators so @parameterized.expand must be used.
Why not use @pytest.mark.parametrize?
Because spelling is difficult. Also, parameterized doesn't require you to repeat argument names, and (using param) it supports optional keyword arguments.
Why do I get an AttributeError: 'function' object has no attribute 'expand' with @parameterized.expand?
You've likely installed the parametrized (note the missing e) package. Use parameterized (with the e) instead and you'll be all set.
Comments
  • How to apply @parameterized.expand on Class?

    How to apply @parameterized.expand on Class?

    I would like to apply @parameterized.expand on Class so that every test method runs with the common parameter.

    I was making decorator for wrapping the expand decorator but got stuck where to apply decorator manually.

    What I was trying to do is that overring the method with the expand.

    setattr(cls, method_name, parameterized.expand(method)
    

    However, parameterized.expand is @classmethod which does not take a function as the argument. Has anyone any idea?

    opened by legshort 13
  • TypeError: don't know how to make test from: None

    TypeError: don't know how to make test from: None

    I cannot run sample test using Visual Studio 2015, Python 3.5 and unittest2:

    import unittest
    from nose_parameterized import parameterized
    
    class AddTestCase(unittest.TestCase):
        @parameterized.expand([
            ("2 and 3", 2, 3, 5),
            ("3 and 5", 2, 3, 5),
        ])
        def test_add(self, _, a, b, expected):
            assert_equal(a + b, expected)
    
    Test Name:  test_add
    Test Outcome:   Failed
    Result StandardError:   
    Traceback (most recent call last):
      File "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\EXTENSIONS\MICROSOFT\PYTHON TOOLS FOR VISUAL STUDIO\2.2\visualstudio_py_testlauncher.py", line 69, in <module>
        main()
      File "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\EXTENSIONS\MICROSOFT\PYTHON TOOLS FOR VISUAL STUDIO\2.2\visualstudio_py_testlauncher.py", line 62, in main
        test = unittest.defaultTestLoader.loadTestsFromNames(opts.tests, module)
      File "C:\Users\lem1x\AppData\Local\Programs\Python\Python35-32\lib\unittest\loader.py", line 219, in loadTestsFromNames
        suites = [self.loadTestsFromName(name, module) for name in names]
      File "C:\Users\lem1x\AppData\Local\Programs\Python\Python35-32\lib\unittest\loader.py", line 219, in <listcomp>
        suites = [self.loadTestsFromName(name, module) for name in names]
      File "C:\Users\lem1x\AppData\Local\Programs\Python\Python35-32\lib\unittest\loader.py", line 213, in loadTestsFromName
        raise TypeError("don't know how to make test from: %s" % obj)
    TypeError: don't know how to make test from: None
    
    opened by dhermyt 13
  • Name change?

    Name change?

    I love nose-parameterized, it's the best test parameterizer out there that I've seen.

    We use pytest for our tests and I've had several conversations about how we use nose-parameterized and my colleague has said "but wait we use pytest" and I've had to re-explain that it's for all test runners.

    A name change for the next version would solve all these conflicts. Name changes happen occasionally in the python community, e.g. recently pep8 became pycodestyle to avoid confusion. Thoughts?

    opened by adamchainz 10
  • Append details on parameters to expanded function docstrings.

    Append details on parameters to expanded function docstrings.

    Test runners will occassionaly use the docstring of a test method as a means of reporting its execution. Because the docstring is simply copied from the template method to the parameterized method, it isn't very useful in distinguishing between tests.

    We now detect the names of the parameters of the function and the arguments that are being passed as parameters and append that information to the end of the first line of the docstring.

    The generated docstrings might not make perfect sense, so the user can also specify testcase_func_doc to override docstring generation with information that makes more sense.

    Fixes #21

    opened by smspillaz 9
  • Meaningful class names for tests when using parameterized_class with dictionaries (suggestion)

    Meaningful class names for tests when using parameterized_class with dictionaries (suggestion)

    Right now to get meaningful names, I have to use the tuple syntax:

    @parameterized_class(("name", "optimized"), [
        ("Normal", True),
        ("Unoptimized", False)
    ])
    

    However, I would prefer to use the dict syntax, as it's more flexible and less error-prone for me. But, that would result in unnamed class variations, according to current implementation.

    I think you should just take the first key of every dictionary, as all dictionaries in Python3 are ordered (and there is a Python2 backport), and it matches how the function currently works.

    Alternatively, you can allow an optional argument that specifies what is the "name" key.

    pr-wanted 
    opened by erezsh 8
  • @parameterized_class name function callback support

    @parameterized_class name function callback support

    Hi. The @parameterized.expand decorator allows a callback function to be specified that generates the name of each test method that's generated for each tuple in the input data set list. This is fantastic - however I'm using the new @parameterized_class decorator which I noticed doesn't currently support a similar mechanism to set the generated class name. I've added support in this PR and added some tests to the unit tests file to demonstrate the use and test it. Is there anything else that you need me to add to this PR before it can be considered for merging in? Cheers, Duncan.

    opened by duncwebb 8
  • Get Data From CSV

    Get Data From CSV

    Gives me the option to get my data from a file. Useful for inputs that are long. Implementation is only for methods for now.

    @parameterized.from_csv("data.csv")
    def test_stuff(foo, bar):
         # assert something 
    

    Comparing my function to yours, there's a lot more going on in the parameterized function but I am willing to implement them as well if you so require.

    opened by jeunito 8
  • Add equivalent of name_func for parameterized_class

    Add equivalent of name_func for parameterized_class

    Hello,

    I would be convenient to add "name_func" argument to parameterized_class since the current behaviour is only adding suffix if parameters are of type string.

    Thanks!

    opened by jeremylanglois 6
  • fix the order when number of cases exceeds 10

    fix the order when number of cases exceeds 10

    When number of cases exceeds 10, the order of cases goes wrong. For example:

    class MyTest(unittest.TestCase):
        @parameterized.expand([
            (1, 1, 2),
            (2, 2, 4),
            (3, 3, 6),
            (4, 4, 8),
            (5, 5, 10),
            (6, 6, 12),
            (7, 7, 14),
            (8, 8, 16),
            (9, 9, 18),
            (10, 10, 20),
            (11, 11, 22)
        ])
        def test_add(self, a, b, c):
            self.assertEqual(a + b, c)
    

    The order is (1, 1, 2) (2, 2, 4) (11, 11, 22) (3, 3, 6) (4, 4, 8) (5, 5, 10) (6, 6, 12) (7, 7, 14) (8, 8, 16) (9, 9, 18) (10, 10, 20), because testMethod is test_add_0, test_add_1, test_add_10, test_add_2... I change the name of testMethod to test_add_00, test_add_01, test_add_02..., so the order corrects now.

    opened by ntflc 6
  • nose: instance variables set by setup test fixture don't exist in parameterized tests

    nose: instance variables set by setup test fixture don't exist in parameterized tests

    Something changed in 0.6.0/0.6.1 that is breaking this:

    from mock import MagicMock
    from nose.tools import assert_true
    from nose_parameterized import parameterized
    
    class TestFoo(object):
        def setup(self):
            self.foo = MagicMock()
    
        def test_foo(self):
            assert_true(hasattr(self, 'foo'))  # passes
    
        @parameterized([
            ('bar',)
        ])
        def test_bar(self, bar_arg):
            assert_true(hasattr(self, 'foo')) # fails in 0.6.0, passes in 0.5.0
    
    opened by katzenbaer 6
  • 0.7.1: test suite is failing

    0.7.1: test suite is failing

    Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.Z6weJ6
    + umask 022
    + cd /home/tkloczko/rpmbuild/BUILD
    + cd parameterized-0.7.1
    + export PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-parameterized-0.7.1-2.fc32.x86_64/usr/lib/python3.8/site-packages
    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-parameterized-0.7.1-2.fc32.x86_64/usr/lib/python3.8/site-packages
    + nosetests-3.8 -v
    parameterized.test.TestOldStyleClass.test_old_style_classes_0_foo ... ok
    parameterized.test.TestOldStyleClass.test_old_style_classes_1_bar ... ok
    test_on_TestCase2_custom_name_42 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase2_custom_name_foo0 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase2_custom_name_foo1 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase2_custom_name_foo2 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase_0 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase_1_foo0 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase_2_foo1 (parameterized.test.TestParamerizedOnTestCase) ... ok
    test_on_TestCase_3_foo2 (parameterized.test.TestParamerizedOnTestCase) ... ok
    parameterized.test.TestParameterized.test_instance_method(42, {}) ... ok
    parameterized.test.TestParameterized.test_instance_method('foo0', {}) ... ok
    parameterized.test.TestParameterized.test_instance_method('foo1', {}) ... ok
    parameterized.test.TestParameterized.test_instance_method('foo2', {'bar': 42}) ... ok
    test_method (parameterized.test.TestParameterizedClassDict_0) ... ok
    test_method (parameterized.test.TestParameterizedClassDict_1) ... ok
    test_method_a (parameterized.test.TestParameterizedClass_0_foo) ... ok
    test_method_b (parameterized.test.TestParameterizedClass_0_foo) ... ok
    test_method_a (parameterized.test.TestParameterizedClass_1_bar) ... ok
    test_method_b (parameterized.test.TestParameterizedClass_1_bar) ... ok
    test_method_a (parameterized.test.TestParameterizedClass_2) ... ok
    test_method_b (parameterized.test.TestParameterizedClass_2) ... ok
    stuff ... FAIL
    Documentation [with foo='foo', bar=12] ... FAIL
    [with foo='foo'] ... FAIL
    Documentation [with foo='foo']. ... FAIL
    Documentation [with foo='foo']. ... FAIL
    Döcumentation [with foo='foo']. ... FAIL
    Documentation [with foo='foo', bar=12] ... FAIL
    test_multiple_function_patch_decorator_0 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    test_multiple_function_patch_decorator_1_foo0 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    test_multiple_function_patch_decorator_2_foo1 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    test_one_function_patch_decorator_0 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    test_one_function_patch_decorator_1_foo0 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    test_one_function_patch_decorator_2_foo1 (parameterized.test.TestParameterizedExpandWithMockPatchForClass) ... ok
    parameterized.test.TestParameterizedExpandWithNoExpand.test_patch_class_no_expand(42, 51, {}) ... ok
    test_multiple_function_patch_decorator_0 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    test_multiple_function_patch_decorator_1_foo0 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    test_multiple_function_patch_decorator_2_foo1 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    test_one_function_patch_decorator_0 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    test_one_function_patch_decorator_1_foo0 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    test_one_function_patch_decorator_2_foo1 (parameterized.test.TestParameterizedExpandWithNoMockPatchForClass) ... ok
    parameterized.test.TestParameterizedExpandWithNoMockPatchForClassNoExpand.test_patch_no_expand(42, 51, {}) ... ok
    parameterized.test.TestSetupTeardown.test_setup(1, {}) ... ok
    parameterized.test.TestSetupTeardown.test_setup(2, {}) ... ok
    parameterized.test.test_warns_when_using_parameterized_with_TestCase ... ok
    parameterized.test.test_helpful_error_on_invalid_parameters ... ok
    parameterized.test.test_helpful_error_on_empty_iterable_input ... ok
    parameterized.test.test_skip_test_on_empty_iterable ... ok
    parameterized.test.test_cases_over_10(0, 1, {}) ... ok
    parameterized.test.test_cases_over_10(1, 2, {}) ... ok
    parameterized.test.test_cases_over_10(2, 3, {}) ... ok
    parameterized.test.test_cases_over_10(3, 4, {}) ... ok
    parameterized.test.test_cases_over_10(4, 5, {}) ... ok
    parameterized.test.test_cases_over_10(5, 6, {}) ... ok
    parameterized.test.test_cases_over_10(6, 7, {}) ... ok
    parameterized.test.test_cases_over_10(7, 8, {}) ... ok
    parameterized.test.test_cases_over_10(8, 9, {}) ... ok
    parameterized.test.test_cases_over_10(9, 10, {}) ... ok
    parameterized.test.test_cases_over_10(10, 11, {}) ... ok
    parameterized.test.test_helpful_error_on_empty_iterable_input_expand ... ok
    parameterized.test.test_mock_patch_standalone_function(42, {}) ... ok
    parameterized.test.test_naked_function(42, {}) ... ok
    parameterized.test.test_naked_function('foo0', {}) ... ok
    parameterized.test.test_naked_function('foo1', {}) ... ok
    parameterized.test.test_naked_function('foo2', {'bar': 42}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('', param(*(), **{}), [], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('*a, **kw', param(*(), **{}), [], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('*a, **kw', param(*(1,), **{'foo': 42}), [('*a', (1,)), ('**kw', {'foo': 42})], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('foo', param(*(1,), **{}), [('foo', 1)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('foo, *a', param(*(1,), **{}), [('foo', 1)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('foo, *a', param(*(1, 9), **{}), [('foo', 1), ('*a', (9,))], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('foo, *a, **kw', param(*(1,), **{'bar': 9}), [('foo', 1), ('**kw', {'bar': 9})], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x=9', param(*(), **{}), [('x', 9)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x=9', param(*(1,), **{}), [('x', 1)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1,), **{}), [('x', 1), ('y', 9)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1, 2), **{}), [('x', 1), ('y', 2)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1, 2, 3), **{}), [('x', 1), ('y', 2), ('*a', (3,))], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1,), **{'y': 2}), [('x', 1), ('y', 2)], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1,), **{'z': 2}), [('x', 1), ('y', 9), ('**kw', {'z': 2})], {}) ... ok
    parameterized.test.test_parameterized_argument_value_pairs('x, y=9, *a, **kw', param(*(1, 2, 3), **{'z': 3}), [('x', 1), ('y', 2), ('*a', (3,)), ('**kw', {'z': 3})], {}) ... ok
    parameterized.test.test_short_repr('abcd', "'abcd'", {}) ... ok
    parameterized.test.test_short_repr('123456789', "'12...89'", {}) ... ok
    parameterized.test.test_short_repr(123456789, '123...789', {}) ... ok
    parameterized.test.test_short_repr(123456789, '12...89', 4, {}) ... ok
    Docstring! [with input='foo'] ... ok
    parameterized.test.test_wrapped_iterable_input('foo', {}) ... ok
    parameterized.test.test_helpful_error_on_non_iterable_input ... ok
    parameterized.test.test_old_style_classes ... SKIP: Py3 doesn't have old-style classes
    
    ======================================================================
    FAIL: stuff
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 265, in test_custom_doc_func
        self._assert_docstring("stuff")
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: Documentation [with foo='foo', bar=12]
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 295, in test_default_values_get_correct_value
        self._assert_docstring("Documentation [with foo=%r, bar=%r]" %(foo, bar))
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: [with foo='foo']
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 275, in test_empty_docstring
        self._assert_docstring("[with foo=%r]" %(foo, ))
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: Documentation [with foo='foo'].
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 282, in test_multiline_documentation
        self._assert_docstring(
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: Documentation [with foo='foo'].
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 270, in test_single_line_docstring
        self._assert_docstring("Documentation [with foo=%r]." %(foo, ))
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: Döcumentation [with foo='foo'].
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 290, in test_unicode_docstring
        self._assert_docstring(u"Döcumentation [with foo=%r]." %(foo, ))
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ======================================================================
    FAIL: Documentation [with foo='foo', bar=12]
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/parameterized.py", line 518, in standalone_func
        return func(*(a + p.args), **p.kwargs)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 302, in test_with_leading_newline
        self._assert_docstring("Documentation [with foo=%r, bar=%r]" %(foo, bar), rstrip=True)
      File "/home/tkloczko/rpmbuild/BUILD/parameterized-0.7.1/parameterized/test.py", line 255, in _assert_docstring
        raise AssertionError("uh oh, unittest changed a local variable name")
    AssertionError: uh oh, unittest changed a local variable name
    
    ----------------------------------------------------------------------
    Ran 89 tests in 0.141s
    
    FAILED (SKIP=1, failures=7)
    error: Bad exit status from /var/tmp/rpm-tmp.Z6weJ6 (%check)
    
    opened by kloczek 5
  • "TypeError: don't know how to make test from: None" when executing just the test method.

    It does look that this is the same issue as: #37

    I just faced that very same issue: TypeError: don't know how to make test from: None using Django==3.2.14, Python=3.9.5, and parametrized==0.8.1, note that I'm using the plain unittest with no other libraries like Nosetests, Pytests etc. It's just the regular Django' unittest suite.

    $ python manage.py test appname.tests.test_file.TestClass.test_method
    ...
    TypeError: don't know how to make test from: None
    

    All the other alternatives to run tests, like the whole test suite, executing just an app, files or even just the Test Class, it works with no issues. Is there any workaround to it? I ask that because this is kind of a blocker for us, thinking on an developer experience POV.

    Thanks in advance.

    opened by luanfonceca 1
  • Allow running tests without nose

    Allow running tests without nose

    This isn’t the prettiest workaround, but it seems to allow running the tests without nose installed.

    See https://fedoraproject.org/wiki/Changes/DeprecateNose.

    opened by musicinmybrain 0
  • Type hints

    Type hints

    I've been rolling out Mypy on a client project. When activating the disallow_untyped_decorators flag, I found I needed type hints for parametrized. I added the below to the project's stubs folder (on mypy_path:

    from __future__ import annotations
    
    from collections.abc import Callable, Iterable, Sequence
    from typing import Any, ParamSpec, TypeVar
    from unittest import TestCase
    
    P = ParamSpec("P")
    T = TypeVar("T")
    
    class param:
        def __init__(self, *args: Any, **kwargs: Any) -> None: ...
    
    InputType = (
        Iterable[str] | Iterable[Sequence[Any]] | Iterable[dict[str, Any]] | Iterable[param]
    )
    
    class parameterized:
        def __init__(
            self,
            input: InputType,
            doc_func: Callable[[Callable[..., Any], int, param], str] | None = None,
            skip_on_empty: bool = False,
        ): ...
        def __call__(self, test_func: Callable[P, T]) -> Callable[P, T]: ...
        @classmethod
        def expand(
            cls,
            input: InputType,
            name_func: Callable[[Callable[..., Any], int, param], str] | None = None,
            skip_on_empty: bool = False,
            **legacy: Any,
        ) -> Callable[[Callable[P, T]], Callable[P, T]]: ...
    
    _TestCaseClass = TypeVar("_TestCaseClass", bound=type[TestCase])
    
    def parameterized_class(input: Any) -> Callable[[_TestCaseClass], _TestCaseClass]: ...
    

    These hints cover the main usage of parameterized. If you're interested, I wouldn't mind contributing full type hint coverage to the package.

    opened by adamchainz 3
  • Python 3.10 Support

    Python 3.10 Support

    After seeing the repo hasn't gotten any commits in the last 1.5 years, I wanted to check if it's still maintained and is there any plan for Python 3.10 support.

    opened by ulgens 0
Owner
David Wolever
David Wolever
PENBUD is penetration testing buddy which helps you in penetration testing by making various important tools interactive.

penbud - Penetration Tester Buddy PENBUD is penetration testing buddy which helps you in penetration testing by making various important tools interac

Himanshu Shukla 15 Feb 1, 2022
pytest plugin for distributed testing and loop-on-failures testing modes.

xdist: pytest distributed testing plugin The pytest-xdist plugin extends pytest with some unique test execution modes: test run parallelization: if yo

pytest-dev 1.1k Dec 30, 2022
PacketPy is an open-source solution for stress testing network devices using different testing methods

PacketPy About PacketPy is an open-source solution for stress testing network devices using different testing methods. Currently, there are only two c

null 4 Sep 22, 2022
Pynguin, The PYthoN General UnIt Test geNerator is a test-generation tool for Python

Pynguin, the PYthoN General UnIt test geNerator, is a tool that allows developers to generate unit tests automatically.

Chair of Software Engineering II, Uni Passau 997 Jan 6, 2023
Generate random test credit card numbers for testing, validation and/or verification purposes.

Generate random test credit card numbers for testing, validation and/or verification purposes.

Dark Hunter 141 5 Nov 14, 2022
Test scripts etc. for experimental rollup testing

rollup node experiments Test scripts etc. for experimental rollup testing. untested, work in progress python -m venv venv source venv/bin/activate #

Diederik Loerakker 14 Jan 25, 2022
pytest_pyramid provides basic fixtures for testing pyramid applications with pytest test suite

pytest_pyramid pytest_pyramid provides basic fixtures for testing pyramid applications with pytest test suite. By default, pytest_pyramid will create

Grzegorz Śliwiński 12 Dec 4, 2022
Ab testing - basically a statistical test in which two or more variants

Ab testing - basically a statistical test in which two or more variants

Buse Yıldırım 5 Mar 13, 2022
A small automated test structure using python to test *.cpp codes

Get Started Insert C++ Codes Add Test Code Run Test Samples Check Coverages Insert C++ Codes you can easily add c++ files in /inputs directory there i

Alireza Zahiri 2 Aug 3, 2022
a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly)

pytest-sugar pytest-sugar is a plugin for pytest that shows failures and errors instantly and shows a progress bar. Requirements You will need the fol

Teemu 963 Dec 28, 2022
Wraps any WSGI application and makes it easy to send test requests to that application, without starting up an HTTP server.

WebTest This wraps any WSGI application and makes it easy to send test requests to that application, without starting up an HTTP server. This provides

Pylons Project 325 Dec 30, 2022
ApiPy was created for api testing with Python pytest framework which has also requests, assertpy and pytest-html-reporter libraries.

ApiPy was created for api testing with Python pytest framework which has also requests, assertpy and pytest-html-reporter libraries. With this f

Mustafa 1 Jul 11, 2022
Generic automation framework for acceptance testing and RPA

Robot Framework Introduction Installation Example Usage Documentation Support and contact Contributing License Introduction Robot Framework is a gener

Robot Framework 7.7k Jan 7, 2023
Sixpack is a language-agnostic a/b-testing framework

Sixpack Sixpack is a framework to enable A/B testing across multiple programming languages. It does this by exposing a simple API for client libraries

null 1.7k Dec 24, 2022
fsociety Hacking Tools Pack – A Penetration Testing Framework

Fsociety Hacking Tools Pack A Penetration Testing Framework, you will have every script that a hacker needs. Works with Python 2. For a Python 3 versi

Manisso 8.2k Jan 3, 2023
Web testing library for Robot Framework

SeleniumLibrary Contents Introduction Keyword Documentation Installation Browser drivers Usage Extending SeleniumLibrary Community Versions History In

Robot Framework 1.2k Jan 3, 2023
A framework-agnostic library for testing ASGI web applications

async-asgi-testclient Async ASGI TestClient is a library for testing web applications that implements ASGI specification (version 2 and 3). The motiva

null 122 Nov 22, 2022
A Modular Penetration Testing Framework

fsociety A Modular Penetration Testing Framework Install pip install fsociety Update pip install --upgrade fsociety Usage usage: fsociety [-h] [-i] [-

fsociety-team 802 Dec 31, 2022
The pytest framework makes it easy to write small tests, yet scales to support complex functional testing

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. An example o

pytest-dev 9.6k Jan 2, 2023