DEV Community

LukasSchmidt295
LukasSchmidt295

Posted on

How to Test Python Marketing Video Jobs from Generation to Download (Marketplace Crops)

Short answer: put contract tests around an asynchronous marketing video job, then make polling and download observable state transitions. For a marketplace that smart-crops seller footage into 16:9, 1:1, and 9:16 versions, this catches an incomplete rendition before a campaign manager sees it.

The key decision is not a clever encoder setting. It is deciding which facts must remain true as a job moves from upload to generation, polling, and retrieval. I treat those facts as an eval harness: a small fixture set, deterministic assertions, and a report that can run in a notebook before it runs in production.

What should generation, polling, and download promise?

Start with a state contract. queued means the source and crop plan are stored; running means a worker owns the attempt; ready means every requested ratio passed validation; failed is terminal for that attempt; expired means the asset may remain retained while its download grant is gone. Timestamps and one correlation id travel with every transition.

The create handler validates duration, dimensions, and an allow-list of codecs, persists an idempotency key, and returns 202 Accepted with a stable job id. It never waits for rendering. A repeated submission with the same key returns the existing id instead of producing a second campaign asset.

Here is a compact contract model. The transition table is the test oracle, not an implementation detail.

from dataclasses import dataclass
from enum import Enum

class State(str, Enum):
    QUEUED = "queued"
    RUNNING = "running"
    READY = "ready"
    FAILED = "failed"
    EXPIRED = "expired"

@dataclass
class Job:
    job_id: str
    ratios: tuple[str, ...]
    state: State = State.QUEUED

    def advance(self, target: State) -> None:
        allowed = {
            State.QUEUED: {State.RUNNING, State.FAILED},
            State.RUNNING: {State.READY, State.FAILED},
            State.READY: {State.EXPIRED},
            State.FAILED: set(),
            State.EXPIRED: set(),
        }
        if target not in allowed[self.state]:
            raise ValueError(f"invalid transition {self.state} -> {target}")
        self.state = target
Enter fullscreen mode Exit fullscreen mode

One invariant matters most: ready is atomic across the ratio set. If the square crop is missing, the job is not ready.

How can a Python eval harness exercise the lifecycle?

I've kept the worker callable without HTTP, then fed it fixtures that resemble the marketplace catalog: a talking-head clip with a face near the edge, a product demo with small text, and a wide shot with a centered subject. The harness checks crop coverage and output metadata, while a separate integration test checks status responses and authorization. That split keeps notebook-to-prod feedback quick without pretending a unit test can measure browser playback. One fixture in particular earns its keep: a seller's vertical clip with a logo 12 pixels from the edge. A center crop passes a naive dimension check but cuts the logo; a focal-point assertion catches it. I record the expected safe area beside the fixture, run the crop twice, and compare both the metadata and the pixel bounds. If either changes unexpectedly, the eval fails before an encoder or queue is involved. This is slower to write than a happy-path test, yet it saves a much longer review loop when a campaign has 400 listings and three ratios each.

def assert_renditions(job_status: dict, expected: set[str]) -> None:
    assert job_status["state"] == "ready"
    actual = {item["ratio"] for item in job_status["renditions"]}
    assert actual == expected
    for item in job_status["renditions"]:
        assert item["bytes"] > 0
        assert item["content_type"] in {"video/mp4", "video/webm"}

fixture = {"state": "ready", "renditions": [
    {"ratio": "16:9", "bytes": 1_240_000, "content_type": "video/mp4"},
    {"ratio": "1:1", "bytes": 980_000, "content_type": "video/mp4"},
    {"ratio": "9:16", "bytes": 1_110_000, "content_type": "video/mp4"},
]}
assert_renditions(fixture, {"16:9", "1:1", "9:16"})
Enter fullscreen mode Exit fullscreen mode

The numbers above are fixture values, not a benchmark. I am not sure one perceptual metric predicts every seller review, so I pair automated checks with a human spot-check of faces, logos, captions, and fine text. Your mileage may vary across browsers because codec support and hardware decoding differ.

Where does polling fail, and how should download grants be verified?

Polling is a bounded read loop. Begin around two seconds, increase the delay with jitter, cap it at 15 seconds, and stop at the product deadline. The client should render a recoverable “still processing” state after the deadline; it should not keep a tab hammering the status endpoint.

import random
import time
from collections.abc import Callable

def wait_for_terminal(get_status: Callable[[str], dict], job_id: str, timeout_s: int = 300) -> dict:
    started = time.monotonic()
    delay = 2.0
    while time.monotonic() - started < timeout_s:
        result = get_status(job_id)
        if result["state"] in {"ready", "failed", "expired"}:
            return result
        time.sleep(delay + random.uniform(0, 0.4))
        delay = min(delay * 1.7, 15.0)
    raise TimeoutError("job status deadline exceeded")
Enter fullscreen mode Exit fullscreen mode

The failure taxonomy is part of the API: invalid input is actionable, a transient worker interruption may be retried, and an authorization denial must not be retried blindly. A status response should include an error category and a safe message, never a stack trace.

Issue a short-lived, job-scoped download grant only after authorization. Log grant issuance separately from byte completion; a ready asset that nobody downloads is a product signal, while a grant that expires immediately is an operational defect. Stream the file from object storage when possible, and keep source retention independent from generated-rendition retention.

For format checks, use standards rather than assumptions. MP4 with H.264 remains a practical baseline for broad browser coverage; WebM can be useful where the playback matrix supports it. Validate the declared content type and inspect the file signature before publishing. MDN's media guide is a good compatibility starting point, not a substitute for testing the devices your buyers use.

The catch is operational weight. A prototype that creates one tiny preview for one user may be better served by a synchronous function and a local file. Stick with that simpler path when there is no multi-tenant authorization, no retry queue, and no need to reproduce a crop later.

That boundary is worth stating plainly.

Move to the explicit lifecycle when campaigns fan out across aspect ratios, reviewers need deterministic reruns, or upload traffic can outlive an HTTP request. Before committing, compare crop acceptance, queue age, render duration, poll count, first-frame delay, and completed-download rate on representative fixtures. Those measurements decide the boundary; a short demo does not.

References

Top comments (0)