GithubHelp home page GithubHelp logo

parameterized's Introduction

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).

  Py3.7 Py3.8 Py3.9 Py3.10 Py3.11 PyPy3 @mock.patch
nose yes yes yes yes no§ no§ yes
nose2 yes yes yes yes yes yes yes
py.test 2 no* no* no* no* no* no* no*
py.test 3 yes yes yes yes no* no* yes
py.test 4 no** no** no** no** no** no** no**
py.test fixtures no† no† no† no† no† no† no†
unittest
(@parameterized.expand)
yes yes yes yes yes yes yes
unittest2
(@parameterized.expand)
yes yes yes yes no§ no§ yes

§: nose and unittest2 - both of which were last updated in 2015 - sadly do not appear to support Python 3.10 or 3.11.

*: py.test 2 does not appear to work under Python 3 (#71), and py.test 3 does not appear to work under Python 3.10 or 3.11 (#154).

**: 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", 3, 5, 8),
    ])
    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 Python 2.X, 3.5, and 3.6 support?
As of version 0.9.0, parameterized no longer supports Python 2.X, 3.5, or 3.6. Previous versions of parameterized - 0.8.1 being the latest - will continue to work, but will not receive any new features or bug fixes.
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.
What happened to nose-parameterized?
Originally only nose was supported. But now everything is supported, and it only made sense to change the name!

parameterized's People

Contributors

adamchainz avatar alexpizarroj avatar alexriina avatar anweshadas avatar bhavyakjain avatar bmannix avatar charlsagente avatar chohner avatar curtissiemens avatar danielbradburn avatar duncan-webb avatar duncwebb avatar graziano-rodrigo avatar ikke avatar jinnovation avatar kolanich avatar lwprogramming avatar marek-mazur avatar musicinmybrain avatar shazow avatar simonw avatar smspillaz avatar toumorokoshi avatar tozech avatar ukinau avatar wolever avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parameterized's Issues

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

Have any way to not change the case name ?

I usually run one case in this way:

$ nosetests test_math.py:TestMathUnitTest.test_floor -v
Failure: ValueError (No such test TestMathUnitTest.test_floor) ... ERROR

======================================================================
ERROR: Failure: ValueError (No such test TestMathUnitTest.test_floor)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/failure.py", line 42, in runTest
    raise self.exc_class(self.exc_val)
ValueError: No such test TestMathUnitTest.test_floor

----------------------------------------------------------------------
Ran 1 test in 0.001s

--collect-only:

$ nosetests test_math.py -v --collect-only
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

I must be run nosetests test_math.py:TestMathUnitTest.test_floor_0_negative -v, It is bad for me and other system(like IDE).
And have a bigger problem, other plugins like nosedep depend case name.

Thanks

Setting skip_on_empty=True isn't workingon Python3

I have an empty list returned in some cases (only checks files that have changed). When I used the skip_on_empty settings, I got this output:

TypeError: <lambda>() takes 0 positional arguments but 1 was given

I change line 479 in parameterized.py from

return wraps(f)(lambda: skip_on_empty_helper())

to

return wraps(f)(skip_on_empty_helper)

And got the output I wanted

test_namespaced (test_namespace.TestNamespace) ... skipped 'parameterized input is empty'

Subclassing not behaving as expected

I'm using the parameterized.expand decorator on a test mixin class that is ultimately subclassed by three separate test cases. If I run these three cases as a single module, individually, everything works as expected. The decorator is generating the correct number of tests via the subclassing of the mixin and they seem to be running appropriately.

The trouble starts when I run the test suite comprehensively with nose, i.e. $ nosetests. Strangely enough the last test case is passed data that was manipulated by the second test case. It seems like there's some kind of namespace pollution going on as a result of subclassing a mixin that uses a parameterized decorator. Is this the intended behavior?

As a control, I rewrote a smaller set of the generated tests manually to ensure they worked as expected. Everything seemed fine. The tests passed and there was no interference from the other test cases.

prameterized.expand make mock.patch class decorator evaluated against same function multiple times

If we use parameterized.expand with mock.patch class decorator, mock.patch decorator is evaluated against same function object multiple times and messed up arguments.

Suppose I have a following code

import os
from mock import patch
from parameterized import parameterized

@patch("os.listdir")
class Test():
    @parameterized.expand([[1,2], [3,4], [5,6]])
    @patch("sys.path")
    def test1(self, t1, t2, mock_syspath, mock_listdir):
        pass

