Testing Files Generator

What people use it for

Five jobs that come up in almost every project that accepts files from people, and the command that does each one. Every example below runs as written.

Upload limits

Testing whether a file size limit is enforced where it says it is

A limit is three test cases, not one: just under, exactly on, and just over. Getting those by hand means computing byte counts and hoping you did not fencepost the arithmetic. Ask for the set instead:

tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges

You get three real PDFs at 1048575, 1048576 and 1048577 bytes, and a manifest saying the first two should be accepted and the third rejected for size_limit. Your test reads the expectation instead of you writing three assertions by hand - and when the limit changes, you change one number and rerun.

The same works without a preset when you want a single boundary set inline:

tfg generate --format png --boundary 5mb --out ./png-edges

Continuous integration

Keeping fixtures out of the repository without losing them

Large binary fixtures make a repository slow to clone and awkward to review, and nobody can tell what changed when one is replaced. A recipe is a few hundred characters of YAML that rebuilds the identical files - byte for byte, on any machine - because every file is derived from the run seed.

- name: build the fixtures
  run: tfg generate fixtures.yaml --out ./fixtures

- name: run the tests
  run: pytest tests/

- name: nothing moved
  run: tfg verify ./fixtures/manifest.json

Every ending has its own exit code, so a pipeline can tell a bad recipe from a full disk from a verification mismatch. A failed run prints nothing on standard output, which keeps a log parser from reading an error as data.

Scale

Finding out what happens when the folder is big

Import routines, nightly jobs and directory listings behave differently at ten thousand files than at ten. Sizes drawn from a range make the set look like real traffic rather than ten thousand identical files, and the draw comes from the seed, so the set is the same tomorrow.

tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./fixtures

Check what a run would cost before it writes anything, which matters when the total is measured in gigabytes:

tfg generate --format log --size-range 1kb-8kb --count 10000 --dry-run

A run larger than the free space on the disk is refused before the first byte is written, rather than filling the disk and failing halfway.

Archives

Testing an unpacker with an archive that really holds files

An empty archive with the right extension proves nothing about code that opens it and walks what is inside. Declare the contents and the archive genuinely holds them:

targets:
  - id: bundle
    format: zip
    contains:
      - format: txt
        count: 200
        size: 4kb

Nesting depth, entry counts and the size of what is inside are all things an import routine has opinions about, and this is how you find out what those opinions are.

Parsers and viewers

Checking that your own code reads a format the way real software does

Every format here is checked against an independent reader before it ships - a PNG is opened and its pixels compared, a DOCX is read back by separate libraries, an archive is extracted. That means a file that your parser rejects is a finding about your parser, not about the generator.

tfg generate --format docx --size 300kb --set paragraphs=120 --out ./documents
tfg generate --format xlsx --size 2mb --set rows=400 --set columns=6 --out ./sheets

The formats page lists the settings each one accepts and the smallest file each can be.

Who this is for

QA engineers, test automation, and anyone whose code has an upload form, an import routine, a parser or a storage quota behind it. It runs on a machine with no network at all, which matters in a closed corporate environment where a browser based generator is not an option.

Free and open source, GPL-3.0. Nothing to sign up for. The binaries are not signed yet, so your system will warn you the first time - the release notes say what to expect.