Documentație
Tot ce face instrumentul, aranjat ca întrebările cu care vin oamenii de fapt. README-ul din repository este referința completă și se potrivește mereu cu versiunea pe care ai descărcat-o.
Ce comenzi există?
Fiecare face un singur lucru:
tfg generate produce fișiere, dintr-o rețetă sau din opțiuni
tfg validate verifică o rețetă fără a scrie nimic
tfg verify verifică un director față de un manifest
tfg cleanup șterge fișierele pe care le listează un manifest
tfg recipe fmt afișează o rețetă în forma ei normalizată
tfg preset construiește un set de fișiere dintr-o întrebare de test cu nume
tfg formats listează formatele acceptate de această versiune
tfg damage listează modurile în care această versiune poate strica un fișier intenționat
tfg tool mici unelte pentru fișiere pe care le ai deja
tfg version afișează versiunea instrumentului
tfg license afișează licența și ce înseamnă ea pentru fișierele generate
Cum generez un singur fișier de dimensiune exactă?
Spune formatul, dimensiunea și unde merge. Dimensiunile se numără din 1024 în 1024, deci
2mb sunt 2097152 octeți. Merge și un simplu număr de octeți, deci --size
10485761 cere exact atât.
tfg generate --format png --size 2mb --out ./out
Opțiunile utile ale comenzii generate:
| Opțiune | Ce face |
|---|---|
--format <id> | formatul fișierelor, de exemplu txt |
--size <size> | dimensiunea exactă a fiecărui fișier, precum 10mb sau un simplu număr de octeți |
--size-range <a-b> | o dimensiune extrasă pentru fiecare fișier dintr-un interval, precum 1kb-8kb. Extragerea vine din seed |
--boundary <size> | trei fișiere în jurul unei limite: un octet sub, limita, un octet peste |
--count <n> | câte fișiere să producă. Implicit 1 |
--name <template> | șablon de nume, de exemplu invoice_{index:04}.txt |
--out <dir> | directorul în care se scrie |
--seed <n> | seed-ul rulării. Același seed dă aceiași octeți |
--set <k>=<v> | o setare de format, repetabilă |
--damage <name> | strică fișierele intenționat, repetabil și aplicat în ordine. Rulează tfg damage pentru listă |
--expected <outcome> | accept, reject, sanitize sau unspecified |
--dry-run | numără și arată, nu scrie absolut nimic |
--json | scrie manifestul la ieșirea standard |
Cum fac un fișier stricat intenționat?
Orice alt fișier scris de acest instrument este corect prin construcție, ceea ce răspunde la două
din cele trei întrebări pe care le pune un validator de încărcare. --damage
răspunde la a treia - se deschide oare fișierul. Fișierul este produs normal și apoi stricat,
deci are în continuare dimensiunea cerută.
tfg generate --format png --size 2mb --damage zero-head --out ./out
tfg generate --format png --size 2mb --damage zero-head:bytes=16 --out ./out
Setările se pun după două puncte. Opțiunea se repetă, iar ordinea în care le scrii este ordinea în
care se aplică. tfg damage listează ce poate face această versiune și ce acceptă
fiecare.
Într-o rețetă cheia este o listă, de nume sau de setări:
targets:
- id: broken
format: png
count: 5
size: 2mb
damage:
- zero-head
- type: zero-head
bytes: 16
Un fișier deteriorat primește expected: reject în manifest, cu deteriorarea consemnată
alături. Două lucruri sunt refuzate înainte de a se scrie ceva, pentru că fiecare ar pune pe
disc un fișier pe care manifestul îl descrie greșit:
- un fișier mai mic decât are nevoie deteriorarea, pentru că ar ieși neschimbat
-
expected: acceptalături de o deteriorare, pentru că nimic nu l-ar putea îndeplini. Scriesanitizedacă sistemul testat trebuie să repare fișierul sauunspecifieddacă exact asta e întrebarea pe care o pui
O a treia nu se poate ști dinainte. Dacă o deteriorare rulează și nu mută niciun octet, fișierul respectiv este abandonat în loc să fie scris - rularea continuă, spune care a fost fișierul și se termină cu codul de ieșire parțial.
Pas cu pas, cu un test care citește manifestul: cum faci un fișier corupt pentru teste.
Cum arată o rețetă?
O rețetă este un fișier YAML care descrie o rulare întreagă. Comite-o lângă testele tale și fixture-urile nu mai sunt binare în repository - oricine le poate reconstrui, octet cu octet, dintr-un fișier de câteva sute de caractere.
# 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
Fiecare target are nevoie de exact una dintre cheile size, size-range,
boundary sau contains. Două este o eroare și la fel niciuna. O rețetă
invalidă nu scrie niciun fișier și raportează toate problemele deodată, nu doar
prima, fiecare numind setarea la care se referă.
Cum declar ce trebuie să facă sistemul meu cu un fișier?
Formă scurtă când rezultatul e de ajuns, formă lungă când contează motivul:
expected: accept
expected:
outcome: reject
reason: size_limit
Rezultatele sunt accept, reject, sanitize și
unspecified. Motivele sunt o listă închisă ca un raport să poată grupa după ele:
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 și size_zero.
Un motiv numește regula în joc, nu verdictul. De aceea același motiv poate sta sub
oricare dintre rezultate - un fișier cu un octet sub o limită este accept, iar
regula la care se referă rămâne size_limit.
Ce conține manifestul?
Se scrie lângă fișiere la sfârșitul fiecărei rulări, inclusiv a uneia întrerupte. O intrare pentru fiecare fișier:
{
"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"
}
}
]
}
Se adaugă un recipe_hash când rularea a venit dintr-o rețetă și preset cu
overrides când a venit dintr-o presetare, astfel încât un manifest poate fi mereu
urmărit până la ce l-a produs.
Fiecare intrare poartă și target_id, id-ul targetului din rețeta care a produs
fișierul, iar summary.by_target numără fișierele la care a ajuns fiecare target. O
rețetă cu mai multe targeturi poate fi verificată astfel target cu target, fără a citi nume de
fișiere.
Ce este o presetare?
Un set de fișiere gata făcut care răspunde unei întrebări de test obișnuite, ca să nu trebuiască să
proiectezi tu setul. Presetările sunt rețete obișnuite pe dedesubt, iar eject
afișează rețeta ca s-o poți edita de acolo. Fiecare presetare are o
pagină proprie cu ce găsește de obicei, ce este în set și fiecare setare pe care o acceptă.
-
Trece un fișier valid, cât de mic permite formatul?
empty-and-minimal -
Gestionarea numelor de fișiere
Va stoca, va afișa și va returna sistemul meu un nume de fișier la care nu se aștepta?
filename-handling -
Este o limită de dimensiune aplicată exact acolo unde este declarată?
size-boundaries -
Supraviețuiește importul meu de tabele la ce exportă instrumentele reale?
tabular-import -
Știe cititorul meu în ce codare este un fișier sau doar ghicește?
text-encoding -
Acceptă formularul meu de încărcare ce trebuie și respinge restul?
upload-validation
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 îți spune cât ar costa setul înainte să-l construiești și spune pe față când un
număr este o valoare provizorie de-a noastră, nu o limită de-a ta.
Ce înseamnă codurile de ieșire?
Fiecare final are propriul cod, ieșirea citibilă de mașină merge la ieșirea standard, iar o rulare eșuată nu tipărește nimic acolo. Tabelul este un contract înghețat - schimbarea sensului unui cod cere o versiune majoră.
| Cod | Semnificație |
|---|---|
0 |
Totul a mers. |
1 |
O eroare neașteptată în interiorul instrumentului. |
2 |
Comandă sau opțiune greșită. |
3 |
Rețeta nu este validă. |
4 |
Formatul nu poate face ce s-a cerut. |
5 |
O citire sau o scriere a eșuat. |
6 |
Nu este destul spațiu pe disc. |
7 |
verify a găsit o nepotrivire. |
8 |
Rularea s-a terminat, dar nu s-a produs totul. |
130 |
Întreruptă cu Ctrl+C. |
143 |
Oprită de un semnal, așa arată o depășire de timp în 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
O rulare oprită cu Ctrl+C lasă totuși un manifest și nu lasă niciodată un fișier scris pe jumătate, așa că un job anulat poate fi curățat de următorul.
Workflow-uri gata făcute pentru GitHub Actions și GitLab CI: cum generezi fișiere de test într-un pipeline CI.
Există o fereastră desktop?
Da, același motor cu o fereastră deasupra, pentru testarea care nu e automatizată. Nu e o versiune redusă: un test compară cele două interfețe capacitate cu capacitate, iar tot ce poate face doar una dintre ele trebuie declarat și justificat, nu lăsat să divergă pe tăcute.
Ecranele sunt un lot, presetări, mai multe loturi deodată și Despre. Arată cât ar costa o rulare înainte să scrie ceva, raportează progresul cât rulează și poate fi anulată pe la jumătate fără să lase un fișier scris pe jumătate. Nu deschide încă un fișier de rețetă - rețetele sunt deocamdată treaba liniei de comandă, iar fereastra își construiește loturile în formular.