如何在pytest中解包多个fixture参数并直接在测试函数中调用?
Hey there! I totally get the urge to pull multiple values from a pytest fixture and use them directly with their own local names in test functions—no more typing my_fix["A"] every time.
You mentioned trying this approach using locals().update():
import pytest @pytest.fixture def my_fix(): return {"A" : 4, "B": 6 } def test_something(my_fix): locals().update(my_fix) assert A == 4 assert B == 6
But if you ran this, you probably hit a NameError saying A isn't defined—right? That's because Python handles local variable names differently than you might expect. When a function is compiled, Python pre-defines all the local variable names it detects in the code. Adding new names via locals().update() doesn't add them to this pre-defined list, so when you try to reference A or B, Python doesn't recognize them as local variables.
Better Alternatives
Let's look at some reliable ways to get the direct variable access you want:
1. Explicit Dictionary Unpacking
The simplest fix is to explicitly unpack the fixture's dictionary values into local variables. It's clear and avoids any weird namespace issues:
import pytest @pytest.fixture def my_fix(): return {"A" : 4, "B": 6 } def test_something(my_fix): A = my_fix["A"] B = my_fix["B"] # Or even more concise (just make sure the order matches the dict's values): # A, B = my_fix.values() assert A == 4 assert B == 6
2. Use a Data Class for Structured Fixture Data
For better readability (especially if your fixture returns more than two values), wrap your data in a dataclass. This makes the fixture's return structure explicit, and accessing values feels clean:
from dataclasses import dataclass import pytest @dataclass class TestData: A: int B: int @pytest.fixture def my_fix(): return TestData(A=4, B=6) def test_something(my_fix): A, B = my_fix.A, my_fix.B # Or you can just use my_fix.A directly in assertions if you prefer assert A == 4 assert B == 6
3. (Not Recommended) Use globals() Instead
If you really want that "auto-unpack" behavior, you could swap locals() for globals(). But I strongly advise against this—it pollutes the global namespace, which can lead to unexpected naming conflicts across tests:
def test_something(my_fix): globals().update(my_fix) assert A == 4 assert B == 6
Final Takeaway
While locals().update() looks like a neat shortcut, it doesn't work as intended in Python function scopes. Explicit unpacking or using structured types like dataclasses are far safer and more readable options for your tests.
内容的提问来源于stack exchange,提问作者Yair Daon

