Skip to content

Commit 2cf4dd3

Browse files
Assert Python activity task parity fixtures
1 parent 67e1b71 commit 2cf4dd3

3 files changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"schema": "durable-workflow.polyglot.control-plane-request-fixture",
3+
"version": 1,
4+
"operation": "activity.complete",
5+
"request": {
6+
"method": "POST",
7+
"path": "/worker/activity-tasks/activity-task-231/complete"
8+
},
9+
"semantic_body": {
10+
"task_id": "activity-task-231",
11+
"activity_attempt_id": "activity-attempt-231",
12+
"lease_owner": "polyglot-worker-231",
13+
"result": {
14+
"items_processed": 3,
15+
"checkpoint": "inventory-page-7"
16+
},
17+
"outcome": "completed"
18+
},
19+
"response_body": {
20+
"task_id": "activity-task-231",
21+
"activity_attempt_id": "activity-attempt-231",
22+
"outcome": "completed"
23+
},
24+
"cli": {
25+
"argv": {
26+
"task-id": "activity-task-231",
27+
"attempt-id": "activity-attempt-231",
28+
"--lease-owner": "polyglot-worker-231",
29+
"--input": "{\"items_processed\":3,\"checkpoint\":\"inventory-page-7\"}",
30+
"--json": true
31+
},
32+
"expected_body": {
33+
"activity_attempt_id": "activity-attempt-231",
34+
"lease_owner": "polyglot-worker-231",
35+
"result": {
36+
"items_processed": 3,
37+
"checkpoint": "inventory-page-7"
38+
}
39+
}
40+
},
41+
"sdk_python": {
42+
"method": "complete_activity_task",
43+
"kwargs": {
44+
"task_id": "activity-task-231",
45+
"activity_attempt_id": "activity-attempt-231",
46+
"lease_owner": "polyglot-worker-231",
47+
"result": {
48+
"items_processed": 3,
49+
"checkpoint": "inventory-page-7"
50+
},
51+
"codec": "json",
52+
"activity_name": "inventory.sync-page"
53+
},
54+
"expected_body": {
55+
"activity_attempt_id": "activity-attempt-231",
56+
"lease_owner": "polyglot-worker-231"
57+
},
58+
"payload_envelope": {
59+
"field": "result",
60+
"codec": "json",
61+
"decoded": {
62+
"items_processed": 3,
63+
"checkpoint": "inventory-page-7"
64+
}
65+
}
66+
}
67+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"schema": "durable-workflow.polyglot.control-plane-request-fixture",
3+
"version": 1,
4+
"operation": "activity.fail",
5+
"request": {
6+
"method": "POST",
7+
"path": "/worker/activity-tasks/activity-task-231/fail",
8+
"body": {
9+
"activity_attempt_id": "activity-attempt-231",
10+
"lease_owner": "polyglot-worker-231",
11+
"failure": {
12+
"message": "Inventory service rejected the batch.",
13+
"type": "UpstreamRejected",
14+
"non_retryable": true
15+
}
16+
}
17+
},
18+
"semantic_body": {
19+
"task_id": "activity-task-231",
20+
"activity_attempt_id": "activity-attempt-231",
21+
"lease_owner": "polyglot-worker-231",
22+
"message": "Inventory service rejected the batch.",
23+
"type": "UpstreamRejected",
24+
"non_retryable": true,
25+
"outcome": "failed"
26+
},
27+
"response_body": {
28+
"task_id": "activity-task-231",
29+
"activity_attempt_id": "activity-attempt-231",
30+
"outcome": "failed"
31+
},
32+
"cli": {
33+
"argv": {
34+
"task-id": "activity-task-231",
35+
"attempt-id": "activity-attempt-231",
36+
"--lease-owner": "polyglot-worker-231",
37+
"--message": "Inventory service rejected the batch.",
38+
"--type": "UpstreamRejected",
39+
"--non-retryable": true,
40+
"--json": true
41+
}
42+
},
43+
"sdk_python": {
44+
"method": "fail_activity_task",
45+
"kwargs": {
46+
"task_id": "activity-task-231",
47+
"activity_attempt_id": "activity-attempt-231",
48+
"lease_owner": "polyglot-worker-231",
49+
"message": "Inventory service rejected the batch.",
50+
"failure_type": "UpstreamRejected",
51+
"non_retryable": true
52+
}
53+
}
54+
}

tests/test_client.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,41 @@ async def test_body_shape(self, client: Client) -> None:
13361336

13371337

13381338
class TestFailActivityTask:
1339+
@pytest.mark.asyncio
1340+
async def test_complete_activity_matches_polyglot_fixture(self, client: Client) -> None:
1341+
fixture_path = Path(__file__).parent / "fixtures" / "control-plane" / "activity-complete-parity.json"
1342+
fixture = json.loads(fixture_path.read_text())
1343+
sdk = fixture["sdk_python"]
1344+
expected = sdk["expected_body"]
1345+
1346+
resp = _mock_response(200, fixture["response_body"])
1347+
with patch.object(client._http, "request", new_callable=AsyncMock, return_value=resp) as mock:
1348+
result = await client.complete_activity_task(**sdk["kwargs"])
1349+
1350+
assert result == fixture["response_body"]
1351+
assert mock.call_args.args[:2] == (fixture["request"]["method"], f"/api{fixture['request']['path']}")
1352+
1353+
body = mock.call_args.kwargs["json"]
1354+
assert body["activity_attempt_id"] == expected["activity_attempt_id"]
1355+
assert body["lease_owner"] == expected["lease_owner"]
1356+
1357+
envelope = body[sdk["payload_envelope"]["field"]]
1358+
assert envelope["codec"] == sdk["payload_envelope"]["codec"]
1359+
assert serializer.decode_envelope(envelope) == sdk["payload_envelope"]["decoded"]
1360+
1361+
@pytest.mark.asyncio
1362+
async def test_fail_activity_matches_polyglot_fixture(self, client: Client) -> None:
1363+
fixture_path = Path(__file__).parent / "fixtures" / "control-plane" / "activity-fail-parity.json"
1364+
fixture = json.loads(fixture_path.read_text())
1365+
1366+
resp = _mock_response(200, fixture["response_body"])
1367+
with patch.object(client._http, "request", new_callable=AsyncMock, return_value=resp) as mock:
1368+
result = await client.fail_activity_task(**fixture["sdk_python"]["kwargs"])
1369+
1370+
assert result == fixture["response_body"]
1371+
assert mock.call_args.args[:2] == (fixture["request"]["method"], f"/api{fixture['request']['path']}")
1372+
assert mock.call_args.kwargs["json"] == fixture["request"]["body"]
1373+
13391374
@pytest.mark.asyncio
13401375
async def test_body_shape(self, client: Client) -> None:
13411376
resp = _mock_response(200, {"task_id": "t1", "outcome": "failed"})

0 commit comments

Comments
 (0)