I expected above test code to be succeeded, but actually above code raise following error

    @wraps(func)
    def patched(*args, **keywargs):
        extra_args = []
        entered_patchers = []

        exc_info = tuple()
        try:
            for patching in patched.patchings:
                arg = patching.__enter__()
                entered_patchers.append(patching)
                if patching.attribute_name is not None:
                    keywargs.update(arg)
                elif patching.new is DEFAULT:
                    extra_args.append(arg)

            args += tuple(extra_args)
>           return func(*args, **keywargs)
E           TypeError: test1() takes exactly 5 arguments (7 given)

The root cause of failure is that mock.patch class decorator add mock.patch function decorator for each methods in class and the function be created by parameterised.expand decorator is also decorated but obviously function object to be wrapped by standalone_func is same among each function created, thus mock.patch function decorator unintentionally executed against same function object and add argument for the times of the number of parameterised argument.
That's why the number of argument miss match exception raised in above test code.

mock module is often used in test and python 3 add it under unittest module so I think it's better to support above case.

TypeError: type object argument after * must be a sequence, not float

@wolever
When did I get this error?

  • While using something like this -
@parameterized.expand([123.0])
    def test_xyz(self, id: float) -> None:

What is the cause?

  • args of float type aren't changed to tuple in this function
 @classmethod
    def from_decorator(cls, args):
        """ Returns an instance of ``param()`` for ``@parameterized`` argument
            ``args``::

                >>> param.from_decorator((42, ))
                param(args=(42, ), kwargs={})
                >>> param.from_decorator("foo")
                param(args=("foo", ), kwargs={})
            """
        if isinstance(args, param):
            return args
        if isinstance(args, string_types):
            args = (args, )
        return cls(*args)

What is the work around I used?

  • passed a tuple
@parameterized.expand([(123.0,)])
    def test_xyz(self, id: float) -> None:

What could be the possible permananent fix?

  • It would be too soon for me to comment on this but is there a reason floats aren't converted to tuple in from_decorator()?

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?

`parameterize_class` and `super()`

Decorated classes fails on super() calls, because after decoration class instance changes to None.

def decorator(base_class):
should returns base_class.

For example:

import unittest

@parameterized.parameterized_class([
    {'foo': 'bar'}
])
class Test(unittest.TestCase):

    def setUp(self):
        super(Test, self).setUp()

    def test(self):
        assert False

Fails with:

... in setUp
    super(Test, self).setUp()
TypeError: super() argument 1 must be type, not None

Not compatible with Python 3

Trying to install nose-parameterized 0.1 from PyPI with Python 3.2:

$ pip-3.2 install nose-parameterized
Downloading/unpacking nose-parameterized
  Running setup.py egg_info for package nose-parameterized

Installing collected packages: nose-parameterized
  Running setup.py install for nose-parameterized
      File "nose_parameterized/test.py", line 33
        except Exception, e:
                        ^
    SyntaxError: invalid syntax


Successfully installed nose-parameterized
Cleaning up...

Maintain GitHub tags

Hello,

It appears that the GitHub tags for releases stopped Nov 6, 2014, while releases on the pip package manager continued.

PyPi announches the latest release as 0.6.1 of 2017-03-21, where's GitHub's most recent release is 0.3.5 of 2014-11-06.

Is there a specific reason why GitHub releases has been dropped from the release cycle? - Is it too much work to include again?

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

Parameters are not shown in nose output if doc strings are used.

If a test function has a doc string then nose uses that doc string instead of the function name in its verbose output:

def test():
    """
    A test.
    """
    pass

yields

A test. ... ok

----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

If this feature is used in combination with parameterized then each parameterized variant of a test case is reported using the same output (the raw doc string), instead of the "parameterized" output that is used when no doc string is present:

from nose_parameterized import parameterized

@parameterized([(1, 1), (2, 2)])
def test1(a, b):
    """
    First test.
    """
    assert a == b


@parameterized([(1, 1), (2, 2)])
def test2(a, b):
    assert a == b

yields

First test. ... ok
First test. ... ok
nosedemo.test2(1, 1) ... ok
nosedemo.test2(2, 2) ... ok

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

OK

I would have expected something like

First test. (1, 1) ... ok
First test. (2, 2) ... ok

This may be due to nose's behavior w.r.t. doc strings and test generators:

def test():
    """
    A test.
    """
    def check(a, b):
        assert a == b
    for case in [(1, 1), (2, 2)]:
        yield check, case[0], case[1]

