pytest parametrize调用有什么问题?

huangapple go评论62阅读模式
英文:

What is wrong with this pytest parametrize invocation?

问题

我广泛使用了 pytest.mark.parametrize,但在一个测试方法中遇到了问题:

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

这导致了以下错误:

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

完整的堆栈跟踪:

(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

有任何想法吗?

更新 我将这个问题简化为单一的测试参数,但仍然出现错误。

另一个更新 当将该方法提取为独立的函数时,相同的 parametrize 正常工作。我们在测试类中有很多 parametrize 的使用,所以我不明白为什么会出现这个问题。

英文:

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

    @pytest.mark.parametrize(&quot;is_except, except_pattern, in_query, table, out_query&quot;,[
        (False,None,&quot;WHERE     Table1.Col1=&#39;Foo&#39;&quot;, &quot;Table1&quot;,&quot;select * from Table1&quot;),
        (True,None,&quot;Table in query (Table11) must match the parameter value (Table1)&quot;, &quot;Table1&quot;,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 = &lt;unittest.case._Outcome object at 0x121d78b20&gt;
test_case = &lt;framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters&gt;
isTest = True

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, isTest=False):
        old_success = self.success
        self.success = True
        try:
&gt;           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 = &lt;framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters&gt;
method = &lt;bound method TestDeltaLakeReader.test_all_parameters of &lt;framework.tests.ddex.reader.test_deltalake_reader.TestDeltaLakeReader testMethod=test_all_parameters&gt;&gt;

    def _callTestMethod(self, method):
&gt;       method()
E       TypeError: TestDeltaLakeReader.test_all_parameters() missing 5 required positional arguments: &#39;is_except&#39;, &#39;except_pattern&#39;, &#39;in_query&#39;, &#39;table&#39;, and &#39;out_query&#39;

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

答案1

得分: 2

你的参数是 &quot;is_except, except_pattern, in_query, table, out_query&quot;

但是这个元组有四个元素。

(False,
None,
&quot;WHERE     Table1.Col1=&#39;Foo&#39;&quot;,
&quot;select * from Table1&quot;)

这个元组有六个元素。

(True,
None,
&quot;Table in query (Table11) must match the parameter value (Table1)&quot;,
&quot;select * from Table11&quot;,
&quot;Table1&quot;,
None)
英文:

Your parameters are &quot;is_except, except_pattern, in_query, table, out_query&quot;.

But this tuple has four elements.

(False,
None,
&quot;WHERE     Table1.Col1=&#39;Foo&#39;&quot;,
&quot;select * from Table1&quot;)

this tuple has six elements.

(True,
None,
&quot;Table in query (Table11) must match the parameter value (Table1)&quot;,
&quot;select * from Table11&quot;,
&quot;Table1&quot;,
None)

答案2

得分: 2

pytest的参数化通常在独立函数上运行良好(正如您所述),通常也适用于实例方法。根据pytest的文档,参数化、固定装置和自定义挂钩明确不适用于继承自unittest.TestCase的类。

正如您所述,参数化在某些类上有效,我怀疑这些类不是继承自unittest的TestCase,或者它们具有一些内部的"魔术"逻辑,使它们与pytest协同工作。根据提供的回溯信息,似乎问题的特定类确实继承自unittest模块,这解释了您遇到的问题。

以下代码应该会引发类似于您所展示的异常:

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

由于这个测试类非常简单,解决方案也很简单。通过移除继承(class TestClass(unittest.TestCase): -> class TestClass:),两个测试应该能够成功通过。

如果这确实是您遇到的问题,我在这里发布了一个更详细的答案,其中包含可能的解决方案。否则,请告诉我您可以提供的任何进一步细节。

英文:

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(&quot;y&quot;, [&quot;a&quot;, &quot;b&quot;])
    def test_x_y(self, y):
        assert y in (&quot;a&quot;, &quot;b&quot;)

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.

答案3

得分: 1

参数数量与传递的值数量不匹配。某处缺少逗号。运行 pytest 后下面的结果显示了错误:

================================================================================================================= ERRORS =================================================================================================================
____________________________________________________________________________________________________ ERROR collecting random_test.py _____________________________________________________________________________________________________
random_test.py::test_all_parameters: 在 "parametrize" 中,名称的数量 (5):
  ['is_except', 'except_pattern', 'in_query', 'table', 'out_query']
必须等于值的数量 (4):
  (False, None, "WHERE     Table1.Col1='Foo'", 'select * from Table1')
英文:

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 &quot;parametrize&quot; the number of names (5):
  [&#39;is_except&#39;, &#39;except_pattern&#39;, &#39;in_query&#39;, &#39;table&#39;, &#39;out_query&#39;]
must be equal to the number of values (4):
  (False, None, &quot;WHERE     Table1.Col1=&#39;Foo&#39;&quot;, &#39;select * from Table1&#39;)

huangapple
  • 本文由 发表于 2023年7月14日 08:41:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76684051.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定