Testing Files Generator
日本語

ドキュメント

ツールの機能を、実際に寄せられる質問の形で整理しています。リポジトリのREADMEが完全なリファレンスで、ダウンロードしたビルドと常に一致しています。

どんなコマンドがありますか。

それぞれが1つのことだけを行います。

tfg generate    レシピまたはフラグからファイルを生成する
tfg validate    レシピを検査し、何も書き込まない
tfg verify      ディレクトリをマニフェストと照合する
tfg cleanup     マニフェストに載っているファイルを削除する
tfg recipe fmt  レシピを整形して出力する
tfg preset      名前の付いたテストの疑問からファイルセットを作る
tfg formats     このビルドが対応する形式を一覧表示する
tfg damage      このビルドがファイルを意図的に壊す方法を一覧表示する
tfg tool        手元にあるファイル向けの小さなツール
tfg version     ツールのバージョンを表示する
tfg license     ライセンスと、生成ファイルにとっての意味を表示する

正確なサイズのファイルを1つ生成するには。

形式、サイズ、出力先を指定します。サイズは1024単位で数えるため、2mbは2097152バイトです。バイト数をそのまま指定することもでき、--size 10485761はちょうどその数のバイトを要求します。

tfg generate --format png --size 2mb --out ./out

generateで便利なフラグ:

フラグ動作
--format <id>ファイルの形式。例:txt
--size <size>各ファイルの正確なサイズ。10mbのような指定、またはバイト数
--size-range <a-b>範囲からファイルごとに決めるサイズ。例:1kb-8kb。抽選はシードから決まります
--boundary <size>制限の前後の3ファイル。1バイト下、制限値ちょうど、1バイト上
--count <n>作成するファイル数。既定は1
--name <template>名前のテンプレート。例:invoice_{index:04}.txt
--out <dir>書き込み先のディレクトリ
--seed <n>実行のシード。同じシードなら同じバイトになります
--set <k>=<v>形式の設定。繰り返し指定できます
--damage <name>ファイルを意図的に壊します。繰り返し指定でき、順番に適用されます。一覧はtfg damageで確認できます
--expected <outcome>accept、reject、sanitize、unspecified
--dry-run数えて表示するだけで、何も書き込みません
--jsonマニフェストを標準出力に書き出します

意図的に壊れたファイルを作るには。

このツールが書き込むそれ以外のファイルは、構造上すべて正しく、アップロード検証が問う3つの疑問のうち2つに答えます。--damageは3つ目、つまりファイルがそもそも開けるかに答えます。ファイルは通常どおり生成されてから壊されるため、要求したサイズのままです。

tfg generate --format png --size 2mb --damage zero-head --out ./out
tfg generate --format png --size 2mb --damage zero-head:bytes=16 --out ./out

設定はコロンの後ろに書きます。フラグは繰り返せて、書いた順に適用されます。tfg damageは、このビルドで何ができるか、それぞれが何を受け付けるかを一覧表示します。

レシピでは、キーは名前または設定のリストになります。

targets:
  - id: broken
    format: png
    count: 5
    size: 2mb
    damage:
      - zero-head
      - type: zero-head
        bytes: 16

壊されたファイルには、マニフェストでexpected: rejectが付き、横に壊した内容が記録されます。次の2つは、何かを書き込む前に拒否されます。どちらもマニフェストの記述と食い違うファイルをディスクに残してしまうためです。

3つ目は事前には分かりません。破壊が実行されても1バイトも変わらなかった場合、そのファイルは書き込まれずに破棄されます。実行は続き、どのファイルだったかを伝え、一部のみ完了した終了コードで終わります。

手順を追って、マニフェストを読むテストつきで説明します。テスト用の破損ファイルを作る方法。

レシピはどんな見た目ですか。

レシピは、実行全体を記述するYAMLファイルです。テストの隣にコミットすれば、フィクスチャはリポジトリ内のバイナリではなくなります。数百文字のファイルから、誰でもバイト単位で再構築できます。

# fixtures.yaml
version: 1
seed: 7741

defaults:
  label: true

targets:
  - id: invoices
    format: pdf
    count: 25
    size: 300kb
    name: invoice_{index:04}.pdf
    properties:
      pages: 3
      page_size: a4
    expected: accept

  - id: over_the_limit
    format: png
    count: 2
    size: 12mb
    expected:
      outcome: reject
      reason: size_limit

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

output:
  dir: ./fixtures
  manifest: manifest.json
tfg validate fixtures.yaml
tfg generate fixtures.yaml

各ターゲットには、size、size-range、boundary、containsのうち、ちょうど1つが必要です。2つはエラーで、ゼロもエラーです。無効なレシピはファイルを1つも書き込まず、最初の問題だけでなくすべての問題をまとめて報告し、それぞれ該当する設定名を示します。