yields

A test. ... ok
A test. ... ok

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

OK

Problems to install from pypi under python X.Y (due to misspelling package name)

In clear virtualenv with python 2.7.12 I had problems to install the package.

Filling this issue it turned out, I misspelled the module name omitting one "e":

(py27)$ pip install nose-parametrized
Collecting nose-parametrized
  Could not find a version that satisfies the requirement nose-parametrized (from versions: )
No matching distribution found for nose-parametrized

Using correct name works:

(py27)$ pip install nose-parameterized
Collecting nose-parameterized
  Using cached nose_parameterized-0.5.0-py2.py3-none-any.whl
Installing collected packages: nose-parameterized
Successfully installed nose-parameterized-0.5.0

It might confuse other people too.

from nose_parameterized import param does not work

First, thanks for this work;

There is an issue with:
from nose_parameterized import param
It does not work as mentioned in the documentation.
I looked at the ini.py of the module and there is no "param" symbol.
Is the documentation up to date?

Thanks.

Licensing issues

Hello,

According to the METADATA information on the package;

cat site-packages/nose_parameterized-0.5.0.dist-info/METADATA

Metadata-Version: 2.0
Name: nose-parameterized
Version: 0.5.0
License: UNKNOWN

Rather then UNKNOWN, perhaps it should say Simplified BSD.

Also the BSD License provided is a little messy with the 'tl;dr;' statement, which causes Github not to pick it up.

error specific to python2.7: AttributeError: 'module' object has no attribute 'instancemethod'

Hello,

I'm getting "AttributeError: 'module' object has no attribute 'instancemethod'" whenever I use nose-parameterized in python 2.7, the s same script(mentioned below) executes fine in python3.4.

Anyone has an idea or faced similar issue ?

Code :

import unittest
from nose_parameterized import parameterized

class autologinTest(unittest.TestCase):
    a = [(['domain', 'url_login', 'logoutXpath']) , (['domain2', 'url_login2', 'logoutXpath2'])]
    print(a)

    @parameterized.expand(a)
    def test_generic_function(self, a, b, c):
        print a,b,c

Error Traceback in python2.7 :

Traceback (most recent call last):
  File "/Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py", line 153, in <module>
    modules = [loadSource(a[0])]
  File "/Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py", line 65, in loadSource
    module = imp.load_source(moduleName, fileName)
  File "/Users/sudaykumar/Documents/Automation/autologin_POC/testing.py", line 4, in <module>
    from nose_parameterized import parameterized
  File "/Library/Python/2.7/site-packages/nose_parameterized/__init__.py", line 1, in <module>
    from .parameterized import parameterized, param
  File "/Library/Python/2.7/site-packages/nose_parameterized/parameterized.py", line 31, in <module>
    new_instancemethod = new.instancemethod
AttributeError: 'module' object has no attribute 'instancemethod'

Support marks?

Hi, is it possible to set marks to a parameterized test? Something like this:

@parameterized.expand([
        (CHANNEL_A, POWER_CURRENT),
        pytest.param(CHANNEL_B, POWER_CURRENT, marks=pytest.mark.xfail),
        pytest.param(CHANNEL_A, POWER_VOLTAGE, marks=pytest.mark.xfail),
        pytest.param(CHANNEL_B, POWER_VOLTAGE, marks=pytest.mark.xfail),
        pytest.param(CHANNEL_A, POWER_RANGE, marks=pytest.mark.xfail),
        pytest.param(CHANNEL_B, POWER_RANGE, marks=pytest.mark.xfail)])

Specify parameter names in docstrings

It would be nice if nose_parameterized could provide some information about parameter names in generated function docstrings. Currently, the docstring is simply just copied from the template method to the generated method.

For test runners which report the running test by the first line of their docstring, this results in what looks like lots of repeated tests.

Getting TypeError: can't set attributes of built-in/extension type 'instance'

My code:

auth_params = [("string-A1", "string-B1", "paramC1", "string-D1"),
("string-A2", "string-B2", "paramC2", "string-D2"),]

class TestAppAuth():
def init(self):
self.x = None

def setUp(self):
    try:
        p = config['servers']['p']
    except KeyError:
        print("no p in configuration")
        sys.exit()

    self.x = AuthHelperClass(p)

@parameterized(auth_params)
def testAuth(self, test_description, username, password, message):
    assert self.x.verifyFailedAuth(test_description, username, password, message)

