测试序列数据共享模式及API测试跨请求数据复用方案问询
Awesome question! Let's break this down clearly, covering both test data sharing across test cases and efficient data passing in API tests, plus tie it to your sample code.
When you need to share data between individual test cases in a test suite, here are the most practical patterns:
- Module-level variables: Define a variable at the top of your test file (e.g.,
shared_item_uuid = None), then assign it in one test and read it in others. It’s simple, but watch out—most test frameworks (like pytest) run tests in random order by default, so this only works if you force execution order. - Test class instance attributes: If you structure tests in a class (common in unittest-style frameworks), store data on
self(e.g.,self.item_uuid = ...). All tests in the same class can access this data, but it won’t be shared across different classes. - Session/module-scoped fixtures (pytest recommended): Use pytest fixtures with
scope="session"orscope="module"to generate or fetch data once, then reuse it across all relevant tests. This is the cleanest approach because it controls data lifecycle, avoids redundant work, and keeps tests isolated when needed. - Temporary storage (files/databases): For large or complex data, write to a temporary JSON/CSV file or a dedicated test database. Just make sure to clean up this storage after tests finish to avoid side effects.
Your sample code repeats the get_json('/item') call in multiple tests to fetch an item UUID for the update request. While this works, it’s inefficient and can lead to inconsistent results if the /item endpoint returns different data between calls. Here are better patterns:
1. Reusable Fixtures (Best Practice)
Wrap the logic to fetch a valid item UUID in a pytest fixture, then inject it into any test that needs it:
import pytest @pytest.fixture(scope="module") def valid_item_uuid(): # Fetch the item list once and validate the UUID r = get_json('/item') assert r.status_code == 200 item_uuid = r.json[0]['uuid'] assert is_uuid(item_uuid) return item_uuid def test_item_get(): r = get_json('/item') assert r.status_code == 200 def test_item_update(valid_item_uuid): # Use the pre-fetched UUID directly r = put_json(f'/item/{valid_item_uuid}', {'description': 'New desc'}) assert r.status_code == 200
This way, you only hit the /item endpoint once per test module, and all tests use the same consistent UUID.
2. Test Context Storage
Use a simple global dictionary or context object to store data between tests. This is quick but depends on test execution order:
# Define a global context at the top of your test file test_context = {} def test_item_get(): r = get_json('/item') assert r.status_code == 200 test_context['item_uuid'] = r.json[0]['uuid'] assert is_uuid(test_context['item_uuid']) def test_item_update(): # Access the UUID stored in the context r = put_json(f'/item/{test_context["item_uuid"]}', {'description': 'New desc'}) assert r.status_code == 200
⚠️ Note: This will fail if test_item_update runs before test_item_get, so you’ll need to enforce test order (e.g., with pytest markers) if you use this pattern.
3. Encapsulated Helper Functions
Wrap the data-fetching logic in a reusable helper function to avoid code duplication:
def fetch_valid_item_uuid(): r = get_json('/item') assert r.status_code == 200 item_uuid = r.json[0]['uuid'] assert is_uuid(item_uuid) return item_uuid def test_item_update(): item_uuid = fetch_valid_item_uuid() r = put_json(f'/item/{item_uuid}', {'description': 'New desc'}) assert r.status_code == 200
This cleans up your test code, but it still makes a new /item request every time the helper is called—so fixtures are more efficient for repeated use.
内容的提问来源于stack exchange,提问作者n4nn31355

