0

I have extensively used pytest.mark.parametrize but am stumbling on its use in one test method:

    @pytest.mark.parametrize("is_except, except_pattern, in_query, table, out_query",[
        (False,None,"WHERE     Table1.Col1='Foo'", "Table1","select * from Table1"),
        (True,None,"Table in query (Table11) must match the parameter value (Table1)", "Table1",None)
    ])
    def test_all_parameters(self,is_except,except_pattern,in_query,table,out_query):
        # logic ..

This is resulting in:

E TypeError: TestDeltaLakeReader.test_all_parameters() missing 5 required positional arguments: 'is_except', 'except_pattern', 'in_query', 'table', and 'out_query'

Full stacktrace:

(TestDeltaLakeReader.test_all_parameters)
self = <unittest.case._Outcome object at 0x121d78b20>
test_case = <framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters>
isTest = True

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, isTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

/usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/case.py:59: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/case.py:591: in run
    self._callTestMethod(testMethod)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters>
method = <bound method TestDeltaLakeReader.test_all_parameters of <framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters>>

    def _callTestMethod(self, method):
>       method()
E       TypeError: TestDeltaLakeReader.test_all_parameters() missing 5 required positional arguments: 'is_except', 'except_pattern', 'in_query', 'table', and 'out_query'

/usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/case.py:549: TypeError

Any ideas?

Update I brought this down to a single testing parameter and still get the error.

Another update This same parametrize works fine when the method is extracted out into a standalone function. We have many many uses of parametrize inside test classes so I don't understand this.

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560

3 Answers3

2

Your parameters are "is_except, except_pattern, in_query, table, out_query".

But this tuple has four elements.

(False,
None,
"WHERE     Table1.Col1='Foo'",
"select * from Table1")

this tuple has six elements.

(True,
None,
"Table in query (Table11) must match the parameter value (Table1)",
"select * from Table11",
"Table1",
None)
Constantin Hong
  • 701
  • 1
  • 2
  • 16
2

Pytest's parametrization generally works well on standalone functions (as you stated), and also (generally) on instance methods. According to pytest's documentation, parametrization, fixtures, and custom hooks explicitly do NOT work on classes inheriting from unittest.TestCase.

As you stated that parametrization does work on some classes, I suspect that these classes do not inherit from unittest's TestCase, or that they have some internal "magic" logic to make things play nice with pytest. From the provided traceback it seems that the specific class in question does inherit from the unittest module, which explains the trouble you're facing.

The following code should fail with a similar exception you're exhibiting:

import unittest
import pytest

class TestClass(unittest.TestCase):

    @pytest.mark.parametrize("y", ["a", "b"])
    def test_x_y(self, y):
        assert y in ("a", "b")

As this test class is quite simple, the solution is, too. By removing the inheritance (class TestClass(unittest.TestCase): -> class TestClass:), two tests should pass successfully.

If this indeed is the problem you're experiencing, I've posted a more extensive answer here with possible solutions. Otherwise, please let me know of any further details you can provide.

micromoses
  • 6,747
  • 2
  • 20
  • 29
1

The number of parameters you are passing doesn't match the number of values. You are missing a comma somewhere. The result below from running pytest shows the error:

================================================================================================================= ERRORS =================================================================================================================
____________________________________________________________________________________________________ ERROR collecting random_test.py _____________________________________________________________________________________________________
random_test.py::test_all_parameters: in "parametrize" the number of names (5):
  ['is_except', 'except_pattern', 'in_query', 'table', 'out_query']
must be equal to the number of values (4):
  (False, None, "WHERE     Table1.Col1='Foo'", 'select * from Table1')
spo
  • 304
  • 1
  • 7