It fails:
nosetests -s -v --tc=servers.p:a.example.com tests.py:TestAppAuth.testAuth

Failure: TypeError (can't set attributes of built-in/extension type 'instance') ... ERROR

ERROR: Failure: TypeError (can't set attributes of built-in/extension type 'instance')

Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/loader.py", line 286, in generate
for test in g():
File "/usr/lib/python2.7/site-packages/nose_parameterized-0.3.1-py2.7.egg/nose_parameterized/parameterized.py", line 114, in parameterized_helper_method
f = self.make_bound_method(test_self, test_func)
File "/usr/lib/python2.7/site-packages/nose_parameterized-0.3.1-py2.7.egg/nose_parameterized/parameterized.py", line 144, in make_bound_method
setattr(cls, func.name, im_f)
TypeError: can't set attributes of built-in/extension type 'instance'


Ran 1 test in 0.002s

Instance variables

class SomeTest(TestCase):
    @parameterized.expand([
        {'something': self.something},
        {'something_else': self.something_else},
    )]
    def test_something(self, user):
        pass

Hi there, am wondering about using instance variables with nose-parameterized? Have you any ideas or opinions about this? Edit: Obviously the code above won't compile, it's just to illustrate the use case ;)

Thanks,

@parameterized.expected?

Hi,
in some place in the README.md file, there's a "@parameterized.expected". I think you mean "@parameterized.expand".

That's all. Your project looks very useful.

Fixture are not meant to be called directly

With pytest 4.1.0, it is no longer possible to pass a fixture to a parameterized test:

import pytest
from parameterized import parameterized

@pytest.fixture
def gen_test():
    return [('foo',), ('bar',)]

@parameterized(gen_test)
def test_(arg):
    print(arg)
Fixture "gen_test" called directly. Fixtures are not meant to be called directly,
but are created automatically when test functions request them as parameters.
See https://docs.pytest.org/en/latest/fixture.html for more information about fixtures, and
https://docs.pytest.org/en/latest/deprecations.html#calling-fixtures-directly about how to update your code.

Is there any workaround ? Ideally I would like to avoid passing a regular function (unless for some reason it's bad behavior) because my fixture is dependent on another fixture

Weird behaviour between with_setup and parameterized.expand

Hi!

When using with_setup with parameterized.expand, setup function will not be executed.
However, setup will be executed when using simple parameterized decorator.

from nose.tools import with_setup
from nose_parameterized import parameterized

def mysetup():
    print 'Hi!'

@parameterized.expand([
    ("bla", 0, 1),
    ("blu", 0, 1),
    ("bli", 0, 1),
])
@with_setup(mysetup)
def test_1(_, a, b):
    assert False

@parameterized([
    ("bla", 0, 1),
    ("blu", 0, 1),
    ("bli", 0, 1),
])
@with_setup(mysetup)
def test_2(_, a, b):
    assert False

test1 does not print "Hi!" while test2 does.

Docstrings are wiped out

Docstrings on the original test are wiped out after applying the @parameterized.expand() decorator

Exception raised when test method has docstring

Python version: 3.6
Parameterized version: 0.6.1

When writing tests using unittest.TestCase, test methods decorate with @parameterized.expand([...]) are unable to run when the method has a docstring. Here is an example code snippet:

class StrTest(TestCase):
    @parameterized.expand([(1, "1"), (2, "2")])
    def test_str_test(self, num: int, num_str: str) -> None:
        """Test that str() converts number to a string."""
        self.assertEqual(str(num), num_str)

And the associated traceback when trying to run the tests:

Traceback (most recent call last):
  File "project/test_str.py", line 24, in <module>
    class StrTest(TestCase):
  File "project/test_str.py", line 26, in StrTest
    def test_str_test(self, num: int, num_str: str) -> None:
  File "C:\Users\User\.virtualenvs\project-qf-AIYGt\lib\site-packages\parameterized\parameterized.py", line 383, in parameterized_expand_wrapper
    frame_locals[name].__doc__ = doc_func(f, num, p)
  File "C:\Users\User\.virtualenvs\project-qf-AIYGt\lib\site-packages\parameterized\parameterized.py", line 189, in default_doc_func
    all_args_with_values = parameterized_argument_value_pairs(func, p)
  File "C:\Users\User\.virtualenvs\project-qf-AIYGt\lib\site-packages\parameterized\parameterized.py", line 136, in parameterized_argument_value_pairs
    argspec = inspect.getargspec(func)
  File "C:\Python36\Lib\inspect.py", line 1045, in getargspec
    raise ValueError("Function has keyword-only parameters or annotations"
ValueError: Function has keyword-only parameters or annotations, use getfullargspec() API which can support them

I've attempted to remove the typehints on the arguments in the test_str_test function, as the exception suggests that it may be because of annotations, but no luck there.

Thanks!

Latest version not on PyPI

The latest version of parameterized is currently 0.7.0, but PyPI only has version 0.6.1, which is 2 versions ago.

py.test 2 under Python 3 throws error

$ tox -e py37-pytest2
GLOB sdist-make: /Users/wolever/code/parameterized/setup.py
py37-pytest2 inst-nodeps: /Users/wolever/code/parameterized/.tox/dist/parameterized-0.7.0.zip
py37-pytest2 installed: mock==2.0.0,nose==1.3.7,parameterized==0.7.0,pbr==5.1.3,py==1.8.0,pytest==2.9.2,six==1.12.0
py37-pytest2 run-test-pre: PYTHONHASHSEED='2473274294'
py37-pytest2 runtests: commands[0] | py.test parameterized/test.py
======================================================================== test session starts =========================================================================
platform darwin -- Python 3.7.2, pytest-2.9.2, py-1.8.0, pluggy-0.3.1
rootdir: /Users/wolever/code/parameterized, inifile:
collected 0 items / 1 errors

=============================================================================== ERRORS ===============================================================================
_______________________________________________________________ ERROR collecting parameterized/test.py _______________________________________________________________
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/runner.py:150: in __init__
    self.result = func()
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/main.py:435: in _memocollect
    return self._memoizedcall('_collected', lambda: list(self.collect()))
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/main.py:315: in _memoizedcall
    res = function()
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/main.py:435: in <lambda>
    return self._memoizedcall('_collected', lambda: list(self.collect()))
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/python.py:605: in collect
    return super(Module, self).collect()
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/python.py:459: in collect
    res = self.makeitem(name, obj)
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/python.py:471: in makeitem
    collector=self, name=name, obj=obj)
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:724: in __call__
    return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:338: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:333: in <lambda>
    _MultiCall(methods, kwargs, hook.spec_opts).execute()
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:595: in execute
    return _wrapped_call(hook_impl.function(*args), self.execute)
.tox/py37-pytest2/lib/python3.7/site-packages/_pytest/vendored_packages/pluggy.py:249: in _wrapped_call
    wrap_controller.send(call_outcome)
E   RuntimeError: generator raised StopIteration
====================================================================== 1 error in 0.41 seconds =======================================================================
ERROR: InvocationError for command '/Users/wolever/code/parameterized/.tox/py37-pytest2/bin/py.test parameterized/test.py' (exited with code 1)
______________________________________________________________________________ summary _______________________________________________________________________________
ERROR:   py37-pytest2: commands failed

Clarification of the parameterized decorator arguments

I found your project and was trying it out and I wanted to raise a point with you.. not sure if it is helpful or not. In many places I have been using a loop to test multiple forms:

forms = [
    {   "name": u"Whatever1",
        "address": u"[email protected]",
    },
    {   "name": u"Whatever2",
        "address": u"[email protected]",
    },
]

I was hoping to do:

@parameterized.expand(forms)
def parameterized_test(self, form_data):
    ....

But that throws a KeyError here:

if len(args) > 0 and isinstance(args[0], six.string_types):

The @parameterized.extend() requires tuples, not dicts:

forms = [
    ({   "name": u"Whatever1",
        "address": u"[email protected]",
    },),
    ({   "name": u"Whatever2",
        "address": u"[email protected]",
    },),
] 

where each tuple is the set of args to be passed into the test.

I fixed it with:

@parameterized.expand( (d,) for d in forms)

I understand why you're doing it this way, I just wanted to explain that I think this might be a common mistake and you should maybe test for a list of non-tuples being passed in and throw a better warning explaining what to do.

Also, I think the difference between @parameterized.extend and @parameterized was unclear to me at first.

Anyway, just a note... thanks for the project! It seems pretty cool.

"from parameterized import parameterized_class" fails

After downloading and installing the latest version of parameterized on 2019-01-14, I tried to use the @paramaterized_class decorator in Python 2.7 as per the example given in the documentation. However, the following error was thrown:
ImportError: cannot import name parameterized_class

I believe that adding parameterized_class to parameterized/__init__.py as follows fixes the issue:
from .parameterized import parameterized, param, parameterized_class

Parameterized doens't play nicely with `unittest.mock.patch` decorator

Howdy!

I've found that mixing Python's unittest.mock.patch decorator with parameterized.expand leads to unfortunate side-effects.

@parameterized.expand([("x", "y"),])
@patch("foo")
def test_bar(foo, x, y):
   pass

Will lead to UnboundLocalError: local variable 'patching' referenced before assignment (at unittest\mock.py:1181).
I'm sure this is due to the nature of how expand generates test cases.

There's a workaround, which is use patch as a context manager in the test body. However, I'd still love to use both as decorators for all that delicious syntactic sugar and saved whitespace 😄.

Tests throw a unicode error with Python 2.7

I have packaged parameterized for Debian, since it is a required dependency for testing other packages. Its test suite runs fine at package build time, but it fails against the installed package for Python 2. The tests run fine for Python 3. Here is the relevant portion of the Debian CI log:

test command1: set -e ; for py in $(pyversions -r 2>/dev/null) ; do cd "$AUTOPKGTEST_TMP" ; echo "Testing with $py (unittest):" ; $py -m unittest -v parameterized.test ; echo "Testing with $py (nose):" ; $py -m nose -v parameterized.test ; echo "Testing with $py (nose2):" ; $py -m nose2 -v parameterized.test ; echo "Testing with $py (pytest):" ; $py -m pytest -v --pyargs parameterized.test ; done
autopkgtest [14:39:04]: test command1: [-----------------------
Testing with python2.7 (unittest):
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
test_custom_doc_func_0_foo (parameterized.test.TestParameterizedExpandDocstring)
stuff ... ok
test_default_values_get_correct_value_0_foo (parameterized.test.TestParameterizedExpandDocstring)
Documentation [with foo='foo', bar=12] ... ok
test_empty_docstring_0_foo (parameterized.test.TestParameterizedExpandDocstring)
[with foo='foo'] ... ok
test_multiline_documentation_0_foo (parameterized.test.TestParameterizedExpandDocstring)
Documentation [with foo='foo']. ... ok
test_single_line_docstring_0_foo (parameterized.test.TestParameterizedExpandDocstring)
Documentation [with foo='foo']. ... ok
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.7/unittest/__main__.py", line 12, in <module>
    main(module=None)
  File "/usr/lib/python2.7/unittest/main.py", line 95, in __init__
    self.runTests()
  File "/usr/lib/python2.7/unittest/main.py", line 232, in runTests
    self.result = testRunner.run(self.test)
  File "/usr/lib/python2.7/unittest/runner.py", line 151, in run
    test(result)
  File "/usr/lib/python2.7/unittest/suite.py", line 70, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib/python2.7/unittest/suite.py", line 108, in run
    test(result)
  File "/usr/lib/python2.7/unittest/suite.py", line 70, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib/python2.7/unittest/suite.py", line 108, in run
    test(result)
  File "/usr/lib/python2.7/unittest/suite.py", line 70, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib/python2.7/unittest/suite.py", line 108, in run
    test(result)
  File "/usr/lib/python2.7/unittest/case.py", line 393, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib/python2.7/unittest/case.py", line 304, in run
    result.startTest(self)
  File "/usr/lib/python2.7/unittest/runner.py", line 53, in startTest
    self.stream.write(self.getDescription(test))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 84: ordinal not in range(128)

Cannot run a specific test case (only complete class)

My code:

my_params = [("x-1000", "param1", "param2"),
("x-1001", "param3", "param4"), ]

class TestMyAuth(object):
def init(self):
self.p = None

def setUp(self):
    try:
        serv = config['servers']['serv']
    except KeyError:
        print("no serv in configuration")
        sys.exit()

    self.p = AuthBaseClass(serv)

@parameterized.expand(my_params)
def testAuth(self, _, username, password, message):

...

This works well when I execute:
nosetests -s -v --tc=servers.serv:x.example.com rest-tests.py:TestMyAuth

and fails when trying to run the specific test case:
nosetests -s -v --tc=servers.serv:x.example.com rest-tests.py:TestMyAuth.testAuth

with the failure:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
TypeError: testAuth() takes exactly 5 arguments (1 given)

Looks like the generator is not working for a a specific case?

Pytest 'yield tests are deprecated, and scheduled to be removed in pytest 4.0'

This test leads to a pytest-warning on Pytest 3.0+:

from nose_parameterized import parameterized

@parameterized([
    ('foo',)
])
def test_foo(foo):
    pass

Like:

============================================================== pytest-warning summary ==============================================================
WC1 /path/to/test_foo.py yield tests are deprecated, and scheduled to be removed in pytest 4.0
=================================================== 1 passed, 1 pytest-warnings in 0.10 seconds ====================================================

Maybe the strategy for use within pytest should be reworked.

parameterized.expand 'swallowes' space in test name

I'm using something like:
("x-1000-test that this is good", "param1", param2" ),
("x-1001-test that this is bad" , "param3", param4" ),

and I expected to get something like:
testA_x-1000-test_that_this_is_good
testA_x-1001-test_that_this_is_bad

(in accordance to the example of the documentation)
but instead, it seems to eliminate (not replace) all spaces in the test name and add counter:
testA_0_x1000testthatthisisgood
testA_1_x10001testthatthisisbad

I'm using 0.3.2

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?

Issue with multiprocess or urllib?

I'm potentially having two sets of issues.

First is that I'm getting the following failure when I run my suite with the nose multiprocess plugin and I have a parameterized test with more than 1 set of injected params. If I add more than one set of injected params I see an issue

Failure: TypeError (unbound method address() must be called with Failure instance as first argument (got nothing instead)) ... ERROR

The second issue is that my test suite just hangs, it gets stuck and never executes to completion.

Any advice?

Question

Hi!
I love your module very much!
Can you please put an example of a setup/teardown function?
I have a test that should be repeated for each couple of an array of tuple (pin1, pin2)
I need a setup/teardown metod that accept the tuple and initialize/deinitialize the variables
is possible to have it??

pin_pairs = (
    (3, 5), (7, 13), (8, 10), (11, 36),
    (12, 16), (15, 23), (18, 22), (19, 21),
    (24, 26), (27, 29), (28, 32), (31, 33),
    (35, 37), (38, 40)
)

test_list = [("_".join((str(i), str(p))), i, p)
              for i, p in pin_pairs] + \
             [("_".join((str(p), str(i))), p, i)
              for i, p in pin_pairs]

class TestPins(unittest.TestCase):
    def Setup(self, in_pin, out_pin):
         # setup pins
         self.input_pin = in_pin
         self.output_pin = out_pin

    def TearDown(self, in_pin, out_pin):
         # teardown pin
         self.input_pin = None
         self.output_pin = None

    @parameterized.expand(test_list)
    def testIsNotEqual(self, name, in_pin_no, out_pin_no):
        # how to check the setup, teardown??
        self.assertNotEqual(self.in_pin, self.out_pin)

unittest.main()

Supplying tuple/list as single test argument?

This doesn't work:

@parameterized([
    [1, 1, 1, 1, 1],
    [1, 2, 2],
    [2, 3,],
    [5],
])
def test_list(self, data):
    assert sum(data) == 5

As it results in these errors:

======================================================================
ERROR: <snip>.test_list(2, 3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\dev\env\python\python27\lib\site-packages\nose\case.py", line 197, in runTest
    self.test(*self.arg)
  File "c:\dev\env\python\python27\lib\site-packages\parameterized\parameterized.py", line 280, in <lambda>
    nose_func = wraps(func)(lambda *args: func(*args))
TypeError: test_list() takes exactly 2 arguments (3 given)

======================================================================
ERROR: <snip>.test_list(5,)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\dev\env\python\python27\lib\site-packages\nose\case.py", line 197, in runTest
    self.test(*self.arg)
  File "c:\dev\env\python\python27\lib\site-packages\parameterized\parameterized.py", line 280, in <lambda>
    nose_func = wraps(func)(lambda *args: func(*args))
  File "C:\dev\work\MPI-Test\pyMPI-Test\pem\tests\test_pem_robot.py", line 574, in test_list
    assert sum(data) == 5
TypeError: 'int' object is not iterable

The lists have to be wrapped in useless lists for it to work:

@parameterized([
    [[1, 1, 1, 1, 1]],
    [[1, 2, 2]],
    [[2, 3,]],
    [[5]],
])
def test_list(self, data):
    assert sum(data) == 5

What is the "official" way of supplying iterables as test data with @parameterized? Would it be possible to note the proper idiom in the "Exhaustive Usage Examples"?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.