システムがファイルをどう扱うべきかを宣言するには。

結果だけで足りるなら短い形式を、理由が重要なら長い形式を使います。

expected: accept
expected:
  outcome: reject
  reason: size_limit

結果はaccept、reject、sanitize、unspecifiedです。理由は閉じたリストで、レポートで理由ごとにグループ化できます。content_malformed、count_limit、dimensions_limit、duplicate、encoding_invalid、extension_rule、filename_invalid、filename_too_long、filename_traversal、malware_signature、mime_mismatch、nesting_depth、none、size_limit、size_zero。

理由が示すのは判定ではなく問題になっているルールです。そのため、同じ理由が両方の結果の下に現れることがあります。制限より1バイト小さいファイルはacceptですが、対象となるルールは依然としてsize_limitです。

マニフェストには何が入っていますか。

中断された実行も含め、すべての実行の終了時にファイルの隣へ書き出されます。ファイルごとに1項目です。

{
  "manifest_version": "1.0",
  "tool": { "name": "testing-files-generator", "version": "0.4.0" },
  "run": {
    "id": "run_b359aa8d94",
    "seed": 0,
    "command": "tfg generate --format png --size 2mb --out ./out",
    "platform": { "os": "windows", "arch": "amd64" },
    "complete": true
  },
  "summary": {
    "file_count": 1,
    "total_bytes": 2097152,
    "by_format": { "png": 1 },
    "by_expected": { "unspecified": 1 }
  },
  "files": [
    {
      "path": "files_0001.png",
      "bytes": 2097152,
      "format": "png",
      "fidelity": "full",
      "determinism": "byte",
      "seed": "8dc2d18c",
      "hashes": { "sha256": "1a1f7c..." },
      "properties": { "width": 640, "height": 480 },
      "expected": {
        "outcome": "unspecified",
        "detail": "No expectation was declared for this file.",
        "confidence": "policy_dependent"
      }
    }
  ]
}

実行がレシピから来た場合はrecipe_hashが、プリセットから来た場合はpresetとoverridesが追加されるため、マニフェストは常に生成元までたどれます。

各項目には、ファイルを生成したレシピ内のターゲットのIDであるtarget_idも入り、summary.by_targetが各ターゲットのファイル数を数えます。複数のターゲットを持つレシピも、ファイル名を読まずにターゲットごとに確認できます。

プリセットとは何ですか。

一般的なテストの疑問に答える既製のファイルセットで、セットを自分で設計する必要がありません。プリセットの中身は普通のレシピで、ejectがそのレシピを出力するので、そこから編集できます。各プリセットには、普通は何を見つけるか、セットの内容、受け付ける設定をまとめた専用ページがあります。

tfg preset list
tfg preset show size-boundaries
tfg generate --preset size-boundaries --limit 10mb --out ./edges
tfg preset eject size-boundaries > my.yaml

showは、セットを作る前にかかるコストを伝え、数値があなたの制限ではなくこちらの仮の値である場合は、はっきりそう伝えます。

終了コードは何を意味しますか。

終わり方ごとに専用のコードがあり、機械可読な出力は標準出力に出て、失敗した実行はそこに何も出力しません。この表は凍結された契約で、コードの意味を変えるにはメジャーバージョンを上げる必要があります。

コード 意味
0 すべて正常に動作しました。
1 ツール内部で予期しないエラーが発生しました。
2 コマンドまたはフラグが正しくありません。
3 レシピが正しくありません。
4 その形式では要求された処理ができません。
5 読み取りまたは書き込みに失敗しました。
6 ディスクの空き容量が足りません。
7 verifyが不一致を見つけました。
8 実行は終了しましたが、すべてが生成されたわけではありません。
130 Ctrl+Cで中断されました。
143 シグナルで停止されました。CIのタイムアウトはこう見えます。
- 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

Ctrl+Cで止めた実行でも、マニフェストは残り、書きかけのファイルは決して残りません。そのため、キャンセルされたジョブも次のジョブが片付けられます。

GitHub ActionsとGitLab CI向けのすぐ使えるワークフロー。CIパイプラインでテストファイルを生成する方法。

デスクトップウィンドウはありますか。

はい。同じエンジンにウィンドウを載せたもので、スクリプト化しないテスト向けです。機能削減版ではありません。テストが2つのインターフェースを機能ごとに比較しており、片方にしかできないことは、静かに食い違うのではなく、宣言して理由を示す必要があります。

画面は、単一バッチ、プリセット、複数バッチ同時、バージョン情報です。書き込む前に実行のコストを表示し、実行中は進捗を報告し、途中でキャンセルしても書きかけのファイルは残りません。レシピファイルはまだ開けません。レシピは今のところコマンドラインのもので、ウィンドウはフォームでバッチを組み立てます。