如何使用Pytest将测试用例的参数值传递至下一个测试用例?
Hey there! Let's figure out how to pass test case parameters from one test to another in Pytest. The issue with your original code is that Pytest finalizes all test parameters during the test collection phase (before any tests run). By the time test_add modifies testData2, test_sub has already locked in its parameter list from the initial value of testData2.
Solution 1: Share Data via Class Attributes (Simplest for Same Class)
If your tests are in the same class, use a class attribute to store results from test_add, then loop through those results in test_sub. This runs all sub-tests in a single test case entry:
import pytest def add(x): return x + 1 def sub(x): return x - 1 testData1 = [1, 2] class Test_math(object): # Class attribute to store results from test_add add_outputs = [] @pytest.mark.parametrize('n', testData1) def test_add(self, n): result = add(n) self.__class__.add_outputs.append(result) # Fix the original assertion to validate add works correctly assert result == n + 1 def test_sub(self): # Iterate over results from test_add for val in self.__class__.add_outputs: result = sub(val) # Validate sub works with the passed value assert result == val - 1 if __name__ == '__main__': pytest.main(["-v"])
Solution 2: Generate Separate Test Cases with Fixtures + Indirect Parametrization
If you want each result from test_add to create a separate test_sub case (like proper parametrization), use a class-scoped fixture and indirect=True to dynamically generate parameters at runtime:
import pytest def add(x): return x + 1 def sub(x): return x - 1 testData1 = [1, 2] # Class-scoped fixture to hold shared results @pytest.fixture(scope="class") def shared_results(): return [] class Test_math(object): @pytest.mark.parametrize('n', testData1) def test_add(self, n, shared_results): result = add(n) shared_results.append(result) assert result == n + 1 # Use indirect=True to let the fixture provide parameters @pytest.mark.parametrize('input_val', [None], indirect=True) def test_sub(self, input_val, shared_results): result = sub(input_val) assert result == input_val - 1 # Hook to dynamically update test_sub's parameters after test_add runs def pytest_generate_tests(metafunc): if (metafunc.cls == Test_math and metafunc.function.__name__ == "test_sub"): # Get the shared results fixture results = metafunc.config.getfixturevalue("shared_results") # If we have results, replace the dummy parameter with actual values if results: metafunc.parametrize('input_val', results) if __name__ == '__main__': pytest.main(["-v"])
Solution 3: Use Pytest's Built-in Cache (Cross-Test/Module Sharing)
If you need to share data across different test classes or modules, Pytest's built-in cache works great. It persists data even between test runs (clear it with pytest --cache-clear):
import pytest def add(x): return x + 1 def sub(x): return x - 1 testData1 = [1, 2] class Test_math(object): @pytest.mark.parametrize('n', testData1) def test_add(self, n, request): result = add(n) # Store result in cache with a unique key request.config.cache.set(f"test_add_{n}", result) assert result == n + 1 def test_sub(self, request): # Retrieve all stored results from cache add_results = [] for n in testData1: res = request.config.cache.get(f"test_add_{n}", None) if res is not None: add_results.append(res) # Test each result for val in add_results: result = sub(val) assert result == val - 1 if __name__ == '__main__': pytest.main(["-v"])
Key Notes
- Pytest runs tests in alphabetical order by default, so
test_addwill naturally run beforetest_sub. For custom order, use plugins likepytest-ordering. - Try to keep tests independent when possible—shared state can make tests harder to debug, but these methods work when you need to pass data between tests.
内容的提问来源于stack exchange,提问作者Chweng Mega

