<p>使用<code>indirect=['getDataA', 'getDataB']</code>应该是可行的,因为它应该是<a href="https://docs.pytest.org/en/6.2.x/example/parametrize.html#apply-indirect-on-particular-arguments" rel="nofollow noreferrer">pass a list or tuple of arguments’ names to ^{<cd2>} for fixtures to indirectly parametrize</a>。但是,根据您当前的代码:</p>
<pre><code>@pytest.mark.parametrize("getDataA, getDataB ", ["DetailedDataElementinA", " DetailedDataElementinB"], indirect=["getDataA ", "getDataB"])
def test_comparedata(getDataA, getDataB):
assert(getDataA == getDataB)
</code></pre>
<p>您有<strong>2个</strong>间接参数化装置,但在每次<em>测试运行时,您只有<strong>1个</strong>参数值传递给它。<a href="https://docs.pytest.org/en/6.2.x/reference.html#pytest.python.Metafunc.parametrize" rel="nofollow noreferrer">^{<cd3>}</a>的第二个参数应该是要传递给<em>每个测试运行</em>上的<em>每个夹具</em>的参数值:</p>
<blockquote>
<p>If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname.</p>
</blockquote>
<p>第一次运行将尝试将<em>仅</em><code>"DetailedDataElementinA"</code>传递到2个装置中,并将失败:</p>
<pre><code>test.py::test_comparedata: in "parametrize" the number of names (2):
['getDataA', 'getDataB']
must be equal to the number of values (22):
DetailedDataElementinA
</code></pre>
<p>因为它期望每个装置有<strong>2</strong>个值,<strong>1</strong></p>
<p>按照方法的描述,由于存在<strong>2个</strong>装置,因此每个装置需要<strong>2个</strong>-元组值,<strong>1个</strong>值</p>
<p>(<em>这里我简化了示例fixture,使fixture只返回param值,然后让断言无法看到<code>getDataA</code>和<code>getDataB</code></em>的实际返回值)</p>
<pre><code>@pytest.fixture
def getDataA(request):
return request.param.replace('ThisWillBePassedTo', 'FixtureReceived')
@pytest.fixture
def getDataB(request):
return request.param.replace('ThisWillBePassedTo', 'FixtureReceived')
@pytest.mark.parametrize(
'getDataA, getDataB',
[
('ThisWillBePassedToA-1', 'ThisWillBePassedToB-1'),
('ThisWillBePassedToA-2', 'ThisWillBePassedToB-2'),
('ThisWillBePassedToA-3', 'ThisWillBePassedToB-3'),
],
indirect=['getDataA', 'getDataB'],
)
def test_comparedata(getDataA, getDataB):
assert (getDataA == getDataB)
</code></pre>
<p>应该有3个测试(3个元组),每次运行时,索引<code>[0]</code>处的元组元素将传递给<code>getDataA</code>,索引<code>[1]</code>处的元组元素将传递给<code>getDataB</code>,顺序与定义夹具的顺序相同:</p>
<pre><code>test.py::test_comparedata[ThisWillBePassedToA-1-ThisWillBePassedToB-1] FAILED [ 33%]
test.py::test_comparedata[ThisWillBePassedToA-2-ThisWillBePassedToB-2] FAILED [ 66%]
test.py::test_comparedata[ThisWillBePassedToA-3-ThisWillBePassedToB-3] FAILED [100%]
getDataA = 'FixtureReceivedA-1', getDataB = 'FixtureReceivedB-1'
> assert (getDataA == getDataB)
E AssertionError: assert 'FixtureReceivedA-1' == 'FixtureReceivedB-1'
E - FixtureReceivedB-1
E ? ^
E + FixtureReceivedA-1
E ?
getDataA = 'FixtureReceivedA-2', getDataB = 'FixtureReceivedB-2'
> assert (getDataA == getDataB)
E AssertionError: assert 'FixtureReceivedA-2' == 'FixtureReceivedB-2'
E - FixtureReceivedB-2
E ? ^
E + FixtureReceivedA-2
E ?
</code></pre>
<p>虽然这样做有效,但当你有很多固定装置时可能会出现问题,因为你必须自己列出所有不同的组合,而且依赖顺序也会让人困惑</p>
<p>您可以改为使用<a href="https://docs.pytest.org/en/6.2.x/parametrize.html" rel="nofollow noreferrer">stack the parametrized tests</a>,它将获得所有参数组合:</p>
<pre><code>@pytest.fixture
def getDataA(request):
return request.param.replace('ThisWillBePassedTo', 'FixtureReceived')
@pytest.fixture
def getDataB(request):
return request.param.replace('ThisWillBePassedTo', 'FixtureReceived')
@pytest.mark.parametrize(
'getDataB',
[
'ThisWillBePassedToB-1',
'ThisWillBePassedToB-2',
'ThisWillBePassedToB-3',
],
indirect=True,
)
@pytest.mark.parametrize(
'getDataA',
[
'ThisWillBePassedToA-1',
'ThisWillBePassedToA-2',
'ThisWillBePassedToA-3',
],
indirect=True,
)
def test_comparedata(getDataA, getDataB):
assert (getDataA == getDataB)
</code></pre>
<p>在这里,您可以简单地使用普通的<code>indirect=True</code>,参数值更清晰,仅用于<code>getDataA</code>或仅用于<code>getDataB</code>。参数化仍然遵循一个顺序:最里面的<code>parametrize</code>d fixture也应该是传递给函数的最里面/第一个fixture。然后它会向外扩散</p>
<p>运行该命令将导致:</p>
<pre><code>test.py::test_comparedata[ThisWillBePassedToA-1-ThisWillBePassedToB-1] ...
test.py::test_comparedata[ThisWillBePassedToA-1-ThisWillBePassedToB-2] ...
test.py::test_comparedata[ThisWillBePassedToA-1-ThisWillBePassedToB-3] ...
test.py::test_comparedata[ThisWillBePassedToA-2-ThisWillBePassedToB-1] ...
test.py::test_comparedata[ThisWillBePassedToA-2-ThisWillBePassedToB-2] ...
test.py::test_comparedata[ThisWillBePassedToA-2-ThisWillBePassedToB-3] ...
test.py::test_comparedata[ThisWillBePassedToA-3-ThisWillBePassedToB-1] ...
test.py::test_comparedata[ThisWillBePassedToA-3-ThisWillBePassedToB-2] ...
test.py::test_comparedata[ThisWillBePassedToA-3-ThisWillBePassedToB-3] ...
getDataA = 'FixtureReceivedA-1', getDataB = 'FixtureReceivedB-3'
> assert (getDataA == getDataB)
E AssertionError: assert 'FixtureReceivedA-1' == 'FixtureReceivedB-3'
E - FixtureReceivedB-3
E ? ^ ^
E + FixtureReceivedA-1
E ?
</code></pre>