diff --git a/CHANGELOG.md b/CHANGELOG.md index 435c72a9..d9a48603 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,24 @@ because it turns other people's test suites red. ### Added +- **The website in twenty-two languages.** Beside English and Polish it now + reads in Simplified and Traditional Chinese, Japanese, German, French, + Spanish, Brazilian Portuguese, Italian, Indonesian, Russian, Turkish, Czech, + Vietnamese, Hindi, Korean, Arabic, Romanian, Dutch, Ukrainian and Thai. + Every page exists in every language, with the same facts: the numbers come + from the program, the same as before. A menu in the header lists the + languages by the names they call themselves. Arabic reads from right to + left, and commands and code stay left to right in it. Each page tells a + search engine which language it is in and where its translations are, so + somebody searching in their own language is sent to the page in it. The + pages of Latin-script languages have addresses in the language + (`/de/dokumentation/`), the others keep the English words under the + language prefix (`/ja/docs/`). The window and the command line are not + part of this. +- **Two guides on the website.** How to make a corrupt file for testing, with + the damages listed from the program itself, and how to generate test files in + a CI pipeline, with a GitHub Actions workflow, a GitLab job and the + PowerShell catch. Both are in every language of the site. - **A Tools tab, and `tfg tool`.** Small things to do with files you already have, in the window and on the command line with the same settings. The first works out the checksum of a file - md5, sha1, sha256, sha512 or crc32, @@ -76,6 +94,9 @@ because it turns other people's test suites red. ### Fixed +- **The FAQ on the website said a deliberately broken file was not possible + yet.** `tfg damage` has been in the tool since 0.3.0, and the answer still + called it a planned feature. It now says how to make one, in every language. - **The window no longer offers to write into a folder it cannot or should not write into.** Started from Finder on macOS it offered `/tfg-out`, which is read-only, so the first run ended in a refusal from the system. diff --git a/internal/guard/edgeexample_test.go b/internal/guard/edgeexample_test.go index 3e1e223e..d7437e8b 100644 --- a/internal/guard/edgeexample_test.go +++ b/internal/guard/edgeexample_test.go @@ -16,10 +16,10 @@ import ( // The three files every first page shows - one byte under a 1 MB limit, the // limit, one byte over - are what size-boundaries actually writes. // -// They stand in four places a stranger reads before anything else: the social -// card, the README, and the site's first page in both languages. All four -// carry them as literals, and the card says outright that everything on it is -// real. Nothing asked the program. An outside review of #148 named it, and +// They stand in the places a stranger reads before anything else: the social +// card, the README, and the site's first page in every language. All of them +// carry the files as literals, and the card says outright that everything on it +// is real. Nothing asked the program. An outside review of #148 named it, and // asking showed it was already half untrue: the card before that one printed // "tfg generate --preset size-boundaries --limit 1mb", which the program // refuses, because the default spread would need a file of 0 B. @@ -52,48 +52,64 @@ func TestTheLimitExampleIsWhatThePresetWrites(t *testing.T) { } root := repoRoot(t) - places := []struct { + type place struct { file string spaced bool outcomes map[string]string command bool - }{ + } + places := []place{ {"web/templates/social.html", true, map[string]string{"accept": "accept", "reject": "reject"}, false}, {"README.md", false, map[string]string{"accept": "**accept**", "reject": "**reject**"}, true}, {"web/content/en/index.html", false, map[string]string{"accept": "accept", "reject": "reject"}, true}, {"web/content/pl/index.html", false, map[string]string{"accept": "przyjąć", "reject": "odrzucić"}, true}, } - for _, place := range places { - body, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(place.file))) + // Every other translation of the first page is held to the same answer. The + // words are asked for rather than guessed: a language whose first page shows + // the three files in a form nobody listed here is a page this guard cannot + // read, and silence about it would be the defect the guard exists for. + for _, l := range languagesOnDisk(t) { + if l.Code == "en" || l.Code == "pl" { + continue + } + words, ok := translatedLimitWords[l.Code] + if !ok { + t.Errorf("the first page in %s is not held to the limit example - add the words it uses for accept and reject to translatedLimitWords", l.Code) + continue + } + places = append(places, place{"web/content/" + l.Code + "/index.html", false, map[string]string{"accept": words[0], "reject": words[1]}, true}) + } + for _, at := range places { + body, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(at.file))) if err != nil { - t.Fatalf("reading %s: %v", place.file, err) + t.Fatalf("reading %s: %v", at.file, err) } text := string(body) - if place.command && !strings.Contains(text, command) { + if at.command && !strings.Contains(text, command) { t.Errorf("%s no longer prints %q, so the files it shows come from a command this guard does not run", - place.file, command) + at.file, command) } for _, f := range manifest.Files { line := lineNaming(text, f.Name) if line == "" { - t.Errorf("%s does not show %s, and the command writes it", place.file, f.Name) + t.Errorf("%s does not show %s, and the command writes it", at.file, f.Name) continue } size := strconv.FormatInt(f.Bytes, 10) - if place.spaced { + if at.spaced { size = spacedBytes(f.Bytes) + " B" } if !strings.Contains(line, size) { - t.Errorf("%s shows %s without its %s:\n%s", place.file, f.Name, size, line) + t.Errorf("%s shows %s without its %s:\n%s", at.file, f.Name, size, line) } - word, ok := place.outcomes[f.Expected.Outcome] + word, ok := at.outcomes[f.Expected.Outcome] if !ok { - t.Errorf("the manifest declares %q for %s, and %s has no word for it", f.Expected.Outcome, f.Name, place.file) + t.Errorf("the manifest declares %q for %s, and %s has no word for it", f.Expected.Outcome, f.Name, at.file) continue } if !strings.Contains(line, word) { t.Errorf("%s shows %s without the outcome the manifest declares (%s):\n%s", - place.file, f.Name, word, line) + at.file, f.Name, word, line) } } } @@ -128,3 +144,34 @@ func spacedBytes(n int64) string { } return b.String() } + +// translatedLimitWords are the two words each translated first page uses for +// what the manifest declares - accept first, reject second - in the form that +// stands on the line naming a file. +// +// A word is not unique to a language, and a translation inflects it. Polish +// writes the infinitive in the table and so the list says przyjąć rather than +// przyjmie, and each entry is exactly the form the page shows. The key is the +// language tag, the same as the directory under web/content. +var translatedLimitWords = map[string][2]string{ + "de": {"akzeptieren", "ablehnen"}, + "es": {"aceptar", "rechazar"}, + "fr": {"accepter", "refuser"}, + "it": {"accettare", "rifiutare"}, + "pt-BR": {"aceitar", "rejeitar"}, + "nl": {"accepteren", "weigeren"}, + "ro": {"accepte", "respingă"}, + "cs": {"přijmout", "odmítnout"}, + "id": {"menerima", "menolak"}, + "tr": {"kabul etmeli", "reddetmeli"}, + "vi": {"chấp nhận", "từ chối"}, + "ru": {"принять", "отклонить"}, + "uk": {"прийняти", "відхилити"}, + "zh-Hans": {"接受", "拒绝"}, + "zh-Hant": {"接受", "拒絕"}, + "ja": {"受け入れる", "拒否する"}, + "ko": {"수락", "거부"}, + "ar": {"قبول", "رفض"}, + "hi": {"मंज़ूर करना", "अस्वीकार करना"}, + "th": {"ยอมรับ", "ปฏิเสธ"}, +} diff --git a/internal/guard/site_test.go b/internal/guard/site_test.go index ed5b126f..e474cc8a 100644 --- a/internal/guard/site_test.go +++ b/internal/guard/site_test.go @@ -16,6 +16,7 @@ import ( "testing" "github.com/donislawdev/TestingFilesGenerator/internal/cli" + "github.com/donislawdev/TestingFilesGenerator/internal/damage" "github.com/donislawdev/TestingFilesGenerator/internal/format" _ "github.com/donislawdev/TestingFilesGenerator/internal/format/all" "github.com/donislawdev/TestingFilesGenerator/internal/site" @@ -121,6 +122,7 @@ func factsFromTheProgram(t *testing.T) site.Facts { Version: version.Version, Formats: formats, ExitCodes: exitCodesInOrder(), + Damages: damagesTheProgramHas(), Presets: presetFactsFromTheProgram(t), Commands: commandsTheToolPrints(t), Downloads: declaredDownloads(), @@ -141,6 +143,17 @@ func factsFromTheProgram(t *testing.T) site.Facts { } } +// damagesTheProgramHas is every damage in the order tfg damage lists it, with +// the smallest file it takes at its defaults - the number that command prints, +// from the same call. +func damagesTheProgramHas() []site.Damage { + out := make([]site.Damage, 0, len(damage.All())) + for _, d := range damage.All() { + out = append(out, site.Damage{ID: d.ID, Smallest: d.Floor(d.Defaults()), Settings: d.ParameterNames()}) + } + return out +} + // languagesOnDisk reads every language description under web/content. func languagesOnDisk(t *testing.T) []site.Language { t.Helper() @@ -486,47 +499,6 @@ func TestEveryPageExistsInEveryLanguage(t *testing.T) { } } -// TestThePolishTextStaysOnThePolishPages holds the boundary the owner set when -// the site was allowed into this repository on 2026-08-26. -// -// D9 says text in the repository is English, and the criterion is the place -// rather than the reader. The site extends that rule to a second language and -// the extension is only as good as its border - so the border is machine -// checked here rather than remembered. Anything outside a pl directory that -// carries a character above ASCII is either a translation that leaked or an -// English page somebody typed a curly quote into, and both are defects. -func TestThePolishTextStaysOnThePolishPages(t *testing.T) { - root := webRoot(t) - text := map[string]bool{".html": true, ".json": true, ".css": true, ".xml": true, ".txt": true} - err := filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error { - if err != nil || d.IsDir() || !text[strings.ToLower(filepath.Ext(p))] { - return err - } - rel, relErr := filepath.Rel(root, p) - if relErr != nil { - return relErr - } - slashed := filepath.ToSlash(rel) - polish := strings.Contains(slashed, "/pl/") || strings.HasPrefix(slashed, "pl/") - b, readErr := os.ReadFile(p) - if readErr != nil { - return readErr - } - for n, line := range strings.Split(string(b), "\n") { - for col, r := range line { - if r > 127 && !polish { - t.Errorf("web/%s:%d:%d holds %q - only the Polish pages may carry it", slashed, n+1, col+1, r) - return nil - } - } - } - return nil - }) - if err != nil { - t.Fatalf("walking the site: %v", err) - } -} - // TestTheSiteFollowsThePunctuationRule applies rule 13 to the site. // // Fenced samples are left alone, the same way the README guard leaves licence diff --git a/internal/guard/sitelanguages_test.go b/internal/guard/sitelanguages_test.go new file mode 100644 index 00000000..4307685f --- /dev/null +++ b/internal/guard/sitelanguages_test.go @@ -0,0 +1,249 @@ +package guard + +import ( + "os" + "path/filepath" + "regexp" + "slices" + "strings" + "testing" + + "github.com/donislawdev/TestingFilesGenerator/internal/damage" + "github.com/donislawdev/TestingFilesGenerator/internal/site" +) + +// TestTranslatedTextStaysOnTheTranslatedPages holds the boundary the owner set +// when the site was allowed into this repository on 2026-08-26. +// +// D9 says text in the repository is English, and the criterion is the place +// rather than the reader. The site extends that rule to the languages it is +// translated into and the extension is only as good as its border - so the +// border is machine checked here rather than remembered. A character above +// ASCII may stand in the text of a language that is not the root one, and in +// the pages rendered from it. Anywhere else it is either a translation that +// leaked or an English page somebody typed a curly quote into, and both are +// defects. +// +// One thing from a translation is allowed to appear on every page, and it is +// the list of languages in the header. A visitor reading English has to be +// shown the way to Deutsch and to the Japanese, in the names those languages +// call themselves - a menu that said "German" would not be found by the person +// it is for. So the list is cut out of a page before the page is read, and +// nothing else is: a language name anywhere else in English text is a leak. +// +// This was a check on Polish alone until 2026-10-01, when the site was +// translated into a further twenty languages at the owner's request. The +// border moved with them: it is read from the language files, so a twenty +// third language needs no edit here, and a language that is not listed has no +// directory the border would let its text into. +func TestTranslatedTextStaysOnTheTranslatedPages(t *testing.T) { + root := webRoot(t) + languageMenu := regexp.MustCompile(`(?s)`) + // Relative to the web directory, with a trailing slash so that content/de + // does not let content/deutsch in. + var homes []string + for _, l := range languagesOnDisk(t) { + if l.Dir == "" { + continue + } + homes = append(homes, "content/"+l.Code+"/", "public/"+l.Dir+"/") + } + text := map[string]bool{".html": true, ".json": true, ".css": true, ".xml": true, ".txt": true} + err := filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() || !text[strings.ToLower(filepath.Ext(p))] { + return err + } + rel, relErr := filepath.Rel(root, p) + if relErr != nil { + return relErr + } + slashed := filepath.ToSlash(rel) + translated := slices.ContainsFunc(homes, func(home string) bool { return strings.HasPrefix(slashed, home) }) + b, readErr := os.ReadFile(p) + if readErr != nil { + return readErr + } + page := string(b) + if !translated { + page = languageMenu.ReplaceAllString(page, "") + } + for n, line := range strings.Split(page, "\n") { + for col, r := range line { + if r > 127 && !translated { + t.Errorf("web/%s:%d:%d holds %q - only the pages of a translation may carry it", slashed, n+1, col+1, r) + return nil + } + } + } + return nil + }) + if err != nil { + t.Fatalf("walking the site: %v", err) + } +} + +// TestEveryPageSaysWhichLanguageItIsAndWhereItsTranslationsAre holds what a +// search engine needs to serve the right language to the right reader. +// +// The site is generated, so each page is consistent with the language file it +// came from. What nothing else asks is whether those files, taken together, +// say one coherent thing to a crawler. Every page has to name its own language +// and carry the full set of alternates, its own included, plus x-default - and +// the page an alternate points at has to point back. A pair that does not +// reciprocate is dropped by Google, and the page it was meant to connect goes +// on competing with its own translation. The same page may not reuse the title +// or the description of a sibling in its language either: two pages with one +// title are one result to a search engine, and a snippet it writes itself. +func TestEveryPageSaysWhichLanguageItIsAndWhereItsTranslationsAre(t *testing.T) { + s := siteUnderTest(t) + rendered, err := s.Render() + if err != nil { + t.Fatalf("rendering the site: %v", err) + } + var root site.Language + byDir := map[string]site.Language{} + for _, l := range s.Languages { + if l.Dir == "" { + root = l + continue + } + byDir[l.Dir] = l + } + languageOf := func(file string) site.Language { + first, _, _ := strings.Cut(file, "/") + if l, ok := byDir[first]; ok { + return l + } + return root + } + fileOf := func(address string) string { + path := strings.Trim(strings.TrimPrefix(address, siteOrigin), "/") + if path == "" { + return "index.html" + } + return path + "/index.html" + } + + htmlTag := regexp.MustCompile(``) + alternate := regexp.MustCompile(``) + canonical := regexp.MustCompile(``) + locale := regexp.MustCompile(``) + title := regexp.MustCompile(`([^<]*)`) + description := regexp.MustCompile(``) + + pages := map[string]map[string]string{} + canonicals := map[string]string{} + seenTitle, seenDescription := map[string]string{}, map[string]string{} + for file, body := range rendered { + if filepath.Base(file) != "index.html" { + continue + } + text := string(body) + lang := languageOf(file) + tag := htmlTag.FindStringSubmatch(text) + if tag == nil || tag[1] != lang.Code || (tag[2] != "") != lang.RTL { + t.Errorf("%s should open as lang=%q with dir=rtl %v and says %q", file, lang.Code, lang.RTL, tag) + } + if m := locale.FindStringSubmatch(text); m == nil || m[1] != lang.Locale { + t.Errorf("%s should carry og:locale %q and says %q", file, lang.Locale, m) + } + if m := canonical.FindStringSubmatch(text); m == nil { + t.Errorf("%s has no canonical address", file) + } else { + canonicals[file] = m[1] + } + found := map[string]string{} + for _, m := range alternate.FindAllStringSubmatch(text, -1) { + found[m[1]] = m[2] + } + pages[file] = found + + for _, l := range s.Languages { + if _, ok := found[l.Code]; !ok { + t.Errorf("%s does not name its %s translation, so a search engine is not told it exists", file, l.Code) + } + } + if _, ok := found["x-default"]; !ok || len(found) != len(s.Languages)+1 { + t.Errorf("%s names %d alternates, and the languages are %d plus x-default", file, len(found), len(s.Languages)) + } + for _, field := range []struct { + name string + pattern *regexp.Regexp + seen map[string]string + }{{"title", title, seenTitle}, {"description", description, seenDescription}} { + m := field.pattern.FindStringSubmatch(text) + if m == nil { + t.Errorf("%s has no %s", file, field.name) + continue + } + key := lang.Code + "\x00" + m[1] + if other, dup := field.seen[key]; dup { + t.Errorf("%s and %s have one %s in %s: %q", file, other, field.name, lang.Code, m[1]) + } + field.seen[key] = file + } + } + for file, found := range pages { + lang := languageOf(file) + if found[lang.Code] != canonicals[file] { + t.Errorf("%s names %q as its own %s address and its canonical is %q", file, found[lang.Code], lang.Code, canonicals[file]) + } + for code, address := range found { + if code == "x-default" { + continue + } + other, ok := pages[fileOf(address)] + if !ok { + t.Errorf("%s names %s as its %s translation and nothing is published there", file, address, code) + continue + } + if back := other[lang.Code]; back != canonicals[file] { + t.Errorf("%s names %s as its %s translation, and that page points back to %q instead of %q", file, address, code, back, canonicals[file]) + } + } + } +} + +// TestEveryLanguageDescribesEveryDamage holds the page about corrupt files to +// what the program can break a file with. +// +// The table of damages is made from the registry, so a damage added there is a +// row on every page - and a row needs a sentence in every language, or the page +// would show a blank where the explanation goes. Read the other way as well: a +// sentence about a damage the program no longer has is a description of +// something that cannot be asked for. In English the sentence is the one the +// program prints under the name, word for word, because those are one sentence +// in two places and nothing else compares them. +func TestEveryLanguageDescribesEveryDamage(t *testing.T) { + facts := factsFromTheProgram(t) + if len(facts.Damages) == 0 { + t.Fatal("the program lists no damage, so this guard would pass against any language file") + } + for _, lang := range languagesOnDisk(t) { + for _, d := range facts.Damages { + said, ok := lang.Damages[d.ID] + if !ok { + t.Errorf("the damage %q has no sentence in %s, so its row would be blank", d.ID, lang.Code) + continue + } + if lang.Code == "en" && said != damageDetail(t, d.ID) { + t.Errorf("tfg damage describes %q as %q and the English page says %q", d.ID, damageDetail(t, d.ID), said) + } + } + for id := range lang.Damages { + if !slices.ContainsFunc(facts.Damages, func(d site.Damage) bool { return d.ID == id }) { + t.Errorf("%s describes a damage %q that the program does not have", lang.Code, id) + } + } + } +} + +// damageDetail is the sentence the program prints under one damage. +func damageDetail(t *testing.T, id string) string { + t.Helper() + d, err := damage.Get(id) + if err != nil { + t.Fatalf("the program has no damage %q: %v", id, err) + } + return d.Detail +} diff --git a/internal/site/languages.go b/internal/site/languages.go new file mode 100644 index 00000000..3be9efe2 --- /dev/null +++ b/internal/site/languages.go @@ -0,0 +1,100 @@ +// This file holds what a language has to look like before anything is +// rendered from it. +// +// A language file is written by hand, and the values in it end up in places +// nobody reads twice: the lang of a page, the hreflang of its alternates, the +// og:locale of a shared link, the address of every page and the line of the +// sitemap. A typo in any of them does not break a page. It makes a search +// engine quietly ignore one - an hreflang it cannot parse is dropped, and so +// is the page it was meant to connect. So the values are checked here, once, +// and the render stops and names the language instead. + +package site + +import ( + "fmt" + "regexp" +) + +var ( + // languageTag is a BCP 47 tag of the shapes this site uses: a language, an + // optional script and an optional region, as in de, zh-Hans and pt-BR. + languageTag = regexp.MustCompile(`^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$`) + + // openGraphLocale is language and region joined by an underscore, which is + // the only form the Open Graph protocol defines. + openGraphLocale = regexp.MustCompile(`^[a-z]{2,3}_[A-Z]{2}$`) +) + +// checkLanguages refuses a set of languages that would put a wrong or a +// repeated value on a page. +// +// It asks about the languages as a set because most of what can go wrong is a +// repetition: two languages under one prefix write their pages over each other, +// and two with one tag give a page two alternates that disagree. +func checkLanguages(langs []Language) error { + roots := 0 + claims := claimed{} + for _, l := range langs { + if err := checkLanguage(l); err != nil { + return err + } + if l.Dir == "" { + roots++ + } + if err := claims.add(l); err != nil { + return err + } + } + if roots != 1 { + return fmt.Errorf("%d languages are served at the root and exactly one has to be, because x-default points at it", roots) + } + return nil +} + +// claimed remembers which language holds each value that has to be unique. +type claimed map[string]string + +// add records the values of one language, or says which earlier language +// already holds one of them. +func (c claimed) add(l Language) error { + // In a fixed order, so the same mistake always reads the same. + for _, v := range [][2]string{{"code", l.Code}, {"locale", l.Locale}, {"directory", l.Dir}} { + if v[0] == "directory" && v[1] == "" { + continue + } + key := v[0] + " " + v[1] + if other, taken := c[key]; taken { + return fmt.Errorf("the %s %q is used by both %s and %s", v[0], v[1], other, l.Code) + } + c[key] = l.Code + } + return nil +} + +// checkLanguage asks the questions that need one language only. +func checkLanguage(l Language) error { + if !languageTag.MatchString(l.Code) { + return fmt.Errorf("the language %q has a code that is not a BCP 47 tag such as de, zh-Hans or pt-BR", l.Code) + } + if !openGraphLocale.MatchString(l.Locale) { + return fmt.Errorf("the %s language has the locale %q, and Open Graph wants language and region with an underscore, as in de_DE", l.Code, l.Locale) + } + if l.Name == "" { + return fmt.Errorf("the %s language has no name, so the link that leads to it would be blank", l.Code) + } + if l.Dir != "" && !addressable.MatchString(l.Dir) { + return fmt.Errorf("the %s language is served under %q, which cannot be part of an address - lower case letters, digits and single dashes can", l.Code, l.Dir) + } + seen := map[string]string{} + for _, p := range l.Pages { + if p.Slug != "" && !addressable.MatchString(p.Slug) { + return fmt.Errorf("the %s page %q has the slug %q, which cannot be part of an address - lower case letters, digits and single dashes can", l.Code, p.Key, p.Slug) + } + if other, taken := seen[p.Slug]; taken { + return fmt.Errorf("the %s pages %q and %q share the address %q, so one would be written over the other", l.Code, other, p.Key, p.Slug) + } + seen[p.Slug] = p.Key + } + return nil +} diff --git a/internal/site/render.go b/internal/site/render.go index c6262919..0c56b53d 100644 --- a/internal/site/render.go +++ b/internal/site/render.go @@ -51,6 +51,9 @@ func (s Site) Render() (map[string][]byte, error) { if len(s.Languages) == 0 { return nil, fmt.Errorf("a site with no languages has no pages to render") } + if err := checkLanguages(s.Languages); err != nil { + return nil, err + } out := map[string][]byte{} // Every language is filled in with the facts before anything is rendered, @@ -183,7 +186,7 @@ func (s Site) viewFor(lang Language, page Page) (view, error) { } v.Alternates = append(v.Alternates, Alternate{Lang: other.Code, URL: s.Origin() + pageURL(other, mate)}) if other.Code != lang.Code { - v.Switches = append(v.Switches, Switch{Name: other.Name, URL: pageURL(other, mate), Code: other.Code}) + v.Switches = append(v.Switches, Switch{Name: other.Name, URL: pageURL(other, mate), Code: other.Code, Locale: other.Locale}) } } if root, ok := s.rootLanguage(); ok { diff --git a/internal/site/site.go b/internal/site/site.go index 16adab40..3aa22f91 100644 --- a/internal/site/site.go +++ b/internal/site/site.go @@ -110,6 +110,19 @@ type Command struct { Summary string } +// Damage is one way this build can break a file on purpose, as the page about +// corrupt files lists it. +// +// The identifier, the smallest file and the names of the settings come from +// the registry. What the damage does is a sentence, and a sentence belongs to a +// language, so it is looked up in the language file by the identifier - the +// same split as a command and its summary. +type Damage struct { + ID string + Smallest int64 + Settings []string +} + // Download says which architectures a system actually gets. // // Both lists are here because they differ, and a page that flattened them into @@ -134,6 +147,11 @@ type Facts struct { Presets []PresetFacts Downloads []Download + // Damages is every way the program can break a file, in the order it + // lists them. It exists so the page about corrupt files cannot go on + // describing one when the program has two. + Damages []Damage + // Commands is what tfg --help prints, in the order it prints it, read out // of that help rather than out of a list beside it. Taking it from the // help is the point: it is the text a visitor is comparing the page @@ -205,37 +223,53 @@ type Page struct { Description string `json:"description"` Nav string `json:"nav"` - // The three below are never written in site.json. They are set on the - // pages made from a list rather than by hand - one per preset - and say - // which page they sit under, which content file holds their text, and - // which item of the list they are about. A page with a parent is left out - // of the header, and the parent is marked there while it is open. - Parent string `json:"-"` + // Parent is the key of the page this one sits under. A page with a parent + // is left out of the header, and the parent is marked there while it is + // open. The pages made from a list - one per preset - get one set in + // code, and a page written by hand may name its own in site.json. + Parent string `json:"parent,omitempty"` + + // The two below are never written in site.json. They are set on the + // pages made from a list, and say which content file holds their text and + // which item of the list they are about. Template string `json:"-"` Item string `json:"-"` } // Language is one whole version of the site. // -// Dir is the path prefix. It is empty for the language served at the root, -// which is the one search engines are pointed at by x-default. +// Code is the BCP 47 tag, and it is three things at once: the lang of every +// page, the hreflang other pages name it by, and the directory under +// web/content that holds its text. Locale is the same language the way Open +// Graph spells it, language and region with an underscore - sharing a link in +// German is og:locale de_DE, and a bare "de" is a value the specification does +// not define. Dir is the path prefix, which is a different thing again: lower +// case, so zh-Hans is served under /zh-hans/. // -// Endings, Terms, Presets, Commands and Outcomes are the places where a word -// has to exist for every value the program can produce, and a missing one is -// an error rather than a gap left in English. Endings is keyed by the exit code -// written out in decimal, Terms by the kind, unit or shape exactly as the -// registry spells it, Presets by the identifier, Commands by the name -// tfg --help prints, and Outcomes by the reaction a manifest declares. +// Dir is empty for the language served at the root, which is the one search +// engines are pointed at by x-default. RTL says the language is written right +// to left, which puts dir="rtl" on every page of it. +// +// Endings, Terms, Presets, Commands, Outcomes and Damages are the places where +// a word has to exist for every value the program can produce, and a missing +// one is an error rather than a gap left in English. Endings is keyed by the +// exit code written out in decimal, Terms by the kind, unit or shape exactly +// as the registry spells it, Presets by the identifier, Commands by the name +// tfg --help prints, Outcomes by the reaction a manifest declares and Damages +// by the identifier of the damage. type Language struct { Code string `json:"code"` + Locale string `json:"locale"` Name string `json:"name"` Dir string `json:"dir"` + RTL bool `json:"rtl,omitempty"` Words map[string]string `json:"words"` Endings map[string]string `json:"endings"` Terms map[string]string `json:"terms"` Presets map[string]PresetText `json:"presets"` Commands map[string]string `json:"commands"` Outcomes map[string]string `json:"outcomes"` + Damages map[string]string `json:"damages"` Pages []Page `json:"pages"` Faq []QA `json:"faq"` } @@ -280,9 +314,10 @@ type NavItem struct { // Switch is the link to this page in another language. type Switch struct { - Name string - URL string - Code string + Name string + URL string + Code string + Locale string } // Origin is the address the site is served from, without a trailing slash. diff --git a/internal/site/view.go b/internal/site/view.go index d4fb75ec..e5784de6 100644 --- a/internal/site/view.go +++ b/internal/site/view.go @@ -70,6 +70,7 @@ func (l Language) expand(f Facts) (Language, error) { out.Terms = everyValue(l.Terms) out.Commands = everyValue(l.Commands) out.Outcomes = everyValue(l.Outcomes) + out.Damages = everyValue(l.Damages) if l.Presets != nil { out.Presets = make(map[string]PresetText, len(l.Presets)) for id, text := range l.Presets { @@ -175,6 +176,35 @@ func (v view) CommandList() ([]Command, error) { return out, nil } +// DamageRow is one row of the table of damages. +type DamageRow struct { + ID string + Effect string + Smallest int64 + Settings []string + // None is the word for a damage that takes no settings, so a blank cell + // is never what says so. + None string +} + +// DamageList is every damage the program has, with what each does in the +// language being rendered. +func (v view) DamageList() ([]DamageRow, error) { + none, err := v.Word("noSettings") + if err != nil { + return nil, err + } + out := make([]DamageRow, 0, len(v.Facts.Damages)) + for _, d := range v.Facts.Damages { + effect, ok := v.Lang.Damages[d.ID] + if !ok { + return nil, fmt.Errorf("the damage %q has no sentence written in %s", d.ID, v.Lang.Code) + } + out = append(out, DamageRow{ID: d.ID, Effect: effect, Smallest: d.Smallest, Settings: d.Settings, None: none}) + } + return out, nil +} + // AllowedOf says what one setting accepts, in the language being rendered. // // The numbers come from the registry and the words from the language file. A diff --git a/web/assets/site.css b/web/assets/site.css index c60dcaac..6b90b60e 100644 --- a/web/assets/site.css +++ b/web/assets/site.css @@ -82,18 +82,18 @@ body { .skip { position: absolute; - left: -9999px; + inset-inline-start: -9999px; top: 0; background: var(--accent); color: var(--on-bright); padding: 10px 16px; - border-radius: 0 0 var(--radius) 0; + border-end-end-radius: var(--radius); font-weight: 600; z-index: 100; } .skip:focus { - left: 0; + inset-inline-start: 0; } /* ------------------------------------------------------------------ topbar */ @@ -110,7 +110,7 @@ body { .topbar-inner { display: flex; align-items: center; - gap: 24px; + gap: 16px; min-height: 62px; flex-wrap: wrap; } @@ -132,15 +132,16 @@ body { .mainnav { display: flex; - gap: 4px; + gap: 2px; flex-wrap: wrap; - margin-right: auto; + flex: 1 1 0; + min-width: 0; } .mainnav a { color: var(--text-dim); text-decoration: none; - padding: 6px 10px; + padding: 6px 7px; border-radius: 8px; font-size: 15px; } @@ -155,25 +156,85 @@ body { background: var(--surface-2); } -.langswitch { - display: flex; - gap: 6px; +.langmenu { + position: relative; + margin-inline-start: auto; } -.langswitch a { +.langmenu > summary { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; + list-style: none; font-size: 14px; - color: var(--muted); - text-decoration: none; + color: var(--text-dim); border: 1px solid var(--border); - padding: 4px 10px; + padding: 5px 12px; border-radius: 999px; + user-select: none; +} + +.langmenu > summary::-webkit-details-marker { + display: none; +} + +.langmenu > summary::after { + content: ""; + width: 6px; + height: 6px; + margin-top: -3px; + border-inline-end: 1.5px solid currentColor; + border-bottom: 1.5px solid currentColor; + transform: rotate(45deg); +} + +.langmenu[open] > summary::after { + margin-top: 3px; + transform: rotate(225deg); } -.langswitch a:hover { +.langmenu > summary:hover, +.langmenu[open] > summary { color: var(--text); border-color: var(--accent-dim); } +.langlist { + position: absolute; + inset-inline-end: 0; + top: calc(100% + 8px); + z-index: 50; + list-style: none; + margin: 0; + padding: 8px; + width: min(520px, calc(100vw - 40px)); + max-height: 70vh; + overflow-y: auto; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 2px; + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45); +} + +.langlist a { + display: block; + padding: 7px 10px; + border-radius: 8px; + font-size: 15px; + line-height: 1.4; + color: var(--text-dim); + text-decoration: none; +} + +.langlist a:hover { + color: var(--text); + background: var(--surface-2); +} + /* ------------------------------------------------------------- typography */ main { @@ -456,14 +517,14 @@ ul.plain li { .ticks li { position: relative; - padding-left: 26px; + padding-inline-start: 26px; margin-bottom: 10px; } .ticks li::before { content: ""; position: absolute; - left: 4px; + inset-inline-start: 4px; top: 0.62em; width: 8px; height: 8px; @@ -489,7 +550,7 @@ table.data { table.data th, table.data td { - text-align: left; + text-align: start; padding: 10px 14px; border-bottom: 1px solid var(--border-soft); vertical-align: top; @@ -516,7 +577,7 @@ table.data tbody tr:hover td { } table.data .num { - text-align: right; + text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; } @@ -553,6 +614,14 @@ pre code { white-space: pre; } +/* The short answer of a page is a sentence with a whole command in it, and a + * command can be longer than a phone is wide. A span that cannot break pushes + * the page sideways, so inside a note it may break where it has to. */ +.note code { + white-space: normal; + overflow-wrap: anywhere; +} + /* --------------------------------------------------------------------- faq */ .faq { @@ -610,7 +679,8 @@ pre code { } .qa-body { - padding: 0 20px 18px 46px; + padding: 0 20px 18px; + padding-inline-start: 46px; } .qa-body p:last-child { @@ -620,15 +690,16 @@ pre code { /* ------------------------------------------------------------------ callout */ .note { - border-left: 3px solid var(--accent); + border-inline-start: 3px solid var(--accent); background: var(--surface); - border-radius: 0 var(--radius) var(--radius) 0; + border-start-end-radius: var(--radius); + border-end-end-radius: var(--radius); padding: 16px 20px; margin: 24px 0; } .note.warn { - border-left-color: var(--warning); + border-inline-start-color: var(--warning); } .note p:last-child { @@ -652,14 +723,14 @@ pre code { .steps > li { counter-increment: step; position: relative; - padding-left: 46px; + padding-inline-start: 46px; margin-bottom: 30px; } .steps > li::before { content: counter(step); position: absolute; - left: 0; + inset-inline-start: 0; top: 0; width: 30px; height: 30px; @@ -737,6 +808,12 @@ pre code { padding-top: 40px; } + /* Sticky is a luxury of a header one row high. With the longer labels of + * some languages it takes a third of a phone, so it scrolls away here. */ + .topbar { + position: static; + } + .topbar-inner { gap: 12px; padding-top: 10px; @@ -745,8 +822,8 @@ pre code { .mainnav { order: 3; + flex-basis: 100%; width: 100%; - margin-right: 0; } .footer-inner { @@ -755,6 +832,91 @@ pre code { } .qa-body { - padding-left: 20px; + padding-inline-start: 20px; + } + + .langlist { + grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +/* --------------------------------------------------------------- languages */ + +/* The site loads no font in any language it is served in, so what a page is + * drawn in is whatever the visitor's system carries. + * The stacks below only put the right one first. A language tag on the page + * already tells a browser which regional form of a Han character to draw, but + * an unlucky default can still pick a face with no glyphs for the script, and + * naming the system faces is cheaper than finding out from a bug report. + * Every name is a face the operating system ships - nothing here is fetched. */ + +:root:lang(zh-Hans) { + --sans: system-ui, -apple-system, "PingFang SC", "Hiragino Sans GB", + "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif; +} + +:root:lang(zh-Hant) { + --sans: system-ui, -apple-system, "PingFang TC", "Microsoft JhengHei", + "Noto Sans CJK TC", "Noto Sans TC", sans-serif; +} + +:root:lang(ja) { + --sans: system-ui, -apple-system, "Hiragino Sans", "Hiragino Kaku Gothic ProN", + "Yu Gothic", Meiryo, "Noto Sans CJK JP", "Noto Sans JP", sans-serif; +} + +/* Japanese has no spaces to break a line at, so a browser that can read the + * phrases breaks between them rather than in the middle of one, and the strict + * rules keep small kana and the long vowel mark off the start of a line. A + * browser that does not know the first property ignores it and breaks as it + * always did. */ +:root:lang(ja) { + word-break: auto-phrase; + line-break: strict; +} + +:root:lang(ko) { + --sans: system-ui, -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", + "Noto Sans CJK KR", "Noto Sans KR", sans-serif; +} + +:root:lang(hi) { + --sans: system-ui, -apple-system, "Kohinoor Devanagari", "Nirmala UI", + "Noto Sans Devanagari", sans-serif; +} + +:root:lang(th) { + --sans: system-ui, -apple-system, "Thonburi", "Leelawadee UI", + "Noto Sans Thai", sans-serif; +} + +:root:lang(ar) { + --sans: system-ui, -apple-system, "Segoe UI", "Geeza Pro", Tahoma, + "Noto Sans Arabic", sans-serif; +} + +/* Thai and Devanagari carry marks above and below the line, and the body + * line height that suits Latin text crowds them. */ +:root:lang(th) body, +:root:lang(hi) body { + line-height: 1.85; +} + +/* Tracking is a Latin habit. Arabic letters join, so any space between them + * breaks a word apart, and in Devanagari and Thai it pulls the marks away + * from the letters they belong to. The headings and the small capitals above + * are tracked, so it is switched off for the whole page. */ +:root:lang(ar) *, +:root:lang(hi) *, +:root:lang(th) * { + letter-spacing: normal; +} + +/* Code is always left to right, in a page that reads right to left as well. + * Isolated, so the dashes and brackets of a flag stay where they were typed + * instead of being reordered by the sentence around them. */ +pre, +code { + direction: ltr; + unicode-bidi: isolate; +} diff --git a/web/content/ar/ci.html b/web/content/ar/ci.html new file mode 100644 index 00000000..46488b45 --- /dev/null +++ b/web/content/ar/ci.html @@ -0,0 +1,183 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

كيف تولّد ملفات الاختبار في خط CI

+

+ الملف الثنائي الثابت في المستودع يبقى في سجله إلى الأبد، ولا يمكن مراجعته في diff، ويصبح مستحيلًا + حين يكبر الملف. ولِّد الملفات بدلًا من ذلك داخل الخط من وصفة. الوصفة نص، والبايتات تخرج متطابقة في + كل مرة، وخطوة أخيرة تثبت أن شيئًا لم يتحرك. +

+ +
+

الجواب المختصر

+

+ ثبّت tfg، وشغّل tfg generate fixtures.yaml --out ./fixtures قبل + الاختبارات، وtfg verify ./fixtures/manifest.json بعدها. كلتا الخطوتين تُفشلان + البناء من تلقاء نفسيهما، برمز خروج يقول السبب. +

+
+ +
+

لماذا لا نودعها

+

لماذا لا ينبغي أن يعيش الملف الثابت في المستودع

+ +

+ الذي يُودَع هو الوصفة. الوصفة نفسها مع البذرة نفسها تكتب البايتات نفسها على أي جهاز، فالملف المولَّد + في الخط هو الملف الذي كان عندك على حاسوبك المحمول. +

+
+ +
+

الوصفة

+

وصفة تعيش بجانب الاختبارات

+

+ تكتب هذه خمسًا وعشرين فاتورة ينبغي قبولها وصورتين فوق الحد ينبغي رفضهما، ويسجّل البيان التوقعين + معًا: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml يفحصها دون أن يكتب شيئًا، ويسمّي كل المشكلات دفعة واحدة. +

+
+ +
+

GitHub Actions

+

سير عمل يثبّت الأداة ويبني الملفات الثابتة

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ سطر المجموع الاختباري يقارن الأرشيف بالملف verify-SHA256SUMS.txt من الإصدار نفسه. + الإصدار مثبَّت، فلا يغيّر إصدار جديد أبدًا بناءً لم تلمسه. +

+
+ +
+

GitLab CI

+

الشيء نفسه كمهمة في GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

حين يصبح أحمر

+

ما الذي يُفشل خطوة، ولماذا

+

+ لكل نهاية رمز خروج خاص بها، فتفشل الخطوة من تلقاء نفسها ويقول السجل أيّها كان. هذه هي التي يصادفها + الخط: +

+ +

+ التشغيل الفاشل لا يطبع شيئًا على الخرج القياسي، فلا يحسب محلل السجلات خطأً بيانات أبدًا. الجدول + الكامل في صفحة التوثيق. +

+
+ +
+

PowerShell

+

سكربت PowerShell يحتاج سطرًا إضافيًا

+

+ لا ينقل PowerShell رمز خروج برنامج إلى خارج ملف .ps1. شغّل واحدًا بـ -File + فيجيب السكربت 0 حتى حين رفضت الأداة داخله العمل، فيتحول بناء كان ينبغي أن يكون أحمر + إلى أخضر. السطر الأخير هو الإصلاح كله: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ هكذا يتصرف PowerShell، وليس في الأمر شيء يخص هذه الأداة. أما cmd وbash + وzsh فلا تحتاج إلى شيء إضافي. +

+
+ +
+

عدة مهام

+

مشاركة الملفات الثابتة بين المهام

+

+ لا حاجة عادةً إلى رفعها. لأن الوصفة نفسها تكتب البايتات نفسها، تستطيع كل مهمة تشغيل tfg + generate الخاص بها، وهذا أسرع من الرفع ثم التنزيل. وحين تحتاج مهمة إلى استلام ملفات من + أخرى، شغّل tfg verify على البيان بعد النقل، فيخبرك هل ما وصل هو ما كُتب. +

+
+ +
+

التالي

+

إلى أين من هنا

+ +
diff --git a/web/content/ar/damage.html b/web/content/ar/damage.html new file mode 100644 index 00000000..a66cdf66 --- /dev/null +++ b/web/content/ar/damage.html @@ -0,0 +1,164 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

كيف تصنع ملفًا تالفًا للاختبار

+

+ المدقق الذي لم يُعرض عليه إلا ملفات سليمة لم يُختبر حقًّا. إليك طريقة الحصول على ملف أُتلف عمدًا، + ويخرج بالحجم الذي تطلبه تمامًا، ويحمل بيانًا يقول ما الذي ينبغي أن يفعله نظامك + به. +

+ +
+

الجواب المختصر

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out يكتب ملف PNG حجمه + 2097152 بايتًا بالضبط، وبايتاته الأولى أصفار، ويسجّل البيان المجاور له أن نظامك ينبغي أن يرفضه. +

+
+ +
+

الطريقة المعتادة

+

لماذا يُعدّ الملف المتلف يدويًا اختبارًا رديئًا

+

+ الطرق المعتادة هي محرر سداسي عشري، أو سكربت يقلب بضع بايتات عشوائية، أو قصّ الملف بـ + head أو truncate. تنجح مرة واحدة، ثم تكلّفك: +

+ +
+ +
+

ما تحصل عليه

+

الملف التالف يبقى بالحجم الذي طلبته

+

+ يُولَّد الملف كالمعتاد ثم يُتلَف في طريقه إلى القرص. يحتفظ بالحجم الذي طلبته، ويكتب الأمر نفسه + البايتات نفسها مرة أخرى. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ تُكتب الإعدادات بعد النقطتين. يمكن تكرار الخيار، وتُطبَّق أنواع التلف بالترتيب الذي تكتبه. ويعمل مع + كل واحدة من {{ .Facts.FormatCount }} صيغة. +

+
+ +
+

ما الذي يستطيعه

+

ما أنواع التلف المتاحة؟

+

+ هذه هي القائمة التي يطبعها البرنامج، وتُقرأ منه عند بناء هذه الصفحة. يطبع tfg damage + القائمة نفسها، ويبيّن tfg damage <id> ما يقبله واحد منها. +

+ {{ template "damagesTable" . }} +

+ يكتب zero-head أصفارًا فوق بداية الملف. معظم القارئات تنظر إلى هناك أولًا، إلى التوقيع + والترويسة اللذين يقولان ما هو الملف، فتلاحظ ذلك أي قارئة تقريبًا. والنص العادي والسجلات لا توقيع + لها وتُرفض أيضًا، لأن سلسلة من البايتات الصفرية ليست نصًّا. وتحت أربعة بايتات تخرج بعض الصيغ + بتلف لا تشتكي منه أي قارئة، ولهذا يبدأ الإعداد من أربعة. +

+
+ +
+

ما يقوله البيان

+

بيان يقول ما ينبغي أن يحدث

+

+ كل ملف تالف يحصل على مدخل يقول إن نظامك ينبغي أن يرفضه، ويُسجَّل التلف بجانبه: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ يُرفض طلبان قبل أن يُكتب أي شيء، لأن كلًّا منهما سيترك على القرص ملفًا يصفه البيان وصفًا خاطئًا: +

+ +
+ +
+

في وصفة

+

ملفات سليمة وتالفة في تشغيل واحد

+

+ ضع الاثنين في وصفة واحدة، فيحمل البيان المتوقَّع لكل ملف، ولا يحتاج الاختبار إلى قائمة تقول أيها + أيّ: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

في اختبار

+

تحويله إلى اختبار

+

+ يقرأ الاختبار البيان ويتحقق من أن ما حدث هو ما أُعلن. لا يحتاج إلى قائمة بأسماء الملفات: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ الرفض الجيد هو الرفض النظيف. رسالة تقول ما الخطأ هي الجواب الذي تريده. أما خطأ الخادم أو التعليق أو + ملف حُفظ نصفه فهو العيب الذي وُجد هذا الاختبار لاكتشافه. +

+
+ +
+

التالي

+

إلى أين من هنا

+ +
diff --git a/web/content/ar/docs.html b/web/content/ar/docs.html new file mode 100644 index 00000000..73c6f221 --- /dev/null +++ b/web/content/ar/docs.html @@ -0,0 +1,269 @@ +

التوثيق

+

+ كل ما تفعله الأداة، مرتبًا على هيئة الأسئلة التي يأتي بها الناس فعلًا. ملف + README في المستودع هو المرجع الكامل ويطابق دائمًا الإصدار الذي + نزّلته. +

+ +
+

ما الأوامر المتاحة؟

+

كل أمر يؤدي مهمة واحدة:

+ {{ template "commandList" . }} +
+ +
+

كيف أولّد ملفًا واحدًا بحجم دقيق؟

+

+ حدد الصيغة والحجم ووجهة الملف. تُعدّ الأحجام بالمضاعفات 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>ثلاثة ملفات حول حد: أقل بايتًا واحدًا، والحد نفسه، وأكثر بايتًا واحدًا
--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اكتب البيان إلى المخرج القياسي
+
+
+ +
+

كيف أصنع ملفًا تالفًا عمدًا؟

+

+ كل ملف آخر تكتبه هذه الأداة صحيح بحكم بنائه، وهذا يجيب عن اثنين من ثلاثة أسئلة يطرحها مدقق الرفع. + أما --damage فيجيب عن الثالث: هل يُفتح الملف أصلًا. يُنتَج الملف بشكل طبيعي ثم + يُتلف، فيبقى بالحجم الذي طلبته. +

+
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 في البيان، مع تسجيل الإتلاف بجانبه. يُرفض أمران + قبل كتابة أي شيء، لأن كلًّا منهما كان سيضع على القرص ملفًا يصفه البيان وصفًا خاطئًا: +

+ +

+ أما الثالث فلا يمكن معرفته مسبقًا. إذا نُفّذ إتلاف ولم يحرّك أي بايت، يُسقَط ذلك الملف بدل كتابته، + ويستمر التشغيل ويذكر أي ملف كان، وينتهي برمز الخروج الجزئي. +

+

+ خطوة بخطوة، مع اختبار يقرأ البيان: كيف تصنع ملفًا تالفًا + للاختبار. +

+
+ +
+

كيف تبدو الوصفة؟

+

+ الوصفة ملف 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. اثنان خطأ، وعدم وجود أي منها خطأ كذلك. الوصفة غير الصالحة لا + تكتب أي ملف وتبلّغ عن كل المشكلات دفعة واحدة لا عن أولها فقط، وتسمّي كل مشكلة الإعداد + الذي تخصه. +

+
+ +
+

كيف أصرّح بما يجب أن يفعله نظامي بملف ما؟

+

الصيغة القصيرة حين تكفي النتيجة، والطويلة حين يهم السبب:

+
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. +

+

+ يسمّي السبب القاعدة المعنية لا الحكم. ولهذا يمكن أن يقع السبب نفسه تحت أي من + النتيجتين: ملف أقل من الحد بايتًا واحدًا نتيجته accept، والقاعدة المعنية تبقى + size_limit. +

+
+ +
+

ماذا يوجد في البيان؟

+

+ يُكتب بجانب الملفات في نهاية كل تشغيل، بما في ذلك التشغيل الذي أُوقف. عنصر واحد لكل ملف: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 حين يأتي من إعداد مسبق، فيمكن دائمًا تتبّع البيان إلى ما أنتجه. +

+

+ يحمل كل عنصر أيضًا target_id، وهو معرّف الهدف في الوصفة الذي أنتج الملف، ويحصي + summary.by_target الملفات التي انتهى إليها كل هدف. وهكذا يمكن فحص وصفة متعددة + الأهداف هدفًا هدفًا دون قراءة أسماء الملفات. +

+
+ +
+

ما الإعداد المسبق؟

+

+ مجموعة ملفات جاهزة تجيب عن سؤال اختبار شائع، فلا تحتاج إلى تصميم المجموعة بنفسك. الإعدادات المسبقة + وصفات عادية في جوهرها، ويطبع eject الوصفة لتعدّلها من هناك. لكل إعداد مسبق + صفحة خاصة تذكر ما يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+ {{ template "presetsList" . }} +
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 بكلفة المجموعة قبل أن تبنيها، ويقول صراحةً حين يكون رقم ما قيمة مؤقتة منا لا + حدًّا منك. +

+
+ +
+

ما معنى رموز الخروج؟

+

+ لكل نهاية رمزها الخاص، وتذهب المخرجات المقروءة آليًا إلى المخرج القياسي، ولا يطبع التشغيل الفاشل + شيئًا هناك. الجدول عقد مجمّد، وتغيير معنى رمز يتطلب رفع الإصدار الرئيسي. +

+ {{ template "exitCodesTable" . }} +
- 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. +

+
+ +
+

هل توجد نافذة سطح مكتب؟

+

+ نعم، المحرك نفسه بنافذة فوقه، للاختبار الذي لا يُكتب له سكربت. وهي ليست نسخة مبتورة: يقارن اختبار + الواجهتين ميزةً ميزة، وكل ما تستطيع إحداهما فعله دون الأخرى يجب أن يُعلَن ويُبرَّر بدل أن + يتباعدا بصمت. +

+

+ الشاشات هي دفعة واحدة، والإعدادات المسبقة، وعدة دفعات معًا، وحول. تُظهر كلفة التشغيل قبل كتابة أي + شيء، وتبلّغ عن التقدم أثناء العمل، ويمكن إلغاؤها في منتصف الطريق دون ترك ملف مكتوب نصفه. لا تفتح + ملف وصفة بعد، فالوصفات شأن سطر الأوامر حاليًا، وتبني النافذة دفعاتها في النموذج. +

+
diff --git a/web/content/ar/exact-size.html b/web/content/ar/exact-size.html new file mode 100644 index 00000000..9d6614a2 --- /dev/null +++ b/web/content/ar/exact-size.html @@ -0,0 +1,141 @@ +

كيف تنشئ ملفًا بحجم دقيق

+

+ لكل نظام أمر لذلك، والثلاثة كلها أدناه. تعطيك ملفًا بعدد البايتات الصحيح تمامًا، وفي كثير من + الاختبارات هذا كل ما تحتاجه. كل أمر في هذه الصفحة جُرِّب قبل النشر على النظام + الذي ينتمي إليه. +

+ +
+

الجواب المختصر

+

+ ويندوز: fsutil file createnew name 10485760. لينكس: dd if=/dev/zero of=name bs=1M + count=10. ماك: mkfile 10m name. الأحجام بالبايت، و10 MB محسوبة كما يحسبها + مدير الملفات لديك تساوي 10485760. +

+
+ +
+

ويندوز

+

fsutil، ونسخة PowerShell لا تحتاج إلى شيء إضافي

+

+ يأتي fsutil مع ويندوز. يأخذ الحجم بالبايت، فاحسب الرقم أولًا: 10 MB + تساوي 10485760، و100 MB تساوي 104857600، و1 GB تساوي 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ قيس على ويندوز 11: يعمل من موجّه عادي دون حاجة إلى موجّه مرتفع الصلاحيات، ويخرج الملف بحجم 10485760 + بايتًا بالضبط. +

+

يستطيع PowerShell فعل الشيء نفسه دون استدعاء برنامج آخر، ويفهم الوحدات:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ تعني 10MB في PowerShell ما قدره 10485760 بايتًا، وهو العدّ نفسه بأساس 1024 الذي يستخدمه + مستكشف الملفات، فيُنتج الأمران أعلاه الحجم نفسه. +

+
+ +
+

لينكس

+

dd وtruncate وfallocate، والفرق الذي يوقع الناس

+

dd هو الأمر الذي يعرفه الجميع. يكتب البايتات فعلًا:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate فوري، وهنا الفخ. قيس على Alpine Linux، فأبلغ الملف عن 10485760 بايتًا وشغل + صفر كتل، فهو ملف متناثر. كل ما يقرؤه يحصل على عشرة ميغابايت من + الأصفار، لكن القرص لم يتنازل عن المساحة قط: +

+
truncate -s 10M test10mb.bin
+

+ هذا مناسب لاختبار حد الرفع، ومضلل لاختبار حصة القرص. أما fallocate فهو ما تلجأ إليه حين + يجب أن تكون المساحة حقيقية: +

+
fallocate -l 10M test10mb.bin
+

وحين يجب أن يكون المحتوى غير قابل للضغط، حتى لا يستطيع أداة الأرشفة تصغيره من جديد:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

ماك

+

mkfile، وهو غير متناثر، والأمران اللذان تعرفهما بالفعل

+

+ يأتي ماك مع mkfile. قيس على macOS 26.6.2: 10485760 بايتًا و20480 كتلة، فالمساحة مخصصة + فعلًا لا موعودة فقط: +

+
mkfile 10m test10mb.bin
+

dd وtruncate موجودان أيضًا ويتصرفان كما في لينكس:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

أين يتوقف هذا عن الصلاحية

+

ملف بالحجم الصحيح ليس ملفًا من النوع الصحيح

+

+ كل ما سبق يعطيك كتلة من الأصفار. وهذا يكفي حين لا ينظر الشيء المختبَر إلا إلى الحجم، كحد الرفع أو + الحصة أو النقل. ويتوقف عن الكفاية لحظة أن يفتح أي شيء الملف. +

+

+ قيس، وهو يستحق أن تجرّبه بنفسك: أنشئ ملفًا بحجم 2 MB بـ fsutil، وسمّه + photo.png، وسلّمه إلى مكتبة صور. تجيب Pillow بـ cannot identify image + file. إنه ليس PNG. ولم يكن كذلك قط، فالاسم وحده قال ذلك. +

+

+ هذا أهم مما يبدو، بسبب الاتجاه الذي يفشل فيه الاختبار بعد ذلك. ترفض نقطة الرفع عندك + الملف، فيصبح اختبارك أخضر، وتستنتج أن حد الحجم يعمل. لم ترفضه بسبب الحجم. رفضته لأن البايتات لم + تكن صورة، ولم تُبلَغ القاعدة التي أردت اختبارها قط. +

+ +
+ +
+

الطريق الآخر

+

ملف حقيقي من تلك الصيغة، بالحجم الذي طلبته تمامًا

+

+ هذا ما يفعله Testing Files Generator. الملف ملف أصيل من صيغته، يُفتح في البرنامج الذي يملكه، وعدد + بايتاته هو ما طلبته بالضبط، حتى البايت: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ اطلب حجمًا لا تستطيع الصيغة بلوغه فتحصل على خطأ يذكر الحد الأدنى وسببه، لا ملفًا بحجم خاطئ أبدًا. + تسرد صفحة الصيغ كل صيغة مع أصغر ملف تستطيع إنتاجه. +

+

والحد حالات اختبار ثلاث لا حالة واحدة، لذا تبني الأداة الثلاث كلها:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ وهذا يعطيك 10485759 و10485760 و10485761 بايتًا، وبيانًا يقول أيها يجب أن يقبله نظامك وأيها يجب أن + يرفضه. تستعرض صفحة حالات الاستخدام هذا وأربع مهام أخرى بُنيت الأداة + لها. +

+ {{ template "downloadCta" . }} +
+ +
+

فأيهما تستخدم؟

+ +

+ الاثنان في هذه الصفحة لأن كلًّا منهما صواب في بعض الأحيان. الخطأ الذي ينبغي تجنبه هو استخدام الأول + حيث يلزم الثاني وقراءة الاختبار الأخضر كدليل. +

+
diff --git a/web/content/ar/faq.html b/web/content/ar/faq.html new file mode 100644 index 00000000..b526637d --- /dev/null +++ b/web/content/ar/faq.html @@ -0,0 +1,18 @@ +

الأسئلة الشائعة

+

+ الترخيص والخصوصية وقابلية إعادة الإنتاج وما يتحقق منه الناس قبل إدخال مولّد في خط بناء. إذا لم يكن + سؤالك هنا، فإن متتبع المشكلات مفتوح. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

ما زلت تقرر؟

+

+ تعرض صفحة حالات الاستخدام المهام التي بُنيت الأداة لها، وتسرد + صفحة الصيغ كل صيغة مع أصغر ملف تستطيع إنتاجه. وملف + README في المستودع هو المرجع الكامل. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ar/formats.html b/web/content/ar/formats.html new file mode 100644 index 00000000..d521dafe --- /dev/null +++ b/web/content/ar/formats.html @@ -0,0 +1,74 @@ +

{{ .Facts.FormatCount }} صيغة ملف، كلٌّ منها يُولَّد بحجم دقيق

+

+ كلٌّ منها ملف حقيقي من تلك الصيغة. يُفتح في البرنامج الذي يملكه، وعدد بايتاته هو ما + طلبته بالضبط. ولا واحد منها أصفار حشوية أُلصق بها امتداد. +

+ +{{ template "formatsTable" . }} + +
+

معنى الأعمدة

+ +

+ وتتكرر كل صيغة حتى البايت أيضًا: الوصفة نفسها والبذرة نفسها تنتجان ملفات متطابقة على أي جهاز، وهذا + ما يجعل إيداع وصفة بدل بيانات الاختبار نفسها أمرًا آمنًا. +

+
+ +
+

الإعدادات التي تقبلها كل صيغة

+

+ لمعظم الصيغ إعدادات خاصة بها: أبعاد الصورة، وجودة JPEG، وعدد صفحات PDF، والصفوف والأعمدة في جدول + بيانات، وعدد العناصر داخل الأرشيف. اضبطها بـ --set key=value في سطر الأوامر أو تحت + properties: في وصفة. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ القيمة الواقعة خارج ما يقبله الإعداد تُرفض برسالة تسمّي الإعداد والنطاق المسموح وما يُستخدم بدلًا + منه. والإعداد المجهول خطأ أيضًا، وليس قيمة افتراضية صامتة أبدًا، فخطأ مطبعي يُقبل بصمت يعطي + ملفًا بإعدادات خاطئة وساعة من التساؤل عن سبب نجاح اختبار كان ينبغي ألا ينجح. +

+

+ شغّل tfg formats <id> لترى بالضبط ما تقبله صيغة واحدة في الإصدار الذي لديك. +

+
+ +
+

الأرشيفات تحتوي ملفات حقيقية

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} و{{ end }}{{ $c.ID }}{{ end }} يمكن + ملؤها بعناصر بدل تركها قشرة فارغة. الأرشيف المولَّد يحتوي فعلًا على المستندات التي يدّعي + احتواءها، فكل ما يفكّه أثناء اختبار يجد بداخله ملفات حقيقية. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/ar/index.html b/web/content/ar/index.html new file mode 100644 index 00000000..2e2e10c0 --- /dev/null +++ b/web/content/ar/index.html @@ -0,0 +1,193 @@ +
+
+

ولّد ملفات اختبار حقيقية بحجم دقيق

+

+ PDF وPNG وDOCX وZIP، {{ .Facts.FormatCount }} صيغة في المجمل، وكلٌّ منها ملف حقيقي + يُفتح في البرنامج الذي يملكه، وبـالحجم الذي طلبته تمامًا. كما يدوّن كل تشغيل ما + يجب أن يفعله تطبيقك بكل ملف. سطر أوامر ونافذة سطح مكتب، مجاني ومفتوح المصدر، ويعمل بالكامل على + جهازك. +

+ + {{ template "downloadCta" . }} +
+ +
+ نافذة سطح المكتب لـ Testing Files Generator، مجهّزة لكتابة دفعة من ملفات الاختبار +
نافذة سطح المكتب، مجهّزة لكتابة دفعة من الملفات. المحرك نفسه يعمل خلف سطر الأوامر.
+
+
+ + + +
+

المشكلة

+

صنع ملف اختبار واحد سهل. صنع الألف الصحيحة هو الجزء المرهق

+

أنت تختبر برنامجًا يقبل ملفات من الناس. عاجلًا أم آجلًا ستحتاج إلى:

+ +

+ هذا ما يحل محله هذا المولّد. صُمم لمهندسي ضمان الجودة وأتمتة الاختبار، ولكل من خلف شيفرته نموذج رفع + أو روتين استيراد أو محلل أو حصة تخزين. +

+
+ +
+

ما الذي يميّزه

+

المولّدات الأخرى تتوقف عند البايتات. هذا المولّد يجيب عما يسأله اختبارك فعلًا

+

+ مجلد من الملفات يتركك تقرر بنفسك ما يُفترض أن يثبته كل ملف. يكتب كل تشغيل هنا ملف + manifest.json بجانب الملفات، وهو قائمة بسيطة بكل ما أُنتج، ولكل عنصر توقّع + معلن. +

+

لنفترض أن نقطة الرفع عندك تسمح بـ 1 MB. اطلب الملفات الثلاثة الواقعة على هذا الخط:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
الملفالبايتاتما يجب أن يفعله نظامكالسبب
1mb_under_1b.pdf1048575قبولداخل الحد
1mb_at_limit.pdf1048576قبولالحد نفسه مسموح
1mb_over_1b.pdf1048577رفضsize_limit
+
+ +

ثلاثة ملفات، وثلاث إجابات مختلفة، بصيغة تقرؤها الآلة. يقرأ اختبارك البيان بدل أن تكتب التأكيدات يدويًا:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

حين تعتمد الإجابة على سياستك أنت، يقول البيان ذلك

+

+ يسجّل unspecified بدل اختلاق توقّع. المولّد الذي يخمّن يصنع إخفاقات زائفة، ومجموعة + الاختبارات التي تطلق إنذارات كاذبة يُوقف العمل بها. +

+
+
+ +
+

الإعدادات المسبقة

+

اختر السؤال، واحصل على المجموعة كاملة

+

+ الإعداد المسبق مجموعة ملفات اختبار مصممة حول سؤال اختبار واحد، فلا تحتاج إلى معرفة أي الملفات يثبت + ماذا. لكل منها صفحة تذكر ما يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+ {{ template "presetsList" . }} +

كل الإعدادات المسبقة، وعلاقتها بالوصفات

+
+ +
+

بداية سريعة

+

ثلاثة أوامر لترى الأداة تعمل

+
    +
  1. +

    أنشئ ملفًا

    +

    ملف PNG واحد، بحجم ميغابايتين تمامًا:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    أنشئ ملفات كثيرة

    +

    + عشرة آلاف ملف سجل، حجم كل منها بين واحد وثمانية كيلوبايت، تُسحب الأحجام من البذرة ليعطي الغد + المجموعة نفسها. امنح كل تشغيل مجلده الخاص، فالبيان هو السجل الوحيد لما كتبه + التشغيل، لذا ترفض الأداة كتابة بيان ثانٍ فوقه: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    افحصها، ثم احذفها

    +

    يخبرك verify بأن شيئًا لم يتحرك. ويحذف cleanup ما كُتب بالضبط ولا شيء غيره:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ تُعدّ الأحجام بالمضاعفات 1024 كما يفعل مدير الملفات لديك، فـ2mb تعني 2097152 بايتًا. + وعدد البايتات المجرد يصلح أيضًا. يغطي التوثيق الوصفات والبيان ورموز + الخروج. +

+
+ +
+

ما تحصل عليه

+

مبني لمجموعة اختبارات تعمل دون إشراف

+ +
+ +
+

التنزيل

+

اختر الإصدار المناسب لنظامك

+

+ فك ضغط الأرشيف وشغّل الملف. tfg هو سطر الأوامر وtfg-gui هو نافذة سطح + المكتب. لا يوجد مثبّت ولا شيء يُضاف إلى جهازك. +

+ {{ template "downloadsTable" . }} +
+

ما الموقَّع وما غير الموقَّع

+

+ تنزيلات ويندوز وماك موقّعة، لذا تبدأ دون تحذير من مطوّر غير معروف. أما تنزيلات لينكس فغير موقّعة، + لأن لينكس المكتبي لا يملك ما يوقَّع به. وكل أرشيف مدرج في verify-SHA256SUMS.txt + على صفحة الإصدارات، لتتحقق مما نزّلته. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/ar/preset.html b/web/content/ar/preset.html new file mode 100644 index 00000000..6843196d --- /dev/null +++ b/web/content/ar/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ يبني الإعداد المسبق {{ .ID }} بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ +{{ if .Catches }} +
+

ماذا يكتشف عادةً؟

+ +
+{{ end }} + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show {{ .ID }}:

+
+ + + + + + + +
الملفات{{ .Budget.Files }}
الأهداف في وصفته{{ .Budget.Targets }}
الحجم الإجمالي{{ .Bytes }} B
الصيغ{{ join .Budget.Formats ", " }}
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
المتوقعالمعنىالملفات
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

ما الذي يمكنك تغييره؟

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
الإعداديقبلالافتراضيما يفعله
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} هذه القيمة الافتراضية مؤقتة منا، وليست قيمة نظامك. مرّر قيمتك أنت.{{ end }}
+
+ {{- else }} +

لا إعدادات لهذا الإعداد المسبق. المجموعة هي نفسها في كل مرة.

+ {{- end }} +
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/ar/presets.html b/web/content/ar/presets.html new file mode 100644 index 00000000..679ae87a --- /dev/null +++ b/web/content/ar/presets.html @@ -0,0 +1,29 @@ +

إعدادات مسبقة لملفات الاختبار، مجموعة لكل سؤال اختبار

+

+ الإعداد المسبق مجموعة كاملة من ملفات الاختبار مصممة حول سؤال واحد، مع بيان يحدد كيف يجب أن يتفاعل + نظامك مع كل ملف. أنت تختار السؤال، والأداة تبني المجموعة. لكل إعداد مسبق صفحته الخاصة التي تذكر ما + يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+ +{{ template "presetsList" . }} + +
+

بماذا يختلف الإعداد المسبق عن الوصفة؟

+

+ في جوهره، لا يختلف. الإعداد المسبق وصفة تكتبها الأداة لك من بضعة إعدادات. يطبع tfg preset + eject تلك الوصفة لتحتفظ بها بجانب اختباراتك وتعدّلها، ويمكن لوصفة خاصة بك أن تبني على + إعداد مسبق بسطر واحد: extends: preset: يليه معرّفه. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

هل يمكنني الوثوق بالقيم الافتراضية؟

+

+ بالنسبة إلى الملفات، نعم. أما الرقم الذي لا يعرفه إلا نظامك، مثل حد نموذج الرفع، فالقيمة الافتراضية + قيمة مؤقتة منا، وتقول الأداة ذلك في كل مرة تستخدم فيها واحدة. وتعلّم صفحة كل إعداد مسبق تلك + الإعدادات، ويقول tfg preset show ذلك قبل كتابة أي شيء. +

+
diff --git a/web/content/ar/site.json b/web/content/ar/site.json new file mode 100644 index 00000000..a23bceb3 --- /dev/null +++ b/web/content/ar/site.json @@ -0,0 +1,329 @@ +{ + "code": "ar", + "locale": "ar_AR", + "name": "العربية", + "dir": "ar", + "rtl": true, + "pages": [ + { + "key": "index", + "slug": "", + "nav": "الرئيسية", + "title": "مولّد ملفات الاختبار لضمان الجودة - حجم دقيق، {{ .Facts.FormatCount }} صيغة حقيقية", + "description": "مولّد ملفات اختبار مجاني ومفتوح المصدر لضمان الجودة. ملفات PDF وDOCX وPNG وZIP حقيقية بحجم دقيق، مع بيان يحدد كيف يجب أن يتفاعل نظامك." + }, + { + "key": "formats", + "slug": "formats", + "nav": "الصيغ", + "title": "{{ .Facts.FormatCount }} صيغة ملف مدعومة - PDF وDOCX وPNG وZIP وغيرها", + "description": "كل صيغ الملفات التي يولّدها المولّد، وأصغر ملف ممكن لكل صيغة، والإعدادات التي تقبلها. تُفتح كل الصيغ الـ {{ .Facts.FormatCount }} في برامجها الأصلية." + }, + { + "key": "presets", + "slug": "presets", + "nav": "الإعدادات المسبقة", + "title": "إعدادات مسبقة لملفات الاختبار - مجموعات جاهزة لأسئلة ضمان الجودة", + "description": "مجموعات جاهزة من ملفات الاختبار، تجيب كل منها عن سؤال اختبار واحد: حدود الرفع، وأسماء الملفات، والترميزات، واستيراد الجداول، والملفات الفارغة، والتحقق." + }, + { + "key": "docs", + "slug": "docs", + "nav": "التوثيق", + "title": "التوثيق - الأوامر والوصفات والبيان ورموز الخروج", + "description": "كيف تولّد ملفات اختبار من سطر الأوامر أو من وصفة YAML، وما يحتويه البيان، وما معنى كل رمز خروج عند التشغيل في CI." + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "حالات الاستخدام", + "title": "حالات الاستخدام - حدود الرفع وبيانات CI والاختبار الكمي", + "description": "اختبار حد حجم الرفع، وبناء بيانات اختبار قابلة لإعادة الإنتاج لـ CI، وتوليد عشرة آلاف ملف، وملء الأرشيفات بمحتوى حقيقي." + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "الحجم الدقيق", + "title": "كيف تنشئ ملفًا بحجم محدد - ويندوز ولينكس وماك", + "description": "fsutil وdd وtruncate وmkfile، كلٌّ منها مُقاس على نظامه، ولماذا لا يصلح ملف منشأ بهذه الطريقة عندما يحتاج الاختبار إلى PDF أو PNG." + }, + { + "key": "faq", + "slug": "faq", + "nav": "الأسئلة الشائعة", + "title": "الأسئلة الشائعة - عن توليد ملفات الاختبار", + "description": "بماذا يختلف عن dd وfsutil، وهل يمكن إيداع الملفات بأمان، وهل تتكرر التشغيلات بايتًا ببايت، وماذا يحدث إذا تعذر بلوغ حجم ما." + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "ملفات تالفة", + "title": "ملفات اختبار تالفة - ملفات معطوبة بحجم دقيق", + "description": "ملف أُتلف عمدًا بحجم دقيق، مع بيان يقول إن نظامك ينبغي أن يرفضه. لاختبار التحقق من الرفع والمحللات.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "ملفات الاختبار في CI", + "title": "ملفات الاختبار في CI - GitHub Actions وGitLab CI وPowerShell", + "description": "ولّد ملفات الاختبار في الخط بدل إيداع الملفات الثنائية: سير عمل GitHub Actions، ومهمة GitLab، ورموز الخروج، وفخ PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "تخطَّ إلى المحتوى", + "navLabel": "القائمة الرئيسية", + "langLabel": "اللغة", + "breadcrumbHome": "الرئيسية", + "imageAlt": "Testing Files Generator - ملفات اختبار حقيقية بحجم دقيق، مع بيان يحدد كيف يجب أن يتفاعل نظامك مع كل ملف", + "schemaDescription": "مولّد ملفات اختبار مجاني ومفتوح المصدر لضمان الجودة. ينتج ملفات حقيقية بـ {{ .Facts.FormatCount }} صيغة وبحجم دقيق، ويكتب بيانًا يحدد كيف يجب أن يتفاعل النظام قيد الاختبار مع كل ملف.", + "ctaDownload": "تنزيل", + "ctaSource": "عرض الشيفرة المصدرية", + "ctaNote": "مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.", + "colFormat": "الصيغة", + "colName": "الاسم", + "colExtension": "الامتداد", + "colSmallest": "أصغر ملف", + "colFidelity": "الاكتمال", + "colChecked": "يُتحقق منه بواسطة", + "colSetting": "الإعداد", + "colAccepts": "القيم المقبولة", + "colSystem": "النظام", + "colCli": "سطر الأوامر", + "colWindow": "نافذة سطح المكتب", + "noBinary": "لا يوجد ملف تنفيذي بعد", + "colCode": "الرمز", + "colMeaning": "المعنى", + "footerBlurb": "ملفات اختبار لضمان الجودة بحجم دقيق، مع بيان يحدد كيف يجب أن يتفاعل نظامك مع كل ملف.", + "footerProject": "المشروع", + "footerSource": "الشيفرة المصدرية على GitHub", + "footerReleases": "التنزيلات", + "footerIssues": "الإبلاغ عن مشكلة", + "footerSupport": "ادعم المشروع", + "footerPages": "الصفحات", + "footerLicence": "Copyright (C) 2026 DonislawDev. مُصدَر بموجب رخصة جنو العمومية العامة، الإصدار 3. الملفات التي تولّدها ملكك، فالرخصة تشمل الأداة لا مخرجاتها.", + "footerPrivacy": "لا يحمّل هذا الموقع خطوطًا ولا سكربتات ولا متتبعات من أي مكان. ولا يضبط ملفات تعريف الارتباط.", + "notFoundTitle": "هذه الصفحة غير موجودة", + "notFoundLead": "العنوان الذي اتبعته لا يطابق أي صفحة في هذا الموقع.", + "notFoundBack": "العودة إلى الصفحة الرئيسية", + "read.format": "صيغة كل ملف في المجموعة. إنه خيار في الأداة نفسها، والإعداد المسبق يمنحه قيمة افتراضية فقط.", + "readTakes.format": "معرّف صيغة من صفحة الصيغ", + "colDamage": "التلف", + "colEffect": "ما يفعله بالبايتات", + "colSettings": "الإعدادات", + "noSettings": "لا شيء" + }, + "endings": { + "0": "عمل كل شيء.", + "1": "خطأ غير متوقع داخل الأداة.", + "2": "أمر أو خيار خاطئ.", + "3": "الوصفة غير صالحة.", + "4": "لا تستطيع الصيغة فعل ما طُلب منها.", + "5": "فشلت قراءة أو كتابة.", + "6": "لا توجد مساحة كافية على القرص.", + "7": "وجد verify عدم تطابق.", + "8": "انتهى التشغيل لكن لم يُنتَج كل شيء.", + "130": "أُوقف بواسطة Ctrl+C.", + "143": "أوقفته إشارة، وهذا ما يبدو عليه انتهاء مهلة CI." + }, + "presets": { + "empty-and-minimal": { + "question": "هل يمر ملف صالح بأصغر حجم تسمح به الصيغة؟", + "title": "الفارغ والأدنى", + "pageTitle": "أصغر ملفات اختبار صالحة وفارغة في كل صيغة", + "description": "أصغر ملف صالح تكتبه الأداة في كل صيغة من صيغها الـ {{ .Facts.FormatCount }}، وملف فارغ حيث تسمح الصيغة، ومع كل ملف التفاعل المتوقع.", + "catches": [ + "ملف صالح يُرفض لأنه صغير جدًا، لأن الفحص يعدّ البايتات بدل قراءتها", + "ملف فارغ يُسقط القارئ بدل أن يُبلَّغ عنه", + "صورة بعرض بكسل واحد تقسم على صفر في طريقها إلى الصورة المصغرة", + "تخزين يقرأ صفر بايت على أنه رفع فاشل ويواصل إعادة المحاولة" + ], + "details": { + "formats": "الصيغ التي تتكون منها المجموعة. اتركها على all لكل صيغ هذا الإصدار، أو سمِّ الصيغ التي يقبلها نظامك." + } + }, + "filename-handling": { + "question": "هل سيخزّن نظامي ويعرض ويعيد اسم ملف لم يتوقعه؟", + "title": "التعامل مع أسماء الملفات", + "pageTitle": "أسماء ملفات إشكالية للاختبار - يونيكود والطول", + "description": "ملفات بأسماء تكسر الرفع والتخزين: أنظمة كتابة أخرى ورموز تعبيرية، وعكس اتجاه الكتابة، وأحرف غير مرئية، وصيغ shell وSQL، وحدود الطول.", + "catches": [ + "اسم يبدو كاسم آخر على الشاشة أو في السجل أو في قائمة", + "اسم يُقطع أو يُقص أو يُعاد كتابته بين الرفع والتخزين", + "حد للطول يُحسب بالأحرف بينما يحسب التخزين بالبايتات" + ], + "details": {} + }, + "size-boundaries": { + "question": "هل يُطبَّق حد الحجم تمامًا حيث أُعلن عنه؟", + "title": "حدود الحجم", + "pageTitle": "اختبار حد حجم الرفع - ملفات عند الحد تمامًا", + "description": "ملفات أقل بايتًا واحدًا من الحد الذي يعلنه نظامك، وعنده تمامًا، وأكثر منه بايتًا واحدًا، مع خطوات أوسع على الجانبين، وكل ملف مُعلَّم بما إذا كان يجب قبوله.", + "catches": [ + "أخطاء الفرق بواحد عند الحد", + "خلط MB مع MiB، أي 4.8 بالمئة، وهذا كافٍ لتمرير ملف لا ينبغي أن يمر", + "حد يُطبَّق في المتصفح لا على الخادم" + ], + "details": { + "limit": "حد الحجم الذي يعلنه نظامك. كل شيء آخر يُقاس منه.", + "spread": "إلى أي مدى يمتد على جانبي الحد، كقائمة أحجام." + } + }, + "tabular-import": { + "question": "هل يصمد استيراد الجداول عندي أمام ما تصدّره الأدوات الحقيقية؟", + "title": "استيراد الجداول", + "pageTitle": "ملفات اختبار استيراد CSV وExcel - الفواصل والعناوين", + "description": "ملفات CSV بفواصل أخرى ونهايات أسطر CR LF وبلا ترويسة وبعلامات اقتباس مختلفة، وجدول عريض جدًا، وكتاب Excel، وJSON بتخطيطات عدة.", + "catches": [ + "ملف بفاصلة منقوطة يُقرأ كعمود واحد، لأن الفاصل افتُرض بدل أن يُبحث عنه", + "ملف CRLF يُقسَّم إلى صفوف مع صف فارغ بعد كل صف", + "جدول بلا ترويسة يُبتلع صف بياناته الأول كأسماء أعمدة", + "استيراد يحتفظ بالأعمدة التي يستطيع عرضها ويُسقط الباقي دون كلمة", + "قارئ يأخذ سجلات JSON سطرًا سطرًا ويتوقف عند أول مستند بمسافة بادئة" + ], + "details": { + "rows": "عدد الصفوف في الجدول. يُكتب الملف بالحجم الذي تُعبَّأ إليه هذه الصفوف تمامًا، لذا تتحرك الميزانية أعلاه مع هذه القيمة.", + "columns": "عدد الأعمدة في كل صف من الجدول. لحاصل ضرب الصفوف في الأعمدة سقف، وأي طلب يتجاوزه يُرفض قبل أن يُكتب أي شيء." + } + }, + "text-encoding": { + "question": "هل يعرف قارئي ترميز الملف، أم يخمّن؟", + "title": "ترميز النص", + "pageTitle": "ملفات اختبار ترميز النص - UTF-8 وUTF-16 وBOM وCRLF", + "description": "النص نفسه بترميز UTF-8 وUTF-16LE وUTF-16BE، مع علامة ترتيب البايتات وبدونها، ونهايات أسطر CR LF وLF، لاختبار كيف يفك القارئ ترميز النص.", + "catches": [ + "قارئ يفترض UTF-8 فيعرض ملف UTF-16 بحرف واحد من كل ثلاثة أو كصفوف من المربعات", + "علامة ترتيب بايتات تُقرأ كمحتوى، فيبدأ أول حقل في الاستيراد بثلاثة أحرف غريبة", + "مستورد يخمّن الترميز من البايتات الأولى ويخمّن بشكل مختلف مع ملف أطول", + "ملف CRLF يُقسَّم إلى صفوف مع صف فارغ بعد كل صف، أو حرف إرجاع الحامل يبقى داخل الحقل الأخير" + ], + "details": { + "sample": "حجم كل ملف في المجموعة. يخزّن UTF-16 بايتين لكل حرف، لذا يُرفض العدد الفردي." + } + }, + "upload-validation": { + "question": "هل يقبل نموذج الرفع عندي ما يجب قبوله ويرفض الباقي؟", + "title": "التحقق من الرفع", + "pageTitle": "ملفات اختبار التحقق من الرفع - النوع والحجم والاسم", + "description": "ملفات لاختبار نموذج الرفع: أنواع مسموحة ومرفوضة، ومحتوى لا يطابق الامتداد، وحد الحجم على جانبيه، وأسماء خبيثة، ورفع جماعي.", + "catches": [ + "حد يُطبَّق في المتصفح لا على الخادم", + "ملف SVG أو HTML يُؤخذ على أنه صورة أو نص عادي، وهي طريقة لتمرير سكربت عبر نموذج", + "ملف يُفحص بامتداده ولا يُفتح أبدًا، فيمر ملف PDF اسمه .jpg", + "نموذج يقرأ الجسم كله في الذاكرة قبل أن ينظر كم حجمه", + "رفع باسم PHOTO.JPG يُرفض بينما يُقبل photo.jpg، أو العكس", + "اسم فيه مسافات أو أقواس أو أحرف خارج ASCII يُكتب على القرص دون تغيير" + ], + "details": { + "limit": "حد الحجم الذي يعلنه نموذج الرفع عندك. تأخذ هذه المجموعة خطوة واحدة على كل جانب منه، ولملف عند كل مسافة شغّل الإعداد المسبق size-boundaries.", + "allow": "الأنواع التي يجب أن يقبلها نموذجك. يصير كل نوع ملفًا حقيقيًا من ذلك النوع، وتشكّل الشاهد الإيجابي للمجموعة كلها.", + "deny": "الامتدادات التي يجب أن يرفضها نموذجك. الامتداد الذي لا صيغة له في هذا الإصدار يحصل مع ذلك على ملف بهذا الاسم يحتوي نصًا عاديًا.", + "far-over": "إلى أي مدى يتجاوز الملف الكبير الوحيد الحد. أوقفه حيث لا يستحق كتابة أضعاف الحد مساحة القرص.", + "bulk": "عدد الملفات في الرفع الجماعي. الصفر يُخرج هذه المجموعة من المجموعة كليًا." + } + } + }, + "commands": { + "generate": "توليد ملفات، من وصفة أو من خيارات", + "validate": "فحص وصفة دون كتابة شيء", + "verify": "فحص مجلد مقابل بيان", + "cleanup": "حذف الملفات التي يسردها بيان", + "recipe fmt": "طباعة وصفة بشكلها المستقر", + "preset": "بناء مجموعة ملفات من سؤال اختبار مُسمّى", + "formats": "سرد الصيغ التي يدعمها هذا الإصدار", + "damage": "سرد الطرق التي يستطيع بها هذا الإصدار إتلاف ملف عمدًا", + "tool": "أدوات صغيرة للملفات التي لديك بالفعل", + "version": "طباعة إصدار الأداة", + "license": "طباعة الرخصة ومعناها للملفات المولَّدة" + }, + "outcomes": { + "accept": "ينبغي أن يقبل نظامك الملف.", + "reject": "ينبغي أن يرفض نظامك الملف.", + "sanitize": "ينبغي أن يقبل نظامك الملف وينظّفه، مثلًا بإعادة تسميته.", + "unspecified": "يعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته." + }, + "damages": { + "zero-head": "يكتب أصفارًا فوق أول بايتات الملف دون المساس بطوله. معظم القارئات تنظر إلى هناك أولًا، فيلاحظ هذا التلف كل شيء تقريبًا." + }, + "terms": { + "oracleNone": "غير منطبق", + "int": "أي عدد صحيح", + "choice": "واحد من مجموعة ثابتة", + "bool": "صحيح أو خاطئ", + "size": "حجم مثل 2mb", + "text": "نص", + "pixels": "بكسل", + "paragraphs": "فقرات", + "rows": "صفوف", + "columns": "أعمدة", + "slides": "شرائح", + "hertz": "هرتز", + "megapixels": "ميغابكسل", + "million cells": "مليون خلية", + "entries per second": "إدخال في الثانية", + "files": "ملفات", + "sizes separated by commas": "أحجام مفصولة بفواصل", + "format ids separated by commas": "معرّفات صيغ مفصولة بفواصل", + "format ids separated by commas, or all": "معرّفات صيغ مفصولة بفواصل، أو all", + "extensions separated by commas": "امتدادات مفصولة بفواصل", + "the id of a format, as tfg formats lists them": "معرّف صيغة، كما يسردها tfg formats", + "the password, in plain text": "كلمة المرور، كنص عادي", + "any text": "أي نص", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "تاريخ مثل 2024-02-29 أو 2024-02-29T13:45:00+02:00، أو none" + }, + "faq": [ + { + "q": "بماذا يختلف عن dd أو fsutil أو truncate؟", + "a": "تلك الأوامر تعطيك ملفًا بالحجم الصحيح مملوءًا بلا شيء. ملف بحجم 2 MB باسم photo.png صُنع بهذه الطريقة ليس PNG، فكل ما يحلله فعلًا يرفضه لسبب خاطئ، ويمر اختبارك أيضًا لسبب خاطئ. هذه الأداة تنتج ملف PNG حقيقيًا بحجم 2 MB تمامًا يُفتح في عارض الصور، ويصل مع بيان عن كيفية معاملة نظامك له.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "هل هو مجاني، وهل يمكنني استخدامه في العمل؟", + "a": "نعم في الحالتين. صدر بموجب GPL-3.0 ولا يكلّف شيئًا. لا يوجد حساب ولا مفتاح ترخيص ولا مستوى مدفوع." + }, + { + "q": "هل يمكنني استخدام الملفات المولَّدة في منتج مغلق المصدر؟", + "a": "نعم. الرخصة تشمل شيفرة الأداة لا ما تنتجه. الملفات والوصفات والبيانات المولَّدة مخرجات لا أعمال مشتقة، فيمكنك إيداعها وتوزيعها دون أي التزام." + }, + { + "q": "هل تحتوي الملفات المولَّدة على بيانات شخصية حقيقية؟", + "a": "لا. كل ما بداخلها يُركَّب من بذرة. لا تُقرأ أي مجموعة بيانات، ولا يُتصل بأي خدمة، ولا يُضمَّن أي محتوى من طرف ثالث. عامل عنوان البريد الإلكتروني المولَّد على أنه غير صالح للاستخدام لا على أنه غير مستخدم، لأن أي سلسلة عشوائية قد تتطابق مصادفة مع سلسلة حقيقية." + }, + { + "q": "هل سأحصل على الملفات نفسها تمامًا على جهاز آخر؟", + "a": "نعم، بايتًا ببايت، مع الوصفة نفسها والبذرة نفسها. يختبر المشروع ذلك مع كل تغيير، وكسره يتطلب رفع الإصدار الرئيسي. وهذا ما يتيح لك إيداع وصفة صغيرة بدل بيانات اختبار ثنائية كبيرة." + }, + { + "q": "هل يحتاج إلى اتصال بالإنترنت؟", + "a": "أبدًا. لا توجد قياسات عن بُعد ولا فحص للتحديثات ولا عميل سحابي، والملف التنفيذي لسطر الأوامر لا تُترجَم فيه حزمة شبكة أصلًا. يعمل على جهاز بلا شبكة وداخل بيئة مؤسسية مغلقة." + }, + { + "q": "ماذا يحدث إذا طلبت حجمًا لا تستطيع الصيغة بلوغه؟", + "a": "تحصل على خطأ يذكر الصيغة وأصغر حجم ممكن وسبب هذا الحد الأدنى وما يجب فعله بدلًا من ذلك، ولا يُكتب أي ملف. الأداة لا تقرّب الحجم بصمت أبدًا. وكل حد أدنى مذكور في صفحة الصيغ.", + "code": "tfg formats png" + }, + { + "q": "هل يمكنني توليد ملف تالف عمدًا؟", + "a": "نعم. أضف --damage zero-head فيخرج الملف بالحجم الذي طلبته تمامًا، وأول بايتاته مكتوب فوقها أصفار، فترفضه القارئة، ويقول البيان إن نظامك ينبغي أن يرفضه. التفاصيل في صفحة ملفات الاختبار التالفة.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "ما الصيغ القادمة؟", + "a": "7z وmp3 وmp4. تعمل اليوم {{ .Facts.FormatCount }} صيغة من البداية إلى النهاية." + }, + { + "q": "على أي أنظمة يمكنني تشغيله؟", + "a": "يعمل سطر الأوامر على ويندوز ولينكس على معالجات Intel وARM، وعلى أجهزة ماك بمعالجات Apple Silicon. تُقدَّم نافذة سطح المكتب لويندوز على Intel، ولينكس على Intel، وأجهزة ماك بمعالجات Apple Silicon. أجهزة ماك بمعالجات Intel غير مدعومة ولا يُبنى لها شيء." + }, + { + "q": "هل أحتاج إلى تثبيت شيء؟", + "a": "لا. نزّل الأرشيف الخاص بنظامك وفك ضغطه وشغّل الملف التنفيذي. لا يوجد مثبّت ولا بيئة تشغيل تُضاف ولا اعتماديات تُحل. وإذا كان لديك Go فيكفي أمر go install واحد أيضًا.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "لماذا يكون التشغيل على آلاف الملفات أبطأ على ويندوز؟", + "a": "لأن ويندوز يتقاضى أكثر عن كل مسار ينظر فيه، والأمر الذي يمر على آلاف الملفات ينظر في آلاف المسارات. قيس على جهاز واحد فيه 3000 ملف بحجم 1 kB، فاستغرق verify نحو 0.9 ثانية على ويندوز ونحو 0.2 ثانية على لينكس داخل حاوية. ويصغّر مسار الإخراج الأقصر رقم ويندوز، لأن كل مجلد فوق الملفات جزء مما يُنظر فيه." + } + ] +} diff --git a/web/content/ar/use-cases.html b/web/content/ar/use-cases.html new file mode 100644 index 00000000..5f7347c7 --- /dev/null +++ b/web/content/ar/use-cases.html @@ -0,0 +1,124 @@ +

فيمَ يستخدمه الناس

+

+ خمس مهام تظهر في كل مشروع تقريبًا يقبل ملفات من الناس، والأمر الذي ينفذ كلًّا منها. كل مثال أدناه + يعمل كما هو مكتوب. +

+ +
+

حدود الرفع

+

اختبار ما إذا كان حد حجم الملف يُطبَّق حيث يقول إنه يُطبَّق

+

+ الحد ثلاث حالات اختبار لا حالة واحدة: أقل منه بقليل، وعنده تمامًا، وأعلى منه بقليل. الحصول عليها + يدويًا يعني حساب أعداد البايتات والأمل في ألا تخطئ بواحد. اطلب المجموعة بدلًا من ذلك: +

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

+ تحصل على ثلاثة ملفات PDF حقيقية بحجم 1048575 و1048576 و1048577 بايتًا، وبيان يقول إن الأولين يجب + قبولهما والثالث يُرفض بسبب size_limit. يقرأ اختبارك التوقّع بدل أن تكتب ثلاثة + تأكيدات يدويًا، وحين يتغير الحد تغيّر رقمًا واحدًا وتعيد التشغيل. +

+

+ ويعمل الأمر نفسه دون إعداد مسبق حين تريد مجموعة حدود واحدة داخل الأمر: +

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

التكامل المستمر

+

إبقاء بيانات الاختبار خارج المستودع دون فقدانها

+

+ بيانات الاختبار الثنائية الكبيرة تُبطئ استنساخ المستودع وتُصعّب مراجعته، ولا أحد يعرف ما الذي تغيّر + حين تُستبدل واحدة. الوصفة بضع مئات من أحرف YAML تعيد بناء الملفات المطابقة، بايتًا ببايت + وعلى أي جهاز، لأن كل ملف مشتق من بذرة التشغيل. +

+
- 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
+

+ لكل نهاية رمز خروج خاص بها، فيستطيع خط البناء التمييز بين وصفة سيئة وقرص ممتلئ وعدم تطابق في التحقق. + والتشغيل الفاشل لا يطبع شيئًا على المخرج القياسي، فلا يقرأ محلل السجلات خطأً على أنه بيانات. +

+
+ +
+

الحجم الكبير

+

معرفة ما يحدث حين يكون المجلد كبيرًا

+

+ تتصرف روتينات الاستيراد والمهام الليلية وقوائم المجلدات بشكل مختلف عند عشرة آلاف ملف عنه عند عشرة. + الأحجام المسحوبة من نطاق تجعل المجموعة تبدو كحركة حقيقية لا كعشرة آلاف ملف متطابق، ويأتي السحب + من البذرة، فتكون المجموعة نفسها غدًا. +

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

+ تحقق من كلفة التشغيل قبل أن يكتب أي شيء، وهذا مهم حين يُقاس المجموع بالغيغابايت: +

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

+ التشغيل الأكبر من المساحة الحرة على القرص يُرفض قبل كتابة أول بايت، بدل أن يملأ القرص ويفشل في منتصف + الطريق. +

+
+ +
+

الأرشيفات

+

اختبار أداة فك الضغط بأرشيف يحتوي ملفات حقيقية فعلًا

+

+ أرشيف فارغ بالامتداد الصحيح لا يثبت شيئًا عن شيفرة تفتحه وتجتاز ما بداخله. صرّح بالمحتوى فيحتويه + الأرشيف فعلًا: +

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

+ عمق التداخل وعدد العناصر وحجم ما بالداخل كلها أمور لروتين الاستيراد رأي فيها، وهكذا تعرف ما هي تلك + الآراء. +

+
+ +
+

المحللات والعارضات

+

التحقق من أن شيفرتك تقرأ الصيغة كما يفعل البرنامج الحقيقي

+

+ كل صيغة هنا تُفحص بقارئ مستقل قبل إصدارها: يُفتح PNG وتُقارَن بكسلاته، ويُقرأ DOCX من جديد بمكتبات + منفصلة، ويُفك أرشيف. وهذا يعني أن ملفًا يرفضه محللك هو نتيجة عن محللك، لا عن المولّد. +

+
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
+

+ تسرد صفحة الصيغ الإعدادات التي تقبلها كل صيغة وأصغر ملف يمكن أن تكونه. +

+
+ +
+

أدلة

+

اثنان منها بتفصيل أكبر

+ +
+ +
+

لمن هذا

+

+ لمهندسي ضمان الجودة وأتمتة الاختبار، ولكل من خلف شيفرته نموذج رفع أو روتين استيراد أو محلل أو حصة + تخزين. يعمل على جهاز بلا شبكة إطلاقًا، وهذا مهم في بيئة مؤسسية مغلقة لا يكون فيها المولّد القائم + على المتصفح خيارًا. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/cs/ci.html b/web/content/cs/ci.html new file mode 100644 index 00000000..e522a130 --- /dev/null +++ b/web/content/cs/ci.html @@ -0,0 +1,187 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Jak generovat testovací soubory v CI pipeline

+

+ Binární fixture v repozitáři zůstává navždy v jeho historii, nedá se posoudit v diffu a při velkém + souboru přestává být možný. Generujte soubory raději v pipeline z receptu. Recept je text, bajty + vycházejí pokaždé stejné a poslední krok dokáže, že se nic nepohnulo. +

+ +
+

Stručná odpověď

+

+ Nainstalujte tfg, před testy spusťte tfg generate fixtures.yaml --out + ./fixtures a po nich tfg verify ./fixtures/manifest.json. Oba kroky shodí + build samy, s návratovým kódem, který říká proč. +

+
+ +
+

Proč je necommitovat

+

Proč fixture nepatří do repozitáře

+ +

+ Commitovat je třeba recept. Stejný recept a stejný seed zapíší na každém počítači stejné bajty, + takže soubor vygenerovaný v pipeline je soubor, který jste měli na notebooku. +

+
+ +
+

Recept

+

Recept, který leží vedle testů

+

+ Tento zapíše pětadvacet faktur, které se mají přijmout, a dva obrázky nad limitem, které se mají + odmítnout, a manifest zaznamená obě očekávání: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml ho zkontroluje, aniž cokoli zapíše, a pojmenuje všechny + problémy najednou. +

+
+ +
+

GitHub Actions

+

Workflow, které nainstaluje nástroj a postaví fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Řádek s kontrolním součtem porovná archiv se souborem verify-SHA256SUMS.txt ze stejného + vydání. Verze je pevně daná, takže nové vydání nikdy nezmění build, na který jste nesáhli. +

+
+ +
+

GitLab CI

+

Totéž jako job v GitLabu

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Když se to zbarví načerveno

+

Co shodí krok, a proč

+

+ Každý konec má vlastní návratový kód, takže krok selže sám a log řekne který. Ty, které pipeline + potká: +

+ +

+ Neúspěšný běh nevypíše nic na standardní výstup, takže parser logů nikdy nevezme chybu za data. Celá + tabulka je na stránce dokumentace. +

+
+ +
+

PowerShell

+

Skript PowerShellu potřebuje ještě jeden řádek

+

+ PowerShell nevynese návratový kód programu ze souboru .ps1. Spusťte ho s + -File a skript odpoví 0, i když nástroj uvnitř práci odmítl, takže + build, který měl být červený, zezelená. Poslední řádek je celá oprava: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Tak se PowerShell chová, nejde o vlastnost tohoto nástroje. cmd, bash a + zsh nepotřebují nic navíc. +

+
+ +
+

Více jobů

+

Sdílení fixtures mezi joby

+

+ Nahrávat je obvykle není třeba. Protože stejný recept zapisuje stejné bajty, může každý job spustit + vlastní tfg generate, což je rychlejší než nahrání a stažení. Když má job přijmout + soubory od jiného, spusťte po přenosu tfg verify nad manifestem a řekne vám, zda + to, co dorazilo, je to, co bylo zapsáno. +

+
+ +
+

Dál

+

Kam jít odtud

+ +
diff --git a/web/content/cs/damage.html b/web/content/cs/damage.html new file mode 100644 index 00000000..a5f339cc --- /dev/null +++ b/web/content/cs/damage.html @@ -0,0 +1,170 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Jak vytvořit poškozený soubor pro testy

+

+ Validátor, kterému se ukazovaly jen zdravé soubory, nebyl opravdu otestován. Tady je postup, jak + získat soubor záměrně rozbitý, který vyjde přesně v požadované velikosti a nese + manifest říkající, co s ním má váš systém udělat. +

+ +
+

Stručná odpověď

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out zapíše PNG o přesně + 2097152 bajtech, jehož první bajty jsou nuly, a manifest vedle něj zaznamená, že ho má váš + systém odmítnout. +

+
+ +
+

Obvyklý způsob

+

Proč je ručně poškozený soubor špatný test

+

+ Obvykle se sáhne po hexadecimálním editoru, skriptu, který převrátí pár náhodných bajtů, nebo po + zkrácení souboru pomocí head či truncate. Jednou to funguje a pak to + stojí: +

+ +
+ +
+

Co dostanete

+

Poškozený soubor má stále velikost, kterou jste chtěli

+

+ Soubor se vygeneruje normálně a poškodí se až potom, cestou na disk. Zachová velikost, kterou jste + chtěli, a stejný příkaz zapíše znovu stejné bajty. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Nastavení se píše za dvojtečku. Přepínač lze opakovat a poškození se použijí v pořadí, v jakém je + zapíšete. Funguje s každým z {{ .Facts.FormatCount }} formátů. +

+
+ +
+

Co umí

+

Jaká poškození existují?

+

+ Toto je seznam, který program vypisuje, načtený z něj při sestavení této stránky. tfg + damage vypíše totéž a tfg damage <id> řekne, co které z nich přijímá. +

+ {{ template "damagesTable" . }} +

+ zero-head zapíše nuly přes začátek souboru. Většina čteček se dívá nejdřív tam, na + signaturu a hlavičku, které říkají, co soubor je, takže si toho všimne téměř každá. Prostý text + a logy signaturu nemají a odmítnou se také, protože řada nulových bajtů není text. Pod čtyřmi + bajty některé formáty vyjdou s poškozením, na které si žádná čtečka nestěžuje, proto nastavení + začíná na čtyřech. +

+
+ +
+

Co říká manifest

+

Manifest, který říká, co se má stát

+

+ Každý poškozený soubor dostane záznam, že ho má váš systém odmítnout, s poškozením zapsaným vedle: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dva požadavky se odmítnou dřív, než se cokoli zapíše, protože každý by na disku nechal soubor, který + manifest popisuje špatně: +

+ +
+ +
+

V receptu

+

Zdravé a rozbité soubory v jednom běhu

+

+ Dejte obojí do jednoho receptu a manifest ponese očekávání každého souboru, takže test nepotřebuje + seznam, který je který: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

V testu

+

Z toho udělat test

+

+ Test přečte manifest a ověří, že to, co se stalo, je to, co bylo uvedeno. Nepotřebuje seznam názvů + souborů: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Dobré odmítnutí je čisté. Zpráva, která říká, co bylo špatně, je odpověď, kterou chcete. Chyba + serveru, zaseknutí nebo napůl uložený soubor je vada, kterou má tento test najít. +

+
+ +
+

Dál

+

Kam jít odtud

+ +
diff --git a/web/content/cs/docs.html b/web/content/cs/docs.html new file mode 100644 index 00000000..3c3423b0 --- /dev/null +++ b/web/content/cs/docs.html @@ -0,0 +1,276 @@ +

Dokumentace

+

+ Vše, co nástroj dělá, uspořádané podle otázek, se kterými lidé skutečně přicházejí. + README v repozitáři je úplná reference a vždy odpovídá verzi, + kterou jste stáhli. +

+ +
+

Jaké příkazy existují?

+

Každý dělá jednu věc:

+ {{ template "commandList" . }} +
+ +
+

Jak vygeneruji jeden soubor přesné velikosti?

+

+ Uveďte formát, velikost a kam soubor půjde. Velikosti se počítají po 1024, takže 2mb je + 2097152 bajtů. Funguje i prostý počet bajtů, takže --size 10485761 žádá přesně + tolik. +

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

Užitečné přepínače příkazu generate:

+
+ + + + + + + + + + + + + + + + + +
PřepínačCo dělá
--format <id>formát souborů, například txt
--size <size>přesná velikost každého souboru, například 10mb nebo prostý počet bajtů
--size-range <a-b>velikost losovaná pro každý soubor z rozsahu, například 1kb-8kb. Losování vychází ze seedu
--boundary <size>tři soubory kolem limitu: o bajt pod, limit, o bajt nad
--count <n>kolik souborů vytvořit. Výchozí 1
--name <template>šablona názvu, například invoice_{index:04}.txt
--out <dir>adresář, do kterého se zapisuje
--seed <n>seed běhu. Stejný seed dává stejné bajty
--set <k>=<v>nastavení formátu, lze opakovat
--damage <name>záměrně soubory poškodit, lze opakovat a uplatňuje se v pořadí. Seznam získáte příkazem tfg damage
--expected <outcome>accept, reject, sanitize nebo unspecified
--dry-runspočítat a ukázat, nic nezapisovat
--jsonzapsat manifest na standardní výstup
+
+
+ +
+

Jak vytvořím soubor, který je záměrně rozbitý?

+

+ Každý jiný soubor, který tento nástroj zapíše, je správný z konstrukce, což odpovídá na dvě ze tří + otázek, které klade validátor nahrávání. --damage odpovídá na třetí - zda se soubor + vůbec otevře. Soubor se vytvoří normálně a pak se rozbije, takže má stále velikost, o kterou + jste požádali. +

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

+ Nastavení se zadávají za dvojtečku. Přepínač se opakuje a pořadí, v jakém je napíšete, je pořadí, v + jakém se uplatní. tfg damage vypíše, co tato verze umí a co která varianta přijímá. +

+

V receptu je klíč seznam, a to názvů nebo nastavení:

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

+ Poškozený soubor dostane v manifestu expected: reject a vedle toho zaznamenané + poškození. Dvě věci jsou odmítnuty dříve, než se cokoli zapíše, protože každá by jinak dala na + disk soubor, který manifest popisuje špatně: +

+ +

+ Třetí se předem zjistit nedá. Pokud se poškození provede a nepohne žádným bajtem, soubor se zahodí + místo zapsání - běh pokračuje, řekne, o který soubor šlo, a skončí s částečným návratovým kódem. +

+

+ Krok za krokem, s testem, který čte manifest: jak + vytvořit poškozený soubor pro testy. +

+
+ +
+

Jak vypadá recept?

+

+ Recept je soubor YAML popisující celý běh. Commitujte ho vedle testů a fixtures přestanou být + binárkami ve vašem repozitáři - kdokoli je může bajt po bajtu znovu sestavit ze souboru o + několika stovkách znaků. +

+
# 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
+

+ Každý target potřebuje přesně jeden z klíčů size, size-range, + boundary nebo contains. Dva jsou chyba a žádný také. Neplatný recept + nezapíše žádné soubory a nahlásí všechny problémy najednou, ne jen první, každý + s názvem nastavení, kterého se týká. +

+
+ +
+

Jak deklaruji, co má můj systém se souborem udělat?

+

Krátká forma, když stačí výsledek, dlouhá forma, když záleží na důvodu:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Výsledky jsou accept, reject, sanitize a + unspecified. Důvody tvoří uzavřený seznam, aby podle nich mohl report seskupovat: + 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 a size_zero. +

+

+ Důvod pojmenovává pravidlo, o které jde, ne verdikt. Proto může stejný důvod stát + pod oběma výsledky - soubor o bajt pod limitem je accept a pravidlo, o které jde, + je stále size_limit. +

+
+ +
+

Co obsahuje manifest?

+

+ Zapisuje se vedle souborů na konci každého běhu, včetně přerušeného. Jedna položka na soubor: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 se přidá, když běh pochází z receptu, a preset s + overrides, když pochází z předvolby, takže manifest lze vždy dohledat k tomu, co ho + vytvořilo. +

+

+ Každá položka nese také target_id, id targetu v receptu, který soubor vytvořil, a + summary.by_target počítá soubory, ke kterým každý target dospěl. Recept s více + targety lze tak kontrolovat target po targetu, aniž by se četly názvy souborů. +

+
+ +
+

Co je předvolba?

+

+ Hotová sada souborů, která odpovídá na běžnou testovací otázku, abyste sadu nemuseli navrhovat sami. + Předvolby jsou pod povrchem obyčejné recepty a eject recept vypíše, takže ho můžete + odtud upravit. Každá předvolba má vlastní stránku s tím, co obvykle + najde, co je v sadě a jaké nastavení přijímá. +

+ {{ template "presetsList" . }} +
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 vám řekne, kolik by sada stála, než ji sestavíte, a otevřeně řekne, když je číslo + naším zástupným údajem, a ne vaším limitem. +

+
+ +
+

Co znamenají návratové kódy?

+

+ Každý konec má svůj kód, strojově čitelný výstup jde na standardní výstup a neúspěšný běh tam + nevypíše nic. Tabulka je zmrazená smlouva - změna významu kódu vyžaduje novou hlavní verzi. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Běh zastavený pomocí Ctrl+C po sobě stále zanechá manifest a nikdy nenechá napůl zapsaný soubor, + takže zrušenou úlohu může následující stále uklidit. +

+

+ Hotová workflow pro GitHub Actions a GitLab CI: jak generovat + testovací soubory v CI pipeline. +

+
+ +
+

Existuje desktopové okno?

+

+ Ano, stejný motor s oknem navrch, pro testování, které se neskriptuje. Není to osekaná verze: test + porovnává obě rozhraní schopnost po schopnosti a cokoli, co umí jen jedno z nich, musí být + deklarováno a zdůvodněno, ne tiše se rozcházet. +

+

+ Obrazovky jsou jedna dávka, předvolby, více dávek najednou a O aplikaci. Ukáže, kolik by běh stál, + než cokoli zapíše, hlásí průběh a lze ho zrušit uprostřed, aniž by zanechal napůl zapsaný + soubor. Soubor receptu zatím neotevře - recepty jsou zatím záležitostí příkazového řádku a okno + sestavuje své dávky ve formuláři. +

+
diff --git a/web/content/cs/exact-size.html b/web/content/cs/exact-size.html new file mode 100644 index 00000000..2d8185e4 --- /dev/null +++ b/web/content/cs/exact-size.html @@ -0,0 +1,143 @@ +

Jak vytvořit soubor přesné velikosti

+

+ Každý systém na to má příkaz a všechny tři jsou níže. Dají vám soubor s přesně správným počtem bajtů + - a pro mnoho testů je to vše, co potřebujete. Každý příkaz na této stránce byl před + zveřejněním spuštěn na systému, kam patří. +

+ +
+

Krátká odpověď

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Velikosti jsou v bajtech a 10 MB + počítané tak, jak je počítá váš správce souborů, je 10485760. +

+
+ +
+

Windows

+

fsutil a verze v PowerShellu, která nepotřebuje nic navíc

+

+ fsutil je součástí Windows. Bere velikost v bajtech, takže si číslo + nejdřív spočítejte - 10 MB je 10485760, 100 MB je 104857600, 1 GB je 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Změřeno na Windows 11: funguje z běžného příkazového řádku a nepotřebuje zvýšená oprávnění a soubor + vyjde přesně na 10485760 bajtů. +

+

PowerShell umí totéž bez volání jiného programu a rozumí jednotkám:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB v PowerShellu znamená 10485760 bajtů, tedy stejné počítání po 1024 jako + Průzkumník, takže oba příkazy výše vytvoří stejnou velikost. +

+
+ +
+

Linux

+

dd, truncate a fallocate a rozdíl, který lidi chytí

+

dd zná každý. Bajty skutečně zapisuje:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate je okamžitý, a to je ten háček. Změřeno na Alpine Linuxu: soubor hlásí + 10485760 bajtů a zabírá nula bloků - je to řídký soubor. + Cokoli, co ho čte, dostane deset megabajtů nul, ale disk místo nikdy neuvolnil: +

+
truncate -s 10M test10mb.bin
+

+ To stačí k testu limitu nahrávání a klame to při testu diskové kvóty. fallocate je ten + správný, když musí být místo skutečné: +

+
fallocate -l 10M test10mb.bin
+

A když musí být obsah nestlačitelný, aby ho archivátor nemohl znovu zmenšit:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, který není řídký, a dva, které už znáte

+

+ macOS dodává mkfile. Změřeno na macOS 26.6.2: 10485760 bajtů a 20480 bloků, takže místo + je skutečně přiděleno, ne jen slíbeno: +

+
mkfile 10m test10mb.bin
+

dd a truncate tam jsou také a chovají se jako na Linuxu:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Kde to přestává stačit

+

Soubor správné velikosti není soubor správného druhu

+

+ Vše výše vám dá blok nul. To stačí, když testovaná věc hledí jen na velikost - limit nahrávání, + kvótu, přenos. Přestane to stačit ve chvíli, kdy soubor cokoli otevře. +

+

+ Změřeno a stojí za to to zkusit samostatně: vytvořte pomocí fsutil soubor o 2 MB, + pojmenujte ho photo.png a předejte ho knihovně pro obrázky. Pillow odpoví + cannot identify image file. Není to PNG. Nikdy nebylo - tvrdil to jen název. +

+

+ To je důležitější, než to zní, kvůli tomu, jakým směrem test pak selže. Váš + endpoint pro nahrávání soubor odmítne, váš test zezelená a vy usoudíte, že limit velikosti + funguje. Neodmítl ho kvůli velikosti. Odmítl ho proto, že bajty nebyly obrázek, a pravidlo, + které jste chtěli otestovat, nebylo nikdy dosaženo. +

+ +
+ +
+

Druhá cesta

+

Skutečný soubor toho formátu, v přesně té velikosti, o kterou jste požádali

+

+ To je to, co dělá Testing Files Generator. Soubor je pravý soubor svého formátu - otevře se v + programu, kam patří - a má přesný počet bajtů, o který jste požádali, na bajt: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Požádejte o velikost, které formát nedosáhne, a dostanete chybu, která pojmenuje minimum a jeho + důvod, nikdy soubor špatné velikosti. Stránka formátů uvádí každý + formát s nejmenším souborem, který umí vytvořit. +

+

A limit jsou tři testovací případy, ne jeden, takže nástroj sestaví všechny tři:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ To vám dá 10485759, 10485760 a 10485761 bajtů a manifest, který říká, které má váš systém přijmout a + které odmítnout. Stránka případů použití to probírá spolu se + čtyřmi dalšími úlohami, pro které je určen. +

+ {{ template "downloadCta" . }} +
+ +
+

Tak který použít?

+ +

+ Oba jsou na této stránce, protože oba mají část času pravdu. Chybou, které je třeba se vyhnout, je + použít první tam, kde je třeba druhý, a číst zelený test jako důkaz. +

+
diff --git a/web/content/cs/faq.html b/web/content/cs/faq.html new file mode 100644 index 00000000..fa0c9d42 --- /dev/null +++ b/web/content/cs/faq.html @@ -0,0 +1,19 @@ +

Často kladené otázky

+

+ Licence, soukromí, opakovatelnost a věci, které lidé ověřují, než generátor zařadí do build + pipeline. Pokud tu vaše otázka není, sledování issues je + otevřené. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Ještě se rozhodujete?

+

+ Stránka případů použití ukazuje úlohy, pro které je určen, a + stránka formátů uvádí každý formát s nejmenším souborem, který umí + vytvořit. README v repozitáři je úplná reference. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/cs/formats.html b/web/content/cs/formats.html new file mode 100644 index 00000000..6262fe37 --- /dev/null +++ b/web/content/cs/formats.html @@ -0,0 +1,77 @@ +

{{ .Facts.FormatCount }} formátů souborů, každý generovaný v přesné velikosti

+

+ Každý z nich je skutečný soubor toho formátu. Otevře se v programu, kam patří, a má + přesně tolik bajtů, kolik jste požádali. Žádný není vycpávka z nul s přilepenou příponou. +

+ +{{ template "formatsTable" . }} + +
+

Co znamenají sloupce

+ +

+ Každý formát se také opakuje na bajt: stejný recept a stejný seed vytvoří na jakémkoli počítači + identické soubory, a to dělá z receptu bezpečnou věc k commitování místo samotných fixtures. +

+
+ +
+

Nastavení, která každý formát přijímá

+

+ Většina formátů má vlastní nastavení - rozměry obrázku, kvalitu JPEG, počet stránek PDF, řádky a + sloupce v tabulce, kolik položek jde do archivu. Nastavte je pomocí --set key=value + v příkazovém řádku nebo pod properties: v receptu. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Hodnota mimo to, co nastavení přijímá, je odmítnuta zprávou, která pojmenuje nastavení, povolený + rozsah a co použít místo toho. Neznámé nastavení je také chyba, nikdy tichá výchozí hodnota - + tiše přijatý překlep dá soubor se špatným nastavením a hodinu přemýšlení, proč test prochází, + když neměl. +

+

+ Spusťte tfg formats <id> a uvidíte přesně, co jeden formát v dané verzi přijímá. +

+
+ +
+

Archivy obsahují skutečné soubory

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} a {{ end }}{{ $c.ID }}{{ end }} lze + naplnit položkami, místo aby zůstaly prázdnou skořápkou. Vygenerovaný archiv skutečně obsahuje + dokumenty, které tvrdí, že obsahuje, takže cokoli ho během testu rozbalí, uvnitř najde skutečné + soubory. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/cs/index.html b/web/content/cs/index.html new file mode 100644 index 00000000..004d394d --- /dev/null +++ b/web/content/cs/index.html @@ -0,0 +1,195 @@ +
+
+

Generujte skutečné testovací soubory v přesné velikosti

+

+ PDF, PNG, DOCX, ZIP - celkem {{ .Facts.FormatCount }} formátů a každý je skutečný + soubor, který se otevře v programu, kam patří, v přesně té velikosti, o kterou jste + požádali. Každý běh také zapisuje, co má vaše aplikace s každým souborem udělat. + Příkazový řádek a desktopové okno, zdarma a open source, celé na vašem počítači. +

+ + {{ template "downloadCta" . }} +
+ +
+ Desktopové okno Testing Files Generator připravené zapsat dávku testovacích souborů +
Desktopové okno připravené zapsat dávku souborů. Za příkazovým řádkem běží stejný motor.
+
+
+ + + +
+

Problém

+

Vytvořit jeden testovací soubor je snadné. Vytvořit těch správných tisíc je ta únavná část

+

Testujete software, který přijímá soubory od lidí. Dříve nebo později budete potřebovat:

+ +

+ To je to, co toto nahrazuje. Je určeno pro QA inženýry, automatizaci testů a každého, za jehož kódem + stojí formulář pro nahrávání, importní rutina, parser nebo kvóta úložiště. +

+
+ +
+

Čím se liší

+

Jiné generátory končí u bajtů. Tento odpovídá na to, na co se váš test skutečně ptá

+

+ Složka souborů vás stále nechává rozhodovat, co má který dokazovat. Každý běh tady zapíše vedle + souborů manifest.json - prostý seznam všeho vytvořeného a u každé položky + deklarované očekávání. +

+

Řekněme, že váš endpoint pro nahrávání povoluje 1 MB. Požádejte o tři soubory, které leží na té hranici:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
SouborBajtyVáš systém máProtože
1mb_under_1b.pdf1048575přijmoutje uvnitř limitu
1mb_at_limit.pdf1048576přijmoutsamotný limit je povolen
1mb_over_1b.pdf1048577odmítnoutsize_limit
+
+ +

Tři soubory, tři různé odpovědi, ve strojově čitelné podobě. Váš test čte manifest místo toho, abyste vy ručně psali aserce:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Kde odpověď závisí na vaší vlastní politice, manifest to říká

+

+ Zapíše unspecified, místo aby vymýšlel očekávání. Generátor, který hádá, vytváří + falešná selhání a sada testů, která křičí vlk, bude vypnuta. +

+
+
+ +
+

Předvolby

+

Vyberte otázku, získejte celou sadu

+

+ Předvolba je sada testovacích souborů navržená kolem jedné testovací otázky, abyste nemuseli + vymýšlet, které soubory co dokazují. Každá má stránku, která říká, co obvykle najde, co je v + sadě a jaké nastavení přijímá. +

+ {{ template "presetsList" . }} +

Všechny předvolby a jak souvisejí s recepty

+
+ +
+

Rychlý start

+

Tři příkazy, abyste to viděli fungovat

+
    +
  1. +

    Vytvořte soubor

    +

    Jedno PNG, přesně dva megabajty:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Vytvořte hodně souborů

    +

    + Deset tisíc souborů logu, každý mezi jedním a osmi kilobajty, s velikostmi losovanými ze seedu, aby + zítra vyšla stejná sada. Dejte každému běhu vlastní adresář - manifest je + jediný záznam o tom, co běh zapsal, takže nástroj odmítne zapsat druhý přes něj: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Ověřte je a pak je odstraňte

    +

    verify vám řekne, že se nic nepohnulo. cleanup odstraní přesně to, co bylo zapsáno, a nic jiného:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Velikosti se počítají po 1024, jak to dělá váš správce souborů, takže 2mb znamená + 2097152 bajtů. Funguje i prostý počet bajtů. Dokumentace pokrývá + recepty, manifest a návratové kódy. +

+
+ +
+

Co získáte

+

Vytvořeno pro sadu testů, která běží bez dozoru

+ +
+ +
+

Stažení

+

Vyberte verzi pro svůj systém

+

+ Rozbalte archiv a spusťte ho. tfg je příkazový řádek a tfg-gui je + desktopové okno. Není tu instalátor a nic, co by se do vašeho počítače přidávalo. +

+ {{ template "downloadsTable" . }} +
+

Co je podepsáno a co ne

+

+ Soubory ke stažení pro Windows a macOS jsou podepsané, takže se spustí bez varování o neznámém + vývojáři. Ty pro Linux ne, protože desktopový Linux nemá ekvivalent, kterým by je šlo + podepsat. Každý archiv je uveden v verify-SHA256SUMS.txt na stránce vydání, takže + můžete ověřit, co jste stáhli. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/cs/preset.html b/web/content/cs/preset.html new file mode 100644 index 00000000..e3417165 --- /dev/null +++ b/web/content/cs/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Předvolba {{ .ID }} sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ +{{ if .Catches }} +
+

Co obvykle najde?

+ +
+{{ end }} + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show {{ .ID }}:

+
+ + + + + + + +
Soubory{{ .Budget.Files }}
Targety v receptu{{ .Budget.Targets }}
Celková velikost{{ .Bytes }} B
Formáty{{ join .Budget.Formats ", " }}
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
OčekávánoVýznamSoubory
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Co můžete změnit?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
NastaveníPřijímáVýchozíCo dělá
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Tato výchozí hodnota je náš zástupný údaj, ne hodnota vašeho systému. Zadejte vlastní.{{ end }}
+
+ {{- else }} +

Tato předvolba nemá žádná nastavení. Sada je pokaždé stejná.

+ {{- end }} +
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/cs/presets.html b/web/content/cs/presets.html new file mode 100644 index 00000000..afab517a --- /dev/null +++ b/web/content/cs/presets.html @@ -0,0 +1,31 @@ +

Předvolby testovacích souborů, jedna sada pro každou testovací otázku

+

+ Předvolba je celá sada testovacích souborů navržená kolem jedné otázky, s manifestem, který říká, + jak má váš systém na každý soubor reagovat. Vy vyberete otázku, nástroj sestaví sadu. Každá + předvolba má vlastní stránku s tím, co obvykle najde, co je v sadě a jaké nastavení přijímá. +

+ +{{ template "presetsList" . }} + +
+

Čím se předvolba liší od receptu?

+

+ Pod povrchem ničím. Předvolba je recept, který za vás nástroj napíše z několika nastavení. tfg + preset eject tento recept vypíše, abyste si ho mohli ponechat vedle testů a upravovat, a + váš vlastní recept může na předvolbě stavět jedním řádkem, extends: preset: + následovaným jejím id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Mohu výchozím hodnotám věřit?

+

+ U souborů ano. U čísla, které zná jen váš systém, například limitu formuláře pro nahrávání, je + výchozí hodnota naším zástupným údajem a nástroj to řekne pokaždé, když nějaký použije. Stránka + každé předvolby tato nastavení označuje a tfg preset show to řekne dřív, než se + cokoli zapíše. +

+
diff --git a/web/content/cs/site.json b/web/content/cs/site.json new file mode 100644 index 00000000..cc557440 --- /dev/null +++ b/web/content/cs/site.json @@ -0,0 +1,328 @@ +{ + "code": "cs", + "locale": "cs_CZ", + "name": "Čeština", + "dir": "cs", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Úvod", + "title": "Generátor testovacích souborů - přesná velikost, {{ .Facts.FormatCount }} formátů", + "description": "Bezplatný open source generátor testovacích souborů pro QA. Skutečné PDF, DOCX, PNG a ZIP v přesné velikosti a manifest s očekávanou reakcí vašeho systému." + }, + { + "key": "formats", + "slug": "formaty", + "nav": "Formáty", + "title": "{{ .Facts.FormatCount }} podporovaných formátů souborů - PDF, DOCX, PNG, ZIP a další", + "description": "Všechny formáty, které generátor vytváří, nejmenší možný soubor každého z nich a jejich nastavení. Všech {{ .Facts.FormatCount }} se otevře ve svém programu." + }, + { + "key": "presets", + "slug": "predvolby", + "nav": "Předvolby", + "title": "Předvolby testovacích souborů - hotové sady pro QA", + "description": "Hotové sady testovacích souborů, každá odpovídá na jednu otázku: limity nahrávání, názvy souborů, kódování, import tabulek, prázdné soubory a validace." + }, + { + "key": "docs", + "slug": "dokumentace", + "nav": "Dokumentace", + "title": "Dokumentace - příkazy, recepty, manifest, návratové kódy", + "description": "Jak generovat testovací soubory z příkazového řádku nebo z receptu YAML, co obsahuje manifest a co znamená každý návratový kód při běhu v CI." + }, + { + "key": "use-cases", + "slug": "pripady-pouziti", + "nav": "Případy použití", + "title": "Případy použití - limity nahrávání, fixtures pro CI, testy", + "description": "Test limitu velikosti nahrávání, opakovatelné fixtures pro CI, vygenerování deseti tisíc souborů a archivy naplněné skutečným obsahem." + }, + { + "key": "exact-size", + "slug": "vytvoreni-souboru-presne-velikosti", + "nav": "Přesná velikost", + "title": "Vytvoření souboru přesné velikosti - Windows, Linux, macOS", + "description": "fsutil, dd, truncate a mkfile, každý změřený na svém systému, a proč takto vytvořený soubor není PDF ani PNG, když to test potřebuje." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - otázky ke generování testovacích souborů", + "description": "Čím se liší od dd a fsutil, zda lze soubory commitovat, zda se běhy opakují bajt po bajtu a co se stane, když nelze velikosti dosáhnout." + }, + { + "key": "damage", + "slug": "poskozene-testovaci-soubory", + "nav": "Poškozené soubory", + "title": "Poškozené testovací soubory - rozbité soubory přesné velikosti", + "description": "Soubor záměrně rozbitý, přesné velikosti, s manifestem, který říká, že ho má váš systém odmítnout. Pro testování validace nahrávání a parserů.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "testovaci-soubory-v-ci", + "nav": "Testovací soubory v CI", + "title": "Testovací soubory v CI - GitHub Actions, GitLab CI a PowerShell", + "description": "Generujte testovací soubory v pipeline místo commitování binárek: workflow pro GitHub Actions, job v GitLabu, návratové kódy a past PowerShellu.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Přejít na obsah", + "navLabel": "Hlavní", + "langLabel": "Jazyk", + "breadcrumbHome": "Úvod", + "imageAlt": "Testing Files Generator - skutečné testovací soubory v přesné velikosti s manifestem, který říká, jak má váš systém na každý z nich reagovat", + "schemaDescription": "Bezplatný open source generátor testovacích souborů pro QA. Vytváří skutečné soubory v {{ .Facts.FormatCount }} formátech v přesné velikosti a zapisuje manifest, který říká, jak má testovaný systém na každý z nich reagovat.", + "ctaDownload": "Stáhnout", + "ctaSource": "Zobrazit zdrojový kód", + "ctaNote": "Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.", + "colFormat": "Formát", + "colName": "Název", + "colExtension": "Přípona", + "colSmallest": "Nejmenší soubor", + "colFidelity": "Úplnost", + "colChecked": "Ověřeno pomocí", + "colSetting": "Nastavení", + "colAccepts": "Přijímá", + "colSystem": "Systém", + "colCli": "Příkazový řádek", + "colWindow": "Desktopové okno", + "noBinary": "zatím bez binárky", + "colCode": "Kód", + "colMeaning": "Význam", + "footerBlurb": "Testovací soubory pro QA v přesné velikosti s manifestem, který říká, jak má váš systém na každý z nich reagovat.", + "footerProject": "Projekt", + "footerSource": "Zdrojový kód na GitHubu", + "footerReleases": "Stažení", + "footerIssues": "Nahlásit problém", + "footerSupport": "Podpořit projekt", + "footerPages": "Stránky", + "footerLicence": "Copyright (C) 2026 DonislawDev. Vydáno pod licencí GNU General Public License, verze 3. Soubory, které vygenerujete, jsou vaše - licence se vztahuje na nástroj, ne na jeho výstup.", + "footerPrivacy": "Tento web odnikud nenačítá písma, skripty ani sledovače. Nenastavuje cookies.", + "notFoundTitle": "Tato stránka tu není", + "notFoundLead": "Adresa, kterou jste následovali, neodpovídá žádné stránce tohoto webu.", + "notFoundBack": "Přejít na úvodní stránku", + "read.format": "Formát každého souboru v sadě. Je to přepínač samotného nástroje a předvolba mu jen dává výchozí hodnotu.", + "readTakes.format": "id formátu ze stránky formátů", + "colDamage": "Poškození", + "colEffect": "Co dělá s bajty", + "colSettings": "Nastavení", + "noSettings": "žádné" + }, + "endings": { + "0": "Vše fungovalo.", + "1": "Neočekávaná chyba uvnitř nástroje.", + "2": "Špatný příkaz nebo přepínač.", + "3": "Recept není platný.", + "4": "Formát neumí to, co bylo požadováno.", + "5": "Čtení nebo zápis selhal.", + "6": "Nedostatek místa na disku.", + "7": "verify našel nesrovnalost.", + "8": "Běh skončil, ale nebylo vytvořeno všechno.", + "130": "Přerušeno pomocí Ctrl+C.", + "143": "Zastaveno signálem, tak vypadá vypršení času v CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Projde platný soubor tak malý, jak formát dovolí?", + "title": "Prázdné a minimální", + "pageTitle": "Nejmenší platné a prázdné testovací soubory v každém formátu", + "description": "Nejmenší platný soubor, který nástroj zapíše v každém ze svých {{ .Facts.FormatCount }} formátů, a prázdný soubor tam, kde to formát dovolí, vždy s očekávanou reakcí.", + "catches": [ + "platný soubor odmítnutý jako příliš malý, protože kontrola počítá bajty místo toho, aby je četla", + "prázdný soubor, který shodí čtečku, místo aby byl nahlášen", + "obrázek široký jeden pixel, který cestou k náhledu dělí nulou", + "úložiště, které čte nula bajtů jako selhané nahrání a stále to opakuje" + ], + "details": { + "formats": "Z jakých formátů se sada skládá. Ponechte all pro všechny formáty této verze, nebo uveďte ty, které váš systém přijímá." + } + }, + "filename-handling": { + "question": "Uloží, zobrazí a vrátí můj systém název souboru, který nečekal?", + "title": "Zacházení s názvy souborů", + "pageTitle": "Problematické názvy souborů pro testování - Unicode a délka", + "description": "Soubory s názvy, které rozbíjejí nahrávání a úložiště: jiná písma a emoji, přepsání směru textu, neviditelné znaky, syntaxe shellu a SQL, limity délky.", + "catches": [ + "název, který na obrazovce, v logu nebo v seznamu vypadá jako jiný", + "název oříznutý, zkrácený nebo přepsaný mezi nahráním a uložením", + "limit délky počítaný ve znacích tam, kde úložiště počítá bajty" + ], + "details": {} + }, + "size-boundaries": { + "question": "Je limit velikosti vynucován přesně tam, kde je deklarován?", + "title": "Hranice velikosti", + "pageTitle": "Test limitu velikosti nahrávání - soubory přesně na hranici", + "description": "Soubory o bajt pod, přesně na a o bajt nad limitem, který váš systém deklaruje, a širší kroky na obě strany, každý označený, zda má být přijat.", + "catches": [ + "chyby o jedna na hranici limitu", + "MB zaměněné za MiB, což je 4,8 procenta a stačí to k propuštění souboru, který projít neměl", + "limit vynucovaný v prohlížeči a ne na serveru" + ], + "details": { + "limit": "Limit velikosti, který váš systém deklaruje. Vše ostatní se měří od něj.", + "spread": "Jak daleko na obě strany od limitu zajít, jako seznam velikostí." + } + }, + "tabular-import": { + "question": "Přežije můj import tabulek to, co exportují skutečné nástroje?", + "title": "Import tabulek", + "pageTitle": "Testovací soubory pro import CSV a Excelu - oddělovače", + "description": "CSV s jinými oddělovači, konci řádků CR LF, bez hlavičky a s jinými uvozovkami, velmi široká tabulka, sešit Excelu a JSON v několika rozloženích.", + "catches": [ + "soubor se středníky přečtený jako jediný sloupec, protože oddělovač se předpokládal, místo aby se hledal", + "soubor CRLF rozdělený na řádky s prázdným řádkem za každým", + "tabulka bez hlavičky, jejíž první datový řádek se spolkne jako názvy sloupců", + "import, který ponechá sloupce, které umí zobrazit, a zbytek beze slova zahodí", + "čtečka, která bere záznamy JSON po jednom řádku a zastaví se u prvního odsazeného dokumentu" + ], + "details": { + "rows": "Kolik řádků tabulka obsahuje. Zapisuje se přesně v takové velikosti, jakou tolik řádků zabere, takže rozpočet výše se s touto hodnotou posouvá.", + "columns": "Kolik sloupců má každý řádek tabulky. Řádky krát sloupce mají strop a požadavek nad ním je odmítnut dříve, než se cokoli zapíše." + } + }, + "text-encoding": { + "question": "Ví moje čtečka, v jakém kódování soubor je, nebo hádá?", + "title": "Kódování textu", + "pageTitle": "Testovací soubory kódování textu - UTF-8, UTF-16, BOM, CRLF", + "description": "Stejný text v UTF-8, UTF-16LE a UTF-16BE, s označením pořadí bajtů i bez něj, a konce řádků CR LF a LF, k ověření, jak čtečka dekóduje text.", + "catches": [ + "čtečka, která předpokládá UTF-8 a zobrazí soubor UTF-16 jako každý třetí znak nebo jako řady čtverečků", + "označení pořadí bajtů přečtené jako obsah, takže první pole importu začíná třemi cizími znaky", + "importér, který hádá kódování z prvních bajtů a u delšího souboru hádá jinak", + "soubor CRLF rozdělený na řádky s prázdným řádkem za každým, nebo návrat vozíku zůstávající v posledním poli" + ], + "details": { + "sample": "Jak velký je každý soubor sady. UTF-16 ukládá dva bajty na znak, takže lichý počet je odmítnut." + } + }, + "upload-validation": { + "question": "Přijme můj formulář pro nahrávání to, co má, a zbytek odmítne?", + "title": "Validace nahrávání", + "pageTitle": "Testovací soubory validace nahrávání - typ, velikost a název", + "description": "Soubory k testu formuláře pro nahrávání: povolené a zakázané typy, obsah neodpovídající příponě, limit velikosti, nepřátelské názvy a hromadné nahrání.", + "catches": [ + "limit vynucovaný v prohlížeči a ne na serveru", + "SVG nebo HTML považované za obrázek či prostý text, což je způsob, jak protlačit skript formulářem", + "soubor kontrolovaný podle přípony a nikdy neotevřený, takže PDF s názvem .jpg projde", + "formulář, který načte celé tělo do paměti, než se podívá, jak je velké", + "nahrání s názvem PHOTO.JPG odmítnuté tam, kde se photo.jpg přijme, nebo naopak", + "název s mezerami, závorkami nebo znaky mimo ASCII zapsaný na disk beze změny" + ], + "details": { + "limit": "Limit velikosti, který váš formulář pro nahrávání deklaruje. Tato sada udělá jeden krok na každou stranu - pro soubor v každé vzdálenosti spusťte předvolbu size-boundaries.", + "allow": "Které typy má váš formulář přijímat. Každý se stane skutečným souborem toho typu a tvoří pozitivní kontrolu celé sady.", + "deny": "Které přípony má váš formulář odmítat. Přípona, pro kterou tato verze nemá formát, přesto dostane soubor s tímto názvem, obsahující prostý text.", + "far-over": "Jak daleko za limit sahá jediný velký soubor. Vypněte, kde zapsání několikanásobku limitu nestojí za místo na disku.", + "bulk": "Kolik souborů obsahuje hromadné nahrání. Nula tuto skupinu ze sady úplně vynechá." + } + } + }, + "commands": { + "generate": "vytvořit soubory z receptu nebo z přepínačů", + "validate": "zkontrolovat recept a nic nezapisovat", + "verify": "zkontrolovat adresář proti manifestu", + "cleanup": "odstranit soubory, které manifest uvádí", + "recipe fmt": "vypsat recept v ustáleném tvaru", + "preset": "sestavit sadu souborů z pojmenované testovací otázky", + "formats": "vypsat formáty, které tato verze podporuje", + "damage": "vypsat způsoby, jak tato verze umí soubor schválně poškodit", + "tool": "drobné pomůcky pro soubory, které už máte", + "version": "vypsat verzi nástroje", + "license": "vypsat licenci a co znamená pro generované soubory" + }, + "outcomes": { + "accept": "Váš systém má soubor přijmout.", + "reject": "Váš systém má soubor odmítnout.", + "sanitize": "Váš systém má soubor přijmout a vyčistit, například přejmenováním.", + "unspecified": "Záleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli." + }, + "damages": { + "zero-head": "Přepíše prvních několik bajtů souboru nulami a jeho délku nechá být. Většina čteček se dívá nejdřív tam, takže si tohoto poškození všimne téměř cokoli." + }, + "terms": { + "oracleNone": "nelze použít", + "int": "libovolné celé číslo", + "choice": "jedna z pevné množiny", + "bool": "pravda nebo nepravda", + "size": "velikost, například 2mb", + "text": "text", + "pixels": "pixelů", + "paragraphs": "odstavců", + "rows": "řádků", + "columns": "sloupců", + "slides": "snímků", + "hertz": "hertzů", + "megapixels": "megapixelů", + "million cells": "milionů buněk", + "entries per second": "položek za sekundu", + "files": "souborů", + "sizes separated by commas": "velikosti oddělené čárkami", + "format ids separated by commas": "id formátů oddělená čárkami", + "format ids separated by commas, or all": "id formátů oddělená čárkami, nebo all", + "extensions separated by commas": "přípony oddělené čárkami", + "the id of a format, as tfg formats lists them": "id formátu tak, jak je vypisuje tfg formats", + "the password, in plain text": "heslo ve formě prostého textu", + "any text": "libovolný text", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "datum, například 2024-02-29 nebo 2024-02-29T13:45:00+02:00, nebo none" + }, + "faq": [ + { + "q": "Čím se to liší od dd, fsutil nebo truncate?", + "a": "Ty vám dají soubor správné velikosti plný ničeho. Soubor o 2 MB pojmenovaný photo.png vytvořený takto není PNG, takže ho cokoli, co ho skutečně zpracovává, odmítne z nesprávného důvodu a váš test pak projde také z nesprávného důvodu. Tohle vytvoří skutečné PNG o přesně 2 MB, které se otevře v prohlížeči obrázků, a přichází s prohlášením, jak s ním má váš systém naložit.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Je to zdarma a mohu to používat v práci?", + "a": "Ano k obojímu. Je vydáno pod GPL-3.0 a nestojí nic. Není tu účet, licenční klíč ani placená úroveň." + }, + { + "q": "Mohu generované soubory použít v produktu s uzavřeným zdrojovým kódem?", + "a": "Ano. Licence se vztahuje na kód nástroje, ne na to, co nástroj vytváří. Generované soubory, recepty a manifesty jsou výstup, nikoli odvozená díla, takže je můžete commitovat a dodávat bez jakékoli povinnosti." + }, + { + "q": "Obsahují generované soubory skutečné osobní údaje?", + "a": "Ne. Vše uvnitř je syntetizováno ze seedu. Nečte se žádný datový soubor, nekontaktuje se žádná služba a nevkládá se obsah třetích stran. Vygenerovanou e-mailovou adresu považujte za nepoužitelnou, ne za nepoužitou, protože libovolný náhodný řetězec se může shodou okolností shodovat se skutečným." + }, + { + "q": "Dostanu na jiném počítači přesně stejné soubory?", + "a": "Ano, bajt po bajtu, při stejném receptu a stejném seedu. Projekt to testuje při každé změně a porušit to vyžaduje novou hlavní verzi. Díky tomu můžete commitovat malý recept místo velkých binárních fixtures." + }, + { + "q": "Potřebuje připojení k internetu?", + "a": "Nikdy. Není tu telemetrie, kontrola aktualizací ani cloudový klient a do binárky příkazového řádku není zkompilován žádný síťový zásobník. Funguje na počítači bez sítě i v uzavřeném firemním prostředí." + }, + { + "q": "Co se stane, když požádám o velikost, které formát nedosáhne?", + "a": "Dostanete chybu, která pojmenuje formát, nejmenší možnou velikost, důvod tohoto minima a co dělat místo toho, a nezapíše se žádný soubor. Nástroj nikdy velikost mlčky nezaokrouhlí. Každé minimum je uvedeno na stránce formátů.", + "code": "tfg formats png" + }, + { + "q": "Mohu vygenerovat soubor, který je záměrně rozbitý?", + "a": "Ano. Přidejte --damage zero-head a soubor vyjde v přesně požadované velikosti, s prvními bajty přepsanými nulami, takže ho čtečka odmítne, a manifest říká, že ho má váš systém odmítnout. Podrobnosti jsou na stránce o poškozených testovacích souborech.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Které formáty přijdou dál?", + "a": "7z, mp3 a mp4. Dnes funguje od začátku do konce {{ .Facts.FormatCount }} formátů." + }, + { + "q": "Na kterých systémech to mohu spustit?", + "a": "Příkazový řádek běží na Windows a Linuxu na Intelu i ARM a na Macích s Apple Silicon. Desktopové okno se dodává pro Windows na Intelu, Linux na Intelu a Macy s Apple Silicon. Intel Macy nejsou podporovány a nic se pro ně nesestavuje." + }, + { + "q": "Musím něco instalovat?", + "a": "Ne. Stáhněte archiv pro svůj systém, rozbalte ho a spusťte binárku. Není tu instalátor, běhové prostředí k doplnění ani závislost k vyřešení. Pokud máte Go, funguje i jediný příkaz go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Proč je běh nad tisíci soubory na Windows pomalejší?", + "a": "Protože Windows si účtuje víc za každou cestu, na kterou se podívá, a příkaz, který prochází tisíce souborů, se dívá na tisíce cest. Změřeno na jednom počítači s 3000 soubory po 1 kB: verify trvá na Windows asi 0,9 sekundy a na Linuxu v kontejneru asi 0,2 sekundy. Kratší výstupní cesta číslo na Windows zmenší, protože každá složka nad soubory je součástí toho, na co se dívá." + } + ] +} diff --git a/web/content/cs/use-cases.html b/web/content/cs/use-cases.html new file mode 100644 index 00000000..3d2376fc --- /dev/null +++ b/web/content/cs/use-cases.html @@ -0,0 +1,129 @@ +

K čemu to lidé používají

+

+ Pět úloh, které se objevují téměř v každém projektu přijímajícím soubory od lidí, a příkaz, který + každou provede. Každý příklad níže běží tak, jak je napsán. +

+ +
+

Limity nahrávání

+

Test, zda je limit velikosti souboru vynucován tam, kde se tvrdí

+

+ Limit jsou tři testovací případy, ne jeden: těsně pod, přesně na něm a těsně nad. Získat je ručně + znamená počítat počty bajtů a doufat, že jste se nespletli o jedna. Požádejte raději o sadu: +

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

+ Dostanete tři skutečná PDF o 1048575, 1048576 a 1048577 bajtech a manifest, který říká, že první dvě + mají být přijata a třetí odmítnuto pro size_limit. Váš test čte očekávání místo + toho, abyste ručně psali tři aserce - a když se limit změní, změníte jedno číslo a spustíte + znovu. +

+

+ Totéž funguje bez předvolby, když chcete jedinou sadu hranic přímo v příkazu: +

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

Průběžná integrace

+

Držet fixtures mimo repozitář, aniž byste o ně přišli

+

+ Velké binární fixtures zpomalují klonování repozitáře a znepříjemňují revizi a nikdo nepozná, co se + změnilo, když se jeden vymění. Recept je pár set znaků YAML, které znovu sestaví totožné soubory + - bajt po bajtu, na jakémkoli počítači - protože každý soubor je odvozen ze + seedu běhu. +

+
- 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
+

+ Každý konec má svůj vlastní návratový kód, takže pipeline rozliší špatný recept od plného disku a od + nesrovnalosti při ověření. Neúspěšný běh nevypíše na standardní výstup nic, takže parser logu + nečte chybu jako data. +

+
+ +
+

Rozsah

+

Zjistit, co se stane, když je složka velká

+

+ Importní rutiny, noční úlohy a výpisy adresářů se chovají při deseti tisících souborů jinak než při + deseti. Velikosti losované z rozsahu dělají ze sady něco, co vypadá jako skutečný provoz, a ne + deset tisíc stejných souborů, a losování vychází ze seedu, takže sada je zítra stejná. +

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

+ Zkontrolujte, kolik by běh stál, než cokoli zapíše, což záleží, když se součet měří v gigabajtech: +

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

+ Běh větší než volné místo na disku je odmítnut dřív, než se zapíše první bajt, místo aby zaplnil + disk a selhal v půlce. +

+
+ +
+

Archivy

+

Test rozbalovače s archivem, který skutečně obsahuje soubory

+

+ Prázdný archiv se správnou příponou nic nedokazuje o kódu, který ho otevírá a prochází, co je + uvnitř. Deklarujte obsah a archiv ho skutečně obsahuje: +

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

+ Hloubka vnoření, počet položek a velikost toho, co je uvnitř, jsou věci, o kterých má importní + rutina názor, a takto zjistíte, jaké ty názory jsou. +

+
+ +
+

Parsery a prohlížeče

+

Ověření, že váš vlastní kód čte formát tak, jak to dělá skutečný software

+

+ Každý formát zde je před vydáním ověřen nezávislou čtečkou - PNG se otevře a porovnají se jeho + pixely, DOCX čtou zpět samostatné knihovny, archiv se rozbalí. To znamená, že soubor, který váš + parser odmítne, je zjištění o vašem parseru, ne o generátoru. +

+
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
+

+ Stránka formátů uvádí nastavení, která každý formát přijímá, a nejmenší + soubor, jakým každý může být. +

+
+ +
+

Návody

+

Dva z nich podrobněji

+ +
+ +
+

Pro koho to je

+

+ QA inženýry, automatizaci testů a každého, za jehož kódem stojí formulář pro nahrávání, importní + rutina, parser nebo kvóta úložiště. Běží na počítači bez jakékoli sítě, na čem záleží v + uzavřeném firemním prostředí, kde generátor v prohlížeči není možnost. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/de/ci.html b/web/content/de/ci.html new file mode 100644 index 00000000..95320a8f --- /dev/null +++ b/web/content/de/ci.html @@ -0,0 +1,194 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

So erzeugen Sie Testdateien in einer CI-Pipeline

+

+ Ein binäres Fixture in einem Repository bleibt für immer in dessen Verlauf, lässt sich in einem Diff + nicht prüfen und geht bei großen Dateien gar nicht mehr. Erzeugen Sie die Dateien stattdessen in + der Pipeline aus einem Rezept. Das Rezept ist Text, die Bytes sind jedes Mal dieselben, und ein + letzter Schritt beweist, dass sich nichts verändert hat. +

+ +
+

Die kurze Antwort

+

+ Installieren Sie tfg, führen Sie vor den Tests tfg generate fixtures.yaml --out + ./fixtures aus und danach tfg verify ./fixtures/manifest.json. Beide + Schritte lassen den Build von selbst scheitern, mit einem Exit-Code, der sagt, warum. +

+
+ +
+

Warum nicht einchecken

+

Warum ein Fixture nicht im Repository liegen sollte

+ +

+ Einzuchecken ist das Rezept. Dasselbe Rezept mit demselben Seed schreibt auf jeder Maschine + dieselben Bytes, die in der Pipeline erzeugte Datei ist also die Datei, die Sie auf dem Laptop + hatten. +

+
+ +
+

Das Rezept

+

Ein Rezept, das neben den Tests liegt

+

+ Dieses schreibt fünfundzwanzig Rechnungen, die angenommen werden sollen, und zwei Bilder über einem + Limit, die abgewiesen werden sollen, und das Manifest hält beide Erwartungen fest: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml prüft es, ohne etwas zu schreiben, und nennt jedes Problem + auf einmal. +

+
+ +
+

GitHub Actions

+

Ein Workflow, der das Tool installiert und die Fixtures erzeugt

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Die Prüfsummenzeile vergleicht das Archiv mit verify-SHA256SUMS.txt aus demselben + Release. Die Version ist festgelegt, ein neues Release ändert also nie einen Build, den Sie + nicht angefasst haben. +

+
+ +
+

GitLab CI

+

Dasselbe als GitLab-Job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Wenn es rot wird

+

Was einen Schritt scheitern lässt, und warum

+

+ Jedes Ende hat seinen eigenen Exit-Code, der Schritt scheitert also von selbst, und das Log sagt, + welcher es war. Die, denen eine Pipeline begegnet: +

+ +

+ Ein fehlgeschlagener Lauf gibt nichts auf der Standardausgabe aus, sodass ein Log-Parser nie einen + Fehler für Daten hält. Die ganze Tabelle steht auf der + Dokumentationsseite. +

+
+ +
+

PowerShell

+

Ein PowerShell-Skript braucht eine Zeile mehr

+

+ PowerShell trägt den Exit-Code eines Programms nicht aus einer .ps1-Datei heraus. + Starten Sie eine mit -File, und das Skript antwortet 0, auch wenn das + Tool darin die Arbeit verweigert hat, sodass ein Build, der rot sein sollte, grün wird. Die + letzte Zeile ist die ganze Lösung: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ So verhält sich PowerShell, es liegt nicht an diesem Tool. cmd, bash und + zsh brauchen nichts zusätzlich. +

+
+ +
+

Mehrere Jobs

+

Fixtures zwischen Jobs teilen

+

+ Hochladen ist meist nicht nötig. Weil dasselbe Rezept dieselben Bytes schreibt, kann jeder Job sein + eigenes tfg generate ausführen, und das geht schneller als Hoch- und Herunterladen. + Muss ein Job Dateien von einem anderen erhalten, führen Sie nach der Übertragung tfg + verify auf dem Manifest aus, und es sagt, ob das Angekommene dem Geschriebenen + entspricht. +

+
+ +
+

Weiter

+

Wohin es von hier geht

+ +
diff --git a/web/content/de/damage.html b/web/content/de/damage.html new file mode 100644 index 00000000..5cf84394 --- /dev/null +++ b/web/content/de/damage.html @@ -0,0 +1,178 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

So erzeugen Sie eine beschädigte Datei zum Testen

+

+ Ein Validator, dem man nur gesunde Dateien gezeigt hat, ist nicht wirklich getestet. So bekommen Sie + eine Datei, die absichtlich kaputt ist, genau die Größe hat, die Sie verlangen, + und ein Manifest mitbringt, das sagt, was Ihr System damit tun soll. +

+ +
+

Die kurze Antwort

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out schreibt ein PNG + von genau 2097152 Byte, dessen erste Bytes Nullen sind, und das Manifest daneben hält fest, dass + Ihr System es ablehnen soll. +

+
+ +
+

Der übliche Weg

+

Warum eine von Hand beschädigte Datei ein schlechter Test ist

+

+ Üblich sind ein Hex-Editor, ein Skript, das ein paar zufällige Bytes kippt, oder eine Datei, die mit + head oder truncate gekürzt wird. Das funktioniert einmal, und dann + kostet es Sie: +

+ +
+ +
+

Was Sie bekommen

+

Eine beschädigte Datei hat trotzdem die verlangte Größe

+

+ Die Datei wird normal erzeugt und erst danach auf dem Weg zur Festplatte beschädigt. Sie behält die + verlangte Größe, und derselbe Befehl schreibt wieder dieselben Bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Einstellungen stehen nach einem Doppelpunkt. Die Option lässt sich wiederholen, und die + Beschädigungen werden in der Reihenfolge angewendet, in der Sie sie schreiben. Es funktioniert + mit allen {{ .Facts.FormatCount }} Formaten. +

+
+ +
+

Was möglich ist

+

Welche Beschädigungen gibt es?

+

+ Das ist die Liste, die das Programm ausgibt, beim Erstellen dieser Seite aus ihm gelesen. tfg + damage gibt dieselbe aus, und tfg damage <id> sagt, was eine davon + annimmt. +

+ {{ template "damagesTable" . }} +

+ zero-head schreibt Nullen über den Anfang der Datei. Die meisten Leser schauen zuerst + dorthin, auf die Signatur und den Header, die sagen, was die Datei ist, deshalb bemerkt es fast + jeder Leser. Reiner Text und Logs haben keine Signatur und werden ebenfalls abgewiesen, weil + eine Folge von Nullbytes kein Text ist. Unter vier Bytes entstehen bei manchen Formaten Schäden, + über die sich kein Leser beschwert, deshalb beginnt die Einstellung bei vier. +

+
+ +
+

Was das Manifest sagt

+

Ein Manifest, das sagt, was geschehen soll

+

+ Jede beschädigte Datei bekommt einen Eintrag, der besagt, dass Ihr System sie ablehnen soll, mit der + Beschädigung daneben: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Zwei Anfragen werden abgelehnt, bevor etwas geschrieben wird, denn jede würde eine Datei + hinterlassen, die das Manifest falsch beschreibt: +

+ +
+ +
+

In einem Rezept

+

Gesunde und kaputte Dateien in einem Lauf

+

+ Legen Sie beides in ein Rezept, dann trägt das Manifest die Erwartung jeder Datei, und der Test + braucht keine Liste, welche welche ist: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In einem Test

+

Daraus einen Test machen

+

+ Der Test liest das Manifest und prüft, ob das, was geschah, dem Erklärten entspricht. Er braucht + keine Liste von Dateinamen: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Eine gute Ablehnung ist eine saubere. Eine Meldung, die sagt, was falsch war, ist die gewünschte + Antwort. Ein Serverfehler, ein Hänger oder eine halb gespeicherte Datei ist der Fehler, den + dieser Test finden soll. +

+
+ +
+

Weiter

+

Wohin es von hier geht

+ +
diff --git a/web/content/de/docs.html b/web/content/de/docs.html new file mode 100644 index 00000000..763b4e6c --- /dev/null +++ b/web/content/de/docs.html @@ -0,0 +1,285 @@ +

Dokumentation

+

+ Alles, was das Tool kann, geordnet nach den Fragen, mit denen die Leute tatsächlich kommen. Die + README im Repository ist die vollständige Referenz und passt immer + zu dem Build, den du heruntergeladen hast. +

+ +
+

Welche Befehle gibt es?

+

Jeder tut genau eine Sache:

+ {{ template "commandList" . }} +
+ +
+

Wie erzeuge ich eine einzelne Datei in exakter Größe?

+

+ Nenne das Format, die Größe und das Ziel. Größen zählen in 1024ern, 2mb sind also + 2097152 Bytes. Eine einfache Byte-Zahl funktioniert auch, --size 10485761 verlangt + also genau so viele. +

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

Die nützlichen Flags von generate:

+
+ + + + + + + + + + + + + + + + + +
FlagWas es tut
--format <id>Format der Dateien, zum Beispiel txt
--size <size>exakte Größe jeder Datei, etwa 10mb oder eine einfache Byte-Zahl
--size-range <a-b>eine Größe, die pro Datei aus einem Bereich gezogen wird, etwa 1kb-8kb. Die Ziehung kommt aus dem Seed
--boundary <size>drei Dateien rund um ein Limit: ein Byte darunter, das Limit, ein Byte darüber
--count <n>wie viele Dateien erzeugt werden. Standard 1
--name <template>Namensvorlage, zum Beispiel invoice_{index:04}.txt
--out <dir>Verzeichnis, in das geschrieben wird
--seed <n>Seed des Laufs. Derselbe Seed ergibt dieselben Bytes
--set <k>=<v>eine Formateinstellung, wiederholbar
--damage <name>Dateien absichtlich beschädigen, wiederholbar und der Reihe nach angewendet. Mit tfg damage bekommst du die Liste
--expected <outcome>accept, reject, sanitize oder unspecified
--dry-runzählen und anzeigen, überhaupt nichts schreiben
--jsondas Manifest auf die Standardausgabe schreiben
+
+
+ +
+

Wie erzeuge ich eine absichtlich kaputte Datei?

+

+ Jede andere Datei, die dieses Tool schreibt, ist per Konstruktion korrekt, was zwei der drei Fragen + beantwortet, die ein Upload-Validator stellt. --damage beantwortet die dritte - + lässt sich die Datei überhaupt öffnen. Die Datei wird normal erzeugt und dann beschädigt, sie + hat also weiterhin die verlangte Größe. +

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

+ Einstellungen stehen hinter einem Doppelpunkt. Das Flag lässt sich wiederholen, und die Reihenfolge, + in der du sie schreibst, ist die Reihenfolge, in der sie angewendet werden. tfg + damage listet auf, was dieser Build kann und was jede Variante annimmt. +

+

In einem Rezept ist der Schlüssel eine Liste, aus Namen oder aus Einstellungen:

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

+ Eine beschädigte Datei bekommt im Manifest expected: reject, mit der daneben + festgehaltenen Beschädigung. Zwei Dinge werden abgelehnt, bevor etwas geschrieben wird, weil + sonst jeweils eine Datei auf die Platte käme, die das Manifest falsch beschreibt: +

+ +

+ Eine dritte lässt sich nicht im Voraus wissen. Wenn eine Beschädigung läuft und kein Byte verändert, + wird diese Datei verworfen statt geschrieben - der Lauf macht weiter, sagt, um welche Datei es + ging, und endet mit dem Exit-Code für teilweise erfolgreiche Läufe. +

+

+ Schritt für Schritt, mit einem Test, der das Manifest liest: + So erzeugen Sie eine beschädigte Datei zum Testen. +

+
+ +
+

Wie sieht ein Rezept aus?

+

+ Ein Rezept ist eine YAML-Datei, die einen ganzen Lauf beschreibt. Checke sie neben deinen Tests ein, + und die Fixtures sind keine Binärdateien mehr in deinem Repository - jeder kann sie Byte für + Byte aus einer Datei von wenigen hundert Zeichen neu erzeugen. +

+
# 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
+

+ Jedes Target braucht genau eines von size, size-range, + boundary oder contains. Zwei davon sind ein Fehler, und keines + ebenfalls. Ein ungültiges Rezept schreibt überhaupt keine Dateien und meldet + alle Probleme auf einmal statt nur das erste, jedes mit der Einstellung, um die es geht. +

+
+ +
+

Wie lege ich fest, was mein System mit einer Datei tun soll?

+

Kurzform, wenn das Ergebnis reicht, Langform, wenn der Grund zählt:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Die Ergebnisse sind accept, reject, sanitize und + unspecified. Die Gründe sind eine geschlossene Liste, damit ein Report danach + gruppieren kann: 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 und + size_zero. +

+

+ Ein Grund benennt die Regel, um die es geht, nicht das Urteil. Deshalb kann + derselbe Grund unter beiden Ergebnissen stehen - eine Datei ein Byte unter einem Limit ist + accept, und die Regel, um die es geht, ist trotzdem size_limit. +

+
+ +
+

Was steht im Manifest?

+

+ Es wird am Ende jedes Laufs neben die Dateien geschrieben, auch bei einem unterbrochenen Lauf. Ein + Eintrag pro Datei: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Ein recipe_hash kommt hinzu, wenn der Lauf aus einem Rezept stammt, und + preset mit overrides, wenn er aus einem Preset stammt, sodass sich ein + Manifest immer auf das zurückführen lässt, was es erzeugt hat. +

+

+ Jeder Eintrag trägt außerdem target_id, die ID des Targets im Rezept, das die Datei + erzeugt hat, und summary.by_target zählt, auf wie viele Dateien jedes Target kam. + Ein Rezept mit mehreren Targets lässt sich so Target für Target prüfen, ohne Dateinamen zu + lesen. +

+
+ +
+

Was ist ein Preset?

+

+ Ein fertiges Set aus Dateien, das eine gängige Testfrage beantwortet, damit du das Set nicht selbst + entwerfen musst. Presets sind darunter ganz normale Rezepte, und eject gibt das + Rezept aus, damit du es von dort aus bearbeiten kannst. Jedes Preset hat + eine eigene Seite mit dem, was es meist findet, was im Set steckt und + welche Einstellungen es kennt. +

+ {{ template "presetsList" . }} +
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 sagt dir, was das Set kosten würde, bevor du es baust, und sagt + unmissverständlich, wenn eine Zahl ein Platzhalter von uns statt ein Limit von dir ist. +

+
+ +
+

Was bedeuten die Exit-Codes?

+

+ Jedes Ende hat einen eigenen Code, maschinenlesbare Ausgabe geht auf die Standardausgabe, und ein + fehlgeschlagener Lauf gibt dort nichts aus. Die Tabelle ist ein eingefrorener Vertrag - die + Bedeutung eines Codes zu ändern erfordert einen Major-Versionssprung. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Ein mit Strg+C gestoppter Lauf hinterlässt trotzdem ein Manifest und nie eine halb geschriebene + Datei, sodass ein abgebrochener Job vom nächsten noch aufgeräumt werden kann. +

+

+ Fertige Workflows für GitHub Actions und GitLab CI: So erzeugen Sie + Testdateien in einer CI-Pipeline. +

+
+ +
+

Gibt es ein Desktop-Fenster?

+

+ Ja, dieselbe Engine mit einem Fenster davor, für das Testen, das nicht skriptbar ist. Es ist keine + abgespeckte Version: Ein Test vergleicht die beiden Oberflächen Fähigkeit für Fähigkeit, und + alles, was nur eine von beiden kann, muss deklariert und begründet werden, statt unbemerkt + auseinanderzudriften. +

+

+ Die Bildschirme sind ein Stapel, Presets, mehrere Stapel gleichzeitig und Info. Es zeigt, was ein + Lauf kosten würde, bevor etwas geschrieben wird, meldet den Fortschritt während des Laufs und + lässt sich mittendrin abbrechen, ohne eine halb geschriebene Datei zu hinterlassen. Eine + Rezeptdatei öffnet es noch nicht - Rezepte gibt es vorerst nur auf der Kommandozeile, und das + Fenster baut seine Stapel im Formular. +

+
diff --git a/web/content/de/exact-size.html b/web/content/de/exact-size.html new file mode 100644 index 00000000..b76696e9 --- /dev/null +++ b/web/content/de/exact-size.html @@ -0,0 +1,154 @@ +

So erstellst du eine Datei in exakter Größe

+

+ Jedes System hat dafür einen Befehl, alle drei stehen unten. Sie liefern dir eine Datei mit genau + der richtigen Byte-Zahl - und für viele Tests ist das alles, was du brauchst. Jeder Befehl + auf dieser Seite wurde vor der Veröffentlichung ausgeführt, auf dem System, zu dem er + gehört. +

+ +
+

Die kurze Antwort

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Größen werden in Bytes angegeben, + und 10 MB, so gezählt wie dein Dateimanager zählt, sind 10485760 davon. +

+
+ +
+

Windows

+

fsutil und eine PowerShell-Variante, die nichts Zusätzliches braucht

+

+ fsutil gehört zu Windows. Es nimmt die Größe in Bytes, rechne die Zahl + also vorher aus - 10 MB sind 10485760, 100 MB sind 104857600, 1 GB ist 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Gemessen unter Windows 11: Es funktioniert in einer normalen Eingabeaufforderung und braucht keine + erhöhten Rechte, und die Datei hat genau 10485760 Bytes. +

+

PowerShell kann dasselbe, ohne ein anderes Programm aufzurufen, und versteht Einheiten:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB bedeutet in PowerShell 10485760 Bytes, dieselbe Zählung auf 1024er-Basis, die der + Explorer verwendet, die beiden Befehle oben erzeugen also dieselbe Größe. +

+
+ +
+

Linux

+

dd, truncate und fallocate und der Unterschied, der Leute erwischt

+

dd kennt jeder. Es schreibt die Bytes wirklich:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate ist sofort fertig, und genau das ist der Haken. Gemessen unter Alpine Linux + meldet die Datei 10485760 Bytes und belegt null Blöcke - sie ist eine + Sparse-Datei. Wer sie liest, bekommt zehn Megabyte Nullen, aber der Datenträger + hat den Platz nie hergegeben: +

+
truncate -s 10M test10mb.bin
+

+ Das ist für den Test eines Upload-Limits in Ordnung und für den Test einer Datenträgerquote + irreführend. fallocate ist das Mittel der Wahl, wenn der Platz wirklich belegt sein + muss: +

+
fallocate -l 10M test10mb.bin
+

Und wenn der Inhalt inkompressibel sein muss, damit ein Archivierer ihn nicht wieder zusammendrücken kann:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, das nicht sparse ist, und die beiden, die du schon kennst

+

+ macOS liefert mkfile mit. Gemessen unter macOS 26.6.2: 10485760 Bytes und 20480 Blöcke, + der Platz ist also wirklich belegt statt nur versprochen: +

+
mkfile 10m test10mb.bin
+

dd und truncate gibt es ebenfalls, und sie verhalten sich wie unter Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Wo das nicht mehr reicht

+

Eine Datei in der richtigen Größe ist keine Datei der richtigen Art

+

+ Alles oben Genannte liefert dir einen Block aus Nullen. Das reicht, wenn das Getestete nur auf die + Größe schaut - ein Upload-Limit, eine Quote, eine Übertragung. Es reicht nicht mehr, sobald + irgendetwas die Datei öffnet. +

+

+ Gemessen, und es lohnt sich, das selbst zu probieren: Erzeuge mit fsutil eine + 2-MB-Datei, nenne sie photo.png und gib sie einer Bildbibliothek. Pillow antwortet + cannot identify image file. Es ist kein PNG. Es war nie eines - nur der Name + behauptete es. +

+

+ Das ist wichtiger, als es klingt, wegen der Richtung, in der der Test dann + fehlschlägt. Dein Upload-Endpunkt weist die Datei ab, dein Test wird grün, und du + schließt, dass das Größenlimit funktioniert. Er hat sie nicht wegen der Größe abgewiesen. Er hat + sie abgewiesen, weil die Bytes kein Bild waren, und die Regel, die du testen wolltest, wurde nie + erreicht. +

+ +
+ +
+

Der andere Weg

+

Eine echte Datei dieses Formats, in genau der Größe, die du verlangt hast

+

+ Das ist es, was Testing Files Generator tut. Die Datei ist eine echte ihres Formats - sie öffnet + sich in der Software, zu der sie gehört - und hat die exakte Byte-Zahl, die du verlangt hast, + auf das Byte genau: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Verlange eine Größe, die ein Format nicht erreichen kann, und du bekommst einen Fehler, der die + Untergrenze und ihren Grund nennt, nie eine Datei in der falschen Größe. Die + Formate-Seite listet jedes Format mit der kleinsten Datei auf, die es + erzeugen kann. +

+

Und ein Limit sind drei Testfälle statt einem, deshalb baut das Tool alle drei:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Das ergibt 10485759, 10485760 und 10485761 Bytes und ein Manifest, das sagt, welche davon dein + System akzeptieren und welche es ablehnen soll. Die + Anwendungsfälle-Seite geht das und vier weitere Aufgaben + durch, für die es gebaut ist. +

+ {{ template "downloadCta" . }} +
+ +
+

Was solltest du also verwenden?

+ +

+ Beides steht auf dieser Seite, weil beides manchmal richtig ist. Der Fehler, den es zu vermeiden + gilt, ist, das Erste zu verwenden, wo das Zweite nötig ist, und den grünen Test als Beweis zu + lesen. +

+
diff --git a/web/content/de/faq.html b/web/content/de/faq.html new file mode 100644 index 00000000..8f02a81d --- /dev/null +++ b/web/content/de/faq.html @@ -0,0 +1,20 @@ +

Häufig gestellte Fragen

+

+ Lizenz, Datenschutz, Reproduzierbarkeit und das, was Leute prüfen, bevor sie einen Generator in eine + Build-Pipeline einbauen. Wenn deine Frage hier fehlt, ist der + Issue-Tracker offen. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Noch unentschlossen?

+

+ Die Anwendungsfälle-Seite zeigt die Aufgaben, für die es gebaut + ist, und die Formate-Seite listet jedes Format mit der kleinsten + Datei auf, die es erzeugen kann. Die README im Repository ist + die vollständige Referenz. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/de/formats.html b/web/content/de/formats.html new file mode 100644 index 00000000..aaccacc1 --- /dev/null +++ b/web/content/de/formats.html @@ -0,0 +1,81 @@ +

{{ .Facts.FormatCount }} Dateiformate, jedes in exakter Größe erzeugt

+

+ Jedes davon ist eine echte Datei dieses Formats. Sie öffnet sich in der Software, + zu der sie gehört, und hat genau die Byte-Zahl, die du verlangt hast. Keines davon besteht aus + aufgefüllten Nullen mit einer angeklebten Endung. +

+ +{{ template "formatsTable" . }} + +
+

Was die Spalten bedeuten

+ +

+ Jedes Format wiederholt sich außerdem bis aufs Byte: Dasselbe Rezept und derselbe Seed erzeugen auf + jedem Rechner identische Dateien, und genau das macht ein Rezept sicher einzuchecken statt der + Fixtures selbst. +

+
+ +
+

Einstellungen, die jedes Format kennt

+

+ Die meisten Formate haben eigene Einstellungen - Bildmaße, JPEG-Qualität, PDF-Seitenzahl, Zeilen und + Spalten in einer Tabelle, wie viele Einträge in ein Archiv kommen. Setze sie mit --set + key=value auf der Kommandozeile oder unter properties: in einem Rezept. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Ein Wert außerhalb dessen, was eine Einstellung zulässt, wird mit einer Meldung abgewiesen, die die + Einstellung, den erlaubten Bereich und eine Alternative nennt. Eine unbekannte Einstellung ist + ebenfalls ein Fehler, nie ein stiller Standardwert - ein stillschweigend akzeptierter Tippfehler + ergibt eine Datei mit den falschen Einstellungen und eine Stunde Rätselraten, warum der Test + besteht, obwohl er es nicht sollte. +

+

+ Mit tfg formats <id> siehst du genau, was ein Format in dem Build akzeptiert, den + du hast. +

+
+ +
+

Archive enthalten echte Dateien

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} und {{ end }}{{ $c.ID }}{{ end }} + lassen sich mit Einträgen füllen, statt als leere Hülle zu bleiben. Ein erzeugtes Archiv enthält + wirklich die Dokumente, die es zu enthalten vorgibt, sodass alles, was es während eines Tests + entpackt, echte Dateien darin findet. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/de/index.html b/web/content/de/index.html new file mode 100644 index 00000000..188e7d8e --- /dev/null +++ b/web/content/de/index.html @@ -0,0 +1,200 @@ +
+
+

Echte Testdateien in jeder exakten Größe erzeugen

+

+ PDF, PNG, DOCX, ZIP - insgesamt {{ .Facts.FormatCount }} Formate, und jedes ist + eine echte Datei, die sich in der Software öffnet, zu der sie gehört, in genau der + Größe, die du verlangt hast. Jeder Lauf hält außerdem fest, was deine Anwendung mit + jeder Datei tun soll. Kommandozeile und Desktop-Fenster, kostenlos und Open Source, vollständig + auf deinem Rechner. +

+ + {{ template "downloadCta" . }} +
+ +
+ Das Desktop-Fenster von Testing Files Generator, eingerichtet für einen Stapel Testdateien +
Das Desktop-Fenster, eingerichtet für einen Stapel Dateien. Dieselbe Engine läuft hinter der Kommandozeile.
+
+
+ + + +
+

Das Problem

+

Eine Testdatei zu machen ist einfach. Die richtigen tausend zu machen ist das Mühsame

+

Du testest Software, die Dateien von Menschen annimmt. Früher oder später brauchst du:

+ +

+ Genau das ersetzt dieses Tool. Es ist gebaut für QA-Engineers, Testautomatisierung und alle, deren + Code ein Upload-Formular, eine Importroutine, einen Parser oder ein Speicherkontingent hinter + sich hat. +

+
+ +
+

Was es anders macht

+

Andere Generatoren hören bei den Bytes auf. Dieser beantwortet, was dein Test wirklich fragt

+

+ Ein Ordner voller Dateien lässt dich weiter entscheiden, was jede davon belegen soll. Jeder Lauf + schreibt hier ein manifest.json neben die Dateien - eine einfache Liste von allem, + was erzeugt wurde, und zu jedem Eintrag eine deklarierte Erwartung. +

+

Angenommen, dein Upload-Endpunkt erlaubt 1 MB. Fordere die drei Dateien an, die auf dieser Linie liegen:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
DateiBytesDein System sollWeil
1mb_under_1b.pdf1048575akzeptierensie liegt innerhalb des Limits
1mb_at_limit.pdf1048576akzeptierendas Limit selbst ist erlaubt
1mb_over_1b.pdf1048577ablehnensize_limit
+
+ +

Drei Dateien, drei verschiedene Antworten, in maschinenlesbarer Form. Dein Test liest das Manifest, statt dass du die Assertions von Hand schreibst:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Wo die Antwort von deiner eigenen Richtlinie abhängt, sagt das Manifest das

+

+ Es hält unspecified fest, statt eine Erwartung zu erfinden. Ein Generator, der rät, + erzeugt falsche Fehlschläge, und eine Testsuite, die ständig Alarm schlägt, wird abgeschaltet. +

+
+
+ +
+

Presets

+

Wähle die Frage, bekomme das ganze Set

+

+ Ein Preset ist ein Set aus Testdateien, das um eine Testfrage herum entworfen wurde, damit du nicht + selbst herausfinden musst, welche Dateien was belegen. Jedes hat eine eigene Seite mit dem, was + es meist findet, was im Set steckt und welche Einstellungen es kennt. +

+ {{ template "presetsList" . }} +

Alle Presets und wie sie sich zu Rezepten verhalten

+
+ +
+

Schnellstart

+

Drei Befehle, um es in Aktion zu sehen

+
    +
  1. +

    Eine Datei erzeugen

    +

    Ein PNG, genau zwei Megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Viele Dateien erzeugen

    +

    + Zehntausend Logdateien, jede zwischen einem und acht Kilobyte, die Größen werden aus dem Seed + gezogen, sodass morgen dasselbe Set herauskommt. Gib jedem Lauf ein eigenes + Verzeichnis - das Manifest ist die einzige Aufzeichnung dessen, was ein Lauf + geschrieben hat, deshalb weigert sich das Tool, ein zweites darüber zu schreiben: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Prüfen und dann entfernen

    +

    verify sagt dir, dass sich nichts verändert hat. cleanup entfernt genau das, was geschrieben wurde, und sonst nichts:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Größen zählen in 1024ern, wie es dein Dateimanager tut, 2mb bedeutet also 2097152 + Bytes. Eine einfache Byte-Zahl funktioniert auch. Die + Dokumentation behandelt Rezepte, das Manifest und die + Exit-Codes. +

+
+ +
+

Was du bekommst

+

Gebaut für eine Testsuite, die unbeaufsichtigt läuft

+ +
+ +
+

Download

+

Wähle den Build für dein System

+

+ Entpacke das Archiv und starte es. tfg ist die Kommandozeile und tfg-gui + das Desktop-Fenster. Es gibt keinen Installer und nichts, was auf deinem Rechner hinzugefügt + werden müsste. +

+ {{ template "downloadsTable" . }} +
+

Was signiert ist und was nicht

+

+ Die Downloads für Windows und macOS sind signiert und starten daher ohne Warnung vor einem + unbekannten Entwickler. Die für Linux nicht, weil es unter Desktop-Linux nichts Vergleichbares + zum Signieren gibt. Jedes Archiv steht auf der Release-Seite in + verify-SHA256SUMS.txt, sodass du prüfen kannst, was du heruntergeladen hast. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/de/preset.html b/web/content/de/preset.html new file mode 100644 index 00000000..18d2db7a --- /dev/null +++ b/web/content/de/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Das Preset {{ .ID }} baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ +{{ if .Catches }} +
+

Was findet es meistens?

+ +
+{{ end }} + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show {{ .ID }} ausgibt:

+
+ + + + + + + +
Dateien{{ .Budget.Files }}
Targets in seinem Rezept{{ .Budget.Targets }}
Gesamtgröße{{ .Bytes }} B
Formate{{ join .Budget.Formats ", " }}
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
ErwartetBedeutungDateien
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Was kannst du ändern?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
EinstellungNimmtStandardWas es tut
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Dieser Standardwert ist unser Platzhalter, nicht der Wert deines Systems. Gib deinen eigenen an.{{ end }}
+
+ {{- else }} +

Dieses Preset hat keine Einstellungen. Das Set ist jedes Mal dasselbe.

+ {{- end }} +
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/de/presets.html b/web/content/de/presets.html new file mode 100644 index 00000000..e560eb3f --- /dev/null +++ b/web/content/de/presets.html @@ -0,0 +1,32 @@ +

Testdatei-Presets, ein Set für jede Testfrage

+

+ Ein Preset ist ein ganzes Set aus Testdateien, das um eine Frage herum entworfen wurde, mit einem + Manifest, das beschreibt, wie dein System auf jede Datei reagieren soll. Du wählst die Frage, das + Tool baut das Set. Jedes Preset hat eine eigene Seite mit dem, was es meist findet, was im Set + steckt und welche Einstellungen es kennt. +

+ +{{ template "presetsList" . }} + +
+

Worin unterscheidet sich ein Preset von einem Rezept?

+

+ Darunter gar nicht. Ein Preset ist ein Rezept, das das Tool aus ein paar Einstellungen für dich + schreibt. tfg preset eject gibt dieses Rezept aus, damit du es neben deinen Tests + aufbewahren und bearbeiten kannst, und ein eigenes Rezept kann mit einer Zeile auf einem Preset + aufbauen, extends: preset: gefolgt von seiner ID. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Kann ich den Standardwerten trauen?

+

+ Bei den Dateien ja. Bei einer Zahl, die nur dein System kennt, etwa dem Limit eines + Upload-Formulars, ist ein Standardwert ein Platzhalter von uns, und das Tool sagt es jedes Mal, + wenn es einen verwendet. Die Seite jedes Presets markiert diese Einstellungen, und tfg + preset show sagt es, bevor etwas geschrieben wird. +

+
diff --git a/web/content/de/site.json b/web/content/de/site.json new file mode 100644 index 00000000..15d72aaa --- /dev/null +++ b/web/content/de/site.json @@ -0,0 +1,328 @@ +{ + "code": "de", + "locale": "de_DE", + "name": "Deutsch", + "dir": "de", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Start", + "title": "Testdatei-Generator für QA - exakte Größe, {{ .Facts.FormatCount }} echte Formate", + "description": "Kostenloser Open-Source-Generator für QA. Echte PDF-, DOCX-, PNG- und ZIP-Dateien in jeder exakten Größe, dazu ein Manifest, wie dein System reagieren soll." + }, + { + "key": "formats", + "slug": "formate", + "nav": "Formate", + "title": "{{ .Facts.FormatCount }} unterstützte Dateiformate - PDF, DOCX, PNG, ZIP und mehr", + "description": "Alle Dateiformate dieses Generators, die kleinste mögliche Datei je Format und die Einstellungen, die es kennt. Alle {{ .Facts.FormatCount }} öffnen sich in ihrer Software." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Presets", + "title": "Testdatei-Presets - fertige Sets für typische QA-Fragen", + "description": "Fertige Sets aus Testdateien, jedes beantwortet eine Testfrage: Upload-Limits, Dateinamen, Zeichenkodierungen, Tabellenimporte, leere Dateien und Upload-Validierung." + }, + { + "key": "docs", + "slug": "dokumentation", + "nav": "Dokumentation", + "title": "Dokumentation - Befehle, Rezepte, Manifest, Exit-Codes", + "description": "So erzeugst du Testdateien über die Kommandozeile oder ein YAML-Rezept, was das Manifest enthält und was jeder Exit-Code bedeutet, wenn das Tool in der CI läuft." + }, + { + "key": "use-cases", + "slug": "anwendungsfaelle", + "nav": "Anwendungsfälle", + "title": "Anwendungsfälle - Upload-Limits, CI-Fixtures, Massentests", + "description": "Ein Upload-Größenlimit testen, reproduzierbare Fixtures für die CI bauen, zehntausend Dateien erzeugen und Archive mit echtem Inhalt füllen." + }, + { + "key": "exact-size", + "slug": "datei-bestimmter-groesse-erstellen", + "nav": "Dateigröße", + "title": "Datei mit bestimmter Größe erstellen - Windows, Linux, macOS", + "description": "fsutil, dd, truncate und mkfile, jeweils auf dem passenden System gemessen - und warum eine so erzeugte Datei kein PDF und kein PNG ist, wenn ein Test eines braucht." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - Fragen zum Erzeugen von Testdateien", + "description": "Worin sich das Tool von dd und fsutil unterscheidet, ob man die Dateien einchecken kann, ob Läufe reproduzierbar sind und was bei unerreichbaren Größen passiert." + }, + { + "key": "damage", + "slug": "beschaedigte-testdateien", + "nav": "Beschädigte Dateien", + "title": "Beschädigte Testdateien - kaputte Dateien in exakter Größe", + "description": "Eine absichtlich kaputte Datei in exakt der verlangten Größe, mit einem Manifest, das sagt, dass Ihr System sie ablehnen soll. Für Upload-Validierung und Parser.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "testdateien-in-ci", + "nav": "Testdateien in CI", + "title": "Testdateien in CI - GitHub Actions, GitLab CI und PowerShell", + "description": "Testdateien in der Pipeline erzeugen statt einzuchecken: GitHub-Actions-Workflow, GitLab-Job, Exit-Codes, die den Build scheitern lassen, und die PowerShell-Falle.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Zum Inhalt springen", + "navLabel": "Hauptnavigation", + "langLabel": "Sprache", + "breadcrumbHome": "Start", + "imageAlt": "Testing Files Generator - echte Testdateien in jeder exakten Größe, mit einem Manifest, das beschreibt, wie dein System auf jede einzelne reagieren soll", + "schemaDescription": "Ein kostenloser Open-Source-Generator für Testdateien in der QA. Er erzeugt echte Dateien in {{ .Facts.FormatCount }} Formaten in jeder exakten Größe und schreibt ein Manifest, das beschreibt, wie das getestete System auf jede Datei reagieren soll.", + "ctaDownload": "Herunterladen", + "ctaSource": "Quellcode ansehen", + "ctaNote": "Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.", + "colFormat": "Format", + "colName": "Name", + "colExtension": "Endung", + "colSmallest": "Kleinste Datei", + "colFidelity": "Vollständigkeit", + "colChecked": "Geprüft mit", + "colSetting": "Einstellung", + "colAccepts": "Erlaubt", + "colSystem": "System", + "colCli": "Kommandozeile", + "colWindow": "Desktop-Fenster", + "noBinary": "noch keine Binärdatei", + "colCode": "Code", + "colMeaning": "Bedeutung", + "footerBlurb": "Testdateien für die QA in jeder exakten Größe, mit einem Manifest, das beschreibt, wie dein System auf jede einzelne reagieren soll.", + "footerProject": "Projekt", + "footerSource": "Quellcode auf GitHub", + "footerReleases": "Downloads", + "footerIssues": "Problem melden", + "footerSupport": "Projekt unterstützen", + "footerPages": "Seiten", + "footerLicence": "Copyright (C) 2026 DonislawDev. Veröffentlicht unter der GNU General Public License, Version 3. Die Dateien, die du erzeugst, gehören dir - die Lizenz gilt für das Tool, nicht für seine Ausgabe.", + "footerPrivacy": "Diese Website lädt von nirgendwo Schriften, Skripte oder Tracker. Sie setzt keine Cookies.", + "notFoundTitle": "Diese Seite gibt es nicht", + "notFoundLead": "Die Adresse, der du gefolgt bist, passt zu keiner Seite dieser Website.", + "notFoundBack": "Zur Startseite", + "read.format": "Das Format jeder Datei im Set. Es ist ein Flag des Tools selbst, das Preset gibt ihm nur einen Standardwert.", + "readTakes.format": "eine Format-ID von der Formate-Seite", + "colDamage": "Beschädigung", + "colEffect": "Was sie mit den Bytes macht", + "colSettings": "Einstellungen", + "noSettings": "keine" + }, + "endings": { + "0": "Alles hat funktioniert.", + "1": "Ein unerwarteter Fehler im Tool.", + "2": "Falscher Befehl oder falsches Flag.", + "3": "Das Rezept ist ungültig.", + "4": "Das Format kann nicht, was verlangt wurde.", + "5": "Lesen oder Schreiben ist fehlgeschlagen.", + "6": "Nicht genug Speicherplatz.", + "7": "verify hat eine Abweichung gefunden.", + "8": "Der Lauf ist beendet, aber nicht alles wurde erzeugt.", + "130": "Mit Strg+C abgebrochen.", + "143": "Durch ein Signal beendet, so sieht ein CI-Timeout aus." + }, + "presets": { + "empty-and-minimal": { + "question": "Kommt eine gültige Datei durch, die so klein ist, wie das Format es erlaubt?", + "title": "Leer und minimal", + "pageTitle": "Kleinste gültige und leere Testdateien in jedem Format", + "description": "Die kleinste gültige Datei in jedem der {{ .Facts.FormatCount }} Formate, dazu eine leere Datei, wo das Format sie erlaubt, jeweils mit der erwarteten Reaktion.", + "catches": [ + "eine gültige Datei, die als zu klein abgewiesen wird, weil die Prüfung Bytes zählt, statt sie zu lesen", + "eine leere Datei, die den Leser zum Absturz bringt, statt gemeldet zu werden", + "ein Bild mit einem Pixel Breite, das auf dem Weg zur Vorschau durch null teilt", + "ein Speicher, der null Bytes als fehlgeschlagenen Upload liest und immer wieder neu versucht" + ], + "details": { + "formats": "Aus welchen Formaten das Set besteht. Mit all werden alle Formate dieses Builds verwendet, oder du nennst die, die dein System akzeptiert." + } + }, + "filename-handling": { + "question": "Speichert, zeigt und liefert mein System einen Dateinamen korrekt, mit dem es nicht gerechnet hat?", + "title": "Umgang mit Dateinamen", + "pageTitle": "Problematische Dateinamen zum Testen - Unicode und Länge", + "description": "Dateinamen, die Uploads und Speicher aus dem Tritt bringen: andere Schriften, Emoji, Rechts-nach-links-Override, Steuerzeichen, Shell- und SQL-Syntax, Längenlimits.", + "catches": [ + "ein Name, der auf dem Bildschirm, in einem Log oder in einer Liste wie ein anderer aussieht", + "ein Name, der zwischen Upload und Speicherung abgeschnitten, gekürzt oder umgeschrieben wird", + "ein Längenlimit, das in Zeichen gezählt wird, obwohl der Speicher Bytes zählt" + ], + "details": {} + }, + "size-boundaries": { + "question": "Wird ein Größenlimit genau dort durchgesetzt, wo es angegeben ist?", + "title": "Größengrenzen", + "pageTitle": "Upload-Größenlimit testen - Dateien an der exakten Grenze", + "description": "Dateien ein Byte unter, auf und über dem Größenlimit deines Systems, dazu weitere Stufen auf beiden Seiten, jeweils mit der Angabe, ob sie akzeptiert werden sollen.", + "catches": [ + "Off-by-one-Fehler am Limit", + "MB mit MiB verwechselt, was 4,8 Prozent ausmacht und reicht, um eine Datei durchzulassen, die nicht durchkommen dürfte", + "ein Limit, das im Browser durchgesetzt wird und nicht auf dem Server" + ], + "details": { + "limit": "Das Größenlimit, das dein System angibt. Alles andere wird von hier aus gemessen.", + "spread": "Wie weit auf beiden Seiten des Limits gegangen wird, als Liste von Größen." + } + }, + "tabular-import": { + "question": "Übersteht mein Tabellenimport das, was echte Tools exportieren?", + "title": "Tabellenimport", + "pageTitle": "Testdateien für CSV- und Excel-Import - Trennzeichen, Kopfzeilen", + "description": "CSV mit anderen Trennzeichen, CR-LF, ohne Kopfzeile und mit anderer Quotierung, eine sehr breite Tabelle, eine Excel-Arbeitsmappe und JSON in mehreren Layouts.", + "catches": [ + "eine CSV-Datei mit Semikolon, die als eine Spalte gelesen wird, weil das Trennzeichen angenommen statt gesucht wurde", + "eine CRLF-Datei, die in Zeilen mit einer leeren Zeile nach jeder zerlegt wird", + "eine Tabelle ohne Kopfzeile, deren erste Datenzeile als Spaltennamen verschluckt wird", + "ein Import, der die Spalten behält, die er anzeigen kann, und den Rest kommentarlos verwirft", + "ein Leser, der JSON-Datensätze Zeile für Zeile liest und beim ersten eingerückten Dokument aufgibt" + ], + "details": { + "rows": "Wie viele Zeilen die Tabelle enthält. Die Datei wird in genau der Größe geschrieben, auf die sich so viele Zeilen verpacken lassen, daher verschiebt sich das Budget oben mit diesem Wert.", + "columns": "Wie viele Spalten jede Zeile der Tabelle hat. Zeilen mal Spalten hat eine Obergrenze, und wer darüber hinausgeht, wird abgewiesen, bevor etwas geschrieben wird." + } + }, + "text-encoding": { + "question": "Weiß mein Leser, in welcher Kodierung eine Datei vorliegt, oder rät er?", + "title": "Textkodierung", + "pageTitle": "Testdateien für Textkodierung - UTF-8, UTF-16, BOM, CRLF", + "description": "Derselbe Text in UTF-8, UTF-16LE und UTF-16BE, mit und ohne Byte Order Mark, dazu Zeilenenden in CR LF und LF, um zu testen, wie ein Leser Text dekodiert.", + "catches": [ + "ein Leser, der UTF-8 annimmt und eine UTF-16-Datei als jedes dritte Zeichen oder als Reihen von Kästchen anzeigt", + "eine Byte Order Mark, die als Inhalt gelesen wird, sodass das erste Feld eines Imports mit drei fremden Zeichen beginnt", + "ein Importer, der die Kodierung aus den ersten Bytes errät und bei einer längeren Datei anders rät", + "eine CRLF-Datei, die in Zeilen mit einer leeren Zeile nach jeder zerlegt wird, oder ein Wagenrücklauf, der im letzten Feld stehen bleibt" + ], + "details": { + "sample": "Wie groß jede Datei des Sets ist. UTF-16 speichert zwei Bytes pro Zeichen, daher wird eine ungerade Zahl abgewiesen." + } + }, + "upload-validation": { + "question": "Nimmt mein Upload-Formular an, was es soll, und weist den Rest ab?", + "title": "Upload-Validierung", + "pageTitle": "Testdateien für die Upload-Validierung - Typ, Größe und Name", + "description": "Dateien zum Testen eines Upload-Formulars: erlaubte und verbotene Typen, Inhalt, der nicht zur Endung passt, Größenlimit, feindliche Namen und ein Massen-Upload.", + "catches": [ + "ein Limit, das im Browser durchgesetzt wird und nicht auf dem Server", + "eine SVG- oder HTML-Datei, die für ein Bild oder für einfachen Text gehalten wird, womit sich ein Skript an einem Formular vorbeischleusen lässt", + "eine Datei, die nur an der Endung geprüft und nie geöffnet wird, sodass ein PDF namens .jpg durchgeht", + "ein Formular, das den ganzen Body in den Speicher liest, bevor es nachsieht, wie groß er ist", + "ein Upload namens PHOTO.JPG, der abgewiesen wird, während photo.jpg durchkommt, oder umgekehrt", + "ein Name mit Leerzeichen, Klammern oder Zeichen außerhalb von ASCII, der unverändert auf die Platte geschrieben wird" + ], + "details": { + "limit": "Das Größenlimit, das dein Upload-Formular angibt. Dieses Set geht je einen Schritt auf beiden Seiten davon - für eine Datei in jedem Abstand führe das Preset size-boundaries aus.", + "allow": "Welche Typen dein Formular akzeptieren soll. Jeder wird zu einer echten Datei dieses Typs, und sie sind die positive Kontrolle des ganzen Sets.", + "deny": "Welche Endungen dein Formular abweisen soll. Für eine Endung, zu der dieser Build kein Format hat, wird trotzdem eine Datei mit diesem Namen geschrieben, die einfachen Text enthält.", + "far-over": "Wie weit über dem Limit die eine große Datei liegt. Schalte sie ab, wo es das Vielfache des Limits auf der Platte nicht wert ist.", + "bulk": "Wie viele Dateien der Massen-Upload enthält. Bei null fällt diese Gruppe ganz aus dem Set." + } + } + }, + "commands": { + "generate": "Dateien erzeugen, aus einem Rezept oder über Flags", + "validate": "ein Rezept prüfen und nichts schreiben", + "verify": "ein Verzeichnis gegen ein Manifest prüfen", + "cleanup": "die Dateien entfernen, die ein Manifest auflistet", + "recipe fmt": "ein Rezept in seiner festen Form ausgeben", + "preset": "ein Set von Dateien aus einer benannten Testfrage erzeugen", + "formats": "die Formate dieses Builds auflisten", + "damage": "die Arten auflisten, wie dieser Build eine Datei absichtlich beschädigen kann", + "tool": "kleine Helfer für Dateien, die du schon hast", + "version": "die Version des Tools ausgeben", + "license": "die Lizenz ausgeben und was sie für erzeugte Dateien bedeutet" + }, + "outcomes": { + "accept": "Dein System soll die Datei annehmen.", + "reject": "Dein System soll die Datei abweisen.", + "sanitize": "Dein System soll die Datei annehmen und bereinigen, zum Beispiel durch Umbenennen.", + "unspecified": "Das hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast." + }, + "damages": { + "zero-head": "Überschreibt die ersten Bytes der Datei mit Nullen und lässt ihre Länge unverändert. Die meisten Leser schauen zuerst dorthin, deshalb bemerkt fast alles diese Beschädigung." + }, + "terms": { + "oracleNone": "nicht zutreffend", + "int": "jede ganze Zahl", + "choice": "eine aus einer festen Auswahl", + "bool": "wahr oder falsch", + "size": "eine Größe wie 2mb", + "text": "Text", + "pixels": "Pixel", + "paragraphs": "Absätze", + "rows": "Zeilen", + "columns": "Spalten", + "slides": "Folien", + "hertz": "Hertz", + "megapixels": "Megapixel", + "million cells": "Millionen Zellen", + "entries per second": "Einträge pro Sekunde", + "files": "Dateien", + "sizes separated by commas": "Größen, durch Kommas getrennt", + "format ids separated by commas": "Format-IDs, durch Kommas getrennt", + "format ids separated by commas, or all": "Format-IDs, durch Kommas getrennt, oder all", + "extensions separated by commas": "Endungen, durch Kommas getrennt", + "the id of a format, as tfg formats lists them": "die ID eines Formats, wie tfg formats sie auflistet", + "the password, in plain text": "das Passwort im Klartext", + "any text": "beliebiger Text", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "ein Datum wie 2024-02-29 oder 2024-02-29T13:45:00+02:00, oder none" + }, + "faq": [ + { + "q": "Worin unterscheidet sich das von dd, fsutil oder truncate?", + "a": "Diese Befehle liefern dir eine Datei in der richtigen Größe, gefüllt mit nichts. Eine 2 MB große Datei namens photo.png, die so entstanden ist, ist kein PNG. Alles, was sie wirklich parst, weist sie aus dem falschen Grund ab, und dein Test besteht dann ebenfalls aus dem falschen Grund. Dieses Tool erzeugt ein echtes PNG von genau 2 MB, das sich in einem Bildbetrachter öffnet und mit einer Aussage darüber geliefert wird, wie dein System damit umgehen soll.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Ist es kostenlos, und darf ich es bei der Arbeit einsetzen?", + "a": "Ja, beides. Es steht unter der GPL-3.0 und kostet nichts. Es gibt kein Konto, keinen Lizenzschlüssel und keine kostenpflichtige Stufe." + }, + { + "q": "Darf ich die erzeugten Dateien in einem Closed-Source-Produkt verwenden?", + "a": "Ja. Die Lizenz gilt für den Code des Tools, nicht für das, was das Tool erzeugt. Erzeugte Dateien, Rezepte und Manifeste sind Ausgabe und keine abgeleiteten Werke, du kannst sie also einchecken und ohne jede Verpflichtung weitergeben." + }, + { + "q": "Enthalten die erzeugten Dateien echte personenbezogene Daten?", + "a": "Nein. Alles darin wird aus einem Seed synthetisch erzeugt. Es wird kein Datensatz gelesen, kein Dienst kontaktiert und kein Inhalt Dritter eingebettet. Behandle eine erzeugte E-Mail-Adresse als unbrauchbar statt als unbenutzt, denn jede Zufallszeichenfolge kann zufällig mit einer echten übereinstimmen." + }, + { + "q": "Bekomme ich auf einem anderen Rechner genau dieselben Dateien?", + "a": "Ja, Byte für Byte, bei gleichem Rezept und gleichem Seed. Das Projekt testet das bei jeder Änderung, und es zu brechen erfordert einen Major-Versionssprung. Genau deshalb kannst du ein kleines Rezept einchecken statt großer binärer Fixtures." + }, + { + "q": "Braucht es eine Internetverbindung?", + "a": "Nie. Es gibt keine Telemetrie, keine Update-Prüfung und keinen Cloud-Client, und die Kommandozeilen-Binärdatei hat gar keinen Netzwerkstack einkompiliert. Sie läuft auf einem Rechner ohne Netz und in einer abgeschotteten Unternehmensumgebung." + }, + { + "q": "Was passiert, wenn ich eine Größe verlange, die ein Format nicht erreichen kann?", + "a": "Du bekommst einen Fehler, der das Format nennt, die kleinstmögliche Größe, den Grund für diese Untergrenze und was du stattdessen tun kannst, und es wird keine Datei geschrieben. Das Tool rundet eine Größe nie stillschweigend. Jede Untergrenze steht auf der Formate-Seite.", + "code": "tfg formats png" + }, + { + "q": "Kann ich eine absichtlich kaputte Datei erzeugen?", + "a": "Ja. Fügen Sie --damage zero-head hinzu, und die Datei kommt in genau der verlangten Größe heraus, mit Nullen über den ersten Bytes, sodass ein Leser sie abweist, und das Manifest sagt, dass Ihr System sie ablehnen soll. Die Einzelheiten stehen auf der Seite über beschädigte Testdateien.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Welche Formate kommen als Nächstes?", + "a": "7z, mp3 und mp4. {{ .Facts.FormatCount }} Formate funktionieren heute durchgängig." + }, + { + "q": "Auf welchen Systemen läuft es?", + "a": "Die Kommandozeile läuft unter Windows und Linux auf Intel und ARM sowie auf Macs mit Apple Silicon. Das Desktop-Fenster gibt es für Windows auf Intel, Linux auf Intel und Macs mit Apple Silicon. Intel-Macs werden nicht unterstützt, und für sie wird nichts gebaut." + }, + { + "q": "Muss ich etwas installieren?", + "a": "Nein. Lade das Archiv für dein System herunter, entpacke es und starte die Binärdatei. Es gibt keinen Installer, keine Laufzeitumgebung zum Nachrüsten und keine Abhängigkeit, die aufgelöst werden müsste. Wenn du Go hast, funktioniert auch ein einziger go-install-Befehl.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Warum ist ein Lauf über Tausende Dateien unter Windows langsamer?", + "a": "Weil Windows für jeden Pfad, den es ansieht, mehr verlangt, und ein Befehl über Tausende Dateien sieht sich Tausende Pfade an. Gemessen auf einem Rechner mit 3000 Dateien zu je 1 kB braucht verify unter Windows etwa 0,9 Sekunden und unter Linux in einem Container etwa 0,2 Sekunden. Ein kürzerer Ausgabepfad verkleinert den Windows-Wert, denn jeder Ordner über den Dateien gehört zu dem, was angesehen wird." + } + ] +} diff --git a/web/content/de/use-cases.html b/web/content/de/use-cases.html new file mode 100644 index 00000000..c5acce8d --- /dev/null +++ b/web/content/de/use-cases.html @@ -0,0 +1,135 @@ +

Wofür Leute es einsetzen

+

+ Fünf Aufgaben, die in fast jedem Projekt vorkommen, das Dateien von Menschen annimmt, und der + Befehl, der jede erledigt. Jedes Beispiel unten läuft so, wie es geschrieben steht. +

+ +
+

Upload-Limits

+

Testen, ob ein Dateigrößenlimit dort durchgesetzt wird, wo es angegeben ist

+

+ Ein Limit sind drei Testfälle, nicht einer: knapp darunter, genau darauf und knapp darüber. Die von + Hand zu bekommen heißt, Byte-Zahlen auszurechnen und zu hoffen, dass man sich nicht um eins + verzählt hat. Fordere stattdessen das Set an: +

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

+ Du bekommst drei echte PDFs mit 1048575, 1048576 und 1048577 Bytes und ein Manifest, das sagt, dass + die ersten beiden akzeptiert und die dritte wegen size_limit abgelehnt werden soll. + Dein Test liest die Erwartung, statt dass du drei Assertions von Hand schreibst - und wenn sich + das Limit ändert, änderst du eine Zahl und startest neu. +

+

+ Dasselbe geht ohne Preset, wenn du ein einzelnes Grenzen-Set inline willst: +

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

Continuous Integration

+

Fixtures aus dem Repository heraushalten, ohne sie zu verlieren

+

+ Große binäre Fixtures machen ein Repository langsam beim Klonen und mühsam beim Review, und niemand + sieht, was sich geändert hat, wenn eine ersetzt wird. Ein Rezept sind ein paar hundert Zeichen + YAML, die die identischen Dateien neu erzeugen - Byte für Byte, auf jedem + Rechner - weil jede Datei aus dem Seed des Laufs abgeleitet wird. +

+
- 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
+

+ Jedes Ende hat einen eigenen Exit-Code, sodass eine Pipeline ein schlechtes Rezept von einem vollen + Datenträger und von einer Abweichung bei der Prüfung unterscheiden kann. Ein fehlgeschlagener + Lauf gibt nichts auf der Standardausgabe aus, wodurch ein Log-Parser einen Fehler nicht als + Daten liest. +

+
+ +
+

Skalierung

+

Herausfinden, was passiert, wenn der Ordner groß ist

+

+ Importroutinen, nächtliche Jobs und Verzeichnislisten verhalten sich bei zehntausend Dateien anders + als bei zehn. Aus einem Bereich gezogene Größen lassen das Set wie echten Datenverkehr aussehen + statt wie zehntausend identische Dateien, und die Ziehung kommt aus dem Seed, das Set ist also + morgen dasselbe. +

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

+ Prüfe, was ein Lauf kosten würde, bevor er etwas schreibt, was zählt, wenn die Summe in Gigabyte + gemessen wird: +

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

+ Ein Lauf, der größer ist als der freie Platz auf dem Datenträger, wird vor dem ersten geschriebenen + Byte abgelehnt, statt den Datenträger zu füllen und auf halbem Weg zu scheitern. +

+
+ +
+

Archive

+

Einen Entpacker mit einem Archiv testen, das wirklich Dateien enthält

+

+ Ein leeres Archiv mit der richtigen Endung beweist nichts über Code, der es öffnet und durchläuft, + was darin ist. Deklariere den Inhalt, und das Archiv enthält ihn wirklich: +

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

+ Verschachtelungstiefe, Eintragszahlen und die Größe dessen, was darin liegt, sind alles Dinge, zu + denen eine Importroutine Meinungen hat, und so findest du heraus, welche das sind. +

+
+ +
+

Parser und Viewer

+

Prüfen, dass dein eigener Code ein Format so liest wie echte Software

+

+ Jedes Format hier wird vor der Auslieferung mit einem unabhängigen Leser geprüft - ein PNG wird + geöffnet und seine Pixel verglichen, ein DOCX von separaten Bibliotheken zurückgelesen, ein + Archiv entpackt. Das heißt, eine Datei, die dein Parser abweist, ist ein Befund über deinen + Parser, nicht über den 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
+

+ Die Formate-Seite listet die Einstellungen jedes Formats und die kleinste + Datei auf, die es sein kann. +

+
+ +
+

Anleitungen

+

Zwei davon im Detail

+ +
+ +
+

Für wen das gedacht ist

+

+ QA-Engineers, Testautomatisierung und alle, deren Code ein Upload-Formular, eine Importroutine, + einen Parser oder ein Speicherkontingent hinter sich hat. Es läuft auf einem Rechner ganz ohne + Netz, was in einer abgeschotteten Unternehmensumgebung zählt, wo ein browserbasierter Generator + keine Option ist. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/en/ci.html b/web/content/en/ci.html new file mode 100644 index 00000000..73a959e9 --- /dev/null +++ b/web/content/en/ci.html @@ -0,0 +1,187 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

How to generate test files in a CI pipeline

+

+ A binary fixture in a repository stays in its history for good, cannot be reviewed in a diff, and + stops being possible once the file is large. Generate the files inside the pipeline from a recipe + instead. The recipe is text, the bytes come out the same every time, and a last step proves that + nothing moved. +

+ +
+

The short answer

+

+ Install tfg, run tfg generate fixtures.yaml --out ./fixtures before the + tests, and tfg verify ./fixtures/manifest.json after them. Both steps fail the build + by themselves, with an exit code that says why. +

+
+ +
+

Why not commit them

+

Why a fixture should not live in the repository

+ +

+ The recipe is the thing to commit. The same recipe and seed write the same bytes on every machine, + so the file generated in the pipeline is the file you had on your laptop. +

+
+ +
+

The recipe

+

A recipe that lives beside the tests

+

+ This one writes twenty five invoices that should be accepted and two images over a limit that + should be turned away, and the manifest records both expectations: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml checks it without writing anything, and names every + problem at once. +

+
+ +
+

GitHub Actions

+

A workflow that installs the tool and builds the fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ The checksum line compares the archive with verify-SHA256SUMS.txt from the same + release. The version is pinned, so a new release never changes a build you did not touch. +

+
+ +
+

GitLab CI

+

The same thing as a GitLab job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

When it goes red

+

What makes a step fail, and why

+

+ Every ending has its own exit code, so the step fails on its own and the log says which one. The + ones a pipeline meets: +

+ +

+ A failed run prints nothing on standard output, so a log parser never reads an error as data. The + whole table is on the documentation page. +

+
+ +
+

PowerShell

+

A PowerShell script needs one more line

+

+ PowerShell does not carry the exit code of a program out of a .ps1 file. Run one with + -File and the script answers 0 even when the tool inside refused the + work, so a build that should be red goes green. The last line is the whole fix: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ That is how PowerShell behaves, not something about this tool. cmd, + bash and zsh need nothing extra. +

+
+ +
+

Several jobs

+

Sharing the fixtures between jobs

+

+ There is usually no need to upload them. Because the same recipe writes the same bytes, each job + can run its own tfg generate, which is quicker than an upload and a download. When a + job has to receive files from another, run tfg verify on the manifest after the + transfer, and it tells you whether what arrived is what was written. +

+
+ +
+

Next

+

Where to go from here

+ +
diff --git a/web/content/en/damage.html b/web/content/en/damage.html new file mode 100644 index 00000000..6dd3650c --- /dev/null +++ b/web/content/en/damage.html @@ -0,0 +1,172 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

How to make a corrupt file for testing

+

+ A validator that has only ever been shown healthy files has not really been tested. Here is how to + get a file that is broken on purpose, comes out at exactly the size you ask for, + and carries a manifest saying what your system should do with it. +

+ +
+

The short answer

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out writes a PNG of + exactly 2097152 bytes whose first bytes are zeros, and the manifest beside it records that your + system should reject it. +

+
+ +
+

The usual way

+

Why a file corrupted by hand makes a poor test

+

+ The usual ways are a hex editor, a script that flips a few random bytes, or cutting a file short + with head or truncate. They work once, and then they cost you: +

+ +
+ +
+

What you get

+

A damaged file is still the size you asked for

+

+ The file is generated normally and broken afterwards, on its way to the disk. It keeps the size + you asked for, and the same command writes the same bytes again. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Settings go after a colon. The flag can be repeated, and the damages are applied in the order you + write them. It works with every one of the {{ .Facts.FormatCount }} formats. +

+
+ +
+

What it can do

+

Which damages are there?

+

+ This is the list the program prints, read from it when this page is built. tfg damage + prints the same, and tfg damage <id> says what one of them takes. +

+ {{ template "damagesTable" . }} +

+ zero-head writes zeros over the start of the file. Most readers look there first, at + the signature and the header that say what the file is, so almost any reader notices. Plain text + and logs have no signature and are turned away as well, because a run of zero bytes is not text. + Below four bytes some formats come out with damage that no reader complains about, which is why + the setting starts at four. +

+
+ +
+

What the manifest says

+

A manifest that says what should happen

+

+ Every damaged file gets an entry saying your system should reject it, with the damage recorded + beside it: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Two requests are refused before anything is written, because each would leave a file on disk that + the manifest describes wrongly: +

+ +
+ +
+

In a recipe

+

Healthy and broken files in one run

+

+ Put both in one recipe, and the manifest carries the expectation of every file, so the test does + not need a list of which is which: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In a test

+

Turning it into a test

+

+ The test reads the manifest and checks that what happened is what was declared. It needs no list + of file names: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ A good refusal is a clean one. A message that says what was wrong is the answer you want. A server + error, a hang or a half stored file is the defect this test exists to find. +

+
+ +
+

Next

+

Where to go from here

+ +
diff --git a/web/content/en/docs.html b/web/content/en/docs.html index 30b6c027..ca835f61 100644 --- a/web/content/en/docs.html +++ b/web/content/en/docs.html @@ -84,6 +84,9 @@

How do I make a file that is broken on purpose?

dropped rather than written - the run carries on, says which file it was, and ends with the partial exit code.

+

+ Step by step, with a test that reads the manifest: how to make a corrupt file for testing. +

@@ -253,6 +256,9 @@

What do the exit codes mean?

A run stopped with Ctrl+C still leaves a manifest and never leaves a half written file behind, so a cancelled job can still be cleaned up by the next one.

+

+ Ready workflows for GitHub Actions and GitLab CI: how to generate test files in a CI pipeline. +

diff --git a/web/content/en/site.json b/web/content/en/site.json index 1e87bc0c..18ac8878 100644 --- a/web/content/en/site.json +++ b/web/content/en/site.json @@ -1,5 +1,6 @@ { "code": "en", + "locale": "en_US", "name": "English", "dir": "", "pages": [ @@ -51,11 +52,28 @@ "nav": "FAQ", "title": "FAQ - Questions About Generating Test Files", "description": "How this differs from dd and fsutil, whether the files are safe to commit, whether runs repeat byte for byte, and what happens when a size cannot be reached." + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "Corrupt test files", + "title": "Corrupt Test Files - Damaged Files of an Exact Size", + "description": "Make a file that is broken on purpose, at the exact size you ask for, with a manifest saying your system should reject it. For testing upload validation and parsers.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "Test files in CI", + "title": "Test Files in CI - GitHub Actions, GitLab CI and PowerShell", + "description": "Generate test files in the pipeline instead of committing binaries: a GitHub Actions workflow, a GitLab job, exit codes that fail the build and the PowerShell catch.", + "parent": "use-cases" } ], "words": { "skip": "Skip to content", "navLabel": "Main", + "langLabel": "Language", "breadcrumbHome": "Home", "imageAlt": "Testing Files Generator - real test files at any exact size, with a manifest saying how your system should react to each one", "schemaDescription": "A free and open source generator of test files for QA. It produces real files of {{ .Facts.FormatCount }} formats at any exact size and writes a manifest saying how the system under test should react to each one.", @@ -89,7 +107,11 @@ "notFoundLead": "The address you followed does not match any page on this site.", "notFoundBack": "Go to the home page", "read.format": "The format of every file in the set. It is a flag of the tool itself, and the preset only gives it a default.", - "readTakes.format": "a format id from the formats page" + "readTakes.format": "a format id from the formats page", + "colDamage": "Damage", + "colEffect": "What it does to the bytes", + "colSettings": "Settings", + "noSettings": "none" }, "endings": { "0": "Everything worked.", @@ -279,7 +301,8 @@ }, { "q": "Can I generate a file that is deliberately broken?", - "a": "Not yet. Damaged and malformed files are a planned feature. Today every file the tool writes is a valid one of its format." + "a": "Yes. Add --damage zero-head and the file comes out at exactly the size you asked for with its first bytes overwritten by zeros, so a reader turns it away, and the manifest says your system should reject it. The page about corrupt test files has the details.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" }, { "q": "Which formats are coming next?", @@ -298,5 +321,8 @@ "q": "Why is a run over thousands of files slower on Windows?", "a": "Because Windows charges more for every path it looks at, and a command that goes over thousands of files looks at thousands of paths. Measured on one machine with 3000 files of 1 kB, verify takes about 0.9 seconds on Windows and about 0.2 seconds on Linux in a container. A shorter output path makes the Windows figure smaller, because every folder above the files is part of what gets looked at." } - ] + ], + "damages": { + "zero-head": "Overwrites the first bytes of the file with zeros, leaving its length alone. Most readers look there first, so this is the damage almost anything notices." + } } diff --git a/web/content/en/use-cases.html b/web/content/en/use-cases.html index 4ce91b67..b40ca638 100644 --- a/web/content/en/use-cases.html +++ b/web/content/en/use-cases.html @@ -105,6 +105,19 @@

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

+
+

Guides

+

Two of these in more detail

+ +
+

Who this is for

diff --git a/web/content/es/ci.html b/web/content/es/ci.html new file mode 100644 index 00000000..3bfdb861 --- /dev/null +++ b/web/content/es/ci.html @@ -0,0 +1,192 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cómo generar archivos de prueba en un pipeline de CI

+

+ Un fixture binario en un repositorio se queda para siempre en su historial, no se puede revisar en + un diff y deja de ser posible cuando el archivo es grande. Genera los archivos dentro del pipeline + a partir de una receta. La receta es texto, los bytes salen iguales cada vez y un último paso + demuestra que nada se movió. +

+ +
+

La respuesta corta

+

+ Instala tfg, ejecuta tfg generate fixtures.yaml --out ./fixtures antes de + las pruebas y tfg verify ./fixtures/manifest.json después. Los dos pasos hacen + fallar la compilación por sí solos, con un código de salida que dice por qué. +

+
+ +
+

Por qué no subirlos

+

Por qué un fixture no debe vivir en el repositorio

+ +

+ Lo que hay que subir es la receta. La misma receta y la misma semilla escriben los mismos bytes en + cualquier máquina, así que el archivo generado en el pipeline es el que tenías en tu portátil. +

+
+ +
+

La receta

+

Una receta que vive junto a las pruebas

+

+ Esta escribe veinticinco facturas que deben aceptarse y dos imágenes por encima de un límite que + deben rechazarse, y el manifiesto registra las dos expectativas: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la comprueba sin escribir nada y nombra todos los problemas + a la vez. +

+
+ +
+

GitHub Actions

+

Un workflow que instala la herramienta y construye los fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La línea de la suma de comprobación compara el archivo con verify-SHA256SUMS.txt de la + misma versión. La versión está fijada, así que una versión nueva nunca cambia una compilación + que no tocaste. +

+
+ +
+

GitLab CI

+

Lo mismo como job de GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Cuando se pone en rojo

+

Qué hace fallar un paso, y por qué

+

+ Cada final tiene su propio código de salida, así que el paso falla por sí solo y el registro dice + cuál fue. Los que encuentra un pipeline: +

+ +

+ Una ejecución fallida no imprime nada en la salida estándar, así que un analizador de registros + nunca toma un error por datos. La tabla completa está en la + página de documentación. +

+
+ +
+

PowerShell

+

Un script de PowerShell necesita una línea más

+

+ PowerShell no saca el código de salida de un programa fuera de un archivo .ps1. Ejecuta + uno con -File y el script responde 0 incluso cuando la herramienta de + dentro rechazó el trabajo, así que una compilación que debería estar en rojo pasa a verde. La + última línea es toda la solución: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Así se comporta PowerShell, no es algo de esta herramienta. cmd, bash y + zsh no necesitan nada más. +

+
+ +
+

Varios jobs

+

Compartir los fixtures entre jobs

+

+ Normalmente no hace falta subirlos. Como la misma receta escribe los mismos bytes, cada job puede + ejecutar su propio tfg generate, que es más rápido que subir y bajar. Cuando un job + tiene que recibir archivos de otro, ejecuta tfg verify sobre el manifiesto tras la + transferencia y te dice si lo que llegó es lo que se escribió. +

+
+ +
+

Siguiente

+

A dónde ir desde aquí

+ +
diff --git a/web/content/es/damage.html b/web/content/es/damage.html new file mode 100644 index 00000000..10d53d85 --- /dev/null +++ b/web/content/es/damage.html @@ -0,0 +1,175 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cómo crear un archivo corrupto para pruebas

+

+ Un validador al que solo se le han mostrado archivos sanos no está realmente probado. Así se + consigue un archivo roto a propósito, que sale con exactamente el tamaño que + pides y trae un manifiesto que dice qué debe hacer tu sistema con él. +

+ +
+

La respuesta corta

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out escribe un PNG de + exactamente 2097152 bytes cuyos primeros bytes son ceros, y el manifiesto que lo acompaña + registra que tu sistema debe rechazarlo. +

+
+ +
+

La forma habitual

+

Por qué un archivo corrompido a mano es una mala prueba

+

+ Lo habitual es un editor hexadecimal, un script que cambia unos cuantos bytes al azar o cortar un + archivo con head o truncate. Funciona una vez y después sale caro: +

+ +
+ +
+

Lo que obtienes

+

Un archivo dañado conserva el tamaño que pediste

+

+ El archivo se genera con normalidad y se rompe después, de camino al disco. Conserva el tamaño que + pediste, y el mismo comando vuelve a escribir los mismos bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Los ajustes van después de dos puntos. La opción se puede repetir, y los daños se aplican en el + orden en que los escribes. Funciona con cada uno de los {{ .Facts.FormatCount }} formatos. +

+
+ +
+

Lo que puede hacer

+

¿Qué daños hay?

+

+ Esta es la lista que imprime el programa, leída de él al construir esta página. tfg + damage imprime la misma, y tfg damage <id> dice qué admite cada uno. +

+ {{ template "damagesTable" . }} +

+ zero-head escribe ceros sobre el comienzo del archivo. La mayoría de los lectores miran + ahí primero, la firma y la cabecera que dicen qué es el archivo, así que casi cualquier lector + lo nota. El texto plano y los registros no tienen firma y también se rechazan, porque una serie + de bytes nulos no es texto. Por debajo de cuatro bytes algunos formatos salen con un daño del + que ningún lector se queja, por eso el ajuste empieza en cuatro. +

+
+ +
+

Lo que dice el manifiesto

+

Un manifiesto que dice lo que debe ocurrir

+

+ Cada archivo dañado recibe una entrada que dice que tu sistema debe rechazarlo, con el daño anotado + al lado: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Se rechazan dos peticiones antes de escribir nada, porque cada una dejaría en el disco un archivo + que el manifiesto describe mal: +

+ +
+ +
+

En una receta

+

Archivos sanos y rotos en una sola ejecución

+

+ Pon ambos en una receta y el manifiesto lleva lo esperado de cada archivo, así que la prueba no + necesita una lista de cuál es cuál: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

En una prueba

+

Convertirlo en una prueba

+

+ La prueba lee el manifiesto y comprueba que lo ocurrido es lo declarado. No necesita una lista de + nombres de archivo: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un buen rechazo es un rechazo limpio. Un mensaje que dice qué estaba mal es la respuesta que + quieres. Un error de servidor, un bloqueo o un archivo guardado a medias es el defecto que esta + prueba existe para encontrar. +

+
+ +
+

Siguiente

+

A dónde ir desde aquí

+ +
diff --git a/web/content/es/docs.html b/web/content/es/docs.html new file mode 100644 index 00000000..92e8d695 --- /dev/null +++ b/web/content/es/docs.html @@ -0,0 +1,280 @@ +

Documentación

+

+ Todo lo que hace la herramienta, ordenado según las preguntas con las que la gente llega de verdad. + El README del repositorio es la referencia completa y siempre + coincide con la versión que descargaste. +

+ +
+

¿Qué comandos hay?

+

Cada uno hace una sola cosa:

+ {{ template "commandList" . }} +
+ +
+

¿Cómo genero un único archivo de tamaño exacto?

+

+ Indica el formato, el tamaño y dónde va. Los tamaños cuentan de 1024 en 1024, así que + 2mb son 2097152 bytes. Un número de bytes simple también sirve, de modo que + --size 10485761 pide exactamente esa cantidad. +

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

Las opciones útiles de generate:

+
+ + + + + + + + + + + + + + + + + +
OpciónQué hace
--format <id>formato de los archivos, por ejemplo txt
--size <size>tamaño exacto de cada archivo, como 10mb o un número de bytes simple
--size-range <a-b>un tamaño sacado por archivo de un intervalo, como 1kb-8kb. El sorteo viene de la semilla
--boundary <size>tres archivos alrededor de un límite: un byte por debajo, el límite, un byte por encima
--count <n>cuántos archivos producir. Por defecto 1
--name <template>plantilla de nombre, por ejemplo invoice_{index:04}.txt
--out <dir>directorio donde escribir
--seed <n>semilla de la ejecución. La misma semilla da los mismos bytes
--set <k>=<v>un ajuste de formato, repetible
--damage <name>romper los archivos a propósito, repetible y aplicado en orden. Ejecuta tfg damage para ver la lista
--expected <outcome>accept, reject, sanitize o unspecified
--dry-runcontar y mostrar, sin escribir absolutamente nada
--jsonescribir el manifiesto en la salida estándar
+
+
+ +
+

¿Cómo hago un archivo roto a propósito?

+

+ Todos los demás archivos que escribe esta herramienta son correctos por construcción, lo que + responde a dos de las tres preguntas que hace un validador de subidas. --damage + responde a la tercera - si el archivo se abre siquiera. El archivo se produce con normalidad y + luego se rompe, así que conserva el tamaño que pediste. +

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

+ Los ajustes van después de dos puntos. La opción se repite, y el orden en que las escribes es el + orden en que se aplican. tfg damage lista lo que puede hacer esta versión y qué + admite cada una. +

+

En una receta la clave es una lista, de nombres o de ajustes:

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

+ Un archivo dañado recibe expected: reject en el manifiesto, con el daño registrado a su + lado. Dos cosas se rechazan antes de escribir nada, porque cada una dejaría en disco un archivo + que el manifiesto describe mal: +

+ +

+ Una tercera no se puede saber de antemano. Si un daño se ejecuta y no mueve ningún byte, ese archivo + se descarta en lugar de escribirse - la ejecución continúa, dice de qué archivo se trató y + termina con el código de salida parcial. +

+

+ Paso a paso, con una prueba que lee el manifiesto: cómo + crear un archivo corrupto para pruebas. +

+
+ +
+

¿Qué aspecto tiene una receta?

+

+ Una receta es un archivo YAML que describe una ejecución completa. Súbela al repositorio junto a tus + pruebas y los fixtures dejan de ser binarios en tu repositorio - cualquiera puede + reconstruirlos, byte a byte, a partir de un archivo de unos cientos de caracteres. +

+
# 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
+

+ Cada target necesita exactamente una de estas claves: size, size-range, + boundary o contains. Dos es un error y ninguna también. Una receta + inválida escribe ningún archivo e informa de todos los problemas a la vez en + lugar de solo del primero, cada uno nombrando el ajuste al que se refiere. +

+
+ +
+

¿Cómo declaro qué debe hacer mi sistema con un archivo?

+

Forma corta cuando basta con el resultado, forma larga cuando importa el motivo:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Los resultados son accept, reject, sanitize y + unspecified. Los motivos son una lista cerrada para que un informe pueda + agruparlos: 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 y size_zero. +

+

+ Un motivo nombra la regla en juego, no el veredicto. Por eso el mismo motivo puede + estar bajo cualquiera de los dos resultados - un archivo un byte por debajo de un límite es + accept, y la regla de la que trata sigue siendo size_limit. +

+
+ +
+

¿Qué hay en el manifiesto?

+

+ Se escribe junto a los archivos al final de cada ejecución, incluida una ejecución interrumpida. Una + entrada por archivo: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 añade un recipe_hash cuando la ejecución viene de una receta, y preset + con overrides cuando viene de un preset, de modo que un manifiesto siempre se puede + rastrear hasta lo que lo produjo. +

+

+ Cada entrada lleva también target_id, el id del target de la receta que produjo el + archivo, y summary.by_target cuenta los archivos a los que llegó cada target. Una + receta con varios targets se puede comprobar así target por target sin leer nombres de archivo. +

+
+ +
+

¿Qué es un preset?

+

+ Un conjunto de archivos listo que responde a una pregunta de prueba habitual, para que no tengas que + diseñar el conjunto tú. Los presets son recetas normales por debajo, y eject + imprime la receta para que la edites desde ahí. Cada preset tiene una + página propia con lo que suele encontrar, qué hay en el conjunto y cada ajuste que admite. +

+ {{ template "presetsList" . }} +
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 te dice cuánto costaría el conjunto antes de construirlo, y dice sin rodeos cuándo + un número es un marcador nuestro en lugar de un límite tuyo. +

+
+ +
+

¿Qué significan los códigos de salida?

+

+ Cada final tiene su propio código, la salida legible por máquina va a la salida estándar, y una + ejecución fallida no imprime nada allí. La tabla es un contrato congelado - cambiar lo que + significa un código exige una versión mayor. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Una ejecución detenida con Ctrl+C sigue dejando un manifiesto y nunca deja un archivo a medio + escribir, así que un trabajo cancelado aún puede limpiarlo el siguiente. +

+

+ Workflows listos para GitHub Actions y GitLab CI: cómo + generar archivos de prueba en un pipeline de CI. +

+
+ +
+

¿Hay una ventana de escritorio?

+

+ Sí, el mismo motor con una ventana encima, para las pruebas que no se automatizan. No es una versión + recortada: una prueba compara las dos interfaces capacidad por capacidad, y todo lo que solo una + de ellas puede hacer debe declararse y justificarse en lugar de divergir en silencio. +

+

+ Las pantallas son un lote, presets, varios lotes a la vez y Acerca de. Muestra lo que costaría una + ejecución antes de escribir nada, informa del progreso mientras corre y se puede cancelar a + medias sin dejar un archivo a medio escribir. Todavía no abre un archivo de receta - por ahora + las recetas son cosa de la línea de comandos, y la ventana construye sus lotes en el formulario. +

+
diff --git a/web/content/es/exact-size.html b/web/content/es/exact-size.html new file mode 100644 index 00000000..83c13048 --- /dev/null +++ b/web/content/es/exact-size.html @@ -0,0 +1,145 @@ +

Cómo crear un archivo de un tamaño exacto

+

+ Cada sistema tiene un comando para ello, y los tres están abajo. Te dan un archivo con exactamente + el número correcto de bytes - y para muchas pruebas eso es todo lo que necesitas. Cada + comando de esta página se ejecutó antes de publicarse, en el sistema al que pertenece. +

+ +
+

La respuesta corta

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Los tamaños son en bytes, y 10 MB + contados como los cuenta tu gestor de archivos son 10485760. +

+
+ +
+

Windows

+

fsutil, y una versión de PowerShell que no necesita nada extra

+

+ fsutil viene con Windows. Toma el tamaño en bytes, así que calcula + antes el número - 10 MB son 10485760, 100 MB son 104857600, 1 GB es 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Medido en Windows 11: funciona desde un símbolo del sistema normal sin necesitar uno elevado, y el + archivo sale con exactamente 10485760 bytes. +

+

PowerShell puede hacer lo mismo sin llamar a otro programa, y entiende unidades:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB en PowerShell significa 10485760 bytes, el mismo recuento en base 1024 que usa el + Explorador, así que los dos comandos anteriores producen el mismo tamaño. +

+
+ +
+

Linux

+

dd, truncate y fallocate, y la diferencia que pilla a la gente

+

dd es el que todo el mundo conoce. Escribe los bytes de verdad:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate es instantáneo, y esa es la trampa. Medido en Alpine Linux, el archivo informa + de 10485760 bytes y ocupa cero bloques - es un archivo + disperso. Cualquier cosa que lo lea obtiene diez megabytes de ceros, pero el disco + nunca cedió el espacio: +

+
truncate -s 10M test10mb.bin
+

+ Eso sirve para probar un límite de subida y engaña para probar una cuota de disco. + fallocate es el que hay que usar cuando el espacio tiene que ser real: +

+
fallocate -l 10M test10mb.bin
+

Y cuando el contenido tiene que ser incompresible, para que un compresor no pueda volver a reducirlo:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, que no es disperso, y los dos que ya conoces

+

+ macOS incluye mkfile. Medido en macOS 26.6.2: 10485760 bytes y 20480 bloques, así que + el espacio está realmente asignado en lugar de prometido: +

+
mkfile 10m test10mb.bin
+

dd y truncate también están y se comportan como en Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Dónde esto deja de funcionar

+

Un archivo del tamaño correcto no es un archivo del tipo correcto

+

+ Todo lo anterior te da un bloque de ceros. Eso basta cuando lo que se prueba solo mira el tamaño - + un límite de subida, una cuota, una transferencia. Deja de bastar en cuanto algo + abre el archivo. +

+

+ Medido, y merece la pena que lo hagas tú: crea un archivo de 2 MB con fsutil, llámalo + photo.png y pásaselo a una biblioteca de imágenes. Pillow responde cannot + identify image file. No es un PNG. Nunca lo fue - solo lo decía el nombre. +

+

+ Eso importa más de lo que parece, por la forma en que la prueba falla entonces. Tu + endpoint de subida rechaza el archivo, tu prueba se pone en verde y concluyes que el límite de + tamaño funciona. No lo rechazó por el tamaño. Lo rechazó porque los bytes no eran una imagen, y + la regla que querías probar nunca se alcanzó. +

+ +
+ +
+

La otra vía

+

Un archivo real de ese formato, con exactamente el tamaño que pediste

+

+ Esto es lo que hace Testing Files Generator. El archivo es uno genuino de su formato - se abre en el + programa que le corresponde - y tiene el número exacto de bytes que pediste, al byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Pide un tamaño que un formato no puede alcanzar y obtienes un error que nombra el suelo y su motivo, + nunca un archivo del tamaño equivocado. La página de formatos lista + cada formato con el archivo más pequeño que puede producir. +

+

Y un límite son tres casos de prueba y no uno, así que la herramienta construye los tres:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Eso te da 10485759, 10485760 y 10485761 bytes, y un manifiesto que dice cuáles debe aceptar tu + sistema y cuáles rechazar. La página de casos de uso repasa eso + y otras cuatro tareas para las que está pensada. +

+ {{ template "downloadCta" . }} +
+ +
+

Entonces, ¿cuál debes usar?

+ +

+ Ambos están en esta página porque ambos aciertan parte del tiempo. El error que conviene evitar es + usar el primero donde hace falta el segundo y leer la prueba en verde como una demostración. +

+
diff --git a/web/content/es/faq.html b/web/content/es/faq.html new file mode 100644 index 00000000..29dece9c --- /dev/null +++ b/web/content/es/faq.html @@ -0,0 +1,20 @@ +

Preguntas frecuentes

+

+ Licencia, privacidad, reproducibilidad y lo que la gente comprueba antes de poner un generador en + una canalización de compilación. Si tu pregunta no está aquí, el + gestor de incidencias está abierto. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

¿Aún lo estás pensando?

+

+ La página de casos de uso muestra las tareas para las que está + pensada, y la página de formatos lista cada formato con el archivo + más pequeño que puede producir. El README del repositorio es la + referencia completa. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/es/formats.html b/web/content/es/formats.html new file mode 100644 index 00000000..98a0ccb7 --- /dev/null +++ b/web/content/es/formats.html @@ -0,0 +1,81 @@ +

{{ .Facts.FormatCount }} formatos de archivo, cada uno generado a un tamaño exacto

+

+ Cada uno es un archivo real de ese formato. Se abre en el programa que le + corresponde y tiene exactamente el número de bytes que pediste. Ninguno es relleno de ceros con + una extensión pegada. +

+ +{{ template "formatsTable" . }} + +
+

Qué significan las columnas

+ +

+ Cada formato también se repite byte a byte: la misma receta y la misma semilla producen archivos + idénticos en cualquier máquina, y eso es lo que hace seguro subir al repositorio una receta en + lugar de los fixtures mismos. +

+
+ +
+

Ajustes que admite cada formato

+

+ La mayoría de los formatos tienen ajustes propios - dimensiones de imagen, calidad JPEG, número de + páginas de PDF, filas y columnas de una hoja de cálculo, cuántas entradas van dentro de un + archivo comprimido. Defínelos con --set key=value en la línea de comandos, o bajo + properties: en una receta. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Un valor fuera de lo que admite un ajuste se rechaza con un mensaje que nombra el ajuste, el + intervalo permitido y qué usar en su lugar. Un ajuste desconocido también es un error, nunca un + valor por defecto silencioso - una errata aceptada en silencio da un archivo con los ajustes + equivocados y una hora preguntándote por qué la prueba pasa cuando no debería. +

+

+ Ejecuta tfg formats <id> para ver exactamente qué admite un formato en la versión + que tienes. +

+
+ +
+

Los archivos comprimidos contienen archivos reales

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} y {{ end }}{{ $c.ID }}{{ end }} se + pueden llenar de entradas en lugar de quedar como un cascarón vacío. Un archivo comprimido + generado contiene de verdad los documentos que dice contener, así que todo lo que lo descomprima + durante una prueba encuentra archivos reales dentro. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/es/index.html b/web/content/es/index.html new file mode 100644 index 00000000..8c133a30 --- /dev/null +++ b/web/content/es/index.html @@ -0,0 +1,199 @@ +
+
+

Genera archivos de prueba reales al tamaño exacto

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formatos en total, y cada uno es un + archivo real que se abre en el programa que le corresponde, con exactamente el tamaño + que pediste. Cada ejecución también anota qué debe hacer tu aplicación con cada + archivo. Línea de comandos y ventana de escritorio, gratis y de código abierto, funcionando por + completo en tu máquina. +

+ + {{ template "downloadCta" . }} +
+ +
+ La ventana de escritorio de Testing Files Generator, lista para escribir un lote de archivos de prueba +
La ventana de escritorio, lista para escribir un lote de archivos. El mismo motor funciona detrás de la línea de comandos.
+
+
+ + + +
+

El problema

+

Hacer un archivo de prueba es fácil. Hacer los mil correctos es la parte tediosa

+

Estás probando software que acepta archivos de personas. Tarde o temprano necesitas:

+ +

+ Eso es lo que esto sustituye. Está pensado para ingenieros de QA, automatización de pruebas y + cualquiera cuyo código tenga detrás un formulario de subida, una rutina de importación, un + analizador o una cuota de almacenamiento. +

+
+ +
+

Qué lo hace distinto

+

Otros generadores se quedan en los bytes. Este responde a lo que tu prueba realmente pregunta

+

+ Una carpeta de archivos te deja aún decidiendo qué se supone que demuestra cada uno. Cada ejecución + escribe aquí un manifest.json junto a los archivos - una lista simple de todo lo + producido y, para cada entrada, una expectativa declarada. +

+

Supón que tu endpoint de subida permite 1 MB. Pide los tres archivos que están sobre esa línea:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ArchivoBytesTu sistema debePorque
1mb_under_1b.pdf1048575aceptarestá dentro del límite
1mb_at_limit.pdf1048576aceptarel propio límite está permitido
1mb_over_1b.pdf1048577rechazarsize_limit
+
+ +

Tres archivos, tres respuestas distintas, en forma legible por máquina. Tu prueba lee el manifiesto en lugar de que escribas las aserciones a mano:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Donde la respuesta depende de tu propia política, el manifiesto lo dice

+

+ Registra unspecified en lugar de inventar una expectativa. Un generador que adivina + produce falsos fallos, y un conjunto de pruebas que da falsas alarmas acaba apagado. +

+
+
+ +
+

Presets

+

Elige la pregunta, obtén el conjunto entero

+

+ Un preset es un conjunto de archivos de prueba diseñado en torno a una pregunta de prueba, para que + no tengas que averiguar qué archivos demuestran qué. Cada uno tiene una página que dice qué + suele encontrar, qué hay en el conjunto y cada ajuste que admite. +

+ {{ template "presetsList" . }} +

Todos los presets, y cómo se relacionan con las recetas

+
+ +
+

Inicio rápido

+

Tres comandos para verlo funcionar

+
    +
  1. +

    Crea un archivo

    +

    Un PNG, exactamente dos megabytes:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Crea muchos archivos

    +

    + Diez mil archivos de registro, cada uno de entre uno y ocho kilobytes, con los tamaños sacados de la + semilla para que mañana dé el mismo conjunto. Dale a cada ejecución su propio + directorio - el manifiesto es el único registro de lo que escribió una ejecución, + así que la herramienta se niega a escribir un segundo encima: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Compruébalos y luego elimínalos

    +

    verify te dice que nada se movió. cleanup elimina exactamente lo que se escribió y nada más:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Los tamaños cuentan de 1024 en 1024, como hace tu gestor de archivos, así que 2mb + significa 2097152 bytes. Un número de bytes simple también sirve. La + documentación cubre las recetas, el manifiesto y los códigos de + salida. +

+
+ +
+

Qué obtienes

+

Pensado para un conjunto de pruebas que corre sin supervisión

+ +
+ +
+

Descarga

+

Elige la versión para tu sistema

+

+ Descomprime el archivo y ejecútalo. tfg es la línea de comandos y tfg-gui + es la ventana de escritorio. No hay instalador ni nada que añadir a tu máquina. +

+ {{ template "downloadsTable" . }} +
+

Qué está firmado y qué no

+

+ Las descargas de Windows y macOS están firmadas, así que se inician sin advertencia de desarrollador + desconocido. Las de Linux no, porque Linux de escritorio no tiene un equivalente con el que + firmarlas. Cada archivo aparece en verify-SHA256SUMS.txt en la página de + versiones, para que puedas comprobar lo que descargaste. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/es/preset.html b/web/content/es/preset.html new file mode 100644 index 00000000..79dfde17 --- /dev/null +++ b/web/content/es/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ El preset {{ .ID }} construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ +{{ if .Catches }} +
+

¿Qué suele encontrar?

+ +
+{{ end }} + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show {{ .ID }}:

+
+ + + + + + + +
Archivos{{ .Budget.Files }}
Targets en su receta{{ .Budget.Targets }}
Tamaño total{{ .Bytes }} B
Formatos{{ join .Budget.Formats ", " }}
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
EsperadoSignificadoArchivos
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

¿Qué puedes cambiar?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
AjusteAdmitePor defectoQué hace
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Este valor por defecto es nuestro marcador, no el valor de tu sistema. Pasa el tuyo.{{ end }}
+
+ {{- else }} +

Este preset no tiene ajustes. El conjunto es el mismo cada vez.

+ {{- end }} +
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/es/presets.html b/web/content/es/presets.html new file mode 100644 index 00000000..d62333af --- /dev/null +++ b/web/content/es/presets.html @@ -0,0 +1,32 @@ +

Presets de archivos de prueba, un conjunto para cada pregunta de prueba

+

+ Un preset es un conjunto entero de archivos de prueba diseñado en torno a una pregunta, con un + manifiesto que dice cómo debe reaccionar tu sistema a cada archivo. Tú eliges la pregunta, la + herramienta construye el conjunto. Cada preset tiene su propia página con lo que suele encontrar, + qué hay en el conjunto y cada ajuste que admite. +

+ +{{ template "presetsList" . }} + +
+

¿En qué se diferencia un preset de una receta?

+

+ Por debajo, en nada. Un preset es una receta que la herramienta escribe por ti a partir de unos + pocos ajustes. tfg preset eject imprime esa receta para que la guardes junto a tus + pruebas y la edites, y una receta tuya puede basarse en un preset con una línea, extends: + preset: seguido de su id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

¿Puedo fiarme de los valores por defecto?

+

+ Para los archivos, sí. Para un número que solo conoce tu sistema, como el límite de un formulario de + subida, un valor por defecto es un marcador nuestro, y la herramienta lo dice cada vez que usa + uno. La página de cada preset marca esos ajustes, y tfg preset show lo dice antes + de escribir nada. +

+
diff --git a/web/content/es/site.json b/web/content/es/site.json new file mode 100644 index 00000000..795551ac --- /dev/null +++ b/web/content/es/site.json @@ -0,0 +1,328 @@ +{ + "code": "es", + "locale": "es_ES", + "name": "Español", + "dir": "es", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Inicio", + "title": "Generador de archivos de prueba - tamaño exacto, {{ .Facts.FormatCount }} formatos", + "description": "Generador gratuito y de código abierto de archivos de prueba para QA. PDF, DOCX, PNG y ZIP reales al tamaño exacto, con un manifiesto de la reacción esperada." + }, + { + "key": "formats", + "slug": "formatos", + "nav": "Formatos", + "title": "{{ .Facts.FormatCount }} formatos de archivo - PDF, DOCX, PNG, ZIP y más", + "description": "Todos los formatos que genera, el archivo más pequeño posible de cada uno y los ajustes que admite. Los {{ .Facts.FormatCount }} se abren en el programa que les corresponde." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Presets", + "title": "Presets de archivos de prueba - conjuntos listos para QA", + "description": "Conjuntos listos de archivos de prueba, cada uno responde a una pregunta: límites de subida, nombres, codificaciones, importación, archivos vacíos y validación." + }, + { + "key": "docs", + "slug": "documentacion", + "nav": "Documentación", + "title": "Documentación - comandos, recetas, manifiesto, códigos de salida", + "description": "Cómo generar archivos de prueba desde la línea de comandos o con una receta YAML, qué contiene el manifiesto y qué significa cada código de salida en CI." + }, + { + "key": "use-cases", + "slug": "casos-de-uso", + "nav": "Casos de uso", + "title": "Casos de uso - límites de subida, fixtures, pruebas masivas", + "description": "Probar un límite de tamaño de subida, crear fixtures reproducibles para CI, generar diez mil archivos y llenar archivos comprimidos con contenido real." + }, + { + "key": "exact-size", + "slug": "crear-archivo-de-tamano-exacto", + "nav": "Tamaño exacto", + "title": "Crear un archivo de un tamaño exacto - Windows, Linux, macOS", + "description": "fsutil, dd, truncate y mkfile, medidos cada uno en su sistema, y por qué un archivo así creado no es un PDF ni un PNG cuando una prueba necesita uno." + }, + { + "key": "faq", + "slug": "preguntas-frecuentes", + "nav": "FAQ", + "title": "Preguntas frecuentes - generar archivos de prueba", + "description": "En qué se diferencia de dd y fsutil, si los archivos se pueden subir al repositorio, si las ejecuciones se repiten byte a byte y qué pasa con un tamaño inalcanzable." + }, + { + "key": "damage", + "slug": "archivos-de-prueba-corruptos", + "nav": "Archivos corruptos", + "title": "Archivos de prueba corruptos - archivos rotos de tamaño exacto", + "description": "Un archivo roto a propósito, con el tamaño exacto que pides y un manifiesto que dice que tu sistema debe rechazarlo. Para probar validación de subidas y parsers.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "archivos-de-prueba-en-ci", + "nav": "Archivos de prueba en CI", + "title": "Archivos de prueba en CI - GitHub Actions, GitLab CI y PowerShell", + "description": "Genera archivos de prueba en el pipeline en vez de subir binarios: workflow de GitHub Actions, job de GitLab, códigos de salida y la trampa de PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Saltar al contenido", + "navLabel": "Principal", + "langLabel": "Idioma", + "breadcrumbHome": "Inicio", + "imageAlt": "Testing Files Generator - archivos de prueba reales al tamaño exacto, con un manifiesto que dice cómo debe reaccionar tu sistema a cada uno", + "schemaDescription": "Un generador gratuito y de código abierto de archivos de prueba para QA. Produce archivos reales de {{ .Facts.FormatCount }} formatos al tamaño exacto y escribe un manifiesto que dice cómo debe reaccionar el sistema bajo prueba a cada uno.", + "ctaDownload": "Descargar", + "ctaSource": "Ver el código fuente", + "ctaNote": "Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.", + "colFormat": "Formato", + "colName": "Nombre", + "colExtension": "Extensión", + "colSmallest": "Archivo más pequeño", + "colFidelity": "Fidelidad", + "colChecked": "Comprobado con", + "colSetting": "Ajuste", + "colAccepts": "Admite", + "colSystem": "Sistema", + "colCli": "Línea de comandos", + "colWindow": "Ventana de escritorio", + "noBinary": "aún sin binario", + "colCode": "Código", + "colMeaning": "Significado", + "footerBlurb": "Archivos de prueba para QA, al tamaño exacto, con un manifiesto que dice cómo debe reaccionar tu sistema a cada uno.", + "footerProject": "Proyecto", + "footerSource": "Código en GitHub", + "footerReleases": "Descargas", + "footerIssues": "Informar de un problema", + "footerSupport": "Apoyar el proyecto", + "footerPages": "Páginas", + "footerLicence": "Copyright (C) 2026 DonislawDev. Publicado bajo la Licencia Pública General de GNU, versión 3. Los archivos que generes son tuyos - la licencia cubre la herramienta, no su salida.", + "footerPrivacy": "Este sitio no carga fuentes, scripts ni rastreadores de ningún sitio. No usa cookies.", + "notFoundTitle": "Esa página no está aquí", + "notFoundLead": "La dirección que has seguido no coincide con ninguna página de este sitio.", + "notFoundBack": "Ir al inicio", + "read.format": "El formato de cada archivo del conjunto. Es una opción de la propia herramienta, y el preset solo le da un valor por defecto.", + "readTakes.format": "un id de formato de la página de formatos", + "colDamage": "Daño", + "colEffect": "Qué hace con los bytes", + "colSettings": "Ajustes", + "noSettings": "ninguno" + }, + "endings": { + "0": "Todo ha funcionado.", + "1": "Un error inesperado dentro de la herramienta.", + "2": "Comando u opción incorrectos.", + "3": "La receta no es válida.", + "4": "El formato no puede hacer lo que se pidió.", + "5": "Ha fallado una lectura o una escritura.", + "6": "No hay espacio suficiente en disco.", + "7": "verify ha encontrado una discrepancia.", + "8": "La ejecución terminó, pero no se produjo todo.", + "130": "Interrumpido con Ctrl+C.", + "143": "Detenido por una señal, que es el aspecto de un tiempo de espera agotado en CI." + }, + "presets": { + "empty-and-minimal": { + "question": "¿Pasa un archivo válido y tan pequeño como permite el formato?", + "title": "Vacío y mínimo", + "pageTitle": "Archivos de prueba válidos mínimos y vacíos en cada formato", + "description": "El archivo válido más pequeño que escribe en cada uno de sus {{ .Facts.FormatCount }} formatos, más un archivo vacío donde el formato lo permite, cada uno con su reacción esperada.", + "catches": [ + "un archivo válido rechazado por ser demasiado pequeño, porque la comprobación cuenta bytes en lugar de leerlos", + "un archivo vacío que hace caer al lector en vez de ser notificado", + "una imagen de un píxel de ancho que divide entre cero de camino a la miniatura", + "un almacenamiento que lee cero bytes como una subida fallida y sigue reintentando" + ], + "details": { + "formats": "De qué formatos se compone el conjunto. Déjalo en all para todos los formatos de esta versión, o nombra los que acepta tu sistema." + } + }, + "filename-handling": { + "question": "¿Mi sistema guardará, mostrará y devolverá un nombre de archivo que no esperaba?", + "title": "Manejo de nombres de archivo", + "pageTitle": "Nombres de archivo problemáticos para probar - Unicode y longitud", + "description": "Archivos con nombres que rompen subidas y almacenamiento: otras escrituras, emoji, inversión de dirección, caracteres invisibles, sintaxis de shell y SQL, longitud.", + "catches": [ + "un nombre que parece otro en pantalla, en un registro o en una lista", + "un nombre cortado, recortado o reescrito entre la subida y el almacenamiento", + "un límite de longitud contado en caracteres donde el almacenamiento cuenta bytes" + ], + "details": {} + }, + "size-boundaries": { + "question": "¿Se aplica un límite de tamaño exactamente donde se declara?", + "title": "Límites de tamaño", + "pageTitle": "Probar un límite de tamaño de subida - archivos en el límite", + "description": "Archivos un byte por debajo, justo en y un byte por encima del límite que declara tu sistema, más pasos más amplios, cada uno marcado según deba aceptarse o no.", + "catches": [ + "errores de uno en el límite", + "MB confundido con MiB, que son un 4,8 por ciento y bastan para dejar pasar un archivo que no debería pasar", + "un límite aplicado en el navegador y no en el servidor" + ], + "details": { + "limit": "El límite de tamaño que declara tu sistema. Todo lo demás se mide a partir de él.", + "spread": "Hasta dónde llegar a cada lado del límite, como una lista de tamaños." + } + }, + "tabular-import": { + "question": "¿Sobrevive mi importación de tablas a lo que exportan las herramientas reales?", + "title": "Importación de tablas", + "pageTitle": "Archivos de prueba para importar CSV y Excel - delimitadores", + "description": "CSV con otros delimitadores, finales CR LF, sin cabecera y con otras comillas, una tabla muy ancha, un libro de Excel y JSON en varias formas.", + "catches": [ + "un archivo con punto y coma leído como una sola columna, porque el delimitador se supuso en lugar de buscarse", + "un archivo CRLF partido en filas con una fila vacía después de cada una", + "una tabla sin cabecera cuya primera fila de datos se come como nombres de columna", + "una importación que conserva las columnas que puede mostrar y descarta el resto sin decir nada", + "un lector que toma los registros JSON de uno en uno por línea y se detiene en el primer documento con sangría" + ], + "details": { + "rows": "Cuántas filas contiene la hoja de cálculo. Se escribe exactamente con el tamaño que ocupan tantas filas, así que el presupuesto de arriba se mueve con este valor.", + "columns": "Cuántas columnas tiene cada fila de la hoja de cálculo. Filas por columnas tiene un techo, y pedir más se rechaza antes de escribir nada." + } + }, + "text-encoding": { + "question": "¿Sabe mi lector en qué codificación está un archivo, o lo adivina?", + "title": "Codificación de texto", + "pageTitle": "Archivos de prueba de codificación - UTF-8, UTF-16, BOM, CRLF", + "description": "El mismo texto en UTF-8, UTF-16LE y UTF-16BE, con y sin marca de orden de bytes, y finales de línea CR LF y LF, para probar cómo decodifica un lector.", + "catches": [ + "un lector que supone UTF-8 y muestra un archivo UTF-16 con un carácter de cada tres, o como filas de cuadros", + "una marca de orden de bytes leída como contenido, de modo que el primer campo de una importación empieza con tres caracteres extraños", + "un importador que adivina la codificación por los primeros bytes y adivina distinto con un archivo más largo", + "un archivo CRLF partido en filas con una fila vacía después de cada una, o un retorno de carro que queda dentro del último campo" + ], + "details": { + "sample": "El tamaño de cada archivo del conjunto. UTF-16 guarda dos bytes por carácter, así que un número impar se rechaza." + } + }, + "upload-validation": { + "question": "¿Mi formulario de subida acepta lo que debe y rechaza el resto?", + "title": "Validación de subida", + "pageTitle": "Archivos de prueba de validación de subida - tipo, tamaño y nombre", + "description": "Archivos para probar un formulario de subida: tipos permitidos y denegados, contenido que no coincide con la extensión, tamaño límite, nombres hostiles y subida masiva.", + "catches": [ + "un límite aplicado en el navegador y no en el servidor", + "un SVG o un HTML tomado por una imagen o por texto plano, que es una forma de colar un script por un formulario", + "un archivo comprobado por su extensión y nunca abierto, de modo que un PDF llamado .jpg pasa", + "un formulario que lee todo el cuerpo en memoria antes de mirar su tamaño", + "una subida llamada PHOTO.JPG rechazada donde photo.jpg se acepta, o al revés", + "un nombre con espacios, paréntesis o caracteres fuera de ASCII escrito en disco sin cambios" + ], + "details": { + "limit": "El límite de tamaño que declara tu formulario de subida. Este conjunto da un paso a cada lado - para un archivo a cada distancia, ejecuta el preset size-boundaries.", + "allow": "Qué tipos debe aceptar tu formulario. Cada uno se convierte en un archivo real de ese tipo, y son el control positivo de todo el conjunto.", + "deny": "Qué extensiones debe rechazar tu formulario. Una extensión para la que esta versión no tiene formato recibe igualmente un archivo con ese nombre, con texto plano.", + "far-over": "Cuánto se pasa del límite el único archivo grande. Desactívalo donde escribir varias veces el límite no compense el disco.", + "bulk": "Cuántos archivos contiene la subida masiva. Cero deja ese grupo fuera del conjunto por completo." + } + } + }, + "commands": { + "generate": "producir archivos, desde una receta o desde opciones", + "validate": "comprobar una receta sin escribir nada", + "verify": "comprobar un directorio contra un manifiesto", + "cleanup": "eliminar los archivos que lista un manifiesto", + "recipe fmt": "imprimir una receta en su forma normalizada", + "preset": "construir un conjunto de archivos a partir de una pregunta de prueba con nombre", + "formats": "listar los formatos que admite esta versión", + "damage": "listar las formas en que esta versión puede romper un archivo a propósito", + "tool": "pequeñas utilidades para archivos que ya tienes", + "version": "imprimir la versión de la herramienta", + "license": "imprimir la licencia y qué significa para los archivos generados" + }, + "outcomes": { + "accept": "Tu sistema debe aceptar el archivo.", + "reject": "Tu sistema debe rechazar el archivo.", + "sanitize": "Tu sistema debe aceptar el archivo y limpiarlo, por ejemplo cambiándole el nombre.", + "unspecified": "Depende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías." + }, + "damages": { + "zero-head": "Sobrescribe los primeros bytes del archivo con ceros sin tocar su longitud. La mayoría de los lectores miran ahí primero, así que casi todo nota este daño." + }, + "terms": { + "oracleNone": "no aplicable", + "int": "cualquier número entero", + "choice": "uno de un conjunto fijo", + "bool": "verdadero o falso", + "size": "un tamaño como 2mb", + "text": "texto", + "pixels": "píxeles", + "paragraphs": "párrafos", + "rows": "filas", + "columns": "columnas", + "slides": "diapositivas", + "hertz": "hercios", + "megapixels": "megapíxeles", + "million cells": "millones de celdas", + "entries per second": "entradas por segundo", + "files": "archivos", + "sizes separated by commas": "tamaños separados por comas", + "format ids separated by commas": "ids de formato separados por comas", + "format ids separated by commas, or all": "ids de formato separados por comas, o all", + "extensions separated by commas": "extensiones separadas por comas", + "the id of a format, as tfg formats lists them": "el id de un formato, tal como lo lista tfg formats", + "the password, in plain text": "la contraseña, en texto plano", + "any text": "cualquier texto", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "una fecha como 2024-02-29 o 2024-02-29T13:45:00+02:00, o none" + }, + "faq": [ + { + "q": "¿En qué se diferencia de dd, fsutil o truncate?", + "a": "Esos comandos te dan un archivo del tamaño correcto lleno de nada. Un archivo de 2 MB llamado photo.png hecho así no es un PNG, de modo que cualquier cosa que lo analice de verdad lo rechaza por el motivo equivocado, y tu prueba también pasa por el motivo equivocado. Esto produce un PNG real de exactamente 2 MB que se abre en un visor de imágenes, y llega con una declaración de cómo debe tratarlo tu sistema.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "¿Es gratis, y puedo usarlo en el trabajo?", + "a": "Sí a ambas. Se publica bajo GPL-3.0 y no cuesta nada. No hay cuenta, ni clave de licencia, ni nivel de pago." + }, + { + "q": "¿Puedo usar los archivos generados en un producto de código cerrado?", + "a": "Sí. La licencia cubre el código de la herramienta, no lo que la herramienta produce. Los archivos, recetas y manifiestos generados son una salida y no obras derivadas, así que puedes subirlos al repositorio y distribuirlos sin ninguna obligación." + }, + { + "q": "¿Contienen los archivos generados datos personales reales?", + "a": "No. Todo lo que hay dentro se sintetiza a partir de una semilla. No se lee ningún conjunto de datos, no se contacta con ningún servicio y no se incrusta contenido de terceros. Trata una dirección de correo generada como inutilizable en lugar de como no usada, porque cualquier cadena aleatoria puede coincidir por casualidad con una real." + }, + { + "q": "¿Obtendré exactamente los mismos archivos en otra máquina?", + "a": "Sí, byte a byte, con la misma receta y la misma semilla. El proyecto lo prueba en cada cambio, y romperlo exige una versión mayor. Eso es lo que te permite subir al repositorio una receta pequeña en lugar de fixtures binarios grandes." + }, + { + "q": "¿Necesita conexión a internet?", + "a": "Nunca. No hay telemetría, ni comprobación de actualizaciones, ni cliente en la nube, y el binario de la línea de comandos no lleva compilada ninguna pila de red. Funciona en una máquina sin red y dentro de un entorno corporativo cerrado." + }, + { + "q": "¿Qué pasa si pido un tamaño que un formato no puede alcanzar?", + "a": "Obtienes un error que nombra el formato, lo más pequeño que puede ser, el motivo de ese suelo y qué hacer en su lugar, y no se escribe ningún archivo. La herramienta nunca redondea un tamaño en silencio. Cada suelo aparece en la página de formatos.", + "code": "tfg formats png" + }, + { + "q": "¿Puedo generar un archivo deliberadamente roto?", + "a": "Sí. Añade --damage zero-head y el archivo sale con exactamente el tamaño pedido, con sus primeros bytes sobrescritos por ceros, de modo que un lector lo rechaza, y el manifiesto dice que tu sistema debe rechazarlo. La página sobre archivos de prueba corruptos tiene los detalles.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "¿Qué formatos vienen después?", + "a": "7z, mp3 y mp4. Hoy funcionan de principio a fin {{ .Facts.FormatCount }} formatos." + }, + { + "q": "¿En qué sistemas puedo ejecutarlo?", + "a": "La línea de comandos funciona en Windows y Linux, tanto en Intel como en ARM, y en Mac con Apple Silicon. La ventana de escritorio se entrega para Windows en Intel, Linux en Intel y Mac con Apple Silicon. Los Mac Intel no son compatibles y no se compila nada para ellos." + }, + { + "q": "¿Tengo que instalar algo?", + "a": "No. Descarga el archivo de tu sistema, descomprímelo y ejecuta el binario. No hay instalador, ni entorno de ejecución que añadir, ni dependencia que resolver. Si tienes Go, también sirve un único comando go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "¿Por qué una ejecución sobre miles de archivos es más lenta en Windows?", + "a": "Porque Windows cobra más por cada ruta que mira, y un comando que recorre miles de archivos mira miles de rutas. Medido en una máquina con 3000 archivos de 1 kB, verify tarda unos 0,9 segundos en Windows y unos 0,2 segundos en Linux dentro de un contenedor. Una ruta de salida más corta reduce la cifra de Windows, porque cada carpeta por encima de los archivos forma parte de lo que se mira." + } + ] +} diff --git a/web/content/es/use-cases.html b/web/content/es/use-cases.html new file mode 100644 index 00000000..1fcb3b67 --- /dev/null +++ b/web/content/es/use-cases.html @@ -0,0 +1,134 @@ +

Para qué lo usa la gente

+

+ Cinco tareas que aparecen en casi todos los proyectos que aceptan archivos de personas, y el comando + que hace cada una. Cada ejemplo de abajo se ejecuta tal como está escrito. +

+ +
+

Límites de subida

+

Probar si un límite de tamaño de archivo se aplica donde dice que se aplica

+

+ Un límite son tres casos de prueba, no uno: justo por debajo, exactamente en él y justo por encima. + Conseguirlos a mano significa calcular números de bytes y esperar no haberte equivocado en uno. + Pide el conjunto en su lugar: +

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

+ Obtienes tres PDF reales de 1048575, 1048576 y 1048577 bytes, y un manifiesto que dice que los dos + primeros deben aceptarse y el tercero rechazarse por size_limit. Tu prueba lee la + expectativa en lugar de que escribas tres aserciones a mano - y cuando cambia el límite, cambias + un número y vuelves a ejecutar. +

+

+ Lo mismo funciona sin preset cuando quieres un único conjunto de límites en línea: +

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

Integración continua

+

Mantener los fixtures fuera del repositorio sin perderlos

+

+ Los fixtures binarios grandes hacen lento clonar un repositorio y incómodo revisarlo, y nadie puede + decir qué cambió cuando se sustituye uno. Una receta son unos cientos de caracteres de YAML que + reconstruyen los archivos idénticos - byte a byte, en cualquier máquina - + porque cada archivo se deriva de la semilla de la ejecución. +

+
- 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
+

+ Cada final tiene su propio código de salida, así que una canalización puede distinguir una receta + mala de un disco lleno y de una discrepancia de verificación. Una ejecución fallida no imprime + nada en la salida estándar, lo que evita que un analizador de registros lea un error como datos. +

+
+ +
+

Escala

+

Descubrir qué pasa cuando la carpeta es grande

+

+ Las rutinas de importación, los trabajos nocturnos y los listados de directorios se comportan + distinto con diez mil archivos que con diez. Los tamaños sacados de un intervalo hacen que el + conjunto parezca tráfico real en lugar de diez mil archivos idénticos, y el sorteo viene de la + semilla, así que el conjunto es el mismo mañana. +

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

+ Comprueba cuánto costaría una ejecución antes de que escriba nada, lo que importa cuando el total se + mide en gigabytes: +

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

+ Una ejecución mayor que el espacio libre del disco se rechaza antes de escribir el primer byte, en + lugar de llenar el disco y fallar a medias. +

+
+ +
+

Archivos comprimidos

+

Probar un descompresor con un archivo comprimido que de verdad contiene archivos

+

+ Un archivo comprimido vacío con la extensión correcta no demuestra nada sobre el código que lo abre + y recorre lo que hay dentro. Declara el contenido y el archivo comprimido lo contiene de verdad: +

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

+ La profundidad de anidamiento, el número de entradas y el tamaño de lo que hay dentro son cosas + sobre las que una rutina de importación tiene opiniones, y así descubres cuáles son. +

+
+ +
+

Analizadores y visores

+

Comprobar que tu propio código lee un formato como lo hace el software real

+

+ Cada formato de aquí se comprueba con un lector independiente antes de publicarse - un PNG se abre y + se comparan sus píxeles, un DOCX lo vuelven a leer bibliotecas distintas, un archivo comprimido + se extrae. Eso significa que un archivo que tu analizador rechaza es un hallazgo sobre tu + analizador, no sobre el generador. +

+
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
+

+ La página de formatos lista los ajustes que admite cada uno y el archivo + más pequeño que puede ser cada uno. +

+
+ +
+

Guías

+

Dos de ellos con más detalle

+ +
+ +
+

Para quién es

+

+ Ingenieros de QA, automatización de pruebas y cualquiera cuyo código tenga detrás un formulario de + subida, una rutina de importación, un analizador o una cuota de almacenamiento. Funciona en una + máquina sin red alguna, lo que importa en un entorno corporativo cerrado donde un generador + basado en navegador no es una opción. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/fr/ci.html b/web/content/fr/ci.html new file mode 100644 index 00000000..7d054be5 --- /dev/null +++ b/web/content/fr/ci.html @@ -0,0 +1,194 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Comment générer des fichiers de test dans un pipeline CI

+

+ Une fixture binaire dans un dépôt reste à jamais dans son historique, ne se relit pas dans un diff + et devient impossible dès que le fichier est gros. Générez plutôt les fichiers dans le pipeline à + partir d'une recette. La recette est du texte, les octets sortent identiques à chaque fois, et une + dernière étape prouve que rien n'a bougé. +

+ +
+

La réponse courte

+

+ Installez tfg, lancez tfg generate fixtures.yaml --out ./fixtures avant + les tests et tfg verify ./fixtures/manifest.json après. Les deux étapes font + échouer le build d'elles-mêmes, avec un code de sortie qui dit pourquoi. +

+
+ +
+

Pourquoi ne pas les commiter

+

Pourquoi une fixture ne doit pas vivre dans le dépôt

+ +

+ C'est la recette qu'il faut commiter. La même recette et la même graine écrivent les mêmes octets + sur toute machine, donc le fichier généré dans le pipeline est celui que vous aviez sur votre + portable. +

+
+ +
+

La recette

+

Une recette qui vit à côté des tests

+

+ Celle-ci écrit vingt-cinq factures qui doivent être acceptées et deux images au-dessus d'une limite + qui doivent être refusées, et le manifeste note les deux attentes : +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la vérifie sans rien écrire et nomme tous les problèmes d'un + coup. +

+
+ +
+

GitHub Actions

+

Un workflow qui installe l'outil et construit les fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La ligne de somme de contrôle compare l'archive à verify-SHA256SUMS.txt de la même + version. La version est épinglée, donc une nouvelle version ne change jamais un build que vous + n'avez pas touché. +

+
+ +
+

GitLab CI

+

La même chose en job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quand ça passe au rouge

+

Ce qui fait échouer une étape, et pourquoi

+

+ Chaque fin a son propre code de sortie, donc l'étape échoue d'elle-même et le journal dit lequel. + Ceux que rencontre un pipeline : +

+ +

+ Une exécution échouée n'écrit rien sur la sortie standard, donc un analyseur de journaux ne prend + jamais une erreur pour des données. Le tableau complet est sur + la page de documentation. +

+
+ +
+

PowerShell

+

Un script PowerShell demande une ligne de plus

+

+ PowerShell ne fait pas sortir le code de sortie d'un programme d'un fichier .ps1. + Lancez-en un avec -File et le script répond 0 même quand l'outil à + l'intérieur a refusé le travail, si bien qu'un build qui devrait être rouge passe au vert. La + dernière ligne est toute la correction : +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ C'est ainsi que se comporte PowerShell, pas une particularité de cet outil. cmd, + bash et zsh n'ont besoin de rien de plus. +

+
+ +
+

Plusieurs jobs

+

Partager les fixtures entre les jobs

+

+ Il n'y a généralement pas besoin de les envoyer. Comme la même recette écrit les mêmes octets, + chaque job peut lancer son propre tfg generate, ce qui est plus rapide qu'un envoi + suivi d'un téléchargement. Quand un job doit recevoir des fichiers d'un autre, lancez tfg + verify sur le manifeste après le transfert, et il dit si ce qui est arrivé est ce qui a + été écrit. +

+
+ +
+

Suite

+

Où aller ensuite

+ +
diff --git a/web/content/fr/damage.html b/web/content/fr/damage.html new file mode 100644 index 00000000..b3ef8e08 --- /dev/null +++ b/web/content/fr/damage.html @@ -0,0 +1,178 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Comment fabriquer un fichier corrompu pour les tests

+

+ Un validateur à qui l'on n'a jamais montré que des fichiers sains n'a pas vraiment été testé. Voici + comment obtenir un fichier cassé volontairement, qui sort à exactement la taille + demandée et qui porte un manifeste disant ce que votre système doit en faire. +

+ +
+

La réponse courte

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out écrit un PNG + d'exactement 2097152 octets dont les premiers octets sont des zéros, et le manifeste à côté note + que votre système doit le rejeter. +

+
+ +
+

La méthode habituelle

+

Pourquoi un fichier corrompu à la main fait un mauvais test

+

+ Les moyens habituels sont un éditeur hexadécimal, un script qui inverse quelques octets au hasard, + ou un fichier raccourci avec head ou truncate. Ça marche une fois, + puis ça coûte : +

+ +
+ +
+

Ce que vous obtenez

+

Un fichier abîmé garde la taille demandée

+

+ Le fichier est généré normalement puis cassé, en route vers le disque. Il garde la taille demandée, + et la même commande écrit de nouveau les mêmes octets. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Les réglages se placent après deux-points. L'option peut être répétée, et les dommages s'appliquent + dans l'ordre où vous les écrivez. Ça marche avec chacun des {{ .Facts.FormatCount }} formats. +

+
+ +
+

Ce qu'il sait faire

+

Quels dommages existe-t-il ?

+

+ Voici la liste que le programme affiche, lue dans le programme au moment de construire cette page. + tfg damage affiche la même, et tfg damage <id> dit ce que prend + l'un d'eux. +

+ {{ template "damagesTable" . }} +

+ zero-head écrit des zéros sur le début du fichier. La plupart des lecteurs regardent + d'abord là, la signature et l'en-tête qui disent ce qu'est le fichier, donc presque tout lecteur + le remarque. Le texte brut et les journaux n'ont pas de signature et sont refusés eux aussi, car + une suite d'octets nuls n'est pas du texte. En dessous de quatre octets, certains formats + sortent avec un dommage dont aucun lecteur ne se plaint, c'est pourquoi le réglage commence à + quatre. +

+
+ +
+

Ce que dit le manifeste

+

Un manifeste qui dit ce qui doit se passer

+

+ Chaque fichier abîmé reçoit une entrée disant que votre système doit le rejeter, avec le dommage + noté à côté : +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Deux demandes sont refusées avant que rien ne soit écrit, car chacune laisserait sur le disque un + fichier que le manifeste décrit mal : +

+ +
+ +
+

Dans une recette

+

Fichiers sains et cassés dans une même exécution

+

+ Mettez les deux dans une seule recette, et le manifeste porte l'attente de chaque fichier, de sorte + que le test n'a pas besoin d'une liste disant lequel est lequel : +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Dans un test

+

En faire un test

+

+ Le test lit le manifeste et vérifie que ce qui s'est passé est ce qui a été déclaré. Il n'a pas + besoin d'une liste de noms de fichiers : +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un bon refus est un refus net. Un message qui dit ce qui n'allait pas est la réponse voulue. Une + erreur serveur, un blocage ou un fichier à moitié enregistré est le défaut que ce test existe + pour trouver. +

+
+ +
+

Suite

+

Où aller ensuite

+ +
diff --git a/web/content/fr/docs.html b/web/content/fr/docs.html new file mode 100644 index 00000000..319c49c4 --- /dev/null +++ b/web/content/fr/docs.html @@ -0,0 +1,287 @@ +

Documentation

+

+ Tout ce que fait l'outil, rangé selon les questions avec lesquelles les gens arrivent vraiment. Le + README du dépôt est la référence complète et correspond toujours à + la version que vous avez téléchargée. +

+ +
+

Quelles commandes existe-t-il ?

+

Chacune fait une seule chose :

+ {{ template "commandList" . }} +
+ +
+

Comment générer un seul fichier de taille exacte ?

+

+ Nommez le format, la taille et la destination. Les tailles se comptent par 1024, donc + 2mb font 2097152 octets. Un nombre d'octets brut fonctionne aussi, donc + --size 10485761 demande exactement ce nombre. +

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

Les options utiles de generate :

+
+ + + + + + + + + + + + + + + + + +
OptionCe qu'elle fait
--format <id>format des fichiers, par exemple txt
--size <size>taille exacte de chaque fichier, comme 10mb ou un nombre d'octets brut
--size-range <a-b>une taille tirée par fichier dans une plage, comme 1kb-8kb. Le tirage vient de la graine
--boundary <size>trois fichiers autour d'une limite : un octet en dessous, la limite, un octet au-dessus
--count <n>combien de fichiers produire. Par défaut 1
--name <template>modèle de nom, par exemple invoice_{index:04}.txt
--out <dir>répertoire où écrire
--seed <n>graine de l'exécution. La même graine donne les mêmes octets
--set <k>=<v>un réglage de format, répétable
--damage <name>abîmer les fichiers exprès, répétable et appliqué dans l'ordre. Lancez tfg damage pour la liste
--expected <outcome>accept, reject, sanitize ou unspecified
--dry-runcompter et montrer, sans rien écrire du tout
--jsonécrire le manifeste sur la sortie standard
+
+
+ +
+

Comment fabriquer un fichier volontairement cassé ?

+

+ Tout autre fichier écrit par cet outil est correct par construction, ce qui répond à deux des trois + questions que pose un validateur d'envoi. --damage répond à la troisième - le + fichier s'ouvre-t-il seulement. Le fichier est produit normalement puis abîmé, il garde donc la + taille demandée. +

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

+ Les réglages se placent après deux-points. L'option se répète, et l'ordre dans lequel vous les + écrivez est l'ordre dans lequel ils sont appliqués. tfg damage liste ce que cette + version sait faire et ce que chacun accepte. +

+

Dans une recette, la clé est une liste, de noms ou de réglages :

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

+ Un fichier abîmé reçoit expected: reject dans le manifeste, avec l'altération notée à + côté. Deux choses sont refusées avant que rien ne soit écrit, car chacune mettrait sinon sur le + disque un fichier que le manifeste décrit à tort : +

+ +

+ Une troisième ne peut pas être connue à l'avance. Si une altération s'exécute sans déplacer un seul + octet, ce fichier est abandonné plutôt qu'écrit - l'exécution continue, dit de quel fichier il + s'agissait et se termine avec le code de sortie partiel. +

+

+ Pas à pas, avec un test qui lit le manifeste : + comment fabriquer un fichier corrompu pour les + tests. +

+
+ +
+

À quoi ressemble une recette ?

+

+ Une recette est un fichier YAML qui décrit toute une exécution. Commitez-la à côté de vos tests et + les fixtures cessent d'être des binaires dans votre dépôt - n'importe qui peut les reconstruire, + à l'octet près, à partir d'un fichier de quelques centaines de caractères. +

+
# 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
+

+ Chaque cible exige exactement une de ces clés : size, size-range, + boundary ou contains. Deux est une erreur, et aucune aussi. Une + recette invalide n'écrit aucun fichier et signale tous les problèmes d'un coup + plutôt que le premier seulement, chacun nommant le réglage concerné. +

+
+ +
+

Comment déclarer ce que mon système doit faire d'un fichier ?

+

Forme courte quand le résultat suffit, forme longue quand la raison compte :

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Les résultats sont accept, reject, sanitize et + unspecified. Les raisons forment une liste fermée pour qu'un rapport puisse les + regrouper : 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 et + size_zero. +

+

+ Une raison nomme la règle en jeu, pas le verdict. C'est pourquoi la même raison + peut se trouver sous l'un ou l'autre résultat - un fichier un octet sous une limite est + accept, et la règle concernée reste size_limit. +

+
+ +
+

Que contient le manifeste ?

+

+ Il est écrit à côté des fichiers à la fin de chaque exécution, y compris d'une exécution + interrompue. Une entrée par fichier : +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Un recipe_hash est ajouté quand l'exécution vient d'une recette, et preset + avec overrides quand elle vient d'un préréglage, de sorte qu'un manifeste peut + toujours être rattaché à ce qui l'a produit. +

+

+ Chaque entrée porte aussi target_id, l'identifiant de la cible de la recette qui a + produit le fichier, et summary.by_target compte les fichiers de chaque cible. Une + recette à plusieurs cibles peut donc être vérifiée cible par cible sans lire les noms de + fichiers. +

+
+ +
+

Qu'est-ce qu'un préréglage ?

+

+ Un jeu de fichiers prêt à l'emploi qui répond à une question de test courante, pour que vous n'ayez + pas à concevoir le jeu vous-même. Les préréglages sont des recettes ordinaires en dessous, et + eject affiche la recette pour que vous puissiez la modifier. Chaque préréglage a + sa propre page qui dit ce qu'il trouve d'habitude, ce que + contient le jeu et chaque réglage qu'il accepte. +

+ {{ template "presetsList" . }} +
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 vous dit ce que coûterait le jeu avant que vous ne le construisiez, et dit + franchement quand un nombre est un substitut de notre part plutôt qu'une limite de la vôtre. +

+
+ +
+

Que signifient les codes de sortie ?

+

+ Chaque fin a son propre code, la sortie lisible par machine va sur la sortie standard, et une + exécution échouée n'y écrit rien. Le tableau est un contrat figé - changer le sens d'un code + exige une version majeure. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Une exécution arrêtée avec Ctrl+C laisse quand même un manifeste et ne laisse jamais de fichier à + moitié écrit, si bien qu'une tâche annulée peut encore être nettoyée par la suivante. +

+

+ Des workflows prêts pour GitHub Actions et GitLab CI : + comment générer des fichiers de test dans un pipeline + CI. +

+
+ +
+

Y a-t-il une fenêtre de bureau ?

+

+ Oui, le même moteur avec une fenêtre, pour les tests qui ne sont pas scriptés. Ce n'est pas une + version amputée : un test compare les deux interfaces fonctionnalité par fonctionnalité, et + tout ce que seule l'une peut faire doit être déclaré et justifié au lieu de diverger + discrètement. +

+

+ Les écrans sont un lot, les préréglages, plusieurs lots à la fois et À propos. Elle montre ce que + coûterait une exécution avant d'écrire quoi que ce soit, indique la progression pendant + l'exécution et peut être annulée en cours de route sans laisser de fichier à moitié écrit. Elle + n'ouvre pas encore de fichier de recette - les recettes sont pour l'instant une affaire de ligne + de commande, et la fenêtre construit ses lots dans le formulaire. +

+
diff --git a/web/content/fr/exact-size.html b/web/content/fr/exact-size.html new file mode 100644 index 00000000..918d447e --- /dev/null +++ b/web/content/fr/exact-size.html @@ -0,0 +1,148 @@ +

Comment créer un fichier d'une taille exacte

+

+ Chaque système a une commande pour cela, et les trois sont ci-dessous. Elles donnent un fichier du + nombre d'octets exact - et pour beaucoup de tests, c'est tout ce qu'il faut. Chaque + commande de cette page a été exécutée avant publication, sur le système auquel elle + appartient. +

+ +
+

La réponse courte

+

+ Windows : fsutil file createnew name 10485760. Linux : dd if=/dev/zero + of=name bs=1M count=10. macOS : mkfile 10m name. Les tailles sont en + octets, et 10 Mo comptés comme les compte votre gestionnaire de fichiers font 10485760 octets. +

+
+ +
+

Windows

+

fsutil, et une version PowerShell qui n'a besoin de rien de plus

+

+ fsutil est fourni avec Windows. Il prend la taille en octets, calculez + donc le nombre d'abord - 10 Mo font 10485760, 100 Mo font 104857600, 1 Go fait 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Mesuré sous Windows 11 : cela fonctionne depuis une invite ordinaire sans exiger de droits + élevés, et le fichier fait exactement 10485760 octets. +

+

PowerShell sait faire la même chose sans appeler un autre programme, et il comprend les unités :

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB en PowerShell signifie 10485760 octets, le même comptage par 1024 qu'utilise + l'Explorateur, donc les deux commandes ci-dessus produisent la même taille. +

+
+ +
+

Linux

+

dd, truncate et fallocate, et la différence qui piège les gens

+

dd est celle que tout le monde connaît. Elle écrit vraiment les octets :

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate est instantané, et c'est là le piège. Mesuré sous Alpine Linux, le fichier + annonce 10485760 octets et occupe zéro bloc - c'est un fichier + creux. Tout ce qui le lit obtient dix mégaoctets de zéros, mais le disque n'a jamais + cédé la place : +

+
truncate -s 10M test10mb.bin
+

+ C'est correct pour tester une limite d'envoi et trompeur pour tester un quota de disque. + fallocate est celui à choisir quand l'espace doit être réel : +

+
fallocate -l 10M test10mb.bin
+

Et quand le contenu doit être incompressible, pour qu'un archiveur ne puisse pas le réduire à nouveau :

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, qui n'est pas creux, et les deux que vous connaissez déjà

+

+ macOS fournit mkfile. Mesuré sous macOS 26.6.2 : 10485760 octets et 20480 blocs, + donc l'espace est réellement alloué plutôt que promis : +

+
mkfile 10m test10mb.bin
+

dd et truncate sont là aussi et se comportent comme sous Linux :

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Là où cela cesse de suffire

+

Un fichier de la bonne taille n'est pas un fichier du bon type

+

+ Tout ce qui précède donne un bloc de zéros. C'est suffisant quand ce qui est testé ne regarde que la + taille - une limite d'envoi, un quota, un transfert. Cela cesse de l'être dès que quelque chose + ouvre le fichier. +

+

+ Mesuré, et cela vaut la peine de le faire vous-même : créez un fichier de 2 Mo avec + fsutil, appelez-le photo.png et donnez-le à une bibliothèque d'images. + Pillow répond cannot identify image file. Ce n'est pas un PNG. Cela n'en a jamais + été un - seul le nom le prétendait. +

+

+ Cela compte plus qu'il n'y paraît, à cause de la façon dont le test échoue ensuite. + Votre point d'envoi refuse le fichier, votre test passe au vert et vous concluez que la limite + de taille fonctionne. Il ne l'a pas refusé pour sa taille. Il l'a refusé parce que les octets + n'étaient pas une image, et la règle que vous vouliez tester n'a jamais été atteinte. +

+ +
+ +
+

L'autre voie

+

Un vrai fichier de ce format, à la taille exacte que vous avez demandée

+

+ C'est ce que fait Testing Files Generator. Le fichier est un vrai fichier de son format - il s'ouvre + dans le logiciel qui lui correspond - et il fait le nombre d'octets exact que vous avez demandé, + à l'octet près : +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Demandez une taille qu'un format ne peut pas atteindre et vous obtenez une erreur qui nomme le + plancher et sa raison, jamais un fichier de mauvaise taille. La page des + formats liste chaque format avec le plus petit fichier qu'il peut produire. +

+

Et une limite, ce sont trois cas de test et non un, donc l'outil construit les trois :

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Cela donne 10485759, 10485760 et 10485761 octets, et un manifeste qui dit lesquels votre système + doit accepter et lesquels il doit refuser. La page des cas + d'usage passe en revue cela et quatre autres tâches pour lesquelles il est conçu. +

+ {{ template "downloadCta" . }} +
+ +
+

Alors lequel utiliser ?

+ +

+ Les deux sont sur cette page parce que les deux sont justes une partie du temps. L'erreur à éviter + est d'utiliser la première là où il faut la seconde et de lire le test vert comme une preuve. +

+
diff --git a/web/content/fr/faq.html b/web/content/fr/faq.html new file mode 100644 index 00000000..c2f8ed1b --- /dev/null +++ b/web/content/fr/faq.html @@ -0,0 +1,20 @@ +

Questions fréquentes

+

+ Licence, vie privée, reproductibilité et ce que les gens vérifient avant de mettre un générateur + dans un pipeline de build. Si votre question n'est pas ici, le suivi + des tickets est ouvert. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Encore indécis ?

+

+ La page des cas d'usage montre les tâches pour lesquelles il est + conçu, et la page des formats liste chaque format avec le plus petit + fichier qu'il peut produire. Le README du dépôt est la référence + complète. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/fr/formats.html b/web/content/fr/formats.html new file mode 100644 index 00000000..07e73e1e --- /dev/null +++ b/web/content/fr/formats.html @@ -0,0 +1,81 @@ +

{{ .Facts.FormatCount }} formats de fichiers, chacun généré à une taille exacte

+

+ Chacun est un vrai fichier de ce format. Il s'ouvre dans le logiciel qui lui + correspond et fait exactement le nombre d'octets que vous avez demandé. Aucun n'est du remplissage + de zéros avec une extension collée dessus. +

+ +{{ template "formatsTable" . }} + +
+

Ce que signifient les colonnes

+ +

+ Chaque format se répète aussi à l'octet près : la même recette et la même graine produisent des + fichiers identiques sur n'importe quelle machine, ce qui rend une recette sûre à commiter à la + place des fixtures elles-mêmes. +

+
+ +
+

Réglages que chaque format accepte

+

+ La plupart des formats ont des réglages propres - dimensions d'image, qualité JPEG, nombre de pages + PDF, lignes et colonnes d'un tableur, nombre d'entrées dans une archive. Définissez-les avec + --set key=value en ligne de commande, ou sous properties: dans une + recette. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Une valeur hors de ce qu'un réglage accepte est refusée avec un message qui nomme le réglage, la + plage autorisée et quoi utiliser à la place. Un réglage inconnu est aussi une erreur, jamais une + valeur par défaut silencieuse - une faute de frappe acceptée en silence donne un fichier aux + mauvais réglages et une heure à se demander pourquoi le test passe alors qu'il ne devrait pas. +

+

+ Lancez tfg formats <id> pour voir exactement ce qu'un format accepte dans la + version que vous avez. +

+
+ +
+

Les archives contiennent de vrais fichiers

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} et {{ end }}{{ $c.ID }}{{ end }} + peuvent être remplis d'entrées plutôt que laissés en coquille vide. Une archive générée contient + réellement les documents qu'elle prétend contenir, si bien que tout ce qui la décompresse + pendant un test y trouve de vrais fichiers. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/fr/index.html b/web/content/fr/index.html new file mode 100644 index 00000000..bce84ed5 --- /dev/null +++ b/web/content/fr/index.html @@ -0,0 +1,200 @@ +
+
+

Générez de vrais fichiers de test à la taille exacte

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formats au total, et chacun est un + vrai fichier qui s'ouvre dans le logiciel qui lui correspond, à la taille exacte que + vous avez demandée. Chaque exécution note aussi ce que votre application doit faire de + chaque fichier. Ligne de commande et fenêtre de bureau, gratuit et open source, entièrement sur + votre machine. +

+ + {{ template "downloadCta" . }} +
+ +
+ La fenêtre de bureau de Testing Files Generator, prête à écrire un lot de fichiers de test +
La fenêtre de bureau, prête à écrire un lot de fichiers. Le même moteur fonctionne derrière la ligne de commande.
+
+
+ + + +
+

Le problème

+

Fabriquer un fichier de test est facile. Fabriquer les mille bons est la partie fastidieuse

+

Vous testez un logiciel qui reçoit des fichiers de la part de personnes. Tôt ou tard, il vous faut :

+ +

+ C'est ce que cela remplace. C'est conçu pour les ingénieurs QA, l'automatisation de tests et tous + ceux dont le code a derrière lui un formulaire d'envoi, une routine d'import, un analyseur ou un + quota de stockage. +

+
+ +
+

Ce qui le distingue

+

Les autres générateurs s'arrêtent aux octets. Celui-ci répond à ce que votre test demande vraiment

+

+ Un dossier de fichiers vous laisse encore décider ce que chacun est censé prouver. Chaque exécution + écrit ici un manifest.json à côté des fichiers - une simple liste de tout ce qui a + été produit et, pour chaque entrée, une attente déclarée. +

+

Admettons que votre point d'envoi accepte 1 Mo. Demandez les trois fichiers situés sur cette ligne :

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FichierOctetsVotre système doitParce que
1mb_under_1b.pdf1048575accepteril est dans la limite
1mb_at_limit.pdf1048576accepterla limite elle-même est permise
1mb_over_1b.pdf1048577refusersize_limit
+
+ +

Trois fichiers, trois réponses différentes, sous forme lisible par machine. Votre test lit le manifeste au lieu que vous écriviez les assertions à la main :

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Quand la réponse dépend de votre propre politique, le manifeste le dit

+

+ Il consigne unspecified plutôt que d'inventer une attente. Un générateur qui devine + produit de faux échecs, et une suite qui crie au loup finit par être désactivée. +

+
+
+ +
+

Préréglages

+

Choisissez la question, obtenez tout le jeu

+

+ Un préréglage est un jeu de fichiers de test conçu autour d'une question de test, pour que vous + n'ayez pas à chercher quels fichiers prouvent quoi. Chacun a une page qui dit ce qu'il trouve + d'habitude, ce que contient le jeu et chaque réglage qu'il accepte. +

+ {{ template "presetsList" . }} +

Tous les préréglages, et leur rapport avec les recettes

+
+ +
+

Démarrage rapide

+

Trois commandes pour le voir fonctionner

+
    +
  1. +

    Créer un fichier

    +

    Un PNG, exactement deux mégaoctets :

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Créer beaucoup de fichiers

    +

    + Dix mille fichiers journaux, chacun entre un et huit kilooctets, avec des tailles tirées de la + graine pour que demain donne le même jeu. Donnez à chaque exécution son propre + répertoire - le manifeste est la seule trace de ce qu'une exécution a écrit, donc + l'outil refuse d'en écrire un second par-dessus : +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Les vérifier, puis les supprimer

    +

    verify vous dit que rien n'a bougé. cleanup supprime exactement ce qui a été écrit et rien d'autre :

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Les tailles se comptent par 1024, comme le fait votre gestionnaire de fichiers, donc + 2mb signifie 2097152 octets. Un nombre d'octets brut fonctionne aussi. La + documentation couvre les recettes, le manifeste et les codes de + sortie. +

+
+ +
+

Ce que vous obtenez

+

Conçu pour une suite qui tourne sans surveillance

+ +
+ +
+

Téléchargement

+

Choisissez la version pour votre système

+

+ Décompressez l'archive et lancez-la. tfg est la ligne de commande et + tfg-gui est la fenêtre de bureau. Il n'y a pas d'installateur et rien à ajouter à + votre machine. +

+ {{ template "downloadsTable" . }} +
+

Ce qui est signé, et ce qui ne l'est pas

+

+ Les téléchargements Windows et macOS sont signés, ils démarrent donc sans avertissement sur un + développeur inconnu. Ceux de Linux ne le sont pas, car Linux de bureau n'a pas d'équivalent + pour les signer. Chaque archive est listée dans verify-SHA256SUMS.txt sur la page + des versions, pour que vous puissiez vérifier ce que vous avez téléchargé. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/fr/preset.html b/web/content/fr/preset.html new file mode 100644 index 00000000..1cfecfa2 --- /dev/null +++ b/web/content/fr/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Le préréglage {{ .ID }} construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ +{{ if .Catches }} +
+

Que trouve-t-il d'habitude ?

+ +
+{{ end }} + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show {{ .ID }} :

+
+ + + + + + + +
Fichiers{{ .Budget.Files }}
Cibles dans sa recette{{ .Budget.Targets }}
Taille totale{{ .Bytes }} B
Formats{{ join .Budget.Formats ", " }}
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
AttenduSignificationFichiers
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Que pouvez-vous modifier ?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
RéglageAcceptePar défautCe qu'il fait
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Cette valeur par défaut est notre substitut, pas la valeur de votre système. Passez la vôtre.{{ end }}
+
+ {{- else }} +

Ce préréglage n'a aucun réglage. Le jeu est le même à chaque fois.

+ {{- end }} +
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/fr/presets.html b/web/content/fr/presets.html new file mode 100644 index 00000000..a112ec21 --- /dev/null +++ b/web/content/fr/presets.html @@ -0,0 +1,32 @@ +

Préréglages de fichiers de test, un jeu pour chaque question de test

+

+ Un préréglage est tout un jeu de fichiers de test conçu autour d'une question, avec un manifeste qui + dit comment votre système doit réagir à chaque fichier. Vous choisissez la question, l'outil + construit le jeu. Chaque préréglage a sa propre page qui dit ce qu'il trouve d'habitude, ce que + contient le jeu et chaque réglage qu'il accepte. +

+ +{{ template "presetsList" . }} + +
+

En quoi un préréglage diffère-t-il d'une recette ?

+

+ En dessous, il n'en diffère pas. Un préréglage est une recette que l'outil écrit pour vous à partir + de quelques réglages. tfg preset eject affiche cette recette pour que vous la + gardiez à côté de vos tests et la modifiiez, et une recette à vous peut s'appuyer sur un + préréglage en une ligne, extends: preset: suivi de son identifiant. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Puis-je me fier aux valeurs par défaut ?

+

+ Pour les fichiers, oui. Pour un nombre que seul votre système connaît, comme la limite d'un + formulaire d'envoi, une valeur par défaut est un substitut de notre part, et l'outil le dit + chaque fois qu'il en utilise une. La page de chaque préréglage marque ces réglages, et tfg + preset show le dit avant que rien ne soit écrit. +

+
diff --git a/web/content/fr/site.json b/web/content/fr/site.json new file mode 100644 index 00000000..1dfc1835 --- /dev/null +++ b/web/content/fr/site.json @@ -0,0 +1,328 @@ +{ + "code": "fr", + "locale": "fr_FR", + "name": "Français", + "dir": "fr", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Accueil", + "title": "Générateur de fichiers de test - taille exacte, {{ .Facts.FormatCount }} vrais formats", + "description": "Générateur gratuit et open source de fichiers de test pour la QA. De vrais PDF, DOCX, PNG et ZIP à la taille exacte, avec un manifeste de la réaction attendue." + }, + { + "key": "formats", + "slug": "formats", + "nav": "Formats", + "title": "{{ .Facts.FormatCount }} formats de fichiers - PDF, DOCX, PNG, ZIP et plus", + "description": "Tous les formats générés, le plus petit fichier possible pour chacun et les réglages qu'il accepte. Les {{ .Facts.FormatCount }} s'ouvrent dans le logiciel qui leur correspond." + }, + { + "key": "presets", + "slug": "prereglages", + "nav": "Préréglages", + "title": "Préréglages de fichiers de test - jeux prêts à l'emploi pour la QA", + "description": "Jeux de fichiers de test prêts à l'emploi, un par question : limites d'envoi, noms de fichiers, encodages, import de tableaux, fichiers vides, validation d'envoi." + }, + { + "key": "docs", + "slug": "documentation", + "nav": "Documentation", + "title": "Documentation - commandes, recettes, manifeste, codes de sortie", + "description": "Comment générer des fichiers de test en ligne de commande ou avec une recette YAML, ce que contient le manifeste et ce que signifie chaque code de sortie en CI." + }, + { + "key": "use-cases", + "slug": "cas-d-usage", + "nav": "Cas d'usage", + "title": "Cas d'usage - limites d'envoi, fixtures de CI, tests en masse", + "description": "Tester une limite de taille d'envoi, bâtir des fixtures reproductibles pour la CI, générer dix mille fichiers et remplir des archives avec du vrai contenu." + }, + { + "key": "exact-size", + "slug": "creer-fichier-taille-exacte", + "nav": "Taille exacte", + "title": "Créer un fichier d'une taille précise - Windows, Linux, macOS", + "description": "fsutil, dd, truncate et mkfile, mesurés chacun sur son système, et pourquoi un fichier ainsi créé n'est ni un PDF ni un PNG quand un test en exige un." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - questions sur la génération de fichiers de test", + "description": "Différence avec dd et fsutil, fichiers commitables ou non, exécutions identiques à l'octet près, et ce qui arrive quand une taille est inatteignable." + }, + { + "key": "damage", + "slug": "fichiers-de-test-corrompus", + "nav": "Fichiers corrompus", + "title": "Fichiers de test corrompus - fichiers cassés à taille exacte", + "description": "Un fichier cassé volontairement, à la taille exacte, avec un manifeste disant que votre système doit le rejeter. Pour tester la validation d'envoi et les parseurs.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "fichiers-de-test-en-ci", + "nav": "Fichiers de test en CI", + "title": "Fichiers de test en CI - GitHub Actions, GitLab CI et PowerShell", + "description": "Générez des fichiers de test dans le pipeline plutôt que de commiter des binaires : workflow GitHub Actions, job GitLab, codes de sortie et piège PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Aller au contenu", + "navLabel": "Navigation principale", + "langLabel": "Langue", + "breadcrumbHome": "Accueil", + "imageAlt": "Testing Files Generator - de vrais fichiers de test à la taille exacte, avec un manifeste qui dit comment votre système doit réagir à chacun", + "schemaDescription": "Un générateur gratuit et open source de fichiers de test pour la QA. Il produit de vrais fichiers dans {{ .Facts.FormatCount }} formats, à la taille exacte, et écrit un manifeste qui dit comment le système testé doit réagir à chacun.", + "ctaDownload": "Télécharger", + "ctaSource": "Voir le code source", + "ctaNote": "Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.", + "colFormat": "Format", + "colName": "Nom", + "colExtension": "Extension", + "colSmallest": "Plus petit fichier", + "colFidelity": "Fidélité", + "colChecked": "Vérifié avec", + "colSetting": "Réglage", + "colAccepts": "Accepte", + "colSystem": "Système", + "colCli": "Ligne de commande", + "colWindow": "Fenêtre de bureau", + "noBinary": "pas encore de binaire", + "colCode": "Code", + "colMeaning": "Signification", + "footerBlurb": "Des fichiers de test pour la QA, à la taille exacte, avec un manifeste qui dit comment votre système doit réagir à chacun.", + "footerProject": "Projet", + "footerSource": "Code source sur GitHub", + "footerReleases": "Téléchargements", + "footerIssues": "Signaler un problème", + "footerSupport": "Soutenir le projet", + "footerPages": "Pages", + "footerLicence": "Copyright (C) 2026 DonislawDev. Publié sous la licence publique générale GNU, version 3. Les fichiers que vous générez vous appartiennent - la licence couvre l'outil, pas sa sortie.", + "footerPrivacy": "Ce site ne charge ni polices, ni scripts, ni traceurs, d'où que ce soit. Il ne dépose aucun cookie.", + "notFoundTitle": "Cette page n'existe pas", + "notFoundLead": "L'adresse que vous avez suivie ne correspond à aucune page de ce site.", + "notFoundBack": "Aller à l'accueil", + "read.format": "Le format de chaque fichier du jeu. C'est une option de l'outil lui-même, et le préréglage ne fait que lui donner une valeur par défaut.", + "readTakes.format": "un identifiant de format de la page des formats", + "colDamage": "Dommage", + "colEffect": "Ce qu'il fait aux octets", + "colSettings": "Réglages", + "noSettings": "aucun" + }, + "endings": { + "0": "Tout a fonctionné.", + "1": "Une erreur inattendue dans l'outil.", + "2": "Commande ou option incorrecte.", + "3": "La recette n'est pas valide.", + "4": "Le format ne peut pas faire ce qui était demandé.", + "5": "Une lecture ou une écriture a échoué.", + "6": "Espace disque insuffisant.", + "7": "verify a trouvé une différence.", + "8": "L'exécution s'est terminée mais tout n'a pas été produit.", + "130": "Interrompu avec Ctrl+C.", + "143": "Arrêté par un signal, ce qui ressemble à un délai dépassé en CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Un fichier valide et aussi petit que le format le permet passe-t-il ?", + "title": "Vide et minimal", + "pageTitle": "Fichiers de test valides minimaux et vides, dans chaque format", + "description": "Le plus petit fichier valide que cet outil écrit dans chacun de ses {{ .Facts.FormatCount }} formats, plus un fichier vide quand le format l'autorise, chacun avec la réaction attendue.", + "catches": [ + "un fichier valide refusé parce que trop petit, quand le contrôle compte les octets au lieu de les lire", + "un fichier vide qui fait tomber le lecteur au lieu d'être signalé", + "une image d'un pixel de large qui divise par zéro en route vers la miniature", + "un stockage qui lit zéro octet comme un envoi échoué et recommence sans fin" + ], + "details": { + "formats": "Les formats dont le jeu est fait. Laissez all pour tous les formats de cette version, ou nommez ceux que votre système accepte." + } + }, + "filename-handling": { + "question": "Mon système va-t-il stocker, afficher et restituer un nom de fichier auquel il ne s'attendait pas ?", + "title": "Gestion des noms de fichiers", + "pageTitle": "Noms de fichiers problématiques pour tester - Unicode et longueur", + "description": "Fichiers aux noms qui font échouer envois et stockage : autres écritures, emoji, inversion du sens d'écriture, caractères invisibles, syntaxe shell et SQL.", + "catches": [ + "un nom qui ressemble à un autre à l'écran, dans un journal ou dans une liste", + "un nom coupé, rogné ou réécrit entre l'envoi et le stockage", + "une limite de longueur comptée en caractères là où le stockage compte en octets" + ], + "details": {} + }, + "size-boundaries": { + "question": "Une limite de taille est-elle appliquée exactement là où elle est déclarée ?", + "title": "Limites de taille", + "pageTitle": "Tester une limite de taille d'envoi - fichiers à la limite exacte", + "description": "Des fichiers un octet sous, pile sur et un octet au-dessus de la limite de taille de votre système, plus des paliers plus larges, chacun marqué accepté ou refusé.", + "catches": [ + "des erreurs d'un à la limite", + "Mo confondu avec Mio, soit 4,8 pour cent, assez pour laisser passer un fichier qui ne devrait pas passer", + "une limite appliquée dans le navigateur et pas sur le serveur" + ], + "details": { + "limit": "La limite de taille que déclare votre système. Tout le reste se mesure à partir d'elle.", + "spread": "Jusqu'où aller de part et d'autre de la limite, sous forme de liste de tailles." + } + }, + "tabular-import": { + "question": "Mon import de tableaux résiste-t-il à ce qu'exportent les vrais outils ?", + "title": "Import de tableaux", + "pageTitle": "Fichiers de test d'import CSV et Excel - séparateurs, en-têtes", + "description": "CSV avec d'autres séparateurs, fins de ligne CR LF, sans en-tête, autres guillemets, tableau très large, classeur Excel et JSON en plusieurs dispositions.", + "catches": [ + "un fichier à point-virgule lu comme une seule colonne, parce que le séparateur a été supposé au lieu d'être cherché", + "un fichier CRLF découpé en lignes avec une ligne vide après chacune", + "un tableau sans en-tête dont la première ligne de données est avalée comme noms de colonnes", + "un import qui garde les colonnes qu'il peut afficher et abandonne le reste sans un mot", + "un lecteur qui prend les enregistrements JSON une ligne à la fois et s'arrête au premier document indenté" + ], + "details": { + "rows": "Le nombre de lignes du tableur. Il est écrit exactement à la taille que font autant de lignes, donc le budget ci-dessus bouge avec cette valeur.", + "columns": "Le nombre de colonnes de chaque ligne du tableur. Lignes fois colonnes a un plafond, et le dépasser est refusé avant que rien ne soit écrit." + } + }, + "text-encoding": { + "question": "Mon lecteur sait-il dans quel encodage est un fichier, ou devine-t-il ?", + "title": "Encodage du texte", + "pageTitle": "Fichiers de test d'encodage de texte - UTF-8, UTF-16, BOM, CRLF", + "description": "Le même texte en UTF-8, UTF-16LE et UTF-16BE, avec et sans BOM, et des fins de ligne CR LF et LF, pour tester le décodage d'un lecteur.", + "catches": [ + "un lecteur qui suppose de l'UTF-8 et montre un fichier UTF-16 avec un caractère sur trois, ou en rangées de carrés", + "une marque d'ordre des octets lue comme du contenu, si bien que le premier champ d'un import commence par trois caractères parasites", + "un importeur qui devine l'encodage d'après les premiers octets et devine autrement pour un fichier plus long", + "un fichier CRLF découpé en lignes avec une ligne vide après chacune, ou un retour chariot resté dans le dernier champ" + ], + "details": { + "sample": "La taille de chaque fichier du jeu. L'UTF-16 stocke deux octets par caractère, donc un nombre impair est refusé." + } + }, + "upload-validation": { + "question": "Mon formulaire d'envoi accepte-t-il ce qu'il doit et refuse-t-il le reste ?", + "title": "Validation d'envoi", + "pageTitle": "Fichiers de test de validation d'envoi - type, taille et nom", + "description": "Fichiers pour tester un formulaire d'envoi : types autorisés et refusés, contenu qui ne correspond pas à l'extension, limite de taille, noms hostiles, envoi en masse.", + "catches": [ + "une limite appliquée dans le navigateur et pas sur le serveur", + "un SVG ou un HTML pris pour une image ou pour du texte brut, un moyen de faire passer un script à travers un formulaire", + "un fichier contrôlé par son extension et jamais ouvert, si bien qu'un PDF nommé .jpg passe", + "un formulaire qui lit tout le corps en mémoire avant de regarder sa taille", + "un envoi nommé PHOTO.JPG refusé là où photo.jpg est accepté, ou l'inverse", + "un nom avec des espaces, des parenthèses ou des caractères hors ASCII écrit sur le disque tel quel" + ], + "details": { + "limit": "La limite de taille que déclare votre formulaire d'envoi. Ce jeu fait un pas de chaque côté - pour un fichier à chaque distance, lancez le préréglage size-boundaries.", + "allow": "Les types que votre formulaire doit accepter. Chacun devient un vrai fichier de ce type, et ils forment le témoin positif de tout le jeu.", + "deny": "Les extensions que votre formulaire doit refuser. Une extension pour laquelle cette version n'a pas de format reçoit quand même un fichier à ce nom, contenant du texte brut.", + "far-over": "Jusqu'où le grand fichier dépasse la limite. Désactivez-le là où écrire plusieurs fois la limite ne vaut pas le disque.", + "bulk": "Le nombre de fichiers de l'envoi en masse. Zéro retire complètement ce groupe du jeu." + } + } + }, + "commands": { + "generate": "produire des fichiers, depuis une recette ou des options", + "validate": "vérifier une recette sans rien écrire", + "verify": "comparer un répertoire à un manifeste", + "cleanup": "supprimer les fichiers qu'un manifeste liste", + "recipe fmt": "afficher une recette sous sa forme normalisée", + "preset": "construire un jeu de fichiers à partir d'une question de test nommée", + "formats": "lister les formats pris en charge par cette version", + "damage": "lister les façons dont cette version peut abîmer un fichier exprès", + "tool": "de petits outils pour des fichiers que vous avez déjà", + "version": "afficher la version de l'outil", + "license": "afficher la licence et ce qu'elle implique pour les fichiers générés" + }, + "outcomes": { + "accept": "Votre système doit accepter le fichier.", + "reject": "Votre système doit refuser le fichier.", + "sanitize": "Votre système doit accepter le fichier et le nettoyer, par exemple en le renommant.", + "unspecified": "Cela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu." + }, + "damages": { + "zero-head": "Écrase les premiers octets du fichier avec des zéros, sans toucher à sa longueur. La plupart des lecteurs regardent d'abord là, donc presque tout remarque ce dommage." + }, + "terms": { + "oracleNone": "sans objet", + "int": "tout nombre entier", + "choice": "une valeur d'un ensemble fixe", + "bool": "vrai ou faux", + "size": "une taille comme 2mb", + "text": "texte", + "pixels": "pixels", + "paragraphs": "paragraphes", + "rows": "lignes", + "columns": "colonnes", + "slides": "diapositives", + "hertz": "hertz", + "megapixels": "mégapixels", + "million cells": "millions de cellules", + "entries per second": "entrées par seconde", + "files": "fichiers", + "sizes separated by commas": "tailles séparées par des virgules", + "format ids separated by commas": "identifiants de format séparés par des virgules", + "format ids separated by commas, or all": "identifiants de format séparés par des virgules, ou all", + "extensions separated by commas": "extensions séparées par des virgules", + "the id of a format, as tfg formats lists them": "l'identifiant d'un format, comme le liste tfg formats", + "the password, in plain text": "le mot de passe, en clair", + "any text": "n'importe quel texte", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "une date comme 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none" + }, + "faq": [ + { + "q": "En quoi est-ce différent de dd, fsutil ou truncate ?", + "a": "Ces commandes donnent un fichier de la bonne taille rempli de rien. Un fichier de 2 Mo nommé photo.png fabriqué ainsi n'est pas un PNG, donc tout ce qui l'analyse vraiment le refuse pour la mauvaise raison, et votre test réussit alors lui aussi pour la mauvaise raison. Cet outil produit un vrai PNG d'exactement 2 Mo, qui s'ouvre dans une visionneuse d'images, accompagné d'une déclaration sur la façon dont votre système doit le traiter.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Est-ce gratuit, et puis-je l'utiliser au travail ?", + "a": "Oui aux deux. Il est publié sous GPL-3.0 et ne coûte rien. Il n'y a ni compte, ni clé de licence, ni offre payante." + }, + { + "q": "Puis-je utiliser les fichiers générés dans un produit propriétaire ?", + "a": "Oui. La licence couvre le code de l'outil, pas ce qu'il produit. Les fichiers, recettes et manifestes générés sont une sortie et non des œuvres dérivées, vous pouvez donc les commiter et les livrer sans aucune obligation." + }, + { + "q": "Les fichiers générés contiennent-ils de vraies données personnelles ?", + "a": "Non. Tout ce qu'ils contiennent est synthétisé à partir d'une graine. Aucun jeu de données n'est lu, aucun service n'est contacté et aucun contenu tiers n'est intégré. Considérez une adresse e-mail générée comme inutilisable plutôt que comme inutilisée, car n'importe quelle chaîne aléatoire peut coïncider par hasard avec une vraie." + }, + { + "q": "Obtiendrai-je exactement les mêmes fichiers sur une autre machine ?", + "a": "Oui, à l'octet près, avec la même recette et la même graine. Le projet le teste à chaque modification, et le casser exige un changement de version majeure. C'est ce qui vous permet de commiter une petite recette plutôt que de gros fixtures binaires." + }, + { + "q": "Faut-il une connexion internet ?", + "a": "Jamais. Il n'y a ni télémétrie, ni vérification de mises à jour, ni client cloud, et le binaire en ligne de commande n'a aucune pile réseau compilée dedans. Il fonctionne sur une machine sans réseau et dans un environnement d'entreprise fermé." + }, + { + "q": "Que se passe-t-il si je demande une taille qu'un format ne peut pas atteindre ?", + "a": "Vous obtenez une erreur qui nomme le format, la taille minimale possible, la raison de ce plancher et ce qu'il faut faire à la place, et aucun fichier n'est écrit. L'outil n'arrondit jamais une taille en silence. Chaque plancher est listé sur la page des formats.", + "code": "tfg formats png" + }, + { + "q": "Puis-je générer un fichier volontairement cassé ?", + "a": "Oui. Ajoutez --damage zero-head et le fichier sort à la taille exacte demandée, avec ses premiers octets écrasés par des zéros, si bien qu'un lecteur le refuse, et le manifeste dit que votre système doit le rejeter. La page sur les fichiers de test corrompus donne le détail.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Quels formats arrivent ensuite ?", + "a": "7z, mp3 et mp4. {{ .Facts.FormatCount }} formats fonctionnent de bout en bout aujourd'hui." + }, + { + "q": "Sur quels systèmes puis-je l'exécuter ?", + "a": "La ligne de commande fonctionne sous Windows et Linux, sur Intel comme sur ARM, et sur les Mac Apple silicon. La fenêtre de bureau est fournie pour Windows sur Intel, Linux sur Intel et les Mac Apple silicon. Les Mac Intel ne sont pas pris en charge et rien n'est construit pour eux." + }, + { + "q": "Dois-je installer quelque chose ?", + "a": "Non. Téléchargez l'archive de votre système, décompressez-la et lancez le binaire. Il n'y a pas d'installateur, pas d'environnement d'exécution à ajouter et pas de dépendance à résoudre. Si vous avez Go, une seule commande go install fonctionne aussi.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Pourquoi une exécution sur des milliers de fichiers est-elle plus lente sous Windows ?", + "a": "Parce que Windows facture plus cher chaque chemin qu'il examine, et une commande qui parcourt des milliers de fichiers examine des milliers de chemins. Mesuré sur une machine avec 3000 fichiers de 1 ko, verify prend environ 0,9 seconde sous Windows et environ 0,2 seconde sous Linux dans un conteneur. Un chemin de sortie plus court réduit le chiffre de Windows, car chaque dossier au-dessus des fichiers fait partie de ce qui est examiné." + } + ] +} diff --git a/web/content/fr/use-cases.html b/web/content/fr/use-cases.html new file mode 100644 index 00000000..ffe21af4 --- /dev/null +++ b/web/content/fr/use-cases.html @@ -0,0 +1,137 @@ +

À quoi les gens l'utilisent

+

+ Cinq tâches qui reviennent dans presque tous les projets qui reçoivent des fichiers de la part de + personnes, et la commande qui fait chacune. Chaque exemple ci-dessous s'exécute tel qu'il est + écrit. +

+ +
+

Limites d'envoi

+

Tester si une limite de taille de fichier est appliquée là où elle le dit

+

+ Une limite, ce sont trois cas de test, pas un : juste en dessous, pile dessus et juste + au-dessus. Les obtenir à la main revient à calculer des nombres d'octets en espérant ne pas + s'être trompé d'un. Demandez plutôt le jeu : +

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

+ Vous obtenez trois vrais PDF de 1048575, 1048576 et 1048577 octets, et un manifeste qui dit que les + deux premiers doivent être acceptés et le troisième refusé pour size_limit. Votre + test lit l'attente au lieu que vous écriviez trois assertions à la main - et quand la limite + change, vous changez un nombre et relancez. +

+

+ La même chose fonctionne sans préréglage quand vous voulez un seul jeu de limites en ligne : +

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

Intégration continue

+

Garder les fixtures hors du dépôt sans les perdre

+

+ De gros fixtures binaires rendent un dépôt lent à cloner et pénible à relire, et personne ne peut + dire ce qui a changé quand l'un est remplacé. Une recette, ce sont quelques centaines de + caractères de YAML qui reconstruisent les fichiers identiques - à l'octet près, sur + n'importe quelle machine - parce que chaque fichier est dérivé de la graine de + l'exécution. +

+
- 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
+

+ Chaque fin a son propre code de sortie, si bien qu'un pipeline peut distinguer une mauvaise recette + d'un disque plein et d'une différence de vérification. Une exécution échouée n'écrit rien sur la + sortie standard, ce qui évite qu'un analyseur de journaux lise une erreur comme une donnée. +

+
+ +
+

Volume

+

Découvrir ce qui se passe quand le dossier est gros

+

+ Les routines d'import, les tâches de nuit et les listages de répertoires se comportent autrement à + dix mille fichiers qu'à dix. Des tailles tirées dans une plage donnent au jeu l'allure d'un vrai + trafic plutôt que de dix mille fichiers identiques, et le tirage vient de la graine, donc le jeu + est le même demain. +

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

+ Vérifiez ce que coûterait une exécution avant qu'elle n'écrive quoi que ce soit, ce qui compte quand + le total se mesure en gigaoctets : +

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

+ Une exécution plus grande que l'espace libre du disque est refusée avant que le premier octet soit + écrit, au lieu de remplir le disque et d'échouer à mi-chemin. +

+
+ +
+

Archives

+

Tester un décompresseur avec une archive qui contient vraiment des fichiers

+

+ Une archive vide avec la bonne extension ne prouve rien sur le code qui l'ouvre et parcourt ce + qu'elle contient. Déclarez le contenu et l'archive le contient vraiment : +

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

+ La profondeur d'imbrication, le nombre d'entrées et la taille de ce qu'il y a dedans sont autant de + choses sur lesquelles une routine d'import a des opinions, et c'est ainsi que vous découvrez + lesquelles. +

+
+ +
+

Analyseurs et visionneuses

+

Vérifier que votre propre code lit un format comme le fait un vrai logiciel

+

+ Chaque format ici est vérifié avec un lecteur indépendant avant la livraison - un PNG est ouvert et + ses pixels comparés, un DOCX est relu par des bibliothèques distinctes, une archive est + extraite. Cela signifie qu'un fichier que votre analyseur refuse est une trouvaille sur votre + analyseur, pas sur le générateur. +

+
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
+

+ La page des formats liste les réglages que chacun accepte et le plus + petit fichier que chacun peut être. +

+
+ +
+

Guides

+

Deux d'entre eux en détail

+ +
+ +
+

À qui cela s'adresse

+

+ Les ingénieurs QA, l'automatisation de tests et tous ceux dont le code a derrière lui un formulaire + d'envoi, une routine d'import, un analyseur ou un quota de stockage. Il fonctionne sur une + machine sans aucun réseau, ce qui compte dans un environnement d'entreprise fermé où un + générateur dans le navigateur n'est pas une option. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/hi/ci.html b/web/content/hi/ci.html new file mode 100644 index 00000000..4891f0e3 --- /dev/null +++ b/web/content/hi/ci.html @@ -0,0 +1,187 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

CI पाइपलाइन में टेस्ट फ़ाइलें कैसे बनाएँ

+

+ रिपॉज़िटरी में बाइनरी फ़िक्स्चर उसके इतिहास में हमेशा के लिए रह जाता है, diff में उसकी समीक्षा नहीं + हो सकती, और फ़ाइल बड़ी हो तो वह संभव ही नहीं रहता। इसके बजाय फ़ाइलें पाइपलाइन के भीतर रेसिपी से + बनाएँ। रेसिपी पाठ है, बाइट हर बार एक जैसे निकलते हैं, और आख़िरी कदम साबित करता है कि कुछ नहीं + खिसका। +

+ +
+

छोटा जवाब

+

+ tfg इंस्टॉल करें, टेस्ट से पहले tfg generate fixtures.yaml --out + ./fixtures चलाएँ और उनके बाद tfg verify ./fixtures/manifest.json। दोनों कदम + अपने आप बिल्ड को विफल करते हैं, एक ऐसे एग्ज़िट कोड के साथ जो कारण बताता है। +

+
+ +
+

कमिट क्यों न करें

+

फ़िक्स्चर रिपॉज़िटरी में क्यों नहीं रहना चाहिए

+ +

+ कमिट करने की चीज़ रेसिपी है। वही रेसिपी और वही सीड हर मशीन पर वही बाइट लिखते हैं, इसलिए पाइपलाइन में + बनी फ़ाइल वही फ़ाइल है जो आपके लैपटॉप पर थी। +

+
+ +
+

रेसिपी

+

टेस्ट के बगल में रहने वाली रेसिपी

+

+ यह पच्चीस चालान लिखती है जिन्हें स्वीकार होना चाहिए और सीमा से ऊपर की दो छवियाँ जिन्हें अस्वीकार + होना चाहिए, और मैनिफ़ेस्ट दोनों अपेक्षाएँ दर्ज करता है: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml उसे बिना कुछ लिखे जाँचता है और सारी समस्याएँ एक साथ बता देता + है। +

+
+ +
+

GitHub Actions

+

एक वर्कफ़्लो जो टूल इंस्टॉल करता है और फ़िक्स्चर बनाता है

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ चेकसम वाली पंक्ति संग्रह को उसी रिलीज़ की verify-SHA256SUMS.txt से मिलाती है। संस्करण + तय कर दिया गया है, इसलिए नई रिलीज़ कभी ऐसे बिल्ड को नहीं बदलती जिसे आपने छुआ नहीं। +

+
+ +
+

GitLab CI

+

वही बात GitLab जॉब के रूप में

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

जब यह लाल हो जाए

+

क्या किसी कदम को विफल करता है, और क्यों

+

+ हर अंत का अपना एग्ज़िट कोड है, इसलिए कदम अपने आप विफल होता है और लॉग बताता है कि कौन-सा था। जो + पाइपलाइन को मिलते हैं: +

+ +

+ विफल रन स्टैंडर्ड आउटपुट पर कुछ नहीं छापता, इसलिए लॉग पार्सर कभी किसी त्रुटि को डेटा नहीं समझता। + पूरी तालिका दस्तावेज़ के पेज पर है। +

+
+ +
+

PowerShell

+

PowerShell स्क्रिप्ट को एक पंक्ति और चाहिए

+

+ PowerShell किसी प्रोग्राम का एग्ज़िट कोड .ps1 फ़ाइल से बाहर नहीं ले जाता। एक को + -File से चलाएँ तो स्क्रिप्ट 0 देती है, चाहे भीतर के टूल ने काम से + इनकार कर दिया हो, और जो बिल्ड लाल होना चाहिए वह हरा हो जाता है। आख़िरी पंक्ति ही पूरा सुधार है: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell ऐसा ही बरतता है, यह इस टूल की बात नहीं है। cmd, bash और + zsh को कुछ अतिरिक्त नहीं चाहिए। +

+
+ +
+

कई जॉब

+

जॉब के बीच फ़िक्स्चर साझा करना

+

+ आम तौर पर उन्हें अपलोड करने की ज़रूरत नहीं होती। क्योंकि वही रेसिपी वही बाइट लिखती है, हर जॉब अपना + tfg generate चला सकता है, जो अपलोड और डाउनलोड से तेज़ है। जब किसी जॉब को दूसरे से + फ़ाइलें लेनी हों, तो ट्रांसफ़र के बाद मैनिफ़ेस्ट पर tfg verify चलाएँ, और वह बताएगा + कि जो पहुँचा वही है जो लिखा गया था। +

+
+ +
+

आगे

+

यहाँ से कहाँ जाएँ

+ +
diff --git a/web/content/hi/damage.html b/web/content/hi/damage.html new file mode 100644 index 00000000..9d91a08b --- /dev/null +++ b/web/content/hi/damage.html @@ -0,0 +1,171 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

परीक्षण के लिए खराब फ़ाइल कैसे बनाएँ

+

+ जिस वैलिडेटर को केवल स्वस्थ फ़ाइलें दिखाई गई हों, उसे सचमुच परखा नहीं गया है। यहाँ बताया गया है कि + ऐसी फ़ाइल कैसे पाएँ जो जानबूझकर बिगाड़ी गई हो, ठीक उतने आकार की निकले जितना आपने + माँगा, और ऐसा मैनिफ़ेस्ट साथ लाए जो बताता है कि आपके सिस्टम को उसका क्या करना चाहिए। +

+ +
+

छोटा जवाब

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out ठीक 2097152 बाइट की + एक PNG लिखता है जिसके शुरुआती बाइट शून्य हैं, और उसके बगल का मैनिफ़ेस्ट दर्ज करता है कि आपके + सिस्टम को उसे अस्वीकार करना चाहिए। +

+
+ +
+

आम तरीका

+

हाथ से बिगाड़ी गई फ़ाइल खराब टेस्ट क्यों है

+

+ आम तरीके हैं हेक्स एडिटर, कुछ यादृच्छिक बाइट पलटने वाली स्क्रिप्ट, या head अथवा + truncate से फ़ाइल को छोटा काट देना। ये एक बार चलते हैं, फिर महँगे पड़ते हैं: +

+ +
+ +
+

आपको क्या मिलता है

+

खराब फ़ाइल का आकार वही रहता है जो आपने माँगा था

+

+ फ़ाइल सामान्य रूप से बनती है और बाद में, डिस्क तक जाते समय, बिगाड़ी जाती है। वह माँगा हुआ आकार बनाए + रखती है, और वही कमांड फिर वही बाइट लिखता है। +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ सेटिंग कोलन के बाद लिखी जाती है। विकल्प दोहराया जा सकता है, और बिगाड़ आपके लिखे क्रम में लागू होते + हैं। यह सभी {{ .Facts.FormatCount }} फ़ॉर्मैट के साथ चलता है। +

+
+ +
+

यह क्या कर सकता है

+

कौन-कौन से बिगाड़ हैं?

+

+ यह वह सूची है जो प्रोग्राम छापता है, इस पेज को बनाते समय उसी से पढ़ी गई। tfg damage यही + सूची छापता है, और tfg damage <id> बताता है कि उनमें से एक क्या लेता है। +

+ {{ template "damagesTable" . }} +

+ zero-head फ़ाइल की शुरुआत पर शून्य लिख देता है। ज़्यादातर रीडर सबसे पहले वहीं देखते + हैं, उस सिग्नेचर और हेडर पर जो बताते हैं कि फ़ाइल क्या है, इसलिए लगभग हर रीडर इसे भाँप लेता है। + सादे पाठ और लॉग में सिग्नेचर नहीं होता और वे भी अस्वीकार होते हैं, क्योंकि शून्य बाइट की कतार + पाठ नहीं है। चार बाइट से नीचे कुछ फ़ॉर्मैट ऐसे बिगाड़ के साथ निकलते हैं जिसकी कोई रीडर शिकायत + नहीं करता, इसीलिए सेटिंग चार से शुरू होती है। +

+
+ +
+

मैनिफ़ेस्ट क्या कहता है

+

एक मैनिफ़ेस्ट जो बताता है कि क्या होना चाहिए

+

+ हर खराब फ़ाइल को एक प्रविष्टि मिलती है जो कहती है कि आपके सिस्टम को उसे अस्वीकार करना चाहिए, और + बिगाड़ उसके बगल में दर्ज रहता है: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ दो अनुरोध कुछ भी लिखे जाने से पहले ठुकरा दिए जाते हैं, क्योंकि हर एक डिस्क पर ऐसी फ़ाइल छोड़ देता + जिसका मैनिफ़ेस्ट गलत वर्णन करता: +

+ +
+ +
+

रेसिपी में

+

एक रन में स्वस्थ और खराब फ़ाइलें

+

+ दोनों को एक रेसिपी में रखें, और मैनिफ़ेस्ट हर फ़ाइल की अपेक्षा साथ रखता है, इसलिए टेस्ट को यह बताने + वाली सूची नहीं चाहिए कि कौन-सी कौन-सी है: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

टेस्ट में

+

इसे टेस्ट बनाना

+

+ टेस्ट मैनिफ़ेस्ट पढ़ता है और जाँचता है कि जो हुआ वही है जो घोषित किया गया था। उसे फ़ाइल नामों की + सूची नहीं चाहिए: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ अच्छा इनकार साफ़ इनकार होता है। जो संदेश बताए कि क्या गलत था, वही वह जवाब है जो आप चाहते हैं। सर्वर + त्रुटि, अटक जाना या आधी सहेजी फ़ाइल वह खराबी है जिसे ढूँढ़ने के लिए यह टेस्ट है। +

+
+ +
+

आगे

+

यहाँ से कहाँ जाएँ

+ +
diff --git a/web/content/hi/docs.html b/web/content/hi/docs.html new file mode 100644 index 00000000..07707e6c --- /dev/null +++ b/web/content/hi/docs.html @@ -0,0 +1,278 @@ +

दस्तावेज़ीकरण

+

+ टूल जो कुछ भी करता है, उन सवालों के रूप में सजाया गया जिन्हें लेकर लोग सच में आते हैं। + रिपॉज़िटरी का README पूरा संदर्भ है और हमेशा आपके डाउनलोड किए + बिल्ड से मेल खाता है। +

+ +
+

कौन सी कमांड हैं?

+

हर एक सिर्फ़ एक काम करती है:

+ {{ template "commandList" . }} +
+ +
+

सटीक आकार की एक फ़ाइल कैसे बनाऊँ?

+

+ फ़ॉर्मैट, आकार और जगह बताएँ। आकार 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>सीमा के आसपास तीन फ़ाइलें: एक बाइट नीचे, सीमा, एक बाइट ऊपर
--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मैनिफ़ेस्ट को स्टैंडर्ड आउटपुट पर लिखें
+
+
+ +
+

जानबूझकर टूटी फ़ाइल कैसे बनाऊँ?

+

+ यह टूल जो भी दूसरी फ़ाइल लिखता है वह बनावट से सही होती है, और इससे अपलोड वैलिडेटर के तीन सवालों में + से दो का जवाब मिल जाता है। --damage तीसरे का जवाब देता है - क्या फ़ाइल खुलती भी है। + फ़ाइल सामान्य रूप से बनती है और फिर बिगाड़ी जाती है, इसलिए उसका आकार वही रहता है जो आपने माँगा। +

+
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 मिलता है, और बिगाड़ने का ब्योरा + उसके बगल में दर्ज होता है। दो चीज़ें कुछ भी लिखे जाने से पहले ठुकरा दी जाती हैं, क्योंकि हर एक + डिस्क पर ऐसी फ़ाइल छोड़ देती जिसे मैनिफ़ेस्ट गलत बताता: +

+ +

+ तीसरी बात पहले से नहीं जानी जा सकती। अगर कोई बिगाड़ चलता है और एक भी बाइट नहीं हिलाता, तो वह फ़ाइल + लिखे जाने के बजाय छोड़ दी जाती है - रन चलता रहता है, बताता है कि वह कौन सी फ़ाइल थी, और आंशिक + एग्ज़िट कोड के साथ ख़त्म होता है। +

+

+ कदम दर कदम, मैनिफ़ेस्ट पढ़ने वाले एक टेस्ट के साथ: परीक्षण के लिए + खराब फ़ाइल कैसे बनाएँ। +

+
+ +
+

रेसिपी कैसी दिखती है?

+

+ रेसिपी एक 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 में से ठीक एक चाहिए। दो होना त्रुटि है और एक भी न होना भी। अमान्य रेसिपी + कोई फ़ाइल नहीं लिखती और सिर्फ़ पहली नहीं, सारी समस्याएँ एक साथ बताती है, हर एक + उस सेटिंग का नाम लेकर जिससे वह जुड़ी है। +

+
+ +
+

मैं कैसे बताऊँ कि मेरे सिस्टम को किसी फ़ाइल के साथ क्या करना चाहिए?

+

जब नतीजा काफ़ी हो तो छोटा रूप, जब कारण मायने रखे तो लंबा रूप:

+
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। +

+

+ कारण काम कर रहे नियम का नाम लेता है, फ़ैसले का नहीं। इसीलिए एक ही कारण किसी भी + नतीजे के नीचे आ सकता है - सीमा से एक बाइट नीचे की फ़ाइल accept है, और जिस नियम की + बात है वह फिर भी size_limit है। +

+
+ +
+

मैनिफ़ेस्ट में क्या है?

+

+ यह हर रन के अंत में फ़ाइलों के बगल में लिखा जाता है, बीच में रोके गए रन में भी। हर फ़ाइल के लिए एक + प्रविष्टि: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 जुड़ता है, और प्रीसेट से आया हो तो + overrides के साथ preset, इसलिए मैनिफ़ेस्ट को हमेशा उसके स्रोत तक खोजा + जा सकता है। +

+

+ हर प्रविष्टि में target_id भी होता है, यानी रेसिपी के उस टार्गेट का id जिसने फ़ाइल + बनाई, और summary.by_target गिनता है कि हर टार्गेट के हिस्से कितनी फ़ाइलें आईं। + इसलिए कई टार्गेट वाली रेसिपी को फ़ाइल नाम पढ़े बिना टार्गेट-दर-टार्गेट जाँचा जा सकता है। +

+
+ +
+

प्रीसेट क्या है?

+

+ किसी आम टेस्ट सवाल का जवाब देने वाला फ़ाइलों का तैयार सेट, ताकि आपको सेट खुद डिज़ाइन न करना पड़े। + प्रीसेट अंदर से सामान्य रेसिपी हैं, और eject रेसिपी छापता है ताकि आप वहीं से उसे + संपादित कर सकें। हर प्रीसेट का अपना पेज है जो बताता है कि वह आम तौर + पर क्या पकड़ता है, सेट में क्या है और वह कौन सी सेटिंग लेता है। +

+ {{ template "presetsList" . }} +
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 सेट बनाने से पहले बताता है कि उसकी क़ीमत क्या होगी, और साफ़ कहता है जब कोई संख्या + आपकी सीमा नहीं बल्कि हमारी अस्थायी जगह-धारक संख्या हो। +

+
+ +
+

एग्ज़िट कोड का क्या अर्थ है?

+

+ हर अंत का अपना कोड है, मशीन के पढ़ने लायक आउटपुट स्टैंडर्ड आउटपुट पर जाता है, और विफल रन वहाँ कुछ + नहीं छापता। तालिका एक जमाया हुआ अनुबंध है - किसी कोड का अर्थ बदलने के लिए मुख्य संस्करण बढ़ाना + पड़ता है। +

+ {{ template "exitCodesTable" . }} +
- 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 पाइपलाइन में + टेस्ट फ़ाइलें कैसे बनाएँ। +

+
+ +
+

क्या डेस्कटॉप विंडो है?

+

+ हाँ, वही इंजन जिस पर एक विंडो लगी है, उस टेस्टिंग के लिए जो स्क्रिप्ट से नहीं होती। यह घटाया हुआ रूप + नहीं है: एक टेस्ट दोनों इंटरफ़ेस की क्षमता-दर-क्षमता तुलना करता है, और जो सिर्फ़ एक ही कर सकता + है उसे चुपचाप अलग होने देने के बजाय घोषित और उचित ठहराना पड़ता है। +

+

+ स्क्रीन हैं एक बैच, प्रीसेट, एक साथ कई बैच, और परिचय। यह कुछ भी लिखने से पहले रन की क़ीमत दिखाती है, + चलते समय प्रगति बताती है, और बीच में रद्द की जा सकती है बिना आधी लिखी फ़ाइल छोड़े। यह अभी रेसिपी + फ़ाइल नहीं खोलती - फ़िलहाल रेसिपी कमांड लाइन की चीज़ हैं, और विंडो अपने बैच फ़ॉर्म में बनाती है। +

+
diff --git a/web/content/hi/exact-size.html b/web/content/hi/exact-size.html new file mode 100644 index 00000000..e0b94128 --- /dev/null +++ b/web/content/hi/exact-size.html @@ -0,0 +1,144 @@ +

सटीक आकार की फ़ाइल कैसे बनाएँ

+

+ हर सिस्टम में इसके लिए एक कमांड है, और तीनों नीचे हैं। वे आपको ठीक सही बाइट संख्या की फ़ाइल देती हैं + - और बहुत से टेस्ट के लिए आपको बस यही चाहिए। इस पेज की हर कमांड प्रकाशित करने से पहले उस + सिस्टम पर चलाई गई जिसकी वह है। +

+ +
+

छोटा जवाब

+

+ Windows: fsutil file createnew name 10485760। Linux: dd if=/dev/zero of=name + bs=1M count=10। macOS: mkfile 10m name। आकार बाइट में होते हैं, और आपके + फ़ाइल मैनेजर के गिनने के तरीके से 10 MB यानी 10485760। +

+
+ +
+

Windows

+

fsutil, और बिना किसी अतिरिक्त चीज़ वाला PowerShell रूप

+

+ fsutil Windows के साथ आता है। यह आकार बाइट में लेता है, इसलिए पहले + संख्या निकाल लें - 10 MB यानी 10485760, 100 MB यानी 104857600, 1 GB यानी 1073741824। +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11 पर मापा गया: यह सामान्य प्रॉम्प्ट से चलता है और उन्नत प्रॉम्प्ट नहीं माँगता, और फ़ाइल ठीक + 10485760 बाइट की बनती है। +

+

PowerShell बिना किसी दूसरे प्रोग्राम को बुलाए यही कर सकता है, और इकाइयाँ समझता है:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell में 10MB का मतलब 10485760 बाइट है, वही 1024 आधारित गिनती जो एक्सप्लोरर + इस्तेमाल करता है, इसलिए ऊपर की दोनों कमांड एक ही आकार बनाती हैं। +

+
+ +
+

Linux

+

dd, truncate और fallocate, और वह अंतर जो लोगों को फँसाता है

+

dd वह है जिसे सब जानते हैं। यह बाइट सच में लिखता है:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate तुरंत होता है, और यही पेंच है। Alpine Linux पर मापने पर फ़ाइल 10485760 बाइट + बताती है और शून्य ब्लॉक घेरती है - यह एक स्पार्स फ़ाइल है। जो + भी इसे पढ़ता है उसे दस मेगाबाइट शून्य मिलते हैं, पर डिस्क ने जगह कभी दी ही नहीं: +

+
truncate -s 10M test10mb.bin
+

+ अपलोड सीमा परखने के लिए यह ठीक है और डिस्क कोटा परखने के लिए भ्रामक। जब जगह असली होनी चाहिए तब + fallocate की ओर जाएँ: +

+
fallocate -l 10M test10mb.bin
+

और जब सामग्री असंपीड्य होनी चाहिए, ताकि कोई आर्काइवर उसे फिर से छोटा न कर सके:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, जो स्पार्स नहीं है, और वे दो जिन्हें आप पहले से जानते हैं

+

+ macOS में mkfile आता है। macOS 26.6.2 पर मापा गया: 10485760 बाइट और 20480 ब्लॉक, यानी + जगह वादे से नहीं, सच में आवंटित होती है: +

+
mkfile 10m test10mb.bin
+

dd और truncate भी वहाँ हैं और Linux की तरह ही चलते हैं:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

यह कहाँ काम करना बंद कर देता है

+

सही आकार की फ़ाइल सही क़िस्म की फ़ाइल नहीं होती

+

+ ऊपर की सारी चीज़ें आपको शून्यों का एक ब्लॉक देती हैं। जब जाँचा जा रहा हिस्सा सिर्फ़ आकार देखता है - + अपलोड सीमा, कोटा, ट्रांसफ़र - तब यह काफ़ी है। जिस पल कोई चीज़ फ़ाइल को खोलती + है, यह काफ़ी नहीं रहता। +

+

+ मापा गया, और खुद करके देखना लायक है: fsutil से 2 MB की फ़ाइल बनाएँ, उसका नाम + photo.png रखें, और किसी इमेज लाइब्रेरी को दें। Pillow जवाब देता है cannot + identify image file। यह PNG नहीं है। यह कभी था ही नहीं - सिर्फ़ नाम ऐसा कहता था। +

+

+ यह सुनने में जितना लगता है उससे ज़्यादा मायने रखता है, क्योंकि टेस्ट फिर किस तरफ़ विफल होता + है यही सवाल है। आपका अपलोड एंडपॉइंट फ़ाइल ठुकरा देता है, आपका टेस्ट हरा हो जाता है, और + आप मान लेते हैं कि आकार सीमा काम करती है। उसने फ़ाइल आकार की वजह से नहीं ठुकराई। उसने इसलिए + ठुकराई कि बाइट तस्वीर नहीं थे, और जिस नियम को आप जाँचना चाहते थे वह कभी छुआ ही नहीं गया। +

+ +
+ +
+

दूसरा रास्ता

+

उस फ़ॉर्मैट की असली फ़ाइल, ठीक उसी आकार में जो आपने माँगा

+

+ Testing Files Generator यही करता है। फ़ाइल अपने फ़ॉर्मैट की सच्ची फ़ाइल है - वह अपने सॉफ़्टवेयर में + खुलती है - और उसमें ठीक उतने बाइट हैं जितने आपने माँगे, बाइट तक: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ ऐसा आकार माँगें जिस तक कोई फ़ॉर्मैट नहीं पहुँच सकता और आपको न्यूनतम सीमा और उसका कारण बताने वाली + त्रुटि मिलती है, गलत आकार की फ़ाइल कभी नहीं। फ़ॉर्मैट पेज हर फ़ॉर्मैट + को उसकी सबसे छोटी संभव फ़ाइल के साथ सूचीबद्ध करता है। +

+

और एक सीमा एक नहीं, तीन टेस्ट केस होती है, इसलिए टूल तीनों बनाता है:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ इससे आपको 10485759, 10485760 और 10485761 बाइट की फ़ाइलें मिलती हैं, और एक मैनिफ़ेस्ट जो बताता है कि + आपके सिस्टम को किन्हें स्वीकार करना चाहिए और किन्हें अस्वीकार। उपयोग के + मामलों का पेज इसे और चार दूसरे काम समझाता है जिनके लिए यह बना है। +

+ {{ template "downloadCta" . }} +
+ +
+

तो कौन सा इस्तेमाल करें?

+ +

+ दोनों इस पेज पर इसलिए हैं क्योंकि दोनों कभी-कभी सही होते हैं। जिस गलती से बचना है वह है दूसरे की + ज़रूरत वाली जगह पहले को इस्तेमाल करना और हरे टेस्ट को सबूत मान लेना। +

+
diff --git a/web/content/hi/faq.html b/web/content/hi/faq.html new file mode 100644 index 00000000..2ce046b5 --- /dev/null +++ b/web/content/hi/faq.html @@ -0,0 +1,18 @@ +

अक्सर पूछे जाने वाले सवाल

+

+ लाइसेंस, निजता, दोहराव, और वे बातें जो लोग जनरेटर को बिल्ड पाइपलाइन में लगाने से पहले जाँचते हैं। + अगर आपका सवाल यहाँ नहीं है, तो इश्यू ट्रैकर खुला है। +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

अभी तय कर रहे हैं?

+

+ उपयोग के मामलों का पेज वे काम दिखाता है जिनके लिए यह बना है, और + फ़ॉर्मैट पेज हर फ़ॉर्मैट को उसकी सबसे छोटी संभव फ़ाइल के साथ सूचीबद्ध + करता है। रिपॉज़िटरी का README पूरा संदर्भ है। +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/hi/formats.html b/web/content/hi/formats.html new file mode 100644 index 00000000..39ae77c9 --- /dev/null +++ b/web/content/hi/formats.html @@ -0,0 +1,79 @@ +

{{ .Facts.FormatCount }} फ़ाइल फ़ॉर्मैट, हर एक सटीक आकार में बनाया गया

+

+ इनमें से हर एक उस फ़ॉर्मैट की असली फ़ाइल है। वह अपने सॉफ़्टवेयर में खुलती है और + उसमें ठीक उतने बाइट हैं जितने आपने माँगे। इनमें से कोई भी एक्सटेंशन चिपकाए गए भराव के शून्य नहीं + है। +

+ +{{ template "formatsTable" . }} + +
+

कॉलम का अर्थ

+ +

+ हर फ़ॉर्मैट बाइट तक दोहराया भी जाता है: वही रेसिपी और वही सीड किसी भी मशीन पर एक जैसी फ़ाइलें बनाते + हैं, और इसी से फ़िक्स्चर की जगह रेसिपी कमिट करना सुरक्षित होता है। +

+
+ +
+

हर फ़ॉर्मैट की स्वीकार की जाने वाली सेटिंग

+

+ ज़्यादातर फ़ॉर्मैट की अपनी सेटिंग होती हैं - इमेज के आयाम, JPEG गुणवत्ता, PDF के पेज, स्प्रेडशीट की + पंक्तियाँ और कॉलम, आर्काइव के अंदर कितनी प्रविष्टियाँ जाएँ। इन्हें कमांड लाइन पर --set + key=value से, या रेसिपी में properties: के नीचे सेट करें। +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ किसी सेटिंग की स्वीकार्य सीमा से बाहर का मान एक संदेश के साथ ठुकरा दिया जाता है जो सेटिंग, मान्य + सीमा और इसके बदले क्या इस्तेमाल करें यह बताता है। अज्ञात सेटिंग भी त्रुटि है, कभी चुपचाप + डिफ़ॉल्ट नहीं - चुपचाप मान ली गई टाइपो गलत सेटिंग की फ़ाइल देती है और एक घंटा यह सोचने में जाता + है कि जिस टेस्ट को विफल होना था वह पास क्यों हो रहा है। +

+

+ जो बिल्ड आपके पास है उसमें कोई फ़ॉर्मैट ठीक क्या स्वीकार करता है, यह देखने के लिए tfg formats + <id> चलाएँ। +

+
+ +
+

आर्काइव में असली फ़ाइलें होती हैं

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} और {{ end }}{{ $c.ID }}{{ end }} को + खाली खोल छोड़ने के बजाय प्रविष्टियों से भरा जा सकता है। बनाया गया आर्काइव सच में वे दस्तावेज़ + रखता है जिनका वह दावा करता है, इसलिए टेस्ट के दौरान उसे खोलने वाली कोई भी चीज़ अंदर असली फ़ाइलें + पाती है। +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/hi/index.html b/web/content/hi/index.html new file mode 100644 index 00000000..5e3b74cc --- /dev/null +++ b/web/content/hi/index.html @@ -0,0 +1,195 @@ +
+
+

सटीक आकार की असली टेस्ट फ़ाइलें बनाएँ

+

+ PDF, PNG, DOCX, ZIP - कुल {{ .Facts.FormatCount }} फ़ॉर्मैट, और हर एक असली फ़ाइल है + जो अपने सॉफ़्टवेयर में खुलती है, ठीक उसी आकार में जो आपने माँगा। हर रन यह भी + लिखता है कि आपके एप्लिकेशन को हर फ़ाइल के साथ क्या करना चाहिए। कमांड लाइन और डेस्कटॉप विंडो, + मुफ़्त और ओपन सोर्स, पूरी तरह आपकी मशीन पर चलता है। +

+ + {{ template "downloadCta" . }} +
+ +
+ Testing Files Generator की डेस्कटॉप विंडो, टेस्ट फ़ाइलों का बैच लिखने के लिए तैयार +
फ़ाइलों का बैच लिखने के लिए तैयार डेस्कटॉप विंडो। कमांड लाइन के पीछे वही इंजन चलता है।
+
+
+ + + +
+

समस्या

+

एक टेस्ट फ़ाइल बनाना आसान है। सही हज़ार बनाना थकाऊ हिस्सा है

+

आप ऐसे सॉफ़्टवेयर को टेस्ट कर रहे हैं जो लोगों से फ़ाइलें लेता है। देर-सबेर आपको चाहिए होगा:

+ +

+ यही वह है जिसे यह बदलता है। यह QA इंजीनियरों, टेस्ट ऑटोमेशन और हर उस व्यक्ति के लिए बना है जिसके कोड + के पीछे अपलोड फ़ॉर्म, इंपोर्ट रूटीन, पार्सर या स्टोरेज कोटा है। +

+
+ +
+

यह अलग क्यों है

+

दूसरे जनरेटर बाइट पर रुक जाते हैं। यह वह बताता है जो आपका टेस्ट असल में पूछता है

+

+ फ़ाइलों से भरा फ़ोल्डर आपको फिर भी तय करने देता है कि हर फ़ाइल क्या साबित करे। यहाँ हर रन फ़ाइलों के + बगल में एक manifest.json लिखता है - जो कुछ बना उसकी सादी सूची, और हर प्रविष्टि के + लिए एक घोषित अपेक्षा। +

+

मान लें कि आपका अपलोड एंडपॉइंट 1 MB की अनुमति देता है। उस रेखा पर आने वाली तीन फ़ाइलें माँगें:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
फ़ाइलबाइटआपके सिस्टम को चाहिएक्योंकि
1mb_under_1b.pdf1048575मंज़ूर करनायह सीमा के अंदर है
1mb_at_limit.pdf1048576मंज़ूर करनासीमा ख़ुद अनुमत है
1mb_over_1b.pdf1048577अस्वीकार करनाsize_limit
+
+ +

तीन फ़ाइलें, तीन अलग जवाब, मशीन के पढ़ने लायक रूप में। आपका टेस्ट असर्शन हाथ से लिखने के बजाय मैनिफ़ेस्ट पढ़ता है:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

जहाँ जवाब आपकी अपनी नीति पर निर्भर है, वहाँ मैनिफ़ेस्ट यही कहता है

+

+ वह कोई अपेक्षा गढ़ने के बजाय unspecified दर्ज करता है। अंदाज़ा लगाने वाला जनरेटर झूठी + विफलताएँ पैदा करता है, और झूठा शोर मचाने वाला टेस्ट सूट आख़िरकार बंद कर दिया जाता है। +

+
+
+ +
+

प्रीसेट

+

सवाल चुनें, पूरा सेट पाएँ

+

+ प्रीसेट एक टेस्ट सवाल के इर्द-गिर्द बनाया गया टेस्ट फ़ाइलों का सेट है, ताकि आपको खुद न सोचना पड़े कि + कौन सी फ़ाइल क्या साबित करती है। हर एक का एक पेज है जो बताता है कि वह आम तौर पर क्या पकड़ता है, + सेट में क्या है और वह कौन सी सेटिंग लेता है। +

+ {{ template "presetsList" . }} +

सभी प्रीसेट, और रेसिपी से उनका संबंध

+
+ +
+

जल्दी शुरू करें

+

इसे चलते देखने के लिए तीन कमांड

+
    +
  1. +

    एक फ़ाइल बनाएँ

    +

    एक PNG, ठीक दो मेगाबाइट की:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    बहुत सी फ़ाइलें बनाएँ

    +

    + दस हज़ार लॉग फ़ाइलें, हर एक एक से आठ किलोबाइट के बीच, आकार सीड से निकाले गए ताकि कल वही सेट मिले। + हर रन को उसकी अपनी डायरेक्टरी दें - रन ने जो लिखा उसका एकमात्र रिकॉर्ड + मैनिफ़ेस्ट है, इसलिए टूल उसके ऊपर दूसरा लिखने से इनकार कर देता है: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    उन्हें जाँचें, फिर हटाएँ

    +

    verify बताता है कि कुछ नहीं खिसका। cleanup जो लिखा गया था उसे ही हटाता है, और कुछ नहीं:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ आकार 1024 के गुणकों में गिने जाते हैं, जैसा आपका फ़ाइल मैनेजर करता है, इसलिए 2mb का + मतलब 2097152 बाइट है। सादी बाइट संख्या भी चलती है। दस्तावेज़ीकरण में + रेसिपी, मैनिफ़ेस्ट और एग्ज़िट कोड समझाए गए हैं। +

+
+ +
+

आपको क्या मिलता है

+

बिना निगरानी के चलने वाले सूट के लिए बना

+ +
+ +
+

डाउनलोड

+

अपने सिस्टम का बिल्ड चुनें

+

+ आर्काइव खोलें और चलाएँ। tfg कमांड लाइन है और tfg-gui डेस्कटॉप विंडो। कोई + इंस्टॉलर नहीं और आपकी मशीन पर जोड़ने को कुछ नहीं। +

+ {{ template "downloadsTable" . }} +
+

क्या हस्ताक्षरित है, और क्या नहीं

+

+ Windows और macOS के डाउनलोड हस्ताक्षरित हैं, इसलिए वे अज्ञात डेवलपर की चेतावनी के बिना शुरू होते + हैं। Linux वाले नहीं हैं, क्योंकि डेस्कटॉप Linux में उन पर हस्ताक्षर करने का कोई समकक्ष तरीका + नहीं है। हर आर्काइव रिलीज़ पेज पर verify-SHA256SUMS.txt में सूचीबद्ध है, ताकि आप + जाँच सकें कि आपने क्या डाउनलोड किया। +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/hi/preset.html b/web/content/hi/preset.html new file mode 100644 index 00000000..e2204955 --- /dev/null +++ b/web/content/hi/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }} प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ +{{ if .Catches }} +
+

यह आम तौर पर क्या पकड़ता है?

+ +
+{{ end }} + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show {{ .ID }} बताता है:

+
+ + + + + + + +
फ़ाइलें{{ .Budget.Files }}
इसकी रेसिपी में टार्गेट{{ .Budget.Targets }}
कुल आकार{{ .Bytes }} B
फ़ॉर्मैट{{ join .Budget.Formats ", " }}
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
अपेक्षितअर्थफ़ाइलें
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

आप क्या बदल सकते हैं?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} यह डिफ़ॉल्ट हमारी अस्थायी जगह-धारक संख्या है, आपके सिस्टम का मान नहीं। अपना मान दें।{{ end }}
+
+ {{- else }} +

इस प्रीसेट की कोई सेटिंग नहीं है। सेट हर बार वही रहता है।

+ {{- end }} +
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/hi/presets.html b/web/content/hi/presets.html new file mode 100644 index 00000000..5528bfd4 --- /dev/null +++ b/web/content/hi/presets.html @@ -0,0 +1,32 @@ +

टेस्ट फ़ाइल प्रीसेट, हर टेस्ट सवाल के लिए एक सेट

+

+ प्रीसेट एक सवाल के इर्द-गिर्द बनाया गया टेस्ट फ़ाइलों का पूरा सेट है, एक मैनिफ़ेस्ट के साथ जो बताता + है कि आपके सिस्टम को हर फ़ाइल पर क्या प्रतिक्रिया देनी चाहिए। आप सवाल चुनते हैं, टूल सेट बनाता है। + हर प्रीसेट का अपना पेज है जो बताता है कि वह आम तौर पर क्या पकड़ता है, सेट में क्या है और वह कौन सी + सेटिंग लेता है। +

+ +{{ template "presetsList" . }} + +
+

प्रीसेट और रेसिपी में क्या अंतर है?

+

+ अंदर से, कोई नहीं। प्रीसेट वह रेसिपी है जो टूल कुछ सेटिंग से आपके लिए लिखता है। tfg preset + eject उस रेसिपी को छापता है ताकि आप उसे अपने टेस्ट के बगल में रखकर संपादित कर सकें, और + आपकी अपनी रेसिपी एक पंक्ति से प्रीसेट पर आगे बन सकती है, extends: preset: और उसके + बाद उसका id। +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

क्या मैं डिफ़ॉल्ट पर भरोसा कर सकता हूँ?

+

+ फ़ाइलों के लिए, हाँ। ऐसी संख्या के लिए जो सिर्फ़ आपका सिस्टम जानता है, जैसे अपलोड फ़ॉर्म की सीमा, + डिफ़ॉल्ट हमारी अस्थायी जगह-धारक संख्या होती है, और टूल जब भी ऐसा कोई इस्तेमाल करता है तब यह + बताता है। हर प्रीसेट का पेज उन सेटिंग पर निशान लगाता है, और tfg preset show कुछ भी + लिखे जाने से पहले यह बता देता है। +

+
diff --git a/web/content/hi/site.json b/web/content/hi/site.json new file mode 100644 index 00000000..85ac5f3f --- /dev/null +++ b/web/content/hi/site.json @@ -0,0 +1,328 @@ +{ + "code": "hi", + "locale": "hi_IN", + "name": "हिन्दी", + "dir": "hi", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "होम", + "title": "QA के लिए टेस्ट फ़ाइल जनरेटर - सटीक आकार, {{ .Facts.FormatCount }} असली फ़ॉर्मैट", + "description": "QA के लिए मुफ़्त, ओपन सोर्स टेस्ट फ़ाइल जनरेटर। सटीक आकार की असली PDF, DOCX, PNG और ZIP फ़ाइलें, और एक मैनिफ़ेस्ट जो बताता है कि आपके सिस्टम को क्या करना चाहिए।" + }, + { + "key": "formats", + "slug": "formats", + "nav": "फ़ॉर्मैट", + "title": "{{ .Facts.FormatCount }} समर्थित फ़ाइल फ़ॉर्मैट - PDF, DOCX, PNG, ZIP और अन्य", + "description": "जनरेटर के सभी फ़ाइल फ़ॉर्मैट, हर फ़ॉर्मैट की सबसे छोटी संभव फ़ाइल, और उनकी सेटिंग। सभी {{ .Facts.FormatCount }} अपने सॉफ़्टवेयर में खुलते हैं।" + }, + { + "key": "presets", + "slug": "presets", + "nav": "प्रीसेट", + "title": "टेस्ट फ़ाइल प्रीसेट - QA के सवालों के लिए तैयार सेट", + "description": "टेस्ट फ़ाइलों के तैयार सेट, हर सेट एक सवाल का जवाब देता है: अपलोड सीमा, फ़ाइल नाम, एन्कोडिंग, टेबल इंपोर्ट, खाली फ़ाइलें और अपलोड सत्यापन।" + }, + { + "key": "docs", + "slug": "docs", + "nav": "दस्तावेज़ीकरण", + "title": "दस्तावेज़ीकरण - कमांड, रेसिपी, मैनिफ़ेस्ट, एग्ज़िट कोड", + "description": "कमांड लाइन या YAML रेसिपी से टेस्ट फ़ाइलें कैसे बनाएँ, मैनिफ़ेस्ट में क्या होता है, और CI में चलाने पर हर एग्ज़िट कोड का क्या अर्थ है।" + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "उपयोग के मामले", + "title": "उपयोग के मामले - अपलोड सीमा, CI फ़िक्स्चर, बड़े पैमाने पर टेस्ट", + "description": "अपलोड आकार सीमा की जाँच, CI के लिए दोहराए जा सकने वाले फ़िक्स्चर, दस हज़ार फ़ाइलें बनाना, और आर्काइव में असली सामग्री भरना।" + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "सटीक आकार", + "title": "तय आकार की फ़ाइल कैसे बनाएँ - Windows, Linux, macOS", + "description": "fsutil, dd, truncate और mkfile, हर एक अपने सिस्टम पर मापा गया, और जब टेस्ट को PDF या PNG चाहिए तब इस तरह बनी फ़ाइल क्यों काम नहीं आती।" + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - टेस्ट फ़ाइलें बनाने के बारे में सवाल", + "description": "dd और fsutil से अंतर, क्या फ़ाइलें कमिट करना सुरक्षित है, क्या हर रन बाइट-दर-बाइट दोहराया जाता है, और आकार न मिल पाने पर क्या होता है।" + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "खराब फ़ाइलें", + "title": "खराब टेस्ट फ़ाइलें - सटीक आकार की बिगड़ी फ़ाइलें", + "description": "जानबूझकर बिगाड़ी गई, सटीक आकार की फ़ाइल, साथ में ऐसा मैनिफ़ेस्ट जो कहता है कि सिस्टम को उसे अस्वीकार करना चाहिए। अपलोड वैलिडेशन और पार्सर परखने के लिए।", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "CI में टेस्ट फ़ाइलें", + "title": "CI में टेस्ट फ़ाइलें - GitHub Actions, GitLab CI और PowerShell", + "description": "बाइनरी कमिट करने के बजाय पाइपलाइन में टेस्ट फ़ाइलें बनाएँ: GitHub Actions वर्कफ़्लो, GitLab जॉब, एग्ज़िट कोड और PowerShell का जाल।", + "parent": "use-cases" + } + ], + "words": { + "skip": "सामग्री पर जाएँ", + "navLabel": "मुख्य मेनू", + "langLabel": "भाषा", + "breadcrumbHome": "होम", + "imageAlt": "Testing Files Generator - सटीक आकार की असली टेस्ट फ़ाइलें, और एक मैनिफ़ेस्ट जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या प्रतिक्रिया देनी चाहिए", + "schemaDescription": "QA के लिए मुफ़्त और ओपन सोर्स टेस्ट फ़ाइल जनरेटर। यह {{ .Facts.FormatCount }} फ़ॉर्मैट में सटीक आकार की असली फ़ाइलें बनाता है और एक मैनिफ़ेस्ट लिखता है जो बताता है कि जाँचे जा रहे सिस्टम को हर फ़ाइल पर क्या प्रतिक्रिया देनी चाहिए।", + "ctaDownload": "डाउनलोड करें", + "ctaSource": "सोर्स कोड देखें", + "ctaNote": "मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।", + "colFormat": "फ़ॉर्मैट", + "colName": "नाम", + "colExtension": "एक्सटेंशन", + "colSmallest": "सबसे छोटी फ़ाइल", + "colFidelity": "पूर्णता", + "colChecked": "जाँच का साधन", + "colSetting": "सेटिंग", + "colAccepts": "स्वीकार्य मान", + "colSystem": "सिस्टम", + "colCli": "कमांड लाइन", + "colWindow": "डेस्कटॉप विंडो", + "noBinary": "अभी बाइनरी नहीं", + "colCode": "कोड", + "colMeaning": "अर्थ", + "footerBlurb": "QA के लिए सटीक आकार की टेस्ट फ़ाइलें, और एक मैनिफ़ेस्ट जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या प्रतिक्रिया देनी चाहिए।", + "footerProject": "प्रोजेक्ट", + "footerSource": "GitHub पर सोर्स कोड", + "footerReleases": "डाउनलोड", + "footerIssues": "समस्या बताएँ", + "footerSupport": "प्रोजेक्ट का समर्थन करें", + "footerPages": "पेज", + "footerLicence": "Copyright (C) 2026 DonislawDev। GNU जनरल पब्लिक लाइसेंस, संस्करण 3 के तहत जारी। आपकी बनाई फ़ाइलें आपकी हैं - लाइसेंस टूल पर लागू होता है, उसके आउटपुट पर नहीं।", + "footerPrivacy": "यह साइट कहीं से भी फ़ॉन्ट, स्क्रिप्ट या ट्रैकर लोड नहीं करती। यह कोई कुकी नहीं लगाती।", + "notFoundTitle": "यह पेज यहाँ नहीं है", + "notFoundLead": "आपने जो पता खोला वह इस साइट के किसी पेज से मेल नहीं खाता।", + "notFoundBack": "होम पेज पर जाएँ", + "read.format": "सेट की हर फ़ाइल का फ़ॉर्मैट। यह टूल का अपना फ़्लैग है, और प्रीसेट बस उसे एक डिफ़ॉल्ट देता है।", + "readTakes.format": "फ़ॉर्मैट पेज से एक फ़ॉर्मैट id", + "colDamage": "बिगाड़", + "colEffect": "बाइट के साथ क्या करता है", + "colSettings": "सेटिंग", + "noSettings": "कोई नहीं" + }, + "endings": { + "0": "सब कुछ ठीक चला।", + "1": "टूल के अंदर एक अप्रत्याशित त्रुटि।", + "2": "गलत कमांड या फ़्लैग।", + "3": "रेसिपी मान्य नहीं है।", + "4": "फ़ॉर्मैट वह नहीं कर सकता जो माँगा गया।", + "5": "पढ़ना या लिखना विफल रहा।", + "6": "डिस्क पर पर्याप्त जगह नहीं है।", + "7": "verify को असंगति मिली।", + "8": "रन पूरा हुआ, पर सब कुछ नहीं बना।", + "130": "Ctrl+C से रोका गया।", + "143": "एक सिग्नल से रोका गया, CI का टाइमआउट ऐसा ही दिखता है।" + }, + "presets": { + "empty-and-minimal": { + "question": "क्या फ़ॉर्मैट की अनुमति जितनी छोटी वैध फ़ाइल पास हो जाती है?", + "title": "खाली और न्यूनतम", + "pageTitle": "हर फ़ॉर्मैट की सबसे छोटी वैध और खाली टेस्ट फ़ाइलें", + "description": "यह टूल अपने {{ .Facts.FormatCount }} फ़ॉर्मैट में से हर एक में जो सबसे छोटी वैध फ़ाइल लिखता है, और जहाँ फ़ॉर्मैट अनुमति दे वहाँ एक खाली फ़ाइल, हर एक के साथ अपेक्षित प्रतिक्रिया।", + "catches": [ + "एक वैध फ़ाइल जो बहुत छोटी होने के कारण ठुकरा दी जाती है, क्योंकि जाँच बाइट पढ़ने के बजाय गिनती है", + "एक खाली फ़ाइल जो रिपोर्ट होने के बजाय रीडर को क्रैश कर देती है", + "एक पिक्सेल चौड़ी तस्वीर जो थंबनेल तक के रास्ते में शून्य से भाग देती है", + "ऐसा स्टोरेज जो शून्य बाइट को असफल अपलोड समझकर बार-बार कोशिश करता रहता है" + ], + "details": { + "formats": "सेट किन फ़ॉर्मैट से बना है। इस बिल्ड के सभी फ़ॉर्मैट के लिए all रहने दें, या वे फ़ॉर्मैट लिखें जिन्हें आपका सिस्टम स्वीकार करता है।" + } + }, + "filename-handling": { + "question": "क्या मेरा सिस्टम ऐसा फ़ाइल नाम सहेजेगा, दिखाएगा और लौटाएगा जिसकी उसे उम्मीद नहीं थी?", + "title": "फ़ाइल नाम का प्रबंधन", + "pageTitle": "टेस्टिंग के लिए समस्या वाले फ़ाइल नाम - Unicode और लंबाई", + "description": "ऐसे नामों वाली फ़ाइलें जो अपलोड और स्टोरेज बिगाड़ती हैं: अन्य लिपियाँ और इमोजी, दाएँ से बाएँ ओवरराइड, अदृश्य अक्षर, शेल और SQL सिंटैक्स, लंबाई की सीमाएँ।", + "catches": [ + "ऐसा नाम जो स्क्रीन, लॉग या सूची में किसी और नाम जैसा दिखता है", + "ऐसा नाम जो अपलोड और स्टोरेज के बीच कट जाता है, छँट जाता है या दोबारा लिख दिया जाता है", + "अक्षरों में गिनी जाने वाली लंबाई की सीमा, जबकि स्टोरेज बाइट गिनता है" + ], + "details": {} + }, + "size-boundaries": { + "question": "क्या आकार की सीमा ठीक वहीं लागू होती है जहाँ उसकी घोषणा की गई है?", + "title": "आकार की सीमाएँ", + "pageTitle": "अपलोड आकार सीमा की जाँच - ठीक सीमा पर की फ़ाइलें", + "description": "आपके सिस्टम की घोषित आकार सीमा से एक बाइट कम, ठीक बराबर और एक बाइट अधिक की फ़ाइलें, दोनों ओर चौड़े क़दम, हर एक पर चिह्न कि उसे स्वीकार होना चाहिए या नहीं।", + "catches": [ + "सीमा पर एक से चूकने वाली गलतियाँ", + "MB और MiB का घालमेल, जो 4.8 प्रतिशत का फ़र्क है और ऐसी फ़ाइल निकल जाने देने के लिए काफ़ी है जिसे नहीं निकलना चाहिए", + "सीमा जो ब्राउज़र में लागू होती है, सर्वर पर नहीं" + ], + "details": { + "limit": "आपके सिस्टम की घोषित आकार सीमा। बाकी सब कुछ इसी से नापा जाता है।", + "spread": "सीमा के दोनों ओर कितनी दूर तक जाना है, आकारों की सूची के रूप में।" + } + }, + "tabular-import": { + "question": "क्या मेरा टेबल इंपोर्ट वह झेल पाता है जो असली टूल एक्सपोर्ट करते हैं?", + "title": "टेबल इंपोर्ट", + "pageTitle": "CSV और Excel इंपोर्ट टेस्ट फ़ाइलें - डेलिमिटर, हेडर", + "description": "अलग डेलिमिटर, CR LF लाइन अंत, बिना हेडर और अलग कोटिंग वाली CSV, बहुत चौड़ी टेबल, एक Excel वर्कबुक और कई ढाँचों में JSON।", + "catches": [ + "अर्धविराम वाली फ़ाइल जो एक ही कॉलम की तरह पढ़ी जाती है, क्योंकि डेलिमिटर खोजा नहीं गया, मान लिया गया", + "CRLF फ़ाइल जो पंक्तियों में बँट जाती है और हर पंक्ति के बाद एक खाली पंक्ति आ जाती है", + "बिना हेडर की टेबल जिसकी डेटा की पहली पंक्ति कॉलम नाम समझकर निगल ली जाती है", + "ऐसा इंपोर्ट जो दिखा सकने वाले कॉलम रखता है और बाकी चुपचाप गिरा देता है", + "ऐसा रीडर जो JSON रिकॉर्ड एक-एक पंक्ति में लेता है और पहले इंडेंट वाले दस्तावेज़ पर रुक जाता है" + ], + "details": { + "rows": "स्प्रेडशीट में कितनी पंक्तियाँ हैं। फ़ाइल ठीक उसी आकार में लिखी जाती है जितने में उतनी पंक्तियाँ पैक होती हैं, इसलिए ऊपर का बजट इस मान के साथ खिसकता है।", + "columns": "स्प्रेडशीट की हर पंक्ति में कितने कॉलम हैं। पंक्तियों गुणा कॉलम की एक ऊपरी सीमा है, और उससे आगे माँगने पर कुछ भी लिखे जाने से पहले ही इनकार कर दिया जाता है।" + } + }, + "text-encoding": { + "question": "क्या मेरा रीडर जानता है कि फ़ाइल किस एन्कोडिंग में है, या अंदाज़ा लगा रहा है?", + "title": "टेक्स्ट एन्कोडिंग", + "pageTitle": "टेक्स्ट एन्कोडिंग टेस्ट फ़ाइलें - UTF-8, UTF-16, BOM, CRLF", + "description": "वही टेक्स्ट UTF-8, UTF-16LE और UTF-16BE में, बाइट ऑर्डर मार्क के साथ और बिना, और CR LF तथा LF लाइन अंत, यह जाँचने के लिए कि रीडर टेक्स्ट कैसे डिकोड करता है।", + "catches": [ + "ऐसा रीडर जो UTF-8 मान लेता है और UTF-16 फ़ाइल को तीन में से एक अक्षर या डिब्बों की पंक्तियों की तरह दिखाता है", + "बाइट ऑर्डर मार्क जो सामग्री की तरह पढ़ा जाता है, जिससे इंपोर्ट का पहला फ़ील्ड तीन अनजान अक्षरों से शुरू होता है", + "ऐसा इंपोर्टर जो शुरुआती बाइट से एन्कोडिंग का अंदाज़ा लगाता है और लंबी फ़ाइल पर अलग अंदाज़ा लगाता है", + "CRLF फ़ाइल जो हर पंक्ति के बाद खाली पंक्ति के साथ बँट जाती है, या कैरिज रिटर्न जो आख़िरी फ़ील्ड में रह जाता है" + ], + "details": { + "sample": "सेट की हर फ़ाइल कितनी बड़ी है। UTF-16 हर अक्षर के लिए दो बाइट रखता है, इसलिए विषम संख्या अस्वीकार हो जाती है।" + } + }, + "upload-validation": { + "question": "क्या मेरा अपलोड फ़ॉर्म वह लेता है जो उसे लेना चाहिए और बाकी को लौटा देता है?", + "title": "अपलोड सत्यापन", + "pageTitle": "अपलोड सत्यापन टेस्ट फ़ाइलें - प्रकार, आकार और नाम", + "description": "अपलोड फ़ॉर्म जाँचने की फ़ाइलें: अनुमत और निषिद्ध प्रकार, एक्सटेंशन से न मिलती सामग्री, आकार सीमा के दोनों ओर, हानिकारक नाम और एक साथ अपलोड।", + "catches": [ + "सीमा जो ब्राउज़र में लागू होती है, सर्वर पर नहीं", + "SVG या HTML फ़ाइल जिसे तस्वीर या सादा टेक्स्ट समझ लिया जाता है, जो फ़ॉर्म से स्क्रिप्ट निकाल ले जाने का एक तरीका है", + "फ़ाइल जो सिर्फ़ एक्सटेंशन से जाँची जाती है और कभी खोली नहीं जाती, इसलिए .jpg नाम की PDF निकल जाती है", + "ऐसा फ़ॉर्म जो आकार देखने से पहले पूरी बॉडी मेमोरी में पढ़ लेता है", + "PHOTO.JPG नाम का अपलोड जो ठुकरा दिया जाता है जबकि photo.jpg ले लिया जाता है, या उल्टा", + "रिक्त स्थान, कोष्ठक या ASCII से बाहर के अक्षरों वाला नाम जो बिना बदले डिस्क पर लिख दिया जाता है" + ], + "details": { + "limit": "आपके अपलोड फ़ॉर्म की घोषित आकार सीमा। यह सेट इसके दोनों ओर एक-एक क़दम लेता है - हर दूरी की फ़ाइल के लिए size-boundaries प्रीसेट चलाएँ।", + "allow": "आपका फ़ॉर्म किन प्रकारों को स्वीकार करे। हर प्रकार उसी प्रकार की असली फ़ाइल बन जाता है, और ये पूरे सेट का सकारात्मक नियंत्रण हैं।", + "deny": "आपका फ़ॉर्म किन एक्सटेंशन को ठुकराए। जिस एक्सटेंशन का इस बिल्ड में कोई फ़ॉर्मैट नहीं है, उसे भी उसी नाम की एक फ़ाइल मिलती है जिसमें सादा टेक्स्ट होता है।", + "far-over": "एकमात्र बड़ी फ़ाइल सीमा से कितनी आगे जाती है। जहाँ सीमा के कई गुना लिखना डिस्क के लायक न हो, वहाँ इसे बंद कर दें।", + "bulk": "एक साथ अपलोड में कितनी फ़ाइलें हैं। शून्य होने पर वह समूह सेट से पूरी तरह हट जाता है।" + } + } + }, + "commands": { + "generate": "रेसिपी या फ़्लैग से फ़ाइलें बनाएँ", + "validate": "रेसिपी जाँचें और कुछ न लिखें", + "verify": "किसी डायरेक्टरी को मैनिफ़ेस्ट से मिलाकर जाँचें", + "cleanup": "मैनिफ़ेस्ट में सूचीबद्ध फ़ाइलें हटाएँ", + "recipe fmt": "रेसिपी को उसके स्थिर रूप में छापें", + "preset": "किसी नामित टेस्ट सवाल से फ़ाइलों का सेट बनाएँ", + "formats": "इस बिल्ड के समर्थित फ़ॉर्मैट सूचीबद्ध करें", + "damage": "इस बिल्ड द्वारा किसी फ़ाइल को जानबूझकर बिगाड़ने के तरीके सूचीबद्ध करें", + "tool": "आपके पास पहले से मौजूद फ़ाइलों के लिए छोटे टूल", + "version": "टूल का संस्करण छापें", + "license": "लाइसेंस और बनाई गई फ़ाइलों के लिए उसका अर्थ छापें" + }, + "outcomes": { + "accept": "आपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।", + "reject": "आपके सिस्टम को फ़ाइल अस्वीकार करनी चाहिए।", + "sanitize": "आपके सिस्टम को फ़ाइल मंज़ूर करके उसे साफ़ करना चाहिए, जैसे उसका नाम बदलकर।", + "unspecified": "यह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।" + }, + "damages": { + "zero-head": "फ़ाइल के शुरुआती बाइट को शून्य से ढक देता है और लंबाई नहीं छेड़ता। ज़्यादातर रीडर सबसे पहले वहीं देखते हैं, इसलिए यह बिगाड़ लगभग हर चीज़ पकड़ लेती है।" + }, + "terms": { + "oracleNone": "लागू नहीं", + "int": "कोई भी पूर्ण संख्या", + "choice": "एक तय समूह में से एक", + "bool": "सही या गलत", + "size": "2mb जैसा आकार", + "text": "टेक्स्ट", + "pixels": "पिक्सेल", + "paragraphs": "अनुच्छेद", + "rows": "पंक्तियाँ", + "columns": "कॉलम", + "slides": "स्लाइड", + "hertz": "हर्ट्ज़", + "megapixels": "मेगापिक्सेल", + "million cells": "दस लाख सेल", + "entries per second": "प्रति सेकंड प्रविष्टियाँ", + "files": "फ़ाइलें", + "sizes separated by commas": "अल्पविराम से अलग किए गए आकार", + "format ids separated by commas": "अल्पविराम से अलग किए गए फ़ॉर्मैट id", + "format ids separated by commas, or all": "अल्पविराम से अलग किए गए फ़ॉर्मैट id, या all", + "extensions separated by commas": "अल्पविराम से अलग किए गए एक्सटेंशन", + "the id of a format, as tfg formats lists them": "किसी फ़ॉर्मैट का id, जैसा tfg formats सूचीबद्ध करता है", + "the password, in plain text": "पासवर्ड, सादे टेक्स्ट में", + "any text": "कोई भी टेक्स्ट", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "2024-02-29 या 2024-02-29T13:45:00+02:00 जैसी तारीख, या none" + }, + "faq": [ + { + "q": "यह dd, fsutil या truncate से कैसे अलग है?", + "a": "वे आपको सही आकार की फ़ाइल देते हैं जो खालीपन से भरी होती है। इस तरह बनी photo.png नाम की 2 MB की फ़ाइल PNG नहीं होती, इसलिए जो भी उसे सच में पार्स करता है वह गलत कारण से उसे ठुकरा देता है, और आपका टेस्ट भी गलत कारण से पास हो जाता है। यह टूल ठीक 2 MB की असली PNG बनाता है जो इमेज व्यूअर में खुलती है, और उसके साथ यह घोषणा आती है कि आपके सिस्टम को उसके साथ क्या करना चाहिए।", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "क्या यह मुफ़्त है, और क्या मैं इसे काम पर इस्तेमाल कर सकता हूँ?", + "a": "दोनों के लिए हाँ। यह GPL-3.0 के तहत जारी है और इसकी कोई कीमत नहीं। कोई खाता, लाइसेंस कुंजी या सशुल्क स्तर नहीं है।" + }, + { + "q": "क्या मैं बनाई गई फ़ाइलें क्लोज़्ड सोर्स उत्पाद में इस्तेमाल कर सकता हूँ?", + "a": "हाँ। लाइसेंस टूल के कोड पर लागू होता है, उस पर नहीं जो टूल बनाता है। बनाई गई फ़ाइलें, रेसिपी और मैनिफ़ेस्ट आउटपुट हैं, व्युत्पन्न कृतियाँ नहीं, इसलिए आप उन्हें बिना किसी बाध्यता के कमिट और वितरित कर सकते हैं।" + }, + { + "q": "क्या बनाई गई फ़ाइलों में असली निजी डेटा होता है?", + "a": "नहीं। अंदर का सब कुछ एक सीड से बनाया जाता है। कोई डेटासेट नहीं पढ़ा जाता, किसी सेवा से संपर्क नहीं किया जाता और किसी तीसरे पक्ष की सामग्री नहीं जोड़ी जाती। बनाए गए ईमेल पते को अप्रयुक्त नहीं, बल्कि अनुपयोगी मानें, क्योंकि कोई भी यादृच्छिक स्ट्रिंग संयोग से किसी असली पते से मेल खा सकती है।" + }, + { + "q": "क्या मुझे दूसरी मशीन पर ठीक वही फ़ाइलें मिलेंगी?", + "a": "हाँ, बाइट-दर-बाइट, उसी रेसिपी और उसी सीड के साथ। प्रोजेक्ट हर बदलाव पर इसका परीक्षण करता है, और इसे तोड़ने के लिए मुख्य संस्करण बढ़ाना पड़ता है। इसी वजह से आप बड़े बाइनरी फ़िक्स्चर की जगह एक छोटी रेसिपी कमिट कर सकते हैं।" + }, + { + "q": "क्या इसे इंटरनेट कनेक्शन चाहिए?", + "a": "कभी नहीं। कोई टेलीमेट्री नहीं, कोई अपडेट जाँच नहीं और कोई क्लाउड क्लाइंट नहीं, और कमांड लाइन बाइनरी में नेटवर्क स्टैक कंपाइल ही नहीं किया गया है। यह बिना नेटवर्क की मशीन पर और बंद कॉर्पोरेट माहौल में भी चलता है।" + }, + { + "q": "अगर मैं ऐसा आकार माँगूँ जो कोई फ़ॉर्मैट हासिल नहीं कर सकता, तो क्या होता है?", + "a": "आपको एक त्रुटि मिलती है जो फ़ॉर्मैट, सबसे छोटा संभव आकार, उस न्यूनतम सीमा का कारण और इसके बदले क्या करें यह बताती है, और कोई फ़ाइल नहीं लिखी जाती। टूल कभी आकार को चुपचाप राउंड नहीं करता। हर न्यूनतम सीमा फ़ॉर्मैट पेज पर सूचीबद्ध है।", + "code": "tfg formats png" + }, + { + "q": "क्या मैं जानबूझकर टूटी हुई फ़ाइल बना सकता हूँ?", + "a": "हाँ। --damage zero-head जोड़ें और फ़ाइल ठीक माँगे गए आकार में निकलती है, शुरुआती बाइट शून्य से ढके हुए, इसलिए रीडर उसे ठुकरा देता है, और मैनिफ़ेस्ट कहता है कि आपके सिस्टम को उसे अस्वीकार करना चाहिए। ब्योरा खराब टेस्ट फ़ाइलों वाले पेज पर है।", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "आगे कौन से फ़ॉर्मैट आ रहे हैं?", + "a": "7z, mp3 और mp4। आज {{ .Facts.FormatCount }} फ़ॉर्मैट शुरू से अंत तक काम करते हैं।" + }, + { + "q": "मैं इसे किन सिस्टम पर चला सकता हूँ?", + "a": "कमांड लाइन Windows और Linux पर Intel और ARM दोनों पर, और Apple Silicon Mac पर चलती है। डेस्कटॉप विंडो Intel पर Windows, Intel पर Linux और Apple Silicon Mac के लिए आती है। Intel Mac समर्थित नहीं हैं और उनके लिए कुछ नहीं बनाया जाता।" + }, + { + "q": "क्या मुझे कुछ इंस्टॉल करना होगा?", + "a": "नहीं। अपने सिस्टम का आर्काइव डाउनलोड करें, खोलें और बाइनरी चलाएँ। कोई इंस्टॉलर नहीं, जोड़ने के लिए कोई रनटाइम नहीं और सुलझाने के लिए कोई निर्भरता नहीं। अगर आपके पास Go है तो एक ही go install कमांड भी काम करती है।", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "हज़ारों फ़ाइलों पर रन Windows पर धीमा क्यों है?", + "a": "क्योंकि Windows हर उस पाथ के लिए ज़्यादा वसूलता है जिसे वह देखता है, और हज़ारों फ़ाइलों से गुज़रने वाली कमांड हज़ारों पाथ देखती है। 1 kB की 3000 फ़ाइलों वाली एक मशीन पर मापने पर, verify को Windows पर लगभग 0.9 सेकंड और कंटेनर में Linux पर लगभग 0.2 सेकंड लगे। छोटा आउटपुट पाथ Windows का आँकड़ा घटाता है, क्योंकि फ़ाइलों के ऊपर का हर फ़ोल्डर उसमें शामिल होता है जिसे देखा जाता है।" + } + ] +} diff --git a/web/content/hi/use-cases.html b/web/content/hi/use-cases.html new file mode 100644 index 00000000..388419f9 --- /dev/null +++ b/web/content/hi/use-cases.html @@ -0,0 +1,131 @@ +

लोग इसका इस्तेमाल किसलिए करते हैं

+

+ पाँच काम जो लोगों से फ़ाइलें लेने वाले लगभग हर प्रोजेक्ट में आते हैं, और हर एक को करने वाली कमांड। + नीचे का हर उदाहरण जैसा लिखा है वैसा चलता है। +

+ +
+

अपलोड सीमाएँ

+

यह जाँचना कि फ़ाइल आकार सीमा वहीं लागू होती है जहाँ वह कहती है

+

+ एक सीमा एक नहीं, तीन टेस्ट केस है: ठीक नीचे, ठीक पर, और ठीक ऊपर। इन्हें हाथ से बनाने का मतलब बाइट + संख्या निकालना और उम्मीद करना है कि आप एक से नहीं चूके। इसके बजाय सेट माँगें: +

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

+ आपको 1048575, 1048576 और 1048577 बाइट की तीन असली PDF मिलती हैं, और एक मैनिफ़ेस्ट जो कहता है कि पहली + दो स्वीकार होनी चाहिए और तीसरी size_limit के कारण अस्वीकार। आपका टेस्ट तीन असर्शन + हाथ से लिखने के बजाय अपेक्षा पढ़ता है - और जब सीमा बदलती है तो आप एक संख्या बदलकर दोबारा चलाते + हैं। +

+

+ जब आप इनलाइन एक ही सीमा सेट चाहें तो यही प्रीसेट के बिना भी चलता है: +

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

सतत एकीकरण

+

फ़िक्स्चर को खोए बिना रिपॉज़िटरी से बाहर रखना

+

+ बड़े बाइनरी फ़िक्स्चर रिपॉज़िटरी क्लोन करना धीमा और रिव्यू करना कठिन बनाते हैं, और किसी एक के बदले + जाने पर कोई नहीं बता सकता कि क्या बदला। रेसिपी कुछ सौ अक्षरों की YAML है जो वही फ़ाइलें दोबारा + बना देती है - किसी भी मशीन पर बाइट-दर-बाइट - क्योंकि हर फ़ाइल रन के सीड से + निकलती है। +

+
- 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
+

+ हर अंत का अपना एग्ज़िट कोड है, इसलिए पाइपलाइन खराब रेसिपी, भरी डिस्क और सत्यापन असंगति में अंतर कर + सकती है। विफल रन स्टैंडर्ड आउटपुट पर कुछ नहीं छापता, जिससे लॉग पार्सर किसी त्रुटि को डेटा नहीं + पढ़ता। +

+
+ +
+

पैमाना

+

यह जानना कि फ़ोल्डर बड़ा होने पर क्या होता है

+

+ इंपोर्ट रूटीन, रात के जॉब और डायरेक्टरी सूचियाँ दस हज़ार फ़ाइलों पर दस की तुलना में अलग व्यवहार करती + हैं। किसी सीमा से निकाले गए आकार सेट को दस हज़ार एक जैसी फ़ाइलों के बजाय असली ट्रैफ़िक जैसा + दिखाते हैं, और निकालना सीड से होता है, इसलिए सेट कल भी वही रहता है। +

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

+ कुछ भी लिखे जाने से पहले देखें कि रन की क़ीमत क्या होगी, जो तब मायने रखता है जब कुल गीगाबाइट में + नापा जाए: +

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

+ डिस्क की खाली जगह से बड़ा रन पहला बाइट लिखे जाने से पहले ठुकरा दिया जाता है, डिस्क भरकर बीच में विफल + होने के बजाय। +

+
+ +
+

आर्काइव

+

ऐसे आर्काइव से अनपैकर का परीक्षण जिसमें सच में फ़ाइलें हैं

+

+ सही एक्सटेंशन वाला खाली आर्काइव उस कोड के बारे में कुछ साबित नहीं करता जो उसे खोलकर अंदर की चीज़ों + से गुज़रता है। सामग्री घोषित करें और आर्काइव सच में उसे रखता है: +

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

+ नेस्टिंग की गहराई, प्रविष्टियों की संख्या और अंदर की चीज़ों का आकार, ये सब वे बातें हैं जिन पर + इंपोर्ट रूटीन की अपनी राय होती है, और इसी तरह आप जानते हैं कि वह राय क्या है। +

+
+ +
+

पार्सर और व्यूअर

+

यह जाँचना कि आपका अपना कोड फ़ॉर्मैट को असली सॉफ़्टवेयर की तरह पढ़ता है

+

+ यहाँ का हर फ़ॉर्मैट भेजे जाने से पहले स्वतंत्र रीडर से जाँचा जाता है - PNG खोली जाती है और उसके + पिक्सेल मिलाए जाते हैं, DOCX अलग लाइब्रेरी से वापस पढ़ा जाता है, आर्काइव खोला जाता है। इसका मतलब + है कि जो फ़ाइल आपका पार्सर ठुकराता है वह आपके पार्सर के बारे में एक खोज है, जनरेटर के बारे में + नहीं। +

+
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
+

+ फ़ॉर्मैट पेज हर एक की स्वीकार की जाने वाली सेटिंग और हर एक की सबसे छोटी + संभव फ़ाइल सूचीबद्ध करता है। +

+
+ +
+

गाइड

+

इनमें से दो, विस्तार से

+ +
+ +
+

यह किसके लिए है

+

+ QA इंजीनियर, टेस्ट ऑटोमेशन और हर वह व्यक्ति जिसके कोड के पीछे अपलोड फ़ॉर्म, इंपोर्ट रूटीन, पार्सर या + स्टोरेज कोटा है। यह बिना किसी नेटवर्क की मशीन पर चलता है, जो बंद कॉर्पोरेट माहौल में मायने रखता + है जहाँ ब्राउज़र आधारित जनरेटर विकल्प नहीं होता। +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/id/ci.html b/web/content/id/ci.html new file mode 100644 index 00000000..71d4d301 --- /dev/null +++ b/web/content/id/ci.html @@ -0,0 +1,189 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cara membuat file uji di pipeline CI

+

+ Fixture biner di repositori tinggal selamanya dalam riwayatnya, tidak bisa ditinjau di diff, dan + menjadi mustahil ketika filenya besar. Buat file di dalam pipeline dari sebuah resep. Resep adalah + teks, byte keluar sama setiap kali, dan langkah terakhir membuktikan tidak ada yang bergeser. +

+ +
+

Jawaban singkat

+

+ Pasang tfg, jalankan tfg generate fixtures.yaml --out ./fixtures sebelum + tes dan tfg verify ./fixtures/manifest.json sesudahnya. Kedua langkah menggagalkan + build dengan sendirinya, dengan kode keluar yang menyebut alasannya. +

+
+ +
+

Mengapa tidak di-commit

+

Mengapa fixture tidak seharusnya tinggal di repositori

+ +

+ Yang di-commit adalah resepnya. Resep dan seed yang sama menulis byte yang sama di setiap mesin, + jadi file yang dibuat di pipeline adalah file yang Anda punya di laptop. +

+
+ +
+

Resep

+

Resep yang tinggal di samping tes

+

+ Resep ini menulis dua puluh lima faktur yang harus diterima dan dua gambar di atas batas yang harus + ditolak, dan manifes mencatat kedua harapan itu: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml memeriksanya tanpa menulis apa pun, dan menyebut semua + masalah sekaligus. +

+
+ +
+

GitHub Actions

+

Workflow yang memasang alat dan membangun fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Baris checksum membandingkan arsip dengan verify-SHA256SUMS.txt dari rilis yang sama. + Versinya dikunci, jadi rilis baru tidak pernah mengubah build yang tidak Anda sentuh. +

+
+ +
+

GitLab CI

+

Hal yang sama sebagai job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Saat berubah merah

+

Apa yang membuat sebuah langkah gagal, dan mengapa

+

+ Setiap akhir punya kode keluarnya sendiri, jadi langkah gagal dengan sendirinya dan log menyebut + yang mana. Yang dijumpai pipeline: +

+ +

+ Proses yang gagal tidak mencetak apa pun ke keluaran standar, sehingga parser log tidak pernah salah + mengira error sebagai data. Tabel lengkapnya ada di halaman + dokumentasi. +

+
+ +
+

PowerShell

+

Skrip PowerShell butuh satu baris lagi

+

+ PowerShell tidak membawa kode keluar sebuah program keluar dari file .ps1. Jalankan + satu dengan -File dan skrip menjawab 0 bahkan ketika alat di dalamnya + menolak pekerjaan, sehingga build yang seharusnya merah menjadi hijau. Baris terakhir adalah + seluruh perbaikannya: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Begitulah PowerShell bekerja, bukan sesuatu dari alat ini. cmd, bash, dan + zsh tidak butuh tambahan apa pun. +

+
+ +
+

Beberapa job

+

Berbagi fixture antar job

+

+ Biasanya tidak perlu mengunggahnya. Karena resep yang sama menulis byte yang sama, setiap job bisa + menjalankan tfg generate sendiri, yang lebih cepat daripada mengunggah lalu + mengunduh. Ketika sebuah job harus menerima file dari job lain, jalankan tfg verify + pada manifes setelah transfer, dan ia menyatakan apakah yang tiba sama dengan yang ditulis. +

+
+ +
+

Berikutnya

+

Ke mana dari sini

+ +
diff --git a/web/content/id/damage.html b/web/content/id/damage.html new file mode 100644 index 00000000..7922552b --- /dev/null +++ b/web/content/id/damage.html @@ -0,0 +1,174 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cara membuat file rusak untuk pengujian

+

+ Validator yang hanya pernah diberi file sehat belum benar-benar diuji. Inilah cara mendapatkan file + yang sengaja dirusak, keluar dengan tepat sebesar yang Anda minta, dan membawa + manifes yang menyatakan apa yang harus dilakukan sistem Anda terhadapnya. +

+ +
+

Jawaban singkat

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out menulis PNG + berukuran tepat 2097152 byte yang byte pertamanya nol, dan manifes di sebelahnya mencatat bahwa + sistem Anda harus menolaknya. +

+
+ +
+

Cara yang biasa

+

Mengapa file yang dirusak dengan tangan adalah tes yang buruk

+

+ Cara yang biasa adalah editor hex, skrip yang membalik beberapa byte acak, atau memotong file dengan + head atau truncate. Berhasil sekali, lalu merugikan Anda: +

+ +
+ +
+

Yang Anda dapatkan

+

File yang rusak tetap berukuran seperti yang Anda minta

+

+ File dibuat seperti biasa lalu dirusak, dalam perjalanan ke disk. Ukurannya tetap seperti yang Anda + minta, dan perintah yang sama menulis byte yang sama lagi. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Pengaturan ditulis setelah titik dua. Opsi ini bisa diulang, dan kerusakan diterapkan menurut urutan + yang Anda tulis. Berlaku untuk semua {{ .Facts.FormatCount }} format. +

+
+ +
+

Yang bisa dilakukan

+

Kerusakan apa saja yang ada?

+

+ Ini daftar yang dicetak program, dibaca darinya saat halaman ini dibangun. tfg damage + mencetak daftar yang sama, dan tfg damage <id> menjelaskan apa yang diterima + salah satunya. +

+ {{ template "damagesTable" . }} +

+ zero-head menulis nol di atas awal file. Sebagian besar pembaca melihat ke sana lebih + dulu, ke tanda pengenal dan header yang menyatakan file itu apa, jadi hampir semua pembaca + menyadarinya. Teks biasa dan log tidak punya tanda pengenal dan juga ditolak, karena deretan + byte nol bukan teks. Di bawah empat byte, sebagian format keluar dengan kerusakan yang tidak + dikeluhkan pembaca mana pun, itulah sebabnya pengaturan dimulai dari empat. +

+
+ +
+

Yang dikatakan manifes

+

Manifes yang menyatakan apa yang harus terjadi

+

+ Setiap file yang rusak mendapat catatan yang menyatakan sistem Anda harus menolaknya, dengan + kerusakannya dicatat di sampingnya: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dua permintaan ditolak sebelum apa pun ditulis, karena masing-masing akan meninggalkan file di disk + yang dijelaskan keliru oleh manifes: +

+ +
+ +
+

Dalam resep

+

File sehat dan rusak dalam satu proses

+

+ Taruh keduanya dalam satu resep, dan manifes membawa harapan setiap file, sehingga tes tidak butuh + daftar mana yang mana: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Dalam tes

+

Menjadikannya tes

+

+ Tes membaca manifes dan memeriksa bahwa yang terjadi sama dengan yang dinyatakan. Tidak perlu daftar + nama file: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Penolakan yang baik adalah penolakan yang bersih. Pesan yang menyebut apa yang salah adalah jawaban + yang Anda inginkan. Kesalahan server, macet, atau file yang tersimpan setengah adalah cacat yang + ingin ditemukan tes ini. +

+
+ +
+

Berikutnya

+

Ke mana dari sini

+ +
diff --git a/web/content/id/docs.html b/web/content/id/docs.html new file mode 100644 index 00000000..4b043388 --- /dev/null +++ b/web/content/id/docs.html @@ -0,0 +1,283 @@ +

Dokumentasi

+

+ Semua yang dilakukan alat ini, disusun sebagai pertanyaan yang benar-benar dibawa orang. + README di repositori adalah referensi lengkap dan selalu sesuai + dengan build yang Anda unduh. +

+ +
+

Perintah apa saja yang ada?

+

Masing-masing melakukan satu hal:

+ {{ template "commandList" . }} +
+ +
+

Bagaimana cara membuat satu file dengan ukuran tepat?

+

+ Sebutkan format, ukuran, dan tujuannya. Ukuran dihitung dalam kelipatan 1024, jadi 2mb + adalah 2097152 byte. Jumlah byte biasa juga bisa, jadi --size 10485761 meminta + persis sebanyak itu. +

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

Opsi yang berguna pada generate:

+
+ + + + + + + + + + + + + + + + + +
OpsiFungsinya
--format <id>format file, misalnya txt
--size <size>ukuran tepat setiap file, seperti 10mb atau jumlah byte biasa
--size-range <a-b>ukuran yang diundi per file dari suatu rentang, seperti 1kb-8kb. Undiannya berasal dari seed
--boundary <size>tiga file di sekitar batas: satu byte di bawah, batas itu sendiri, satu byte di atas
--count <n>berapa banyak file yang dibuat. Bawaan 1
--name <template>templat nama, misalnya invoice_{index:04}.txt
--out <dir>direktori tujuan penulisan
--seed <n>seed run. Seed yang sama menghasilkan byte yang sama
--set <k>=<v>pengaturan format, dapat diulang
--damage <name>merusak file dengan sengaja, dapat diulang dan diterapkan berurutan. Jalankan tfg damage untuk daftarnya
--expected <outcome>accept, reject, sanitize, atau unspecified
--dry-runmenghitung dan menampilkan, tidak menulis apa pun
--jsonmenulis manifes ke keluaran standar
+
+
+ +
+

Bagaimana membuat file yang sengaja dirusak?

+

+ Setiap file lain yang ditulis alat ini benar menurut konstruksinya, yang menjawab dua dari tiga + pertanyaan yang diajukan validator unggahan. --damage menjawab yang ketiga - apakah + file itu dapat dibuka sama sekali. File dibuat secara normal lalu dirusak, sehingga ukurannya + tetap seperti yang Anda minta. +

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

+ Pengaturan ditulis setelah titik dua. Opsinya dapat diulang, dan urutan penulisannya adalah urutan + penerapannya. tfg damage mendaftar apa yang bisa dilakukan build ini dan apa yang + diterima masing-masing. +

+

Dalam resep, kuncinya adalah daftar, berisi nama atau pengaturan:

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

+ File yang dirusak mendapat expected: reject di manifes, dengan kerusakan dicatat di + sampingnya. Dua hal ditolak sebelum apa pun ditulis, karena masing-masing akan menaruh file di + disk yang digambarkan manifes secara keliru: +

+ +

+ Yang ketiga tidak dapat diketahui sebelumnya. Bila suatu kerusakan berjalan dan tidak menggeser satu + byte pun, file itu dibuang alih-alih ditulis - run berlanjut, menyebut file mana itu, dan + berakhir dengan kode keluar parsial. +

+

+ Langkah demi langkah, dengan tes yang membaca manifes: cara membuat + file rusak untuk pengujian. +

+
+ +
+

Seperti apa bentuk sebuah resep?

+

+ Resep adalah file YAML yang menggambarkan satu run utuh. Commit di samping pengujian Anda dan + fixture berhenti menjadi biner di repositori Anda - siapa pun dapat membangunnya kembali, byte + demi byte, dari file berisi beberapa ratus karakter. +

+
# 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
+

+ Setiap target memerlukan tepat satu dari size, size-range, + boundary, atau contains. Dua adalah galat dan tidak ada juga galat. + Resep yang tidak valid menulis tidak ada file sama sekali dan melaporkan semua + masalah sekaligus, bukan hanya yang pertama, masing-masing menyebut pengaturan yang dimaksud. +

+
+ +
+

Bagaimana menyatakan apa yang harus dilakukan sistem saya terhadap sebuah file?

+

Bentuk pendek bila hasilnya sudah cukup, bentuk panjang bila alasannya penting:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Hasilnya adalah accept, reject, sanitize, dan + unspecified. Alasannya adalah daftar tertutup agar laporan dapat mengelompokkan + berdasarkan itu: 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, dan + size_zero. +

+

+ Alasan menyebut aturan yang berlaku, bukan putusannya. Itulah sebabnya alasan yang + sama dapat berada di bawah kedua hasil - file satu byte di bawah batas adalah + accept, dan aturan yang dimaksud tetap size_limit. +

+
+ +
+

Apa isi manifes?

+

+ Manifes ditulis di samping file pada akhir setiap run, termasuk run yang terhenti. Satu entri per + file: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 ditambahkan bila run berasal dari resep, dan preset dengan + overrides bila berasal dari preset, sehingga manifes selalu dapat ditelusuri ke apa + yang menghasilkannya. +

+

+ Setiap entri juga membawa target_id, id target dalam resep yang menghasilkan file, dan + summary.by_target menghitung file yang dihasilkan tiap target. Resep dengan + beberapa target dapat diperiksa target demi target tanpa membaca nama file. +

+
+ +
+

Apa itu preset?

+

+ Set file siap pakai yang menjawab pertanyaan pengujian umum, sehingga Anda tidak perlu merancang + setnya sendiri. Preset pada dasarnya resep biasa, dan eject mencetak resepnya agar + dapat Anda sunting dari sana. Setiap preset memiliki halamannya + sendiri berisi apa yang biasanya ditemukan, isi set, dan setiap pengaturan yang diterimanya. +

+ {{ template "presetsList" . }} +
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 memberi tahu berapa biaya set sebelum Anda membuatnya, dan menyatakan terus terang + bila sebuah angka adalah nilai sementara dari kami, bukan batas dari Anda. +

+
+ +
+

Apa arti kode keluar?

+

+ Setiap akhir punya kodenya sendiri, keluaran yang terbaca mesin masuk ke keluaran standar, dan run + yang gagal tidak mencetak apa pun di sana. Tabelnya adalah kontrak beku - mengubah arti sebuah + kode memerlukan kenaikan versi mayor. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Run yang dihentikan dengan Ctrl+C tetap meninggalkan manifes dan tidak pernah meninggalkan file yang + tertulis setengah, sehingga job yang dibatalkan masih dapat dibersihkan oleh yang berikutnya. +

+

+ Workflow siap pakai untuk GitHub Actions dan GitLab CI: cara membuat + file uji di pipeline CI. +

+
+ +
+

Apakah ada jendela desktop?

+

+ Ada, mesin yang sama dengan jendela di atasnya, untuk pengujian yang tidak diskripkan. Ini bukan + versi terpangkas: sebuah pengujian membandingkan kedua antarmuka kemampuan demi kemampuan, dan + apa pun yang hanya dapat dilakukan salah satunya harus dinyatakan dan dibenarkan alih-alih + diam-diam menyimpang. +

+

+ Layarnya adalah satu batch, preset, beberapa batch sekaligus, dan tentang. Jendela ini menunjukkan + biaya sebuah run sebelum menulis apa pun, melaporkan kemajuan selama berjalan, dan dapat + dibatalkan di tengah jalan tanpa meninggalkan file yang tertulis setengah. Jendela ini belum + membuka file resep - untuk saat ini resep urusan baris perintah, dan jendela membangun batch-nya + di formulir. +

+
diff --git a/web/content/id/exact-size.html b/web/content/id/exact-size.html new file mode 100644 index 00000000..b81ddd2a --- /dev/null +++ b/web/content/id/exact-size.html @@ -0,0 +1,147 @@ +

Cara membuat file dengan ukuran tepat

+

+ Setiap sistem punya perintah untuk itu, dan ketiganya ada di bawah. Perintah-perintah itu memberi + Anda file dengan jumlah byte yang tepat - dan untuk banyak pengujian itu sudah cukup. + Setiap perintah di halaman ini dijalankan sebelum dipublikasikan, di sistem + tempat perintah itu berada. +

+ +
+

Jawaban singkat

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Ukuran dalam byte, dan 10 MB yang + dihitung seperti pengelola file Anda menghitung adalah 10485760. +

+
+ +
+

Windows

+

fsutil, dan versi PowerShell yang tidak memerlukan tambahan apa pun

+

+ fsutil disertakan dengan Windows. Perintah ini menerima ukuran dalam + byte, jadi hitung dulu angkanya - 10 MB adalah 10485760, 100 MB adalah 104857600, 1 GB + adalah 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Diukur di Windows 11: berjalan dari prompt biasa dan tidak memerlukan prompt dengan hak istimewa, + dan file keluar tepat 10485760 byte. +

+

PowerShell dapat melakukan hal yang sama tanpa memanggil program lain, dan memahami satuan:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB di PowerShell berarti 10485760 byte, hitungan berbasis 1024 yang sama dengan yang + dipakai Explorer, sehingga kedua perintah di atas menghasilkan ukuran yang sama. +

+
+ +
+

Linux

+

dd, truncate, dan fallocate, dan perbedaan yang menjebak orang

+

dd adalah yang dikenal semua orang. Perintah ini benar-benar menulis byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate instan, dan di situlah jebakannya. Diukur di Alpine Linux, file melaporkan + 10485760 byte dan menempati nol blok - ini adalah sparse file. + Apa pun yang membacanya mendapat sepuluh megabyte nol, tetapi disk tidak pernah menyerahkan + ruangnya: +

+
truncate -s 10M test10mb.bin
+

+ Itu baik untuk menguji batas unggahan dan menyesatkan untuk menguji kuota disk. + fallocate adalah yang dipakai bila ruangnya harus nyata: +

+
fallocate -l 10M test10mb.bin
+

Dan bila isinya harus tak dapat dikompres, agar pengarsip tidak bisa memadatkannya kembali:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, yang bukan sparse, dan dua yang sudah Anda kenal

+

+ macOS menyertakan mkfile. Diukur di macOS 26.6.2: 10485760 byte dan 20480 blok, + sehingga ruangnya benar-benar dialokasikan, bukan dijanjikan: +

+
mkfile 10m test10mb.bin
+

dd dan truncate juga ada dan berperilaku seperti di Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Di mana ini berhenti berfungsi

+

File dengan ukuran yang benar bukan file dengan jenis yang benar

+

+ Semua di atas memberi Anda blok nol. Itu cukup bila yang diuji hanya melihat ukuran - batas + unggahan, kuota, transfer. Itu berhenti cukup begitu ada yang membuka file itu. +

+

+ Diukur, dan layak Anda coba sendiri: buat file 2 MB dengan fsutil, namai + photo.png, dan serahkan ke pustaka gambar. Pillow menjawab cannot identify + image file. Itu bukan PNG. Tidak pernah - hanya namanya yang berkata begitu. +

+

+ Itu lebih penting daripada kedengarannya, karena arah kegagalan pengujian itu + kemudian. Endpoint unggah Anda menolak file, pengujian Anda hijau, dan Anda + menyimpulkan batas ukuran berfungsi. Endpoint itu tidak menolaknya karena ukuran. Ia menolaknya + karena byte-nya bukan gambar, dan aturan yang ingin Anda uji tidak pernah tercapai. +

+ +
+ +
+

Jalan lainnya

+

File asli dari format itu, dengan ukuran persis seperti yang Anda minta

+

+ Inilah yang dilakukan Testing Files Generator. File itu adalah file asli dari formatnya - terbuka di + aplikasi yang memilikinya - dan berjumlah byte persis seperti yang Anda minta, sampai ke byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Minta ukuran yang tidak dapat dicapai suatu format dan Anda mendapat galat yang menyebut batas bawah + dan alasannya, tidak pernah file berukuran salah. Halaman format + mencantumkan setiap format beserta file terkecil yang dapat dibuatnya. +

+

Dan sebuah batas adalah tiga kasus uji, bukan satu, jadi alat ini membuat ketiganya:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Itu memberi Anda 10485759, 10485760, dan 10485761 byte, dan manifes yang menyatakan mana yang harus + diterima sistem Anda dan mana yang harus ditolak. Halaman kasus + penggunaan membahas itu dan empat pekerjaan lain yang untuknya alat ini dibuat. +

+ {{ template "downloadCta" . }} +
+ +
+

Jadi mana yang sebaiknya dipakai?

+ +

+ Keduanya ada di halaman ini karena keduanya benar sebagian waktu. Kesalahan yang perlu dihindari + adalah memakai yang pertama di tempat yang kedua dibutuhkan dan membaca pengujian hijau sebagai + bukti. +

+
diff --git a/web/content/id/faq.html b/web/content/id/faq.html new file mode 100644 index 00000000..65aad8cb --- /dev/null +++ b/web/content/id/faq.html @@ -0,0 +1,20 @@ +

Pertanyaan yang sering diajukan

+

+ Lisensi, privasi, reproduksibilitas, dan hal-hal yang diperiksa orang sebelum memasukkan generator + ke pipeline build. Bila pertanyaan Anda tidak ada di sini, pelacak + isu terbuka. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Masih menimbang?

+

+ Halaman kasus penggunaan menunjukkan pekerjaan yang untuknya + alat ini dibuat, dan halaman format mencantumkan setiap format beserta + file terkecil yang dapat dibuatnya. README di repositori adalah + referensi lengkap. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/id/formats.html b/web/content/id/formats.html new file mode 100644 index 00000000..dc4d0db7 --- /dev/null +++ b/web/content/id/formats.html @@ -0,0 +1,80 @@ +

{{ .Facts.FormatCount }} format file, masing-masing dibuat dengan ukuran tepat

+

+ Masing-masing adalah file asli dari format itu. File terbuka di aplikasi yang + memilikinya dan persis berjumlah byte yang Anda minta. Tidak ada yang berupa nol pengisi dengan + ekstensi yang ditempelkan. +

+ +{{ template "formatsTable" . }} + +
+

Arti kolom-kolom

+ +

+ Setiap format juga berulang sampai ke byte: resep dan seed yang sama menghasilkan file identik di + mesin mana pun, dan itulah yang membuat resep aman di-commit menggantikan fixture-nya. +

+
+ +
+

Pengaturan yang diterima setiap format

+

+ Sebagian besar format punya pengaturan sendiri - dimensi gambar, kualitas JPEG, jumlah halaman PDF, + baris dan kolom spreadsheet, berapa banyak entri di dalam arsip. Atur dengan --set + key=value di baris perintah, atau di bawah properties: dalam resep. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Nilai di luar yang diterima suatu pengaturan ditolak dengan pesan yang menyebut pengaturan, rentang + yang diizinkan, dan apa yang dipakai sebagai gantinya. Pengaturan yang tidak dikenal juga galat, + tidak pernah nilai bawaan diam-diam - salah ketik yang diterima diam-diam menghasilkan file + dengan pengaturan yang salah dan satu jam bertanya-tanya mengapa pengujian lolos padahal + seharusnya tidak. +

+

+ Jalankan tfg formats <id> untuk melihat persis apa yang diterima satu format pada + build yang Anda miliki. +

+
+ +
+

Arsip berisi file asli

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} dan {{ end }}{{ $c.ID }}{{ end }} + dapat diisi dengan entri alih-alih dibiarkan sebagai cangkang kosong. Arsip yang dihasilkan + benar-benar berisi dokumen yang diklaimnya, sehingga apa pun yang mengekstraknya selama + pengujian menemukan file asli di dalamnya. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/id/index.html b/web/content/id/index.html new file mode 100644 index 00000000..ef2ff794 --- /dev/null +++ b/web/content/id/index.html @@ -0,0 +1,198 @@ +
+
+

Buat file uji asli dengan ukuran tepat

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} format seluruhnya, dan setiap file + adalah file asli yang terbuka di aplikasi yang memilikinya, dengan ukuran persis seperti + yang Anda minta. Setiap run juga mencatat apa yang harus dilakukan aplikasi Anda + terhadap tiap file. Baris perintah dan jendela desktop, gratis dan open source, bekerja + sepenuhnya di mesin Anda. +

+ + {{ template "downloadCta" . }} +
+ +
+ Jendela desktop Testing Files Generator, siap menulis sekumpulan file uji +
Jendela desktop, siap menulis sekumpulan file. Mesin yang sama berjalan di balik baris perintah.
+
+
+ + + +
+

Masalahnya

+

Membuat satu file uji itu mudah. Membuat seribu yang tepat adalah bagian yang membosankan

+

Anda menguji perangkat lunak yang menerima file dari orang. Cepat atau lambat Anda memerlukan:

+ +

+ Itulah yang digantikan oleh alat ini. Dibuat untuk insinyur QA, otomasi pengujian, dan siapa pun + yang kodenya memiliki formulir unggah, rutinitas impor, parser, atau kuota penyimpanan di + baliknya. +

+
+ +
+

Apa yang membuatnya berbeda

+

Generator lain berhenti di byte. Alat ini menjawab apa yang sebenarnya ditanyakan pengujian Anda

+

+ Sebuah folder berisi file masih membuat Anda yang memutuskan apa yang seharusnya dibuktikan tiap + file. Setiap run di sini menulis manifest.json di samping file - daftar sederhana + semua yang dihasilkan, dan untuk tiap entri sebuah ekspektasi yang dinyatakan. +

+

Misalkan endpoint unggah Anda mengizinkan 1 MB. Mintalah tiga file yang berada di garis itu:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FileByteSistem Anda harusKarena
1mb_under_1b.pdf1048575menerimaberada di dalam batas
1mb_at_limit.pdf1048576menerimabatas itu sendiri diizinkan
1mb_over_1b.pdf1048577menolaksize_limit
+
+ +

Tiga file, tiga jawaban berbeda, dalam bentuk yang terbaca mesin. Pengujian Anda membaca manifes alih-alih Anda menulis asersi secara manual:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Bila jawabannya bergantung pada kebijakan Anda sendiri, manifes mengatakannya

+

+ Alat ini mencatat unspecified alih-alih mengarang ekspektasi. Generator yang menebak + menghasilkan kegagalan palsu, dan suite yang berteriak serigala akhirnya dimatikan. +

+
+
+ +
+

Preset

+

Pilih pertanyaannya, dapatkan seluruh setnya

+

+ Preset adalah set file uji yang dirancang di sekitar satu pertanyaan pengujian, sehingga Anda tidak + perlu mencari tahu file mana yang membuktikan apa. Masing-masing punya halaman yang menjelaskan + apa yang biasanya ditemukan, isi set, dan setiap pengaturan yang diterimanya. +

+ {{ template "presetsList" . }} +

Semua preset, dan hubungannya dengan resep

+
+ +
+

Mulai cepat

+

Tiga perintah untuk melihatnya bekerja

+
    +
  1. +

    Buat satu file

    +

    Satu PNG, tepat dua megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Buat banyak file

    +

    + Sepuluh ribu file log, masing-masing antara satu dan delapan kilobyte, dengan ukuran diundi dari + seed sehingga besok menghasilkan set yang sama. Beri setiap run direktorinya + sendiri - manifes adalah satu-satunya catatan tentang apa yang ditulis sebuah run, + sehingga alat ini menolak menulis manifes kedua di atasnya: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Periksa, lalu hapus

    +

    verify memberi tahu bahwa tidak ada yang bergeser. cleanup menghapus persis apa yang ditulis dan tidak lebih:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Ukuran dihitung dalam kelipatan 1024, seperti pengelola file Anda, jadi 2mb berarti + 2097152 byte. Jumlah byte biasa juga bisa. Dokumentasi membahas + resep, manifes, dan kode keluar. +

+
+ +
+

Yang Anda dapatkan

+

Dibuat untuk suite yang berjalan tanpa pengawasan

+ +
+ +
+

Unduh

+

Pilih build untuk sistem Anda

+

+ Ekstrak arsip dan jalankan. tfg adalah baris perintah dan tfg-gui adalah + jendela desktop. Tidak ada installer dan tidak ada yang perlu ditambahkan ke mesin Anda. +

+ {{ template "downloadsTable" . }} +
+

Apa yang ditandatangani, dan apa yang tidak

+

+ Unduhan Windows dan macOS ditandatangani, sehingga berjalan tanpa peringatan tentang pengembang tak + dikenal. Yang untuk Linux tidak, karena Linux desktop tidak punya padanan untuk + menandatanganinya. Setiap arsip tercantum di verify-SHA256SUMS.txt pada halaman + rilis, sehingga Anda dapat memeriksa apa yang Anda unduh. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/id/preset.html b/web/content/id/preset.html new file mode 100644 index 00000000..d11009e0 --- /dev/null +++ b/web/content/id/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Preset {{ .ID }} membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ +{{ if .Catches }} +
+

Apa yang biasanya ditemukan?

+ +
+{{ end }} + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show {{ .ID }}:

+
+ + + + + + + +
File{{ .Budget.Files }}
Target dalam resepnya{{ .Budget.Targets }}
Ukuran total{{ .Bytes }} B
Format{{ join .Budget.Formats ", " }}
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
DiharapkanArtiFile
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Apa yang dapat Anda ubah?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
PengaturanMenerimaBawaanFungsinya
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Nilai bawaan ini adalah nilai sementara dari kami, bukan nilai sistem Anda. Berikan nilai Anda sendiri.{{ end }}
+
+ {{- else }} +

Preset ini tidak memiliki pengaturan. Setnya sama setiap kali.

+ {{- end }} +
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/id/presets.html b/web/content/id/presets.html new file mode 100644 index 00000000..463669c5 --- /dev/null +++ b/web/content/id/presets.html @@ -0,0 +1,32 @@ +

Preset file uji, satu set untuk setiap pertanyaan pengujian

+

+ Preset adalah satu set lengkap file uji yang dirancang di sekitar satu pertanyaan, dengan manifes + yang menyatakan bagaimana sistem Anda harus bereaksi terhadap tiap file. Anda memilih pertanyaan, + alat membuat setnya. Setiap preset punya halamannya sendiri berisi apa yang biasanya ditemukan, + isi set, dan setiap pengaturan yang diterimanya. +

+ +{{ template "presetsList" . }} + +
+

Apa bedanya preset dengan resep?

+

+ Pada dasarnya tidak ada. Preset adalah resep yang ditulis alat untuk Anda dari beberapa pengaturan. + tfg preset eject mencetak resep itu agar dapat Anda simpan di samping pengujian dan + sunting, dan resep Anda sendiri dapat dibangun di atas preset dengan satu baris, extends: + preset: diikuti id-nya. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Bisakah saya memercayai nilai bawaan?

+

+ Untuk file, ya. Untuk angka yang hanya diketahui sistem Anda, seperti batas formulir unggah, nilai + bawaan adalah nilai sementara dari kami, dan alat menyatakannya setiap kali memakainya. Halaman + setiap preset menandai pengaturan itu, dan tfg preset show menyatakannya sebelum + apa pun ditulis. +

+
diff --git a/web/content/id/site.json b/web/content/id/site.json new file mode 100644 index 00000000..261fc605 --- /dev/null +++ b/web/content/id/site.json @@ -0,0 +1,328 @@ +{ + "code": "id", + "locale": "id_ID", + "name": "Bahasa Indonesia", + "dir": "id", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Beranda", + "title": "Generator File Uji untuk QA - Ukuran Tepat, {{ .Facts.FormatCount }} Format Asli", + "description": "Generator file uji gratis dan open source untuk QA. File PDF, DOCX, PNG, dan ZIP asli berukuran tepat, plus manifes tentang reaksi yang diharapkan dari sistem Anda." + }, + { + "key": "formats", + "slug": "format", + "nav": "Format", + "title": "{{ .Facts.FormatCount }} Format File yang Didukung - PDF, DOCX, PNG, ZIP, dan Lainnya", + "description": "Semua format file yang dihasilkan, file terkecil yang mungkin untuk tiap format, dan pengaturan yang diterimanya. Semua {{ .Facts.FormatCount }} terbuka di aplikasi aslinya." + }, + { + "key": "presets", + "slug": "preset", + "nav": "Preset", + "title": "Preset File Uji - Set Siap Pakai untuk QA", + "description": "Set file uji siap pakai, masing-masing menjawab satu pertanyaan pengujian: batas unggahan, nama file, enkoding, impor tabel, file kosong, dan validasi." + }, + { + "key": "docs", + "slug": "dokumentasi", + "nav": "Dokumentasi", + "title": "Dokumentasi - Perintah, Resep, Manifes, Kode Keluar", + "description": "Cara membuat file uji dari baris perintah atau resep YAML, isi manifes, dan arti setiap kode keluar saat alat ini berjalan di CI." + }, + { + "key": "use-cases", + "slug": "kasus-penggunaan", + "nav": "Kasus Penggunaan", + "title": "Kasus Penggunaan - Batas Unggahan, Fixture CI, Pengujian Massal", + "description": "Menguji batas ukuran unggahan, membuat fixture yang dapat direproduksi untuk CI, membuat sepuluh ribu file, dan mengisi arsip dengan isi sungguhan." + }, + { + "key": "exact-size", + "slug": "membuat-file-ukuran-tepat", + "nav": "Ukuran Tepat", + "title": "Cara Membuat File dengan Ukuran Tertentu - Windows, Linux, macOS", + "description": "fsutil, dd, truncate, dan mkfile, masing-masing diukur di sistemnya, dan mengapa file yang dibuat begitu bukan PDF atau PNG saat pengujian membutuhkannya." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - Pertanyaan tentang Membuat File Uji", + "description": "Apa bedanya dengan dd dan fsutil, apakah file aman di-commit, apakah hasil run sama byte demi byte, dan apa yang terjadi bila ukuran tak tercapai." + }, + { + "key": "damage", + "slug": "file-uji-rusak", + "nav": "File rusak", + "title": "File uji yang rusak - file rusak dengan ukuran tepat", + "description": "File yang sengaja dirusak, berukuran tepat, dengan manifes yang menyatakan sistem Anda harus menolaknya. Untuk menguji validasi unggahan dan parser.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "file-uji-di-ci", + "nav": "File uji di CI", + "title": "File uji di CI - GitHub Actions, GitLab CI, dan PowerShell", + "description": "Buat file uji di pipeline alih-alih meng-commit biner: workflow GitHub Actions, job GitLab, kode keluar, dan jebakan PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Lompat ke konten", + "navLabel": "Utama", + "langLabel": "Bahasa", + "breadcrumbHome": "Beranda", + "imageAlt": "Testing Files Generator - file uji asli dengan ukuran tepat, beserta manifes yang menyatakan bagaimana sistem Anda harus bereaksi terhadap tiap file", + "schemaDescription": "Generator file uji untuk QA yang gratis dan open source. Alat ini membuat file asli dalam {{ .Facts.FormatCount }} format dengan ukuran tepat dan menulis manifes yang menyatakan bagaimana sistem yang diuji harus bereaksi terhadap tiap file.", + "ctaDownload": "Unduh", + "ctaSource": "Lihat kode sumber", + "ctaNote": "Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.", + "colFormat": "Format", + "colName": "Nama", + "colExtension": "Ekstensi", + "colSmallest": "File terkecil", + "colFidelity": "Kelengkapan", + "colChecked": "Diperiksa dengan", + "colSetting": "Pengaturan", + "colAccepts": "Menerima", + "colSystem": "Sistem", + "colCli": "Baris perintah", + "colWindow": "Jendela desktop", + "noBinary": "belum ada biner", + "colCode": "Kode", + "colMeaning": "Arti", + "footerBlurb": "File uji untuk QA dengan ukuran tepat, beserta manifes yang menyatakan bagaimana sistem Anda harus bereaksi terhadap tiap file.", + "footerProject": "Proyek", + "footerSource": "Kode sumber di GitHub", + "footerReleases": "Unduhan", + "footerIssues": "Laporkan masalah", + "footerSupport": "Dukung proyek ini", + "footerPages": "Halaman", + "footerLicence": "Copyright (C) 2026 DonislawDev. Dirilis di bawah Lisensi Publik Umum GNU versi 3. File yang Anda buat adalah milik Anda - lisensi mencakup alatnya, bukan keluarannya.", + "footerPrivacy": "Situs ini tidak memuat font, skrip, atau pelacak dari mana pun. Situs ini tidak memasang cookie.", + "notFoundTitle": "Halaman itu tidak ada di sini", + "notFoundLead": "Alamat yang Anda ikuti tidak cocok dengan halaman mana pun di situs ini.", + "notFoundBack": "Ke beranda", + "read.format": "Format setiap file dalam set. Ini adalah opsi alat itu sendiri, dan preset hanya memberinya nilai bawaan.", + "readTakes.format": "id format dari halaman format", + "colDamage": "Kerusakan", + "colEffect": "Yang dilakukannya pada byte", + "colSettings": "Pengaturan", + "noSettings": "tidak ada" + }, + "endings": { + "0": "Semuanya berjalan.", + "1": "Kesalahan tak terduga di dalam alat.", + "2": "Perintah atau opsi salah.", + "3": "Resep tidak valid.", + "4": "Format tidak dapat melakukan yang diminta.", + "5": "Pembacaan atau penulisan gagal.", + "6": "Ruang disk tidak cukup.", + "7": "verify menemukan ketidakcocokan.", + "8": "Run selesai tetapi tidak semuanya dihasilkan.", + "130": "Dihentikan dengan Ctrl+C.", + "143": "Dihentikan oleh sinyal, seperti tampilan batas waktu CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Apakah file valid yang sekecil yang diizinkan format dapat lolos?", + "title": "Kosong dan minimal", + "pageTitle": "File Uji Valid Terkecil dan Kosong di Setiap Format", + "description": "File valid terkecil yang ditulis alat ini di setiap dari {{ .Facts.FormatCount }} formatnya, plus file kosong bila format mengizinkan, masing-masing dengan reaksi yang diharapkan.", + "catches": [ + "file valid yang ditolak karena terlalu kecil, ketika pemeriksaan menghitung byte alih-alih membacanya", + "file kosong yang membuat pembaca crash alih-alih dilaporkan", + "gambar selebar satu piksel yang membagi dengan nol dalam perjalanan ke thumbnail", + "penyimpanan yang membaca nol byte sebagai unggahan gagal dan terus mencoba ulang" + ], + "details": { + "formats": "Dari format apa set dibuat. Biarkan all untuk setiap format build ini, atau sebutkan format yang diterima sistem Anda." + } + }, + "filename-handling": { + "question": "Apakah sistem saya akan menyimpan, menampilkan, dan mengembalikan nama file yang tidak diduganya?", + "title": "Penanganan nama file", + "pageTitle": "Nama File Bermasalah untuk Pengujian - Unicode dan Panjang", + "description": "File dengan nama yang merusak unggahan dan penyimpanan: aksara lain dan emoji, pembalikan arah tulisan, karakter tak terlihat, sintaks shell dan SQL, batas panjang.", + "catches": [ + "nama yang tampak seperti nama lain di layar, di log, atau dalam daftar", + "nama yang dipotong, dipangkas, atau ditulis ulang antara unggahan dan penyimpanan", + "batas panjang yang dihitung dalam karakter padahal penyimpanan menghitung byte" + ], + "details": {} + }, + "size-boundaries": { + "question": "Apakah batas ukuran ditegakkan tepat di tempat batas itu dinyatakan?", + "title": "Batas ukuran", + "pageTitle": "Menguji Batas Ukuran Unggahan - File di Batas Tepat", + "description": "File satu byte di bawah, tepat di, dan satu byte di atas batas ukuran sistem Anda, plus langkah lebih lebar di kedua sisi, masing-masing ditandai apakah harus diterima.", + "catches": [ + "kesalahan selisih satu di batas", + "MB tertukar dengan MiB, yaitu 4,8 persen dan cukup untuk meloloskan file yang seharusnya tidak lolos", + "batas yang ditegakkan di browser dan tidak di server" + ], + "details": { + "limit": "Batas ukuran yang dinyatakan sistem Anda. Semua yang lain diukur dari sini.", + "spread": "Seberapa jauh menjangkau di kedua sisi batas, sebagai daftar ukuran." + } + }, + "tabular-import": { + "question": "Apakah impor tabel saya tahan terhadap apa yang diekspor alat sungguhan?", + "title": "Impor tabel", + "pageTitle": "File Uji Impor CSV dan Excel - Pemisah, Header", + "description": "CSV dengan pemisah lain, akhir baris CR LF, tanpa header, dan kutipan lain, tabel yang sangat lebar, buku kerja Excel, dan JSON dalam beberapa tata letak.", + "catches": [ + "file titik koma yang terbaca sebagai satu kolom, karena pemisah diasumsikan alih-alih dicari", + "file CRLF yang terpecah menjadi baris dengan baris kosong setelah masing-masing", + "tabel tanpa header yang baris data pertamanya termakan sebagai nama kolom", + "impor yang mempertahankan kolom yang bisa ditampilkan dan membuang sisanya tanpa kata", + "pembaca yang mengambil record JSON satu baris sekaligus dan berhenti di dokumen berindentasi pertama" + ], + "details": { + "rows": "Berapa banyak baris yang dimuat spreadsheet. File ditulis tepat pada ukuran sebanyak itu baris, sehingga anggaran di atas bergeser mengikuti nilai ini.", + "columns": "Berapa banyak kolom di setiap baris spreadsheet. Baris kali kolom memiliki batas atas, dan meminta melebihinya ditolak sebelum apa pun ditulis." + } + }, + "text-encoding": { + "question": "Apakah pembaca saya tahu enkoding suatu file, atau hanya menebak?", + "title": "Enkoding teks", + "pageTitle": "File Uji Enkoding Teks - UTF-8, UTF-16, BOM, CRLF", + "description": "Teks yang sama dalam UTF-8, UTF-16LE, dan UTF-16BE, dengan dan tanpa byte order mark, serta akhir baris CR LF dan LF, untuk menguji cara pembaca mendekode teks.", + "catches": [ + "pembaca yang mengasumsikan UTF-8 dan menampilkan file UTF-16 sebagai satu karakter dari tiga, atau sebagai deretan kotak", + "byte order mark terbaca sebagai isi, sehingga kolom pertama impor dimulai dengan tiga karakter asing", + "importer yang menebak enkoding dari byte pembuka dan menebak berbeda untuk file yang lebih panjang", + "file CRLF yang terpecah menjadi baris dengan baris kosong setelah masing-masing, atau carriage return yang tertinggal di kolom terakhir" + ], + "details": { + "sample": "Seberapa besar setiap file dalam set. UTF-16 menyimpan dua byte untuk setiap karakter, sehingga angka ganjil ditolak." + } + }, + "upload-validation": { + "question": "Apakah formulir unggah saya menerima yang seharusnya dan menolak sisanya?", + "title": "Validasi unggahan", + "pageTitle": "File Uji Validasi Unggahan - Tipe, Ukuran, dan Nama", + "description": "File untuk menguji formulir unggah: tipe yang diizinkan dan ditolak, isi yang tidak cocok dengan ekstensi, batas ukuran, nama berbahaya, dan unggahan massal.", + "catches": [ + "batas yang ditegakkan di browser dan tidak di server", + "file SVG atau HTML yang dikira gambar atau teks biasa, yang merupakan cara meloloskan skrip lewat formulir", + "file yang diperiksa dari ekstensinya dan tak pernah dibuka, sehingga PDF bernama .jpg lolos", + "formulir yang membaca seluruh isi ke memori sebelum melihat seberapa besar isinya", + "unggahan bernama PHOTO.JPG yang ditolak sementara photo.jpg diterima, atau sebaliknya", + "nama dengan spasi, tanda kurung, atau karakter di luar ASCII yang ditulis ke disk tanpa perubahan" + ], + "details": { + "limit": "Batas ukuran yang dinyatakan formulir unggah Anda. Set ini mengambil satu langkah di tiap sisinya - untuk file di setiap jarak, jalankan preset size-boundaries.", + "allow": "Tipe apa yang seharusnya diterima formulir Anda. Masing-masing menjadi file asli bertipe itu, dan menjadi kontrol positif bagi seluruh set.", + "deny": "Ekstensi apa yang seharusnya ditolak formulir Anda. Ekstensi yang tidak punya format di build ini tetap mendapat file bernama itu, berisi teks biasa.", + "far-over": "Seberapa jauh di atas batas file besar tunggal itu. Matikan bila menulis beberapa kali batas tidak sepadan dengan disknya.", + "bulk": "Berapa banyak file dalam unggahan massal. Nol membuang kelompok itu dari set sepenuhnya." + } + } + }, + "commands": { + "generate": "menghasilkan file, dari resep atau dari opsi", + "validate": "memeriksa resep tanpa menulis apa pun", + "verify": "memeriksa direktori terhadap manifes", + "cleanup": "menghapus file yang tercantum dalam manifes", + "recipe fmt": "mencetak resep dalam bentuk bakunya", + "preset": "membuat set file dari pertanyaan pengujian bernama", + "formats": "mendaftar format yang didukung build ini", + "damage": "mendaftar cara build ini dapat merusak file dengan sengaja", + "tool": "alat kecil untuk file yang sudah Anda miliki", + "version": "mencetak versi alat", + "license": "mencetak lisensi dan artinya bagi file yang dihasilkan" + }, + "outcomes": { + "accept": "Sistem Anda harus menerima file ini.", + "reject": "Sistem Anda harus menolak file ini.", + "sanitize": "Sistem Anda harus menerima file ini dan membersihkannya, misalnya dengan mengganti namanya.", + "unspecified": "Tergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda." + }, + "damages": { + "zero-head": "Menimpa byte pertama file dengan nol tanpa mengubah panjangnya. Sebagian besar pembaca melihat ke sana lebih dulu, jadi hampir semua hal menyadari kerusakan ini." + }, + "terms": { + "oracleNone": "tidak berlaku", + "int": "bilangan bulat apa pun", + "choice": "salah satu dari himpunan tetap", + "bool": "benar atau salah", + "size": "ukuran seperti 2mb", + "text": "teks", + "pixels": "piksel", + "paragraphs": "paragraf", + "rows": "baris", + "columns": "kolom", + "slides": "slide", + "hertz": "hertz", + "megapixels": "megapiksel", + "million cells": "juta sel", + "entries per second": "entri per detik", + "files": "file", + "sizes separated by commas": "ukuran dipisahkan koma", + "format ids separated by commas": "id format dipisahkan koma", + "format ids separated by commas, or all": "id format dipisahkan koma, atau all", + "extensions separated by commas": "ekstensi dipisahkan koma", + "the id of a format, as tfg formats lists them": "id sebuah format, seperti yang didaftar tfg formats", + "the password, in plain text": "kata sandi, dalam teks biasa", + "any text": "teks apa pun", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "tanggal seperti 2024-02-29 atau 2024-02-29T13:45:00+02:00, atau none" + }, + "faq": [ + { + "q": "Apa bedanya dengan dd, fsutil, atau truncate?", + "a": "Perintah itu memberi Anda file berukuran benar yang berisi kekosongan. File 2 MB bernama photo.png yang dibuat begitu bukanlah PNG, sehingga apa pun yang benar-benar mem-parsing-nya akan menolaknya karena alasan yang salah, dan pengujian Anda pun lolos karena alasan yang salah juga. Alat ini menghasilkan PNG asli berukuran tepat 2 MB yang terbuka di penampil gambar, dan disertai pernyataan tentang bagaimana sistem Anda harus memperlakukannya.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Apakah gratis, dan bisakah saya pakai di tempat kerja?", + "a": "Ya untuk keduanya. Dirilis di bawah GPL-3.0 dan tidak berbayar. Tidak ada akun, kunci lisensi, atau tingkat berbayar." + }, + { + "q": "Bisakah saya memakai file yang dihasilkan dalam produk closed source?", + "a": "Bisa. Lisensi mencakup kode alatnya, bukan apa yang dihasilkan alat itu. File, resep, dan manifes yang dihasilkan adalah keluaran, bukan karya turunan, sehingga Anda dapat meng-commit dan mendistribusikannya tanpa kewajiban apa pun." + }, + { + "q": "Apakah file yang dihasilkan berisi data pribadi sungguhan?", + "a": "Tidak. Semua isinya disintesis dari sebuah seed. Tidak ada dataset yang dibaca, tidak ada layanan yang dihubungi, dan tidak ada konten pihak ketiga yang disematkan. Perlakukan alamat e-mail yang dihasilkan sebagai tidak dapat dipakai, bukan sekadar belum dipakai, karena string acak apa pun bisa kebetulan sama dengan alamat sungguhan." + }, + { + "q": "Apakah saya akan mendapat file yang persis sama di mesin lain?", + "a": "Ya, byte demi byte, dengan resep dan seed yang sama. Proyek ini mengujinya pada setiap perubahan, dan melanggarnya memerlukan kenaikan versi mayor. Itulah yang memungkinkan Anda meng-commit resep kecil alih-alih fixture biner besar." + }, + { + "q": "Apakah memerlukan koneksi internet?", + "a": "Tidak pernah. Tidak ada telemetri, pemeriksaan pembaruan, atau klien cloud, dan biner baris perintah sama sekali tidak memiliki stack jaringan yang dikompilasi di dalamnya. Alat ini berjalan di mesin tanpa jaringan dan di lingkungan korporat yang tertutup." + }, + { + "q": "Apa yang terjadi bila saya meminta ukuran yang tidak dapat dicapai suatu format?", + "a": "Anda mendapat galat yang menyebut format, ukuran terkecilnya, alasan batas bawah itu, dan apa yang harus dilakukan sebagai gantinya, dan tidak ada file yang ditulis. Alat ini tidak pernah membulatkan ukuran secara diam-diam. Setiap batas bawah tercantum di halaman format.", + "code": "tfg formats png" + }, + { + "q": "Bisakah saya membuat file yang sengaja dirusak?", + "a": "Ya. Tambahkan --damage zero-head dan file keluar dengan ukuran tepat seperti yang diminta, dengan byte pertamanya ditimpa nol, sehingga pembaca menolaknya, dan manifes menyatakan sistem Anda harus menolaknya. Rinciannya ada di halaman tentang file uji yang rusak.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Format apa yang akan hadir berikutnya?", + "a": "7z, mp3, dan mp4. Saat ini {{ .Facts.FormatCount }} format bekerja dari ujung ke ujung." + }, + { + "q": "Di sistem apa saya bisa menjalankannya?", + "a": "Baris perintah berjalan di Windows dan Linux pada Intel maupun ARM, dan di Mac Apple Silicon. Jendela desktop disediakan untuk Windows di Intel, Linux di Intel, dan Mac Apple Silicon. Mac Intel tidak didukung dan tidak ada build untuknya." + }, + { + "q": "Apakah saya harus menginstal sesuatu?", + "a": "Tidak. Unduh arsip untuk sistem Anda, ekstrak, dan jalankan binernya. Tidak ada installer, tidak ada runtime yang harus ditambahkan, dan tidak ada dependensi yang harus diselesaikan. Bila Anda punya Go, satu perintah go install juga bisa.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Mengapa run atas ribuan file lebih lambat di Windows?", + "a": "Karena Windows membebankan lebih banyak untuk setiap path yang diperiksanya, dan perintah yang menelusuri ribuan file memeriksa ribuan path. Diukur di satu mesin dengan 3000 file berukuran 1 kB, verify memakan sekitar 0,9 detik di Windows dan sekitar 0,2 detik di Linux dalam container. Path keluaran yang lebih pendek memperkecil angka Windows, karena setiap folder di atas file ikut diperiksa." + } + ] +} diff --git a/web/content/id/use-cases.html b/web/content/id/use-cases.html new file mode 100644 index 00000000..23879563 --- /dev/null +++ b/web/content/id/use-cases.html @@ -0,0 +1,132 @@ +

Untuk apa orang memakainya

+

+ Lima pekerjaan yang muncul di hampir setiap proyek yang menerima file dari orang, dan perintah yang + melakukan masing-masing. Setiap contoh di bawah berjalan sebagaimana tertulis. +

+ +
+

Batas unggahan

+

Menguji apakah batas ukuran file ditegakkan di tempat yang dinyatakan

+

+ Sebuah batas adalah tiga kasus uji, bukan satu: tepat di bawah, tepat pada, dan tepat di atas. + Mendapatkannya secara manual berarti menghitung jumlah byte dan berharap tidak salah selisih + satu. Mintalah setnya: +

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

+ Anda mendapat tiga PDF asli berukuran 1048575, 1048576, dan 1048577 byte, serta manifes yang + menyatakan dua yang pertama harus diterima dan yang ketiga ditolak karena + size_limit. Pengujian Anda membaca ekspektasi alih-alih Anda menulis tiga asersi + secara manual - dan bila batas berubah, Anda mengganti satu angka dan menjalankan ulang. +

+

+ Hal yang sama berfungsi tanpa preset bila Anda menginginkan satu set batas inline: +

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

Integrasi berkelanjutan

+

Menjaga fixture di luar repositori tanpa kehilangannya

+

+ Fixture biner besar membuat repositori lambat di-clone dan sulit di-review, dan tak seorang pun tahu + apa yang berubah saat satu diganti. Resep adalah beberapa ratus karakter YAML yang membangun + ulang file identik - byte demi byte, di mesin mana pun - karena setiap file + diturunkan dari seed run. +

+
- 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
+

+ Setiap akhir punya kode keluarnya sendiri, sehingga pipeline dapat membedakan resep yang buruk dari + disk penuh dan dari ketidakcocokan verifikasi. Run yang gagal tidak mencetak apa pun di keluaran + standar, sehingga parser log tidak membaca galat sebagai data. +

+
+ +
+

Skala

+

Mencari tahu apa yang terjadi saat folder besar

+

+ Rutinitas impor, job malam, dan daftar direktori berperilaku berbeda pada sepuluh ribu file + dibanding sepuluh. Ukuran yang diundi dari suatu rentang membuat set tampak seperti lalu lintas + nyata alih-alih sepuluh ribu file identik, dan undiannya berasal dari seed, sehingga set itu + sama besok. +

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

+ Periksa berapa biaya sebuah run sebelum menulis apa pun, yang penting bila totalnya diukur dalam + gigabyte: +

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

+ Run yang lebih besar dari ruang kosong di disk ditolak sebelum byte pertama ditulis, alih-alih + memenuhi disk dan gagal di tengah jalan. +

+
+ +
+

Arsip

+

Menguji pengekstrak dengan arsip yang benar-benar berisi file

+

+ Arsip kosong dengan ekstensi yang tepat tidak membuktikan apa pun tentang kode yang membukanya dan + menelusuri isinya. Nyatakan isinya dan arsip benar-benar memuatnya: +

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

+ Kedalaman bersarang, jumlah entri, dan ukuran isinya adalah hal-hal yang dipersoalkan rutinitas + impor, dan begitulah cara Anda mengetahui apa persoalan itu. +

+
+ +
+

Parser dan penampil

+

Memeriksa bahwa kode Anda sendiri membaca format seperti perangkat lunak sungguhan

+

+ Setiap format di sini diperiksa dengan pembaca independen sebelum dirilis - PNG dibuka dan pikselnya + dibandingkan, DOCX dibaca kembali oleh pustaka terpisah, arsip diekstrak. Artinya file yang + ditolak parser Anda adalah temuan tentang parser Anda, bukan tentang 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
+

+ Halaman format mencantumkan pengaturan yang diterima tiap format dan file + terkecil yang dapat dibuat tiap format. +

+
+ +
+

Panduan

+

Dua di antaranya lebih rinci

+ +
+ +
+

Untuk siapa ini

+

+ Insinyur QA, otomasi pengujian, dan siapa pun yang kodenya memiliki formulir unggah, rutinitas + impor, parser, atau kuota penyimpanan di baliknya. Berjalan di mesin tanpa jaringan sama sekali, + yang penting di lingkungan korporat tertutup di mana generator berbasis browser bukan pilihan. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/it/ci.html b/web/content/it/ci.html new file mode 100644 index 00000000..4e064233 --- /dev/null +++ b/web/content/it/ci.html @@ -0,0 +1,192 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Come generare file di test in una pipeline CI

+

+ Una fixture binaria in un repository resta per sempre nella sua cronologia, non si può rivedere in + un diff e diventa impossibile quando il file è grande. Genera invece i file dentro la pipeline a + partire da una ricetta. La ricetta è testo, i byte escono uguali ogni volta e un ultimo passo + dimostra che nulla si è mosso. +

+ +
+

La risposta breve

+

+ Installa tfg, esegui tfg generate fixtures.yaml --out ./fixtures prima dei + test e tfg verify ./fixtures/manifest.json dopo. Entrambi i passi fanno fallire la + build da soli, con un codice di uscita che dice perché. +

+
+ +
+

Perché non committarli

+

Perché una fixture non deve stare nel repository

+ +

+ Quello da committare è la ricetta. La stessa ricetta con lo stesso seme scrive gli stessi byte su + ogni macchina, quindi il file generato nella pipeline è il file che avevi sul portatile. +

+
+ +
+

La ricetta

+

Una ricetta che vive accanto ai test

+

+ Questa scrive venticinque fatture che devono essere accettate e due immagini oltre un limite che + devono essere rifiutate, e il manifest registra entrambe le aspettative: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la controlla senza scrivere nulla e nomina tutti i problemi + in una volta. +

+
+ +
+

GitHub Actions

+

Un workflow che installa lo strumento e costruisce le fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La riga della somma di controllo confronta l'archivio con verify-SHA256SUMS.txt della + stessa versione. La versione è fissata, quindi una nuova versione non cambia mai una build che + non hai toccato. +

+
+ +
+

GitLab CI

+

Lo stesso come job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quando diventa rosso

+

Cosa fa fallire un passo, e perché

+

+ Ogni conclusione ha il suo codice di uscita, quindi il passo fallisce da solo e il log dice quale. + Quelli che incontra una pipeline: +

+ +

+ Un'esecuzione fallita non stampa nulla sullo standard output, così un parser di log non scambia mai + un errore per dati. La tabella completa è nella pagina della + documentazione. +

+
+ +
+

PowerShell

+

Uno script PowerShell richiede una riga in più

+

+ PowerShell non porta fuori da un file .ps1 il codice di uscita di un programma. + Eseguine uno con -File e lo script risponde 0 anche quando lo + strumento al suo interno ha rifiutato il lavoro, così una build che dovrebbe essere rossa + diventa verde. L'ultima riga è tutta la correzione: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ È così che si comporta PowerShell, non qualcosa di questo strumento. cmd, + bash e zsh non richiedono nulla di più. +

+
+ +
+

Più job

+

Condividere le fixture tra i job

+

+ Di solito non serve caricarle. Poiché la stessa ricetta scrive gli stessi byte, ogni job può + eseguire il proprio tfg generate, che è più rapido di un upload e di un download. + Quando un job deve ricevere file da un altro, esegui tfg verify sul manifest dopo + il trasferimento, e ti dice se ciò che è arrivato è ciò che è stato scritto. +

+
+ +
+

Avanti

+

Dove andare da qui

+ +
diff --git a/web/content/it/damage.html b/web/content/it/damage.html new file mode 100644 index 00000000..c6dd49fa --- /dev/null +++ b/web/content/it/damage.html @@ -0,0 +1,176 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Come creare un file corrotto per i test

+

+ Un validatore a cui sono stati mostrati solo file sani non è stato davvero testato. Ecco come + ottenere un file rotto di proposito, che esce con esattamente la dimensione + richiesta e porta un manifest che dice cosa il tuo sistema deve farne. +

+ +
+

La risposta breve

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out scrive un PNG di + esattamente 2097152 byte i cui primi byte sono zeri, e il manifest accanto registra che il tuo + sistema deve rifiutarlo. +

+
+ +
+

Il modo solito

+

Perché un file corrotto a mano è un cattivo test

+

+ I modi soliti sono un editor esadecimale, uno script che cambia qualche byte a caso o un file + accorciato con head o truncate. Funzionano una volta, poi costano: +

+ +
+ +
+

Cosa ottieni

+

Un file danneggiato ha ancora la dimensione richiesta

+

+ Il file viene generato normalmente e rotto dopo, mentre va verso il disco. Mantiene la dimensione + richiesta, e lo stesso comando riscrive gli stessi byte. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Le impostazioni vanno dopo i due punti. L'opzione si può ripetere, e i danni vengono applicati + nell'ordine in cui li scrivi. Funziona con ognuno dei {{ .Facts.FormatCount }} formati. +

+
+ +
+

Cosa sa fare

+

Quali danni ci sono?

+

+ Questa è la lista che il programma stampa, letta da lui quando si costruisce questa pagina. + tfg damage stampa la stessa, e tfg damage <id> dice cosa accetta + ciascuno. +

+ {{ template "damagesTable" . }} +

+ zero-head scrive zeri sull'inizio del file. La maggior parte dei lettori guarda prima + lì, la firma e l'intestazione che dicono cos'è il file, quindi quasi ogni lettore se ne accorge. + Il testo semplice e i log non hanno firma e vengono rifiutati lo stesso, perché una serie di + byte nulli non è testo. Sotto i quattro byte alcuni formati escono con un danno di cui nessun + lettore si lamenta, ed è per questo che l'impostazione parte da quattro. +

+
+ +
+

Cosa dice il manifest

+

Un manifest che dice cosa deve succedere

+

+ Ogni file danneggiato riceve una voce che dice che il tuo sistema deve rifiutarlo, con il danno + registrato accanto: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Due richieste vengono rifiutate prima che venga scritto qualcosa, perché ciascuna lascerebbe su + disco un file che il manifest descrive male: +

+ +
+ +
+

In una ricetta

+

File sani e rotti in una sola esecuzione

+

+ Metti entrambi in una ricetta, e il manifest porta l'aspettativa di ogni file, così il test non ha + bisogno di un elenco di quale sia quale: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In un test

+

Trasformarlo in un test

+

+ Il test legge il manifest e controlla che ciò che è successo sia ciò che era stato dichiarato. Non + ha bisogno di un elenco di nomi di file: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un buon rifiuto è un rifiuto pulito. Un messaggio che dice cosa non andava è la risposta che vuoi. + Un errore del server, un blocco o un file salvato a metà è il difetto che questo test esiste per + trovare. +

+
+ +
+

Avanti

+

Dove andare da qui

+ +
diff --git a/web/content/it/docs.html b/web/content/it/docs.html new file mode 100644 index 00000000..3c1d298f --- /dev/null +++ b/web/content/it/docs.html @@ -0,0 +1,281 @@ +

Documentazione

+

+ Tutto ciò che fa lo strumento, organizzato come le domande con cui le persone arrivano davvero. Il + README nel repository è il riferimento completo e corrisponde + sempre alla build che hai scaricato. +

+ +
+

Quali comandi esistono?

+

Ognuno fa una cosa sola:

+ {{ template "commandList" . }} +
+ +
+

Come genero un singolo file di dimensione esatta?

+

+ Indica il formato, la dimensione e la destinazione. Le dimensioni si contano a 1024, quindi + 2mb sono 2097152 byte. Funziona anche un semplice numero di byte, quindi + --size 10485761 chiede esattamente quel numero. +

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

Le opzioni utili di generate:

+
+ + + + + + + + + + + + + + + + + +
OpzioneCosa fa
--format <id>formato dei file, per esempio txt
--size <size>dimensione esatta di ogni file, come 10mb o un semplice numero di byte
--size-range <a-b>una dimensione estratta per file da un intervallo, come 1kb-8kb. L'estrazione viene dal seed
--boundary <size>tre file attorno a un limite: un byte sotto, il limite, un byte sopra
--count <n>quanti file produrre. Predefinito 1
--name <template>modello del nome, per esempio invoice_{index:04}.txt
--out <dir>directory in cui scrivere
--seed <n>seed dell'esecuzione. Lo stesso seed dà gli stessi byte
--set <k>=<v>un'impostazione di formato, ripetibile
--damage <name>rompere i file di proposito, ripetibile e applicato in ordine. Esegui tfg damage per l'elenco
--expected <outcome>accept, reject, sanitize oppure unspecified
--dry-runcontare e mostrare, senza scrivere assolutamente nulla
--jsonscrivere il manifest sullo standard output
+
+
+ +
+

Come faccio un file rotto di proposito?

+

+ Ogni altro file che questo strumento scrive è corretto per costruzione, il che risponde a due delle + tre domande che pone un validatore di upload. --damage risponde alla terza - il + file si apre, almeno. Il file viene prodotto normalmente e poi rotto, quindi ha ancora la + dimensione che hai chiesto. +

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

+ Le impostazioni vanno dopo i due punti. L'opzione si ripete, e l'ordine in cui le scrivi è l'ordine + in cui vengono applicate. tfg damage elenca cosa può fare questa versione e cosa + accetta ciascuno. +

+

In una ricetta la chiave è un elenco, di nomi o di impostazioni:

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

+ Un file danneggiato riceve expected: reject nel manifest, con il danno registrato + accanto. Due cose vengono rifiutate prima di scrivere qualsiasi cosa, perché ciascuna metterebbe + su disco un file che il manifest descrive in modo sbagliato: +

+ +

+ Una terza non si può sapere in anticipo. Se un danno viene eseguito e non sposta alcun byte, quel + file viene scartato invece di essere scritto - l'esecuzione prosegue, dice di quale file si + trattava e termina con il codice di uscita parziale. +

+

+ Passo dopo passo, con un test che legge il manifest: come + creare un file corrotto per i test. +

+
+ +
+

Che aspetto ha una ricetta?

+

+ Una ricetta è un file YAML che descrive un'intera esecuzione. Committala accanto ai tuoi test e le + fixture smettono di essere binari nel tuo repository - chiunque può ricostruirle, byte per byte, + da un file di poche centinaia di caratteri. +

+
# 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
+

+ Ogni target richiede esattamente una di queste chiavi: size, size-range, + boundary o contains. Due è un errore, e anche nessuna. Una ricetta non + valida scrive nessun file e segnala tutti i problemi insieme invece del solo + primo, ognuno con il nome dell'impostazione a cui si riferisce. +

+
+ +
+

Come dichiaro cosa deve fare il mio sistema con un file?

+

Forma breve quando basta l'esito, forma lunga quando conta il motivo:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Gli esiti sono accept, reject, sanitize e + unspecified. I motivi sono un elenco chiuso così un report può raggrupparli: + 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 e size_zero. +

+

+ Un motivo nomina la regola in gioco, non il verdetto. Ecco perché lo stesso motivo + può stare sotto l'uno o l'altro esito - un file un byte sotto un limite è accept, e + la regola in questione resta size_limit. +

+
+ +
+

Cosa c'è nel manifest?

+

+ Viene scritto accanto ai file alla fine di ogni esecuzione, compresa un'esecuzione interrotta. Una + voce per file: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Un recipe_hash viene aggiunto quando l'esecuzione viene da una ricetta, e + preset con overrides quando viene da un preset, così un manifest si + può sempre ricondurre a ciò che lo ha prodotto. +

+

+ Ogni voce porta anche target_id, l'id del target della ricetta che ha prodotto il file, + e summary.by_target conta i file a cui è arrivato ciascun target. Una ricetta con + più target si può quindi controllare target per target senza leggere i nomi dei file. +

+
+ +
+

Cos'è un preset?

+

+ Un set di file pronto che risponde a una domanda di test comune, così non devi progettare il set tu. + I preset sono ricette ordinarie sotto il cofano, e eject stampa la ricetta così + puoi modificarla da lì. Ogni preset ha una pagina tutta sua con cosa + trova di solito, cosa c'è nel set e ogni impostazione che accetta. +

+ {{ template "presetsList" . }} +
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 ti dice quanto costerebbe il set prima di costruirlo, e dice apertamente quando un + numero è un segnaposto nostro anziché un limite tuo. +

+
+ +
+

Cosa significano i codici di uscita?

+

+ Ogni conclusione ha il suo codice, l'output leggibile da macchina va sullo standard output, e + un'esecuzione fallita non vi stampa nulla. La tabella è un contratto congelato - cambiare il + significato di un codice richiede una versione maggiore. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Un'esecuzione fermata con Ctrl+C lascia comunque un manifest e non lascia mai un file scritto a + metà, così un job annullato può ancora essere ripulito dal successivo. +

+

+ Workflow pronti per GitHub Actions e GitLab CI: come generare file + di test in una pipeline CI. +

+
+ +
+

Esiste una finestra desktop?

+

+ Sì, lo stesso motore con una finestra sopra, per il test che non è automatizzato. Non è una versione + ridotta: un test confronta le due interfacce capacità per capacità, e tutto ciò che può fare + solo una delle due va dichiarato e giustificato invece di divergere in silenzio. +

+

+ Le schermate sono un lotto, i preset, più lotti insieme e Informazioni. Mostra quanto costerebbe + un'esecuzione prima di scrivere qualsiasi cosa, riporta l'avanzamento mentre gira e si può + annullare a metà senza lasciare un file scritto a metà. Non apre ancora un file di ricetta - per + ora le ricette sono una faccenda da riga di comando, e la finestra costruisce i suoi lotti nel + modulo. +

+
diff --git a/web/content/it/exact-size.html b/web/content/it/exact-size.html new file mode 100644 index 00000000..cea4e4d5 --- /dev/null +++ b/web/content/it/exact-size.html @@ -0,0 +1,145 @@ +

Come creare un file di dimensione esatta

+

+ Ogni sistema ha un comando per farlo, e tutti e tre sono qui sotto. Ti danno un file con esattamente + il numero giusto di byte - e per molti test è tutto ciò che serve. Ogni comando di questa + pagina è stato eseguito prima della pubblicazione, sul sistema a cui appartiene. +

+ +
+

La risposta breve

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Le dimensioni sono in byte, e 10 MB + contati come li conta il tuo file manager sono 10485760. +

+
+ +
+

Windows

+

fsutil, e una versione PowerShell che non richiede nulla di extra

+

+ fsutil è incluso in Windows. Prende la dimensione in byte, quindi + calcola prima il numero - 10 MB sono 10485760, 100 MB sono 104857600, 1 GB è 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Misurato su Windows 11: funziona da un prompt normale senza richiederne uno con privilegi elevati, e + il file esce di esattamente 10485760 byte. +

+

PowerShell può fare lo stesso senza chiamare un altro programma, e capisce le unità:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB in PowerShell significa 10485760 byte, lo stesso conteggio in base 1024 che usa + Esplora risorse, quindi i due comandi qui sopra producono la stessa dimensione. +

+
+ +
+

Linux

+

dd, truncate e fallocate, e la differenza che frega le persone

+

dd è quello che conoscono tutti. Scrive davvero i byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate è istantaneo, ed è questa la trappola. Misurato su Alpine Linux, il file + riporta 10485760 byte e occupa zero blocchi - è un file + sparso. Qualsiasi cosa lo legga ottiene dieci megabyte di zeri, ma il disco non ha mai + ceduto lo spazio: +

+
truncate -s 10M test10mb.bin
+

+ Va bene per testare un limite di upload ed è fuorviante per testare una quota di disco. + fallocate è quello da usare quando lo spazio deve essere reale: +

+
fallocate -l 10M test10mb.bin
+

E quando il contenuto deve essere incomprimibile, così un archiviatore non può ridurlo di nuovo:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, che non è sparso, e i due che conosci già

+

+ macOS include mkfile. Misurato su macOS 26.6.2: 10485760 byte e 20480 blocchi, quindi + lo spazio è davvero allocato invece che promesso: +

+
mkfile 10m test10mb.bin
+

Ci sono anche dd e truncate, e si comportano come su Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Dove questo smette di funzionare

+

Un file della dimensione giusta non è un file del tipo giusto

+

+ Tutto quanto sopra ti dà un blocco di zeri. Basta quando ciò che è sotto test guarda solo la + dimensione - un limite di upload, una quota, un trasferimento. Smette di bastare nel momento in + cui qualcosa apre il file. +

+

+ Misurato, e vale la pena provarlo di persona: crea un file da 2 MB con fsutil, chiamalo + photo.png e passalo a una libreria di immagini. Pillow risponde cannot + identify image file. Non è un PNG. Non lo è mai stato - lo diceva solo il nome. +

+

+ Conta più di quanto sembri, per via di come il test fallisce a quel punto. Il tuo + endpoint di upload rifiuta il file, il tuo test diventa verde e concludi che il limite di + dimensione funziona. Non lo ha rifiutato per la dimensione. Lo ha rifiutato perché i byte non + erano un'immagine, e la regola che volevi testare non è mai stata raggiunta. +

+ +
+ +
+

L'altra strada

+

Un file reale di quel formato, della dimensione esatta che hai chiesto

+

+ È ciò che fa Testing Files Generator. Il file è un vero file del suo formato - si apre nel programma + che gli appartiene - e ha l'esatto numero di byte che hai chiesto, al byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Chiedi una dimensione che un formato non può raggiungere e ottieni un errore che nomina il minimo e + il suo motivo, mai un file della dimensione sbagliata. La pagina dei + formati elenca ogni formato con il file più piccolo che può produrre. +

+

E un limite sono tre casi di test anziché uno, quindi lo strumento li costruisce tutti e tre:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Ti dà 10485759, 10485760 e 10485761 byte, e un manifest che dice quali il tuo sistema deve accettare + e quali rifiutare. La pagina dei casi d'uso ripercorre questo e + altri quattro compiti per cui è pensato. +

+ {{ template "downloadCta" . }} +
+ +
+

Quindi, quale usare?

+ +

+ Entrambi sono su questa pagina perché entrambi hanno ragione una parte del tempo. L'errore da + evitare è usare il primo dove serve il secondo e leggere il test verde come una prova. +

+
diff --git a/web/content/it/faq.html b/web/content/it/faq.html new file mode 100644 index 00000000..3fe6fe59 --- /dev/null +++ b/web/content/it/faq.html @@ -0,0 +1,20 @@ +

Domande frequenti

+

+ Licenza, privacy, riproducibilità e le cose che le persone controllano prima di mettere un + generatore in una pipeline di build. Se la tua domanda non c'è, il + tracker delle issue è aperto. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Ancora indeciso?

+

+ La pagina dei casi d'uso mostra i compiti per cui è pensato, e la + pagina dei formati elenca ogni formato con il file più piccolo che + può produrre. Il README nel repository è il riferimento + completo. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/it/formats.html b/web/content/it/formats.html new file mode 100644 index 00000000..37bd4a55 --- /dev/null +++ b/web/content/it/formats.html @@ -0,0 +1,82 @@ +

{{ .Facts.FormatCount }} formati di file, ognuno generato a una dimensione esatta

+

+ Ognuno è un file reale di quel formato. Si apre nel programma che gli appartiene ed + è esattamente il numero di byte che hai chiesto. Nessuno è riempimento di zeri con un'estensione + appiccicata. +

+ +{{ template "formatsTable" . }} + +
+

Cosa significano le colonne

+ +

+ Ogni formato si ripete anche al byte: la stessa ricetta e lo stesso seed producono file identici su + qualsiasi macchina, ed è ciò che rende sicuro committare una ricetta al posto delle fixture + stesse. +

+
+ +
+

Impostazioni che ogni formato accetta

+

+ La maggior parte dei formati ha impostazioni proprie - dimensioni dell'immagine, qualità JPEG, + numero di pagine PDF, righe e colonne di un foglio di calcolo, quante voci vanno dentro un + archivio. Impostale con --set key=value dalla riga di comando, o sotto + properties: in una ricetta. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Un valore fuori da ciò che un'impostazione accetta viene rifiutato con un messaggio che nomina + l'impostazione, l'intervallo consentito e cosa usare al suo posto. Anche un'impostazione + sconosciuta è un errore, mai un valore predefinito silenzioso - un refuso accettato in silenzio + dà un file con le impostazioni sbagliate e un'ora a chiedersi perché il test passa quando non + dovrebbe. +

+

+ Esegui tfg formats <id> per vedere esattamente cosa accetta un formato nella + build che hai. +

+
+ +
+

Gli archivi contengono file reali

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} e {{ end }}{{ $c.ID }}{{ end }} + possono essere riempiti di voci invece di restare un guscio vuoto. Un archivio generato contiene + davvero i documenti che dichiara di contenere, quindi qualsiasi cosa lo decomprima durante un + test trova file reali al suo interno. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/it/index.html b/web/content/it/index.html new file mode 100644 index 00000000..4be0a210 --- /dev/null +++ b/web/content/it/index.html @@ -0,0 +1,198 @@ +
+
+

Genera file di test reali della dimensione esatta

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formati in tutto, e ognuno è un file + reale che si apre nel programma che gli appartiene, di esattamente la dimensione che hai + chiesto. Ogni esecuzione annota anche cosa la tua applicazione deve fare con ogni file. + Riga di comando e finestra desktop, gratuito e open source, interamente sulla tua macchina. +

+ + {{ template "downloadCta" . }} +
+ +
+ La finestra desktop di Testing Files Generator, pronta a scrivere un lotto di file di test +
La finestra desktop, pronta a scrivere un lotto di file. Lo stesso motore gira dietro la riga di comando.
+
+
+ + + +
+

Il problema

+

Fare un file di test è facile. Fare i mille giusti è la parte noiosa

+

Stai testando software che accetta file dalle persone. Prima o poi ti servono:

+ +

+ È ciò che questo sostituisce. È pensato per ingegneri QA, automazione dei test e chiunque abbia + dietro al proprio codice un modulo di upload, una routine di importazione, un parser o una quota + di storage. +

+
+ +
+

Cosa lo rende diverso

+

Gli altri generatori si fermano ai byte. Questo risponde a ciò che il tuo test chiede davvero

+

+ Una cartella di file ti lascia ancora a decidere cosa dovrebbe dimostrare ciascuno. Ogni esecuzione + qui scrive un manifest.json accanto ai file - un semplice elenco di tutto ciò che è + stato prodotto e, per ogni voce, un'aspettativa dichiarata. +

+

Poniamo che il tuo endpoint di upload permetta 1 MB. Chiedi i tre file che stanno su quella linea:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FileByteIl tuo sistema devePerché
1mb_under_1b.pdf1048575accettareè dentro il limite
1mb_at_limit.pdf1048576accettareil limite stesso è consentito
1mb_over_1b.pdf1048577rifiutaresize_limit
+
+ +

Tre file, tre risposte diverse, in forma leggibile da macchina. Il tuo test legge il manifest invece che tu scriva le asserzioni a mano:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Dove la risposta dipende dalla tua politica, il manifest lo dice

+

+ Registra unspecified invece di inventare un'aspettativa. Un generatore che tira a + indovinare produce falsi fallimenti, e una suite che grida al lupo finisce spenta. +

+
+
+ +
+

Preset

+

Scegli la domanda, ottieni l'intero set

+

+ Un preset è un set di file di test progettato attorno a una domanda di test, così non devi capire tu + quali file dimostrano cosa. Ognuno ha una pagina che dice cosa trova di solito, cosa c'è nel set + e ogni impostazione che accetta. +

+ {{ template "presetsList" . }} +

Tutti i preset, e come si rapportano alle ricette

+
+ +
+

Guida rapida

+

Tre comandi per vederlo funzionare

+
    +
  1. +

    Crea un file

    +

    Un PNG, esattamente due megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Crea molti file

    +

    + Diecimila file di log, ciascuno tra uno e otto kilobyte, con le dimensioni estratte dal seed così + domani dà lo stesso set. Dai a ogni esecuzione la sua directory - il + manifest è l'unica traccia di ciò che un'esecuzione ha scritto, quindi lo strumento si + rifiuta di scriverne un secondo sopra: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Controllali, poi rimuovili

    +

    verify ti dice che nulla si è mosso. cleanup rimuove esattamente ciò che è stato scritto e nient'altro:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Le dimensioni si contano a 1024, come fa il tuo file manager, quindi 2mb significa + 2097152 byte. Funziona anche un semplice numero di byte. La + documentazione copre le ricette, il manifest e i codici di + uscita. +

+
+ +
+

Cosa ottieni

+

Costruito per una suite che gira senza supervisione

+ +
+ +
+

Download

+

Scegli la build per il tuo sistema

+

+ Decomprimi l'archivio ed eseguilo. tfg è la riga di comando e tfg-gui è la + finestra desktop. Non c'è un installer e nulla da aggiungere alla tua macchina. +

+ {{ template "downloadsTable" . }} +
+

Cosa è firmato e cosa no

+

+ I download per Windows e macOS sono firmati, quindi si avviano senza l'avviso di sviluppatore + sconosciuto. Quelli per Linux no, perché Linux desktop non ha un equivalente con cui firmarli. + Ogni archivio è elencato in verify-SHA256SUMS.txt nella pagina delle release, + così puoi controllare cosa hai scaricato. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/it/preset.html b/web/content/it/preset.html new file mode 100644 index 00000000..7153b122 --- /dev/null +++ b/web/content/it/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Il preset {{ .ID }} costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ +{{ if .Catches }} +
+

Cosa trova di solito?

+ +
+{{ end }} + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show {{ .ID }}:

+
+ + + + + + + +
File{{ .Budget.Files }}
Target nella sua ricetta{{ .Budget.Targets }}
Dimensione totale{{ .Bytes }} B
Formati{{ join .Budget.Formats ", " }}
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
AttesoSignificatoFile
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Cosa puoi cambiare?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
ImpostazioneAccettaPredefinitoCosa fa
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Questo valore predefinito è un nostro segnaposto, non il valore del tuo sistema. Passa il tuo.{{ end }}
+
+ {{- else }} +

Questo preset non ha impostazioni. Il set è lo stesso ogni volta.

+ {{- end }} +
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/it/presets.html b/web/content/it/presets.html new file mode 100644 index 00000000..5b07a59e --- /dev/null +++ b/web/content/it/presets.html @@ -0,0 +1,32 @@ +

Preset di file di test, un set per ogni domanda di test

+

+ Un preset è un intero set di file di test progettato attorno a una domanda, con un manifest che dice + come il tuo sistema deve reagire a ogni file. Scegli la domanda, lo strumento costruisce il set. + Ogni preset ha una pagina tutta sua con cosa trova di solito, cosa c'è nel set e ogni impostazione + che accetta. +

+ +{{ template "presetsList" . }} + +
+

In cosa un preset è diverso da una ricetta?

+

+ Sotto il cofano, in niente. Un preset è una ricetta che lo strumento scrive per te a partire da + poche impostazioni. tfg preset eject stampa quella ricetta così puoi tenerla + accanto ai tuoi test e modificarla, e una ricetta tua può basarsi su un preset con una riga, + extends: preset: seguito dal suo id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Posso fidarmi dei valori predefiniti?

+

+ Per i file, sì. Per un numero che solo il tuo sistema conosce, come il limite di un modulo di + upload, un valore predefinito è un nostro segnaposto, e lo strumento lo dice ogni volta che ne + usa uno. La pagina di ogni preset marca queste impostazioni, e tfg preset show lo + dice prima che venga scritto qualsiasi cosa. +

+
diff --git a/web/content/it/site.json b/web/content/it/site.json new file mode 100644 index 00000000..c8ab8ee8 --- /dev/null +++ b/web/content/it/site.json @@ -0,0 +1,328 @@ +{ + "code": "it", + "locale": "it_IT", + "name": "Italiano", + "dir": "it", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Home", + "title": "Generatore di file di test - dimensione esatta, {{ .Facts.FormatCount }} formati reali", + "description": "Generatore gratuito e open source di file di test per la QA. PDF, DOCX, PNG e ZIP reali della dimensione esatta, con un manifest su come il tuo sistema deve reagire." + }, + { + "key": "formats", + "slug": "formati", + "nav": "Formati", + "title": "{{ .Facts.FormatCount }} formati di file supportati - PDF, DOCX, PNG, ZIP e altri", + "description": "Tutti i formati che il generatore produce, il file più piccolo possibile per ciascuno e le impostazioni che accetta. Tutti i {{ .Facts.FormatCount }} si aprono nel loro programma." + }, + { + "key": "presets", + "slug": "preset", + "nav": "Preset", + "title": "Preset di file di test - set pronti per la QA", + "description": "Set pronti di file di test, ognuno risponde a una domanda: limiti di upload, nomi dei file, codifiche, importazione di tabelle, file vuoti e validazione." + }, + { + "key": "docs", + "slug": "documentazione", + "nav": "Documentazione", + "title": "Documentazione - comandi, ricette, manifest, codici di uscita", + "description": "Come generare file di test dalla riga di comando o con una ricetta YAML, cosa contiene il manifest e cosa significa ogni codice di uscita in CI." + }, + { + "key": "use-cases", + "slug": "casi-d-uso", + "nav": "Casi d'uso", + "title": "Casi d'uso - limiti di upload, fixture per la CI, test di massa", + "description": "Testare un limite di dimensione dell'upload, costruire fixture riproducibili per la CI, generare diecimila file e riempire archivi con contenuti reali." + }, + { + "key": "exact-size", + "slug": "creare-file-di-dimensione-esatta", + "nav": "Dimensione esatta", + "title": "Creare un file di dimensione esatta - Windows, Linux, macOS", + "description": "fsutil, dd, truncate e mkfile, ciascuno misurato sul proprio sistema, e perché un file fatto così non è un PDF né un PNG quando un test ne richiede uno." + }, + { + "key": "faq", + "slug": "domande-frequenti", + "nav": "FAQ", + "title": "FAQ - domande sulla generazione di file di test", + "description": "In cosa differisce da dd e fsutil, se i file si possono committare, se le esecuzioni si ripetono byte per byte e cosa succede quando una dimensione è irraggiungibile." + }, + { + "key": "damage", + "slug": "file-di-test-corrotti", + "nav": "File corrotti", + "title": "File di test corrotti - file rotti di dimensione esatta", + "description": "Un file rotto di proposito, della dimensione esatta, con un manifest che dice che il tuo sistema deve rifiutarlo. Per testare validazione degli upload e parser.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "file-di-test-in-ci", + "nav": "File di test in CI", + "title": "File di test in CI - GitHub Actions, GitLab CI e PowerShell", + "description": "Genera file di test nella pipeline invece di committare binari: workflow GitHub Actions, job GitLab, codici di uscita e la trappola di PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Vai al contenuto", + "navLabel": "Principale", + "langLabel": "Lingua", + "breadcrumbHome": "Home", + "imageAlt": "Testing Files Generator - file di test reali della dimensione esatta, con un manifest che dice come il tuo sistema deve reagire a ciascuno", + "schemaDescription": "Un generatore gratuito e open source di file di test per la QA. Produce file reali in {{ .Facts.FormatCount }} formati della dimensione esatta e scrive un manifest che dice come il sistema sotto test deve reagire a ciascuno.", + "ctaDownload": "Scarica", + "ctaSource": "Vedi il codice sorgente", + "ctaNote": "Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.", + "colFormat": "Formato", + "colName": "Nome", + "colExtension": "Estensione", + "colSmallest": "File più piccolo", + "colFidelity": "Fedeltà", + "colChecked": "Verificato con", + "colSetting": "Impostazione", + "colAccepts": "Accetta", + "colSystem": "Sistema", + "colCli": "Riga di comando", + "colWindow": "Finestra desktop", + "noBinary": "ancora nessun binario", + "colCode": "Codice", + "colMeaning": "Significato", + "footerBlurb": "File di test per la QA, della dimensione esatta, con un manifest che dice come il tuo sistema deve reagire a ciascuno.", + "footerProject": "Progetto", + "footerSource": "Codice su GitHub", + "footerReleases": "Download", + "footerIssues": "Segnala un problema", + "footerSupport": "Sostieni il progetto", + "footerPages": "Pagine", + "footerLicence": "Copyright (C) 2026 DonislawDev. Rilasciato sotto la GNU General Public License, versione 3. I file che generi sono tuoi - la licenza copre lo strumento, non il suo output.", + "footerPrivacy": "Questo sito non carica font, script o tracker da nessuna parte. Non imposta cookie.", + "notFoundTitle": "Questa pagina non esiste", + "notFoundLead": "L'indirizzo che hai seguito non corrisponde a nessuna pagina di questo sito.", + "notFoundBack": "Vai alla home", + "read.format": "Il formato di ogni file del set. È un'opzione dello strumento stesso, e il preset le dà solo un valore predefinito.", + "readTakes.format": "un id di formato dalla pagina dei formati", + "colDamage": "Danno", + "colEffect": "Cosa fa ai byte", + "colSettings": "Impostazioni", + "noSettings": "nessuna" + }, + "endings": { + "0": "Tutto ha funzionato.", + "1": "Un errore imprevisto dentro lo strumento.", + "2": "Comando od opzione errati.", + "3": "La ricetta non è valida.", + "4": "Il formato non può fare ciò che è stato chiesto.", + "5": "Una lettura o una scrittura è fallita.", + "6": "Spazio su disco insufficiente.", + "7": "verify ha trovato una discrepanza.", + "8": "L'esecuzione è terminata ma non tutto è stato prodotto.", + "130": "Interrotto con Ctrl+C.", + "143": "Fermato da un segnale, che è l'aspetto di un timeout della CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Un file valido e piccolo quanto il formato consente passa?", + "title": "Vuoto e minimo", + "pageTitle": "File di test validi minimi e vuoti in ogni formato", + "description": "Il file valido più piccolo che lo strumento scrive in ciascuno dei suoi {{ .Facts.FormatCount }} formati, più un file vuoto dove il formato lo permette, ognuno con la reazione attesa.", + "catches": [ + "un file valido respinto perché troppo piccolo, quando il controllo conta i byte invece di leggerli", + "un file vuoto che manda in crash il lettore invece di essere segnalato", + "un'immagine larga un pixel che divide per zero lungo la strada verso la miniatura", + "uno storage che legge zero byte come un upload fallito e continua a riprovare" + ], + "details": { + "formats": "Da quali formati è composto il set. Lascia all per tutti i formati di questa versione, oppure indica quelli che il tuo sistema accetta." + } + }, + "filename-handling": { + "question": "Il mio sistema salverà, mostrerà e restituirà un nome di file che non si aspettava?", + "title": "Gestione dei nomi di file", + "pageTitle": "Nomi di file problematici da testare - Unicode e lunghezza", + "description": "File con nomi che mettono in crisi upload e storage: altri alfabeti, emoji, inversione di direzione, caratteri invisibili, sintassi di shell e SQL, lunghezza.", + "catches": [ + "un nome che sembra un altro sullo schermo, in un log o in un elenco", + "un nome tagliato, accorciato o riscritto tra l'upload e il salvataggio", + "un limite di lunghezza contato in caratteri dove lo storage conta byte" + ], + "details": {} + }, + "size-boundaries": { + "question": "Un limite di dimensione viene applicato esattamente dove è dichiarato?", + "title": "Limiti di dimensione", + "pageTitle": "Testare un limite di dimensione dell'upload - file al limite", + "description": "File un byte sotto, esattamente al limite e un byte sopra il limite dichiarato dal tuo sistema, più passi più ampi ai due lati, ognuno marcato se va accettato.", + "catches": [ + "errori di uno in più o in meno al limite", + "MB confuso con MiB, che fa il 4,8 per cento e basta a far passare un file che non dovrebbe passare", + "un limite applicato nel browser e non sul server" + ], + "details": { + "limit": "Il limite di dimensione dichiarato dal tuo sistema. Tutto il resto si misura a partire da esso.", + "spread": "Fin dove spingersi ai due lati del limite, come elenco di dimensioni." + } + }, + "tabular-import": { + "question": "La mia importazione di tabelle regge a ciò che esportano gli strumenti reali?", + "title": "Importazione di tabelle", + "pageTitle": "File di test per importare CSV ed Excel - delimitatori", + "description": "CSV con altri delimitatori, fine riga CR LF, senza intestazione e con altre virgolette, una tabella molto larga, una cartella Excel e JSON in più layout.", + "catches": [ + "un file con punto e virgola letto come una sola colonna, perché il delimitatore è stato dato per scontato invece di cercarlo", + "un file CRLF diviso in righe con una riga vuota dopo ciascuna", + "una tabella senza intestazione la cui prima riga di dati viene mangiata come nomi di colonna", + "un'importazione che tiene le colonne che sa mostrare e scarta il resto senza dire nulla", + "un lettore che prende i record JSON una riga alla volta e si ferma al primo documento indentato" + ], + "details": { + "rows": "Quante righe contiene il foglio di calcolo. Viene scritto esattamente alla dimensione che occupano tante righe, quindi il budget qui sopra si sposta con questo valore.", + "columns": "Quante colonne ha ogni riga del foglio di calcolo. Righe per colonne ha un tetto, e chiedere oltre viene rifiutato prima di scrivere qualsiasi cosa." + } + }, + "text-encoding": { + "question": "Il mio lettore sa in quale codifica è un file, o tira a indovinare?", + "title": "Codifica del testo", + "pageTitle": "File di test per la codifica del testo - UTF-8, UTF-16, BOM, CRLF", + "description": "Lo stesso testo in UTF-8, UTF-16LE e UTF-16BE, con e senza byte order mark, e fine riga CR LF e LF, per testare come un lettore decodifica il testo.", + "catches": [ + "un lettore che presume UTF-8 e mostra un file UTF-16 con un carattere ogni tre, o come file di quadratini", + "un byte order mark letto come contenuto, così il primo campo di un'importazione inizia con tre caratteri estranei", + "un importatore che indovina la codifica dai primi byte e indovina in modo diverso con un file più lungo", + "un file CRLF diviso in righe con una riga vuota dopo ciascuna, o un ritorno a capo rimasto nell'ultimo campo" + ], + "details": { + "sample": "Quanto è grande ogni file del set. UTF-16 memorizza due byte per carattere, quindi un numero dispari viene rifiutato." + } + }, + "upload-validation": { + "question": "Il mio modulo di upload accetta ciò che deve e respinge il resto?", + "title": "Validazione dell'upload", + "pageTitle": "File di test per la validazione dell'upload - tipo e nome", + "description": "File per testare un modulo di upload: tipi consentiti e negati, contenuto che non corrisponde all'estensione, limite di dimensione, nomi ostili e upload di massa.", + "catches": [ + "un limite applicato nel browser e non sul server", + "un SVG o un HTML scambiato per un'immagine o per testo semplice, che è un modo per far passare uno script attraverso un modulo", + "un file controllato dall'estensione e mai aperto, così un PDF chiamato .jpg passa", + "un modulo che legge l'intero corpo in memoria prima di guardare quanto è grande", + "un upload chiamato PHOTO.JPG respinto dove photo.jpg viene accettato, o il contrario", + "un nome con spazi, parentesi o caratteri fuori dall'ASCII scritto su disco senza modifiche" + ], + "details": { + "limit": "Il limite di dimensione dichiarato dal tuo modulo di upload. Questo set fa un passo per lato - per un file a ogni distanza, esegui il preset size-boundaries.", + "allow": "Quali tipi il tuo modulo deve accettare. Ognuno diventa un file reale di quel tipo, e sono il controllo positivo dell'intero set.", + "deny": "Quali estensioni il tuo modulo deve respingere. Un'estensione per cui questa versione non ha un formato riceve comunque un file con quel nome, contenente testo semplice.", + "far-over": "Quanto oltre il limite arriva l'unico file grande. Disattivalo dove scrivere diverse volte il limite non vale il disco.", + "bulk": "Quanti file contiene l'upload di massa. Zero lascia del tutto fuori dal set quel gruppo." + } + } + }, + "commands": { + "generate": "produrre file, da una ricetta o da opzioni", + "validate": "controllare una ricetta senza scrivere nulla", + "verify": "controllare una directory rispetto a un manifest", + "cleanup": "rimuovere i file elencati da un manifest", + "recipe fmt": "stampare una ricetta nella sua forma normalizzata", + "preset": "costruire un set di file a partire da una domanda di test con nome", + "formats": "elencare i formati supportati da questa versione", + "damage": "elencare i modi in cui questa versione può rompere un file di proposito", + "tool": "piccole utilità per file che hai già", + "version": "stampare la versione dello strumento", + "license": "stampare la licenza e cosa significa per i file generati" + }, + "outcomes": { + "accept": "Il tuo sistema deve accettare il file.", + "reject": "Il tuo sistema deve rifiutare il file.", + "sanitize": "Il tuo sistema deve accettare il file e ripulirlo, per esempio rinominandolo.", + "unspecified": "Dipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi." + }, + "damages": { + "zero-head": "Sovrascrive con zeri i primi byte del file, lasciandone intatta la lunghezza. La maggior parte dei lettori guarda prima lì, quindi quasi tutto si accorge di questo danno." + }, + "terms": { + "oracleNone": "non applicabile", + "int": "qualsiasi numero intero", + "choice": "uno di un insieme fisso", + "bool": "vero o falso", + "size": "una dimensione come 2mb", + "text": "testo", + "pixels": "pixel", + "paragraphs": "paragrafi", + "rows": "righe", + "columns": "colonne", + "slides": "diapositive", + "hertz": "hertz", + "megapixels": "megapixel", + "million cells": "milioni di celle", + "entries per second": "voci al secondo", + "files": "file", + "sizes separated by commas": "dimensioni separate da virgole", + "format ids separated by commas": "id di formato separati da virgole", + "format ids separated by commas, or all": "id di formato separati da virgole, oppure all", + "extensions separated by commas": "estensioni separate da virgole", + "the id of a format, as tfg formats lists them": "l'id di un formato, come lo elenca tfg formats", + "the password, in plain text": "la password, in chiaro", + "any text": "qualsiasi testo", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "una data come 2024-02-29 o 2024-02-29T13:45:00+02:00, oppure none" + }, + "faq": [ + { + "q": "In cosa è diverso da dd, fsutil o truncate?", + "a": "Quei comandi ti danno un file della dimensione giusta pieno di niente. Un file da 2 MB chiamato photo.png fatto così non è un PNG, quindi qualsiasi cosa lo analizzi davvero lo rifiuta per il motivo sbagliato, e anche il tuo test passa per il motivo sbagliato. Questo produce un vero PNG di esattamente 2 MB che si apre in un visualizzatore di immagini, e arriva con una dichiarazione su come il tuo sistema deve trattarlo.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "È gratuito, e posso usarlo al lavoro?", + "a": "Sì a entrambe. È rilasciato sotto GPL-3.0 e non costa nulla. Non c'è un account, né una chiave di licenza, né un livello a pagamento." + }, + { + "q": "Posso usare i file generati in un prodotto closed source?", + "a": "Sì. La licenza copre il codice dello strumento, non ciò che lo strumento produce. File, ricette e manifest generati sono output e non opere derivate, quindi puoi committarli e distribuirli senza alcun obbligo." + }, + { + "q": "I file generati contengono dati personali reali?", + "a": "No. Tutto ciò che contengono è sintetizzato da un seed. Nessun dataset viene letto, nessun servizio viene contattato e nessun contenuto di terzi è incorporato. Considera un indirizzo e-mail generato inutilizzabile anziché inutilizzato, perché qualsiasi stringa casuale può coincidere per caso con uno reale." + }, + { + "q": "Otterrò esattamente gli stessi file su un'altra macchina?", + "a": "Sì, byte per byte, con la stessa ricetta e lo stesso seed. Il progetto lo verifica a ogni modifica, e romperlo richiede una versione maggiore. È ciò che ti permette di committare una piccola ricetta invece di grandi fixture binarie." + }, + { + "q": "Serve una connessione a internet?", + "a": "Mai. Non c'è telemetria, né controllo degli aggiornamenti, né client cloud, e il binario della riga di comando non ha alcuno stack di rete compilato al suo interno. Funziona su una macchina senza rete e in un ambiente aziendale chiuso." + }, + { + "q": "Cosa succede se chiedo una dimensione che un formato non può raggiungere?", + "a": "Ottieni un errore che nomina il formato, il minimo possibile, il motivo di quel limite inferiore e cosa fare invece, e nessun file viene scritto. Lo strumento non arrotonda mai una dimensione in silenzio. Ogni minimo è elencato nella pagina dei formati.", + "code": "tfg formats png" + }, + { + "q": "Posso generare un file deliberatamente rotto?", + "a": "Sì. Aggiungi --damage zero-head e il file esce con esattamente la dimensione richiesta, con i primi byte sovrascritti da zeri, così un lettore lo rifiuta, e il manifest dice che il tuo sistema deve rifiutarlo. I dettagli sono nella pagina sui file di test corrotti.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Quali formati arrivano dopo?", + "a": "7z, mp3 e mp4. Oggi {{ .Facts.FormatCount }} formati funzionano da un capo all'altro." + }, + { + "q": "Su quali sistemi posso eseguirlo?", + "a": "La riga di comando gira su Windows e Linux sia su Intel sia su ARM, e sui Mac con Apple Silicon. La finestra desktop è fornita per Windows su Intel, Linux su Intel e Mac con Apple Silicon. I Mac Intel non sono supportati e non viene compilato nulla per loro." + }, + { + "q": "Devo installare qualcosa?", + "a": "No. Scarica l'archivio per il tuo sistema, decomprimilo ed esegui il binario. Non c'è un installer, né un runtime da aggiungere, né una dipendenza da risolvere. Se hai Go, funziona anche un solo comando go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Perché un'esecuzione su migliaia di file è più lenta su Windows?", + "a": "Perché Windows fa pagare di più ogni percorso che esamina, e un comando che passa su migliaia di file esamina migliaia di percorsi. Misurato su una macchina con 3000 file da 1 kB, verify impiega circa 0,9 secondi su Windows e circa 0,2 secondi su Linux in un container. Un percorso di output più corto abbassa il valore di Windows, perché ogni cartella sopra i file fa parte di ciò che viene esaminato." + } + ] +} diff --git a/web/content/it/use-cases.html b/web/content/it/use-cases.html new file mode 100644 index 00000000..ed5130de --- /dev/null +++ b/web/content/it/use-cases.html @@ -0,0 +1,134 @@ +

A cosa lo usano le persone

+

+ Cinque compiti che ricorrono in quasi ogni progetto che accetta file dalle persone, e il comando che + esegue ciascuno. Ogni esempio qui sotto funziona così com'è scritto. +

+ +
+

Limiti di upload

+

Testare se un limite di dimensione dei file è applicato dove dice di esserlo

+

+ Un limite sono tre casi di test, non uno: appena sotto, esattamente sul limite e appena sopra. + Ottenerli a mano significa calcolare numeri di byte sperando di non sbagliare di uno. Chiedi + invece il set: +

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

+ Ottieni tre PDF reali da 1048575, 1048576 e 1048577 byte, e un manifest che dice che i primi due + vanno accettati e il terzo rifiutato per size_limit. Il tuo test legge + l'aspettativa invece che tu scriva tre asserzioni a mano - e quando il limite cambia, cambi un + numero e riesegui. +

+

+ Lo stesso funziona senza preset quando vuoi un singolo set di limiti in linea: +

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

Integrazione continua

+

Tenere le fixture fuori dal repository senza perderle

+

+ Grandi fixture binarie rendono un repository lento da clonare e scomodo da rivedere, e nessuno sa + dire cosa è cambiato quando una viene sostituita. Una ricetta è qualche centinaio di caratteri + di YAML che ricostruiscono i file identici - byte per byte, su qualsiasi + macchina - perché ogni file deriva dal seed dell'esecuzione. +

+
- 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
+

+ Ogni conclusione ha il suo codice di uscita, quindi una pipeline distingue una ricetta sbagliata da + un disco pieno e da una discrepanza di verifica. Un'esecuzione fallita non stampa nulla sullo + standard output, il che evita che un parser di log legga un errore come dato. +

+
+ +
+

Scala

+

Scoprire cosa succede quando la cartella è grande

+

+ Routine di importazione, job notturni ed elenchi di directory si comportano diversamente con + diecimila file che con dieci. Dimensioni estratte da un intervallo fanno sembrare il set + traffico reale anziché diecimila file identici, e l'estrazione viene dal seed, quindi il set è + lo stesso domani. +

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

+ Controlla quanto costerebbe un'esecuzione prima che scriva qualsiasi cosa, il che conta quando il + totale si misura in gigabyte: +

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

+ Un'esecuzione più grande dello spazio libero sul disco viene rifiutata prima che sia scritto il + primo byte, invece di riempire il disco e fallire a metà. +

+
+ +
+

Archivi

+

Testare un decompressore con un archivio che contiene davvero dei file

+

+ Un archivio vuoto con l'estensione giusta non dimostra nulla sul codice che lo apre e percorre ciò + che c'è dentro. Dichiara il contenuto e l'archivio lo contiene davvero: +

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

+ Profondità di annidamento, numero di voci e dimensione di ciò che c'è dentro sono tutte cose su cui + una routine di importazione ha opinioni, ed è così che scopri quali sono. +

+
+ +
+

Parser e visualizzatori

+

Verificare che il tuo codice legga un formato come fa il software reale

+

+ Ogni formato qui è verificato con un lettore indipendente prima del rilascio - un PNG viene aperto e + i suoi pixel confrontati, un DOCX viene riletto da librerie separate, un archivio viene + estratto. Ciò significa che un file che il tuo parser rifiuta è una scoperta sul tuo parser, non + sul generatore. +

+
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
+

+ La pagina dei formati elenca le impostazioni che ciascuno accetta e il + file più piccolo che ciascuno può essere. +

+
+ +
+

Guide

+

Due di questi più in dettaglio

+ +
+ +
+

Per chi è

+

+ Ingegneri QA, automazione dei test e chiunque abbia dietro al proprio codice un modulo di upload, + una routine di importazione, un parser o una quota di storage. Gira su una macchina senza alcuna + rete, il che conta in un ambiente aziendale chiuso dove un generatore basato su browser non è + un'opzione. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ja/ci.html b/web/content/ja/ci.html new file mode 100644 index 00000000..c27eb1f5 --- /dev/null +++ b/web/content/ja/ci.html @@ -0,0 +1,171 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

CIパイプラインでテストファイルを生成する方法

+

+ リポジトリ内のバイナリのフィクスチャは履歴に永遠に残り、diffでレビューできず、ファイルが大きくなると成り立たなくなります。代わりに、パイプラインの中でレシピからファイルを生成してください。レシピはテキストで、バイトは毎回同じになり、最後のステップで何も動いていないことを証明できます。 +

+ +
+

短い答え

+

+ tfgをインストールし、テストの前にtfg generate fixtures.yaml --out + ./fixturesを、テストの後にtfg verify + ./fixtures/manifest.jsonを実行します。どちらのステップも自らビルドを失敗させ、理由を示す終了コードを返します。 +

+
+ +
+

コミットしない理由

+

フィクスチャをリポジトリに置くべきでない理由

+ +

+ コミットするのはレシピです。同じレシピと同じシードは、どのマシンでも同じバイトを書き出すので、パイプラインで生成したファイルは、ノートPCで使っていたファイルと同じものです。 +

+
+ +
+

レシピ

+

テストの隣に置くレシピ

+

+ このレシピは、受け入れられるべき請求書を25件と、上限を超えて拒否されるべき画像を2枚書き出し、マニフェストが両方の期待を記録します。 +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yamlは何も書き込まずにレシピを検査し、すべての問題を一度に挙げます。 +

+
+ +
+

GitHub Actions

+

ツールをインストールしてフィクスチャを作るワークフロー

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ チェックサムの行は、アーカイブを同じリリースのverify-SHA256SUMS.txtと照合します。バージョンは固定されているので、新しいリリースが、手を付けていないビルドを変えることはありません。 +

+
+ +
+

GitLab CI

+

同じことをGitLabのジョブで

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

赤くなったとき

+

ステップを失敗させるものとその理由

+

+ 終わり方ごとに専用の終了コードがあるので、ステップは自ら失敗し、ログがどれかを示します。パイプラインが出会うのは次のものです。 +

+ +

+ 失敗した実行は標準出力に何も出力しないので、ログパーサーがエラーをデータと取り違えることはありません。表の全体はドキュメントのページにあります。 +

+
+ +
+

PowerShell

+

PowerShellのスクリプトにはもう1行必要です

+

+ PowerShellは、プログラムの終了コードを.ps1ファイルの外に持ち出しません。-Fileで実行すると、中のツールが作業を拒否した場合でもスクリプトは0を返し、赤になるはずのビルドが緑になります。最後の1行が修正のすべてです。 +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ これはPowerShellの挙動であり、このツールの話ではありません。cmd、bash、zshには余分な手当ては要りません。 +

+
+ +
+

複数のジョブ

+

ジョブ間でフィクスチャを共有する

+

+ たいていアップロードは不要です。同じレシピは同じバイトを書き出すので、各ジョブが自分でtfg + generateを実行でき、アップロードしてダウンロードするより速くなります。あるジョブが別のジョブからファイルを受け取る必要があるときは、転送の後にマニフェストに対してtfg + verifyを実行すると、届いたものが書き出されたものと同じかどうかが分かります。 +

+
+ +
+

次へ

+

ここからどこへ

+ +
diff --git a/web/content/ja/damage.html b/web/content/ja/damage.html new file mode 100644 index 00000000..445d6497 --- /dev/null +++ b/web/content/ja/damage.html @@ -0,0 +1,149 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

テスト用の破損ファイルを作る方法

+

+ 健全なファイルしか見せたことのない検証は、本当にはテストされていません。ここでは、意図的に壊してあり、求めたとおりのサイズで出てきて、システムがそれをどう扱うべきかを示すマニフェストを伴うファイルの作り方を説明します。 +

+ +
+

短い答え

+

+ tfg generate --format png --size 2mb --damage zero-head --out + ./outは、ちょうど2097152バイトで先頭のバイトがゼロのPNGを書き出し、隣のマニフェストにはシステムがそれを拒否すべきだと記録されます。 +

+
+ +
+

よくあるやり方

+

手作業で壊したファイルがよくないテストになる理由

+

+ よくあるのは、16進エディタ、いくつかのランダムなバイトを反転させるスクリプト、headやtruncateでファイルを短く切る方法です。一度は使えますが、あとで手間がかかります。 +

+ +
+ +
+

得られるもの

+

破損したファイルも、求めたサイズのままです

+

+ ファイルは通常どおり生成され、ディスクへ向かう途中で壊されます。求めたサイズは保たれ、同じコマンドは同じバイトをもう一度書き出します。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 設定はコロンの後ろに書きます。オプションは繰り返せて、破損は書いた順に適用されます。{{ .Facts.FormatCount }}種類すべての形式で使えます。 +

+
+ +
+

できること

+

どんな破損がありますか。

+

+ これはプログラムが出力する一覧で、このページを作るときにプログラムから読み取っています。tfg damageは同じ一覧を出力し、tfg damage + <id>はそのうちの1つが受け取る設定を示します。 +

+ {{ template "damagesTable" . }} +

+ zero-headはファイルの先頭をゼロで上書きします。ほとんどのリーダーはまずそこを見ます。ファイルが何であるかを示すシグネチャとヘッダーです。そのため、ほぼどのリーダーでも気づきます。プレーンテキストやログにはシグネチャがありませんが、これらも拒否されます。ゼロのバイトの連なりはテキストではないからです。4バイト未満では、どのリーダーも文句を言わない破損になる形式があります。設定が4から始まるのはそのためです。 +

+
+ +
+

マニフェストの内容

+

何が起こるべきかを示すマニフェスト

+

+ 破損したファイルにはそれぞれ、システムがそれを拒否すべきことを示す項目が付き、破損の内容がその横に記録されます。 +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 2種類のリクエストは、何かが書き込まれる前に拒否されます。どちらもマニフェストの記述が誤ったファイルをディスクに残してしまうからです。 +

+ +
+ +
+

レシピで

+

1回の実行に健全なファイルと壊れたファイルを

+

+ 両方を1つのレシピに入れると、マニフェストが各ファイルの期待を持つので、テストにどれがどれかの一覧は要りません。 +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

テストで

+

テストにする

+

+ テストはマニフェストを読み、起きたことが宣言どおりかどうかを確かめます。ファイル名の一覧は要りません。 +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ よい拒否は、きれいな拒否です。何が悪かったかを伝えるメッセージが、求めている答えです。サーバーエラー、ハング、書きかけで保存されたファイルは、このテストが見つけるために存在する欠陥です。 +

+
+ +
+

次へ

+

ここからどこへ

+ +
diff --git a/web/content/ja/docs.html b/web/content/ja/docs.html new file mode 100644 index 00000000..67268ea6 --- /dev/null +++ b/web/content/ja/docs.html @@ -0,0 +1,236 @@ +

ドキュメント

+

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

+ +
+

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

+

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

+ {{ template "commandList" . }} +
+ +
+

正確なサイズのファイルを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": "{{ .Facts.Version }}" },
+  "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がそのレシピを出力するので、そこから編集できます。各プリセットには、普通は何を見つけるか、セットの内容、受け付ける設定をまとめた専用ページがあります。 +

+ {{ template "presetsList" . }} +
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は、セットを作る前にかかるコストを伝え、数値があなたの制限ではなくこちらの仮の値である場合は、はっきりそう伝えます。 +

+
+ +
+

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

+

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

+ {{ template "exitCodesTable" . }} +
- 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つのインターフェースを機能ごとに比較しており、片方にしかできないことは、静かに食い違うのではなく、宣言して理由を示す必要があります。 +

+

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

+
diff --git a/web/content/ja/exact-size.html b/web/content/ja/exact-size.html new file mode 100644 index 00000000..16be0860 --- /dev/null +++ b/web/content/ja/exact-size.html @@ -0,0 +1,122 @@ +

正確なサイズのファイルを作る方法

+

+ どのOSにもそのためのコマンドがあり、3つとも以下に載せています。正確なバイト数のファイルが作れ、多くのテストではそれで十分です。このページのコマンドはすべて、公開前に対応するOS上で実行しました。 +

+ +
+

短い答え

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。サイズはバイトで指定し、ファイルマネージャーの数え方での10MBは10485760です。 +

+
+ +
+

Windows

+

fsutilと、追加不要のPowerShell版

+

+ fsutilはWindowsに付属しています。サイズはバイト単位で指定するため、先に数値を計算してください。10MBは10485760、100MBは104857600、1GBは1073741824です。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11で実測しました。通常のプロンプトから実行でき、管理者権限は不要で、ファイルはちょうど10485760バイトになります。 +

+

PowerShellは別のプログラムを呼び出さずに同じことができ、単位も理解します。

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShellの10MBは、エクスプローラーと同じ1024基準の数え方で10485760バイトを意味するため、上の2つのコマンドは同じサイズになります。 +

+
+ +
+

Linux

+

dd、truncate、fallocate、そして人がつまずく違い

+

ddは誰もが知っているコマンドです。実際にバイトを書き込みます。

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncateは一瞬で終わりますが、そこが落とし穴です。Alpine + Linuxで実測すると、ファイルは10485760バイトと報告されるのに、占有するのは0ブロックで、スパースファイルになっています。読み込むものには10メガバイトのゼロが返りますが、ディスクは領域を実際には確保していません。 +

+
truncate -s 10M test10mb.bin
+

+ アップロード制限のテストには問題ありませんが、ディスク容量の制限のテストでは誤解を招きます。領域が実際に必要なときはfallocateを使います。 +

+
fallocate -l 10M test10mb.bin
+

圧縮できない内容が必要で、アーカイバーが再び小さくできないようにしたいときは:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

スパースではないmkfileと、すでにご存じの2つ

+

+ macOSにはmkfileが付属しています。macOS + 26.6.2で実測したところ、10485760バイトで20480ブロックでした。領域は約束だけでなく実際に確保されています。 +

+
mkfile 10m test10mb.bin
+

ddとtruncateもあり、Linuxと同じように動作します。

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

これが通用しなくなる場所

+

正しいサイズのファイルは、正しい種類のファイルではありません

+

+ 上記はどれも、ゼロのかたまりを作ります。テスト対象がサイズだけを見る場合、たとえばアップロード制限、割り当て、転送なら、それで十分です。何かがそのファイルを開いた瞬間に、十分ではなくなります。 +

+

+ 実測しましたので、ぜひご自身でも試してください。fsutilで2MBのファイルを作り、photo.pngという名前を付けて、画像ライブラリに渡します。Pillowはcannot + identify image fileと答えます。それはPNGではありません。最初からそうではなく、名前がそう言っていただけです。 +

+

+ これは見た目以上に重要です。テストがどちらの向きで失敗するかが関わるからです。アップロードのエンドポイントがファイルを拒否し、テストが緑になり、サイズ制限は機能していると結論します。しかし、サイズが理由で拒否したのではありません。バイトが画像ではなかったから拒否したのであり、テストしたかったルールには届いていません。 +

+ +
+ +
+

もう1つの方法

+

その形式の本物のファイルを、要求したとおりのサイズで

+

+ これがTesting Files Generatorの役割です。ファイルはその形式の本物で、対応するソフトウェアで開け、要求したバイト数とぴったり一致します。 +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 形式が到達できないサイズを要求すると、下限とその理由を示すエラーが返り、サイズの違うファイルが作られることはありません。形式ページに、各形式と、生成できる最小のファイルを載せています。 +

+

そして制限は1つではなく3つのテストケースなので、ツールは3つとも作ります。

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 10485759、10485760、10485761バイトのファイルと、システムがどれを受け入れどれを拒否するべきかを示すマニフェストが得られます。利用例のページでは、これと、このツールが想定する他の4つの用途を紹介しています。 +

+ {{ template "downloadCta" . }} +
+ +
+

では、どちらを使うべきでしょうか。

+ +

+ どちらも状況によって正しいため、このページに両方載せています。避けるべき間違いは、後者が必要な場面で前者を使い、緑になったテストを証明と受け取ることです。 +

+
diff --git a/web/content/ja/faq.html b/web/content/ja/faq.html new file mode 100644 index 00000000..8c27f859 --- /dev/null +++ b/web/content/ja/faq.html @@ -0,0 +1,15 @@ +

よくある質問

+

+ ライセンス、プライバシー、再現性、そして生成ツールをビルドパイプラインに組み込む前に人々が確認すること。質問がここにない場合は、イシュートラッカーをご利用ください。 +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

まだ迷っていますか。

+

+ 利用例のページでは、このツールが想定する用途を、形式ページでは、各形式と生成できる最小のファイルを紹介しています。リポジトリのREADMEが完全なリファレンスです。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ja/formats.html b/web/content/ja/formats.html new file mode 100644 index 00000000..cc1b6eb7 --- /dev/null +++ b/web/content/ja/formats.html @@ -0,0 +1,64 @@ +

{{ .Facts.FormatCount }}種類のファイル形式、どれも正確なサイズで生成

+

+ どれもその形式の本物のファイルです。対応するソフトウェアで開け、要求したバイト数とぴったり一致します。拡張子を貼り付けただけのゼロ埋めはひとつもありません。 +

+ +{{ template "formatsTable" . }} + +
+

各列の意味

+ +

+ どの形式もバイト単位で再現できます。同じレシピとシードなら、どのマシンでも同じファイルが生成されるため、フィクスチャ自体の代わりにレシピをコミットしても安全です。 +

+
+ +
+

形式ごとに受け付ける設定

+

+ ほとんどの形式には固有の設定があります。画像のサイズ、JPEGの品質、PDFのページ数、スプレッドシートの行数と列数、アーカイブに入れるエントリ数など。コマンドラインでは--set + key=value、レシピではproperties:の下で設定します。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ 設定が受け付ける範囲外の値は、設定名、許可される範囲、代わりに使うものを示すメッセージとともに拒否されます。未知の設定もエラーで、黙って既定値になることはありません。黙って受け入れられた打ち間違いは、設定の誤ったファイルを生み、通るはずのないテストがなぜ通るのかと悩む1時間を生みます。 +

+

+ tfg formats <id>を実行すると、お使いのビルドで1つの形式が受け付ける内容を正確に確認できます。 +

+
+ +
+

アーカイブには本物のファイルが入ります

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }}と{{ end }}{{ $c.ID }}{{ end }}は、空の殻のままではなく、エントリで満たせます。生成されたアーカイブは、含むと言っているドキュメントを実際に含むため、テスト中にそれを展開するものは、中に本物のファイルを見つけます。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/ja/index.html b/web/content/ja/index.html new file mode 100644 index 00000000..115dd728 --- /dev/null +++ b/web/content/ja/index.html @@ -0,0 +1,178 @@ +
+
+

正確なサイズの本物のテストファイルを生成

+

+ PDF、PNG、DOCX、ZIPなど、全{{ .Facts.FormatCount }}種類の形式に対応し、どれも対応するソフトウェアで開ける本物のファイルで、サイズは要求したとおりちょうどです。各実行では、アプリが各ファイルをどう扱うべきかも書き出します。コマンドラインとデスクトップウィンドウの両方に対応し、無料のオープンソースで、すべてあなたのマシン上で動きます。 +

+ + {{ template "downloadCta" . }} +
+ +
+ テストファイルのバッチを書き出す準備ができたTesting Files Generatorのデスクトップウィンドウ +
ファイルのバッチを書き出す準備ができたデスクトップウィンドウ。コマンドラインの裏でも同じエンジンが動いています。
+
+
+ + + +
+

課題

+

テストファイルを1つ作るのは簡単です。適切な1000個を作るのが面倒な部分です

+

あなたは、人からファイルを受け取るソフトウェアをテストしています。遅かれ早かれ、次のものが必要になります。

+ +

+ これが置き換える対象です。QAエンジニア、テスト自動化、そしてコードの先にアップロードフォーム、取り込み処理、パーサー、ストレージの割り当てがあるすべての人のために作られています。 +

+
+ +
+

他とどう違うか

+

他の生成ツールはバイトで終わります。これは、あなたのテストが本当に問うことに答えます

+

+ ファイルが入ったフォルダーだけでは、各ファイルが何を証明すべきかを自分で決めることになります。ここでは実行のたびに、ファイルの横にmanifest.jsonを書き出します。生成物の単純な一覧で、各項目に宣言された期待値が付きます。 +

+

アップロードのエンドポイントが1MBまでを許可するとします。その線上にある3つのファイルを要求します。

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ファイルバイトシステムの対応理由
1mb_under_1b.pdf1048575受け入れる制限の内側にあるため
1mb_at_limit.pdf1048576受け入れる制限値ちょうどは許可されるため
1mb_over_1b.pdf1048577拒否するsize_limit
+
+ +

3つのファイル、3つの異なる答えを、機械可読な形で示します。アサーションを手書きする代わりに、テストがマニフェストを読みます。

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

答えが自分たちのポリシー次第の場合、マニフェストはそう述べます

+

+ 期待値をでっち上げず、unspecifiedと記録します。推測する生成ツールは誤検出を生み、狼少年のようなテストスイートは最終的に無効にされます。 +

+
+
+ +
+

プリセット

+

疑問を選べば、セット一式が手に入ります

+

+ プリセットは、1つのテストの疑問を軸に設計したテストファイルのセットです。どのファイルが何を証明するのかを自分で考える必要はありません。それぞれに、普通は何を見つけるか、セットの内容、受け付ける設定をまとめたページがあります。 +

+ {{ template "presetsList" . }} +

すべてのプリセットと、レシピとの関係

+
+ +
+

クイックスタート

+

動作を確かめる3つのコマンド

+
    +
  1. +

    ファイルを1つ作る

    +

    PNGを1つ、ちょうど2メガバイトで:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    たくさんのファイルを作る

    +

    + 1KBから8KBの間で、シードから決めたサイズのログファイルを1万個。明日も同じセットになります。実行ごとに専用のディレクトリを使ってください。マニフェストは実行が書いた内容の唯一の記録なので、ツールはその上に2つ目を書くことを拒否します。 +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    検証してから削除する

    +

    verifyは何も動いていないことを伝えます。cleanupは書き込まれたものだけを正確に削除します。

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ サイズはファイルマネージャーと同じく1024単位で数えるため、2mbは2097152バイトです。バイト数をそのまま指定することもできます。ドキュメントで、レシピ、マニフェスト、終了コードを説明しています。 +

+
+ +
+

得られるもの

+

無人で動くテストスイートのために作られています

+ +
+ +
+

ダウンロード

+

お使いのOS向けのビルドを選んでください

+

+ アーカイブを展開して実行します。tfgがコマンドライン、tfg-guiがデスクトップウィンドウです。インストーラーはなく、マシンに追加するものもありません。 +

+ {{ template "downloadsTable" . }} +
+

署名済みのものと、そうでないもの

+

+ WindowsとmacOS向けのダウンロードは署名されているため、未確認の開発元という警告なしで起動します。Linux向けは、デスクトップLinuxに署名できる仕組みがないため署名されていません。すべてのアーカイブはリリースページのverify-SHA256SUMS.txtに載っているので、ダウンロードしたものを確認できます。 +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/ja/preset.html b/web/content/ja/preset.html new file mode 100644 index 00000000..d7a70161 --- /dev/null +++ b/web/content/ja/preset.html @@ -0,0 +1,89 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }}プリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ +{{ if .Catches }} +
+

普通は何を見つけますか。

+ +
+{{ end }} + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show {{ .ID }}が報告するとおりです。

+
+ + + + + + + +
ファイル数{{ .Budget.Files }}
レシピ内のターゲット数{{ .Budget.Targets }}
合計サイズ{{ .Bytes }} B
形式{{ join .Budget.Formats ", " }}
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
期待意味ファイル数
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

何を変更できますか。

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
設定値既定値動作
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} この既定値はこちらの仮の値で、あなたのシステムの値ではありません。ご自身の値を指定してください。{{ end }}
+
+ {{- else }} +

このプリセットに設定はありません。セットは毎回同じです。

+ {{- end }} +
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/ja/presets.html b/web/content/ja/presets.html new file mode 100644 index 00000000..9f2754cf --- /dev/null +++ b/web/content/ja/presets.html @@ -0,0 +1,26 @@ +

テストファイルのプリセット、テストの疑問ごとに1セット

+

+ プリセットは、1つの疑問を軸に設計したテストファイルのセット一式で、システムが各ファイルにどう反応すべきかを示すマニフェストが付きます。疑問を選べば、ツールがセットを作ります。各プリセットには、普通は何を見つけるか、セットの内容、受け付ける設定をまとめた専用ページがあります。 +

+ +{{ template "presetsList" . }} + +
+

プリセットとレシピは何が違いますか。

+

+ 中身は同じです。プリセットは、いくつかの設定からツールが書くレシピです。tfg preset + ejectはそのレシピを出力するので、テストの隣に保管して編集できます。また、自分のレシピはextends: + preset:にIDを続けた1行で、プリセットを土台にできます。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

既定値は信頼できますか。

+

+ ファイルについては信頼できます。アップロードフォームの制限のように、システムだけが知っている数値については、既定値はこちらの仮の値で、ツールは使うたびにそう伝えます。各プリセットのページはそれらの設定に印を付け、tfg + preset showは何かを書き込む前に伝えます。 +

+
diff --git a/web/content/ja/site.json b/web/content/ja/site.json new file mode 100644 index 00000000..ee9a8752 --- /dev/null +++ b/web/content/ja/site.json @@ -0,0 +1,328 @@ +{ + "code": "ja", + "locale": "ja_JP", + "name": "日本語", + "dir": "ja", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "ホーム", + "title": "テストファイル生成ツール - 正確なサイズ、{{ .Facts.FormatCount }}種類の本物の形式", + "description": "QA向けの無料オープンソースのテストファイル生成ツール。正確なサイズの本物のPDF、DOCX、PNG、ZIPと、システムの期待される反応を示すマニフェストを出力します。" + }, + { + "key": "formats", + "slug": "formats", + "nav": "形式", + "title": "対応する{{ .Facts.FormatCount }}種類のファイル形式 - PDF、DOCX、PNG、ZIPほか", + "description": "生成できる全ファイル形式、形式ごとの最小ファイル、受け付ける設定の一覧です。全{{ .Facts.FormatCount }}形式が対応するソフトウェアで開けます。" + }, + { + "key": "presets", + "slug": "presets", + "nav": "プリセット", + "title": "テストファイルのプリセット - QAの疑問に答える既製セット", + "description": "既製のテストファイルセット。それぞれが1つの疑問に答えます。アップロード制限、ファイル名、文字コード、表の取り込み、空ファイル、アップロード検証。" + }, + { + "key": "docs", + "slug": "docs", + "nav": "ドキュメント", + "title": "ドキュメント - コマンド、レシピ、マニフェスト、終了コード", + "description": "コマンドラインやYAMLレシピでテストファイルを生成する方法、マニフェストの中身、CIで実行したときの各終了コードの意味を説明します。" + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "利用例", + "title": "利用例 - アップロード制限、CIのフィクスチャ、大量テスト", + "description": "アップロードのサイズ制限のテスト、CI向けの再現可能なフィクスチャ、1万ファイルの生成、実際の中身を持つアーカイブの作成。" + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "正確なサイズ", + "title": "指定サイズのファイルを作る方法 - Windows、Linux、macOS", + "description": "fsutil、dd、truncate、mkfileを各OSで実測しました。テストがPDFやPNGを必要とするとき、この方法で作ったファイルでは足りない理由も解説します。" + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - テストファイルの生成に関する質問", + "description": "ddやfsutilとの違い、ファイルをコミットしても安全か、実行結果がバイト単位で再現されるか、サイズに到達できない場合どうなるか。" + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "破損ファイル", + "title": "破損したテストファイル - サイズが正確な壊れたファイル", + "description": "意図的に壊した、サイズが正確なファイル。システムが拒否すべきことを示すマニフェスト付き。アップロード検証やパーサーのテスト用。", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "CIでのテストファイル", + "title": "CIでのテストファイル - GitHub Actions、GitLab CI、PowerShell", + "description": "バイナリをコミットする代わりに、パイプラインでテストファイルを生成。GitHub Actionsのワークフロー、GitLabのジョブ、終了コード、PowerShellの落とし穴。", + "parent": "use-cases" + } + ], + "words": { + "skip": "本文へスキップ", + "navLabel": "メインメニュー", + "langLabel": "言語", + "breadcrumbHome": "ホーム", + "imageAlt": "Testing Files Generator - 正確なサイズの本物のテストファイルと、各ファイルに対するシステムの反応を示すマニフェスト", + "schemaDescription": "QA向けの無料オープンソースのテストファイル生成ツールです。{{ .Facts.FormatCount }}種類の形式で正確なサイズの本物のファイルを作り、テスト対象のシステムが各ファイルにどう反応すべきかを示すマニフェストを書き出します。", + "ctaDownload": "ダウンロード", + "ctaSource": "ソースコードを見る", + "ctaNote": "無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。", + "colFormat": "形式", + "colName": "名前", + "colExtension": "拡張子", + "colSmallest": "最小ファイル", + "colFidelity": "完全性", + "colChecked": "検証に使うもの", + "colSetting": "設定", + "colAccepts": "受け付ける値", + "colSystem": "OS", + "colCli": "コマンドライン", + "colWindow": "デスクトップウィンドウ", + "noBinary": "バイナリはまだありません", + "colCode": "コード", + "colMeaning": "意味", + "footerBlurb": "QA向けの正確なサイズのテストファイルと、各ファイルに対するシステムの反応を示すマニフェスト。", + "footerProject": "プロジェクト", + "footerSource": "GitHubのソースコード", + "footerReleases": "ダウンロード", + "footerIssues": "問題を報告", + "footerSupport": "プロジェクトを支援", + "footerPages": "ページ", + "footerLicence": "Copyright (C) 2026 DonislawDev. GNU一般公衆利用許諾契約書バージョン3の下で公開されています。生成したファイルはあなたのものです。ライセンスの対象はツールであり、その出力ではありません。", + "footerPrivacy": "このサイトは、どこからもフォント、スクリプト、トラッカーを読み込みません。Cookieも設定しません。", + "notFoundTitle": "このページは見つかりません", + "notFoundLead": "開いたアドレスは、このサイトのどのページとも一致しません。", + "notFoundBack": "ホームへ戻る", + "read.format": "セット内のすべてのファイルの形式です。ツール自体のフラグで、プリセットは既定値を与えるだけです。", + "readTakes.format": "形式ページにある形式ID", + "colDamage": "破損", + "colEffect": "バイトへの作用", + "colSettings": "設定", + "noSettings": "なし" + }, + "endings": { + "0": "すべて正常に動作しました。", + "1": "ツール内部で予期しないエラーが発生しました。", + "2": "コマンドまたはフラグが正しくありません。", + "3": "レシピが正しくありません。", + "4": "その形式では要求された処理ができません。", + "5": "読み取りまたは書き込みに失敗しました。", + "6": "ディスクの空き容量が足りません。", + "7": "verifyが不一致を見つけました。", + "8": "実行は終了しましたが、すべてが生成されたわけではありません。", + "130": "Ctrl+Cで中断されました。", + "143": "シグナルで停止されました。CIのタイムアウトはこう見えます。" + }, + "presets": { + "empty-and-minimal": { + "question": "形式が許す最小サイズの有効なファイルは通るでしょうか。", + "title": "空ファイルと最小ファイル", + "pageTitle": "全形式の最小の有効ファイルと空ファイル", + "description": "このツールが{{ .Facts.FormatCount }}種類の各形式で書き出す最小の有効ファイルと、形式が許す場合の空ファイル。それぞれに期待される反応を付けています。", + "catches": [ + "検査がバイトを読まずバイト数だけを数えるため、小さすぎると拒否される有効なファイル", + "報告されずに、読み取り側をクラッシュさせる空ファイル", + "サムネイル作成の途中でゼロ除算を起こす幅1ピクセルの画像", + "0バイトを失敗したアップロードと見なして再試行し続けるストレージ" + ], + "details": { + "formats": "セットを構成する形式です。このビルドのすべての形式にするにはallのままにし、システムが受け付ける形式だけを指定することもできます。" + } + }, + "filename-handling": { + "question": "想定外のファイル名を、システムは保存し、表示し、返せるでしょうか。", + "title": "ファイル名の扱い", + "pageTitle": "テスト用の厄介なファイル名 - Unicodeと長さ", + "description": "アップロードや保存を壊す名前のファイル。他の文字体系や絵文字、右から左への上書き、不可視文字、シェルやSQLの構文、長さの制限。", + "catches": [ + "画面やログ、一覧で別の名前に見えるファイル名", + "アップロードから保存までの間に切り詰められたり書き換えられたりするファイル名", + "ストレージがバイトで数えるのに、文字数で数えている長さ制限" + ], + "details": {} + }, + "size-boundaries": { + "question": "サイズ制限は、宣言された位置ちょうどで適用されているでしょうか。", + "title": "サイズの境界", + "pageTitle": "アップロードのサイズ制限をテスト - 境界ちょうどのファイル", + "description": "システムが宣言する制限より1バイト小さい、ちょうど等しい、1バイト大きいファイルと、両側の広めの刻み。それぞれ受け入れるべきかどうかを示します。", + "catches": [ + "制限値での1つずれのエラー", + "MBとMiBの取り違え。差は4.8パーセントで、通すべきでないファイルを通すには十分です", + "サーバーではなくブラウザーだけで適用されている制限" + ], + "details": { + "limit": "システムが宣言するサイズ制限です。他のすべてはこの値を基準に測ります。", + "spread": "制限の両側へどこまで広げるかを、サイズの一覧で指定します。" + } + }, + "tabular-import": { + "question": "実際のツールが出力する表を、取り込みは正しく処理できるでしょうか。", + "title": "表の取り込み", + "pageTitle": "CSVとExcelの取り込みテスト用ファイル - 区切り文字とヘッダー", + "description": "別の区切り文字、CR LFの改行、ヘッダーなし、別の引用符のCSV、非常に幅広い表、Excelブック、複数の構造のJSON。", + "catches": [ + "区切り文字を探さず決めつけたために、1列として読まれるセミコロン区切りのファイル", + "各行の後に空行が入って行分割されるCRLFのファイル", + "最初のデータ行が列名として取り込まれてしまうヘッダーなしの表", + "表示できる列だけを残し、残りを黙って捨てる取り込み", + "JSONレコードを1行ずつ読み、最初のインデント付きドキュメントで止まるリーダー" + ], + "details": { + "rows": "スプレッドシートの行数です。その行数がちょうど収まるサイズで書き出されるため、上の予算はこの値に応じて動きます。", + "columns": "スプレッドシートの各行の列数です。行数と列数の積には上限があり、超える指定は何かを書き込む前に拒否されます。" + } + }, + "text-encoding": { + "question": "読み取り側はファイルの文字コードを知っているのでしょうか。それとも推測でしょうか。", + "title": "文字コード", + "pageTitle": "文字コードのテスト用ファイル - UTF-8、UTF-16、BOM、CRLF", + "description": "同じテキストをUTF-8、UTF-16LE、UTF-16BEで、バイトオーダーマークあり・なしと、CR LFとLFの改行で用意し、リーダーのデコードを確認します。", + "catches": [ + "UTF-8だと決めつけて、UTF-16のファイルを3文字に1文字だけ、または四角の列として表示するリーダー", + "バイトオーダーマークが内容として読まれ、取り込みの最初のフィールドが余分な3文字で始まる問題", + "先頭バイトから文字コードを推測し、長いファイルでは違う推測をするインポーター", + "各行の後に空行が入って行分割されるCRLFのファイル、または最後のフィールドに残るキャリッジリターン" + ], + "details": { + "sample": "セット内の各ファイルの大きさです。UTF-16は1文字に2バイトを使うため、奇数は拒否されます。" + } + }, + "upload-validation": { + "question": "アップロードフォームは、受け入れるべきものを受け入れ、それ以外を拒否できるでしょうか。", + "title": "アップロードの検証", + "pageTitle": "アップロード検証のテスト用ファイル - 種類、サイズ、名前", + "description": "アップロードフォームのテスト用ファイル。許可と拒否の種類、拡張子と一致しない内容、サイズ制限の前後、悪意のある名前、一括アップロード。", + "catches": [ + "サーバーではなくブラウザーだけで適用されている制限", + "画像やプレーンテキストと見なされるSVGやHTMLファイル。スクリプトにフォームの検査をすり抜けさせる手口です", + "拡張子だけで判定され、開かれないファイル。.jpgという名前のPDFが通ってしまいます", + "サイズを確認する前に、本文全体をメモリに読み込むフォーム", + "photo.jpgは受け付けるのにPHOTO.JPGは拒否される、またはその逆になるアップロード", + "スペースやかっこ、ASCII以外の文字を含む名前が、そのままディスクに書き込まれる問題" + ], + "details": { + "limit": "アップロードフォームが宣言するサイズ制限です。このセットは制限の両側に1段ずつ取ります。あらゆる距離のファイルが必要な場合は、size-boundariesプリセットを実行してください。", + "allow": "フォームが受け入れるべき種類です。それぞれがその種類の本物のファイルになり、セット全体の陽性対照になります。", + "deny": "フォームが拒否すべき拡張子です。このビルドに対応する形式がない拡張子でも、その名前でプレーンテキストを含むファイルが作られます。", + "far-over": "1つだけの大きなファイルが制限をどれだけ超えるかです。制限の何倍も書き込むのがディスクの無駄になる場合はオフにします。", + "bulk": "一括アップロードに含めるファイル数です。0にすると、そのグループはセットから完全に外れます。" + } + } + }, + "commands": { + "generate": "レシピまたはフラグからファイルを生成する", + "validate": "レシピを検査し、何も書き込まない", + "verify": "ディレクトリをマニフェストと照合する", + "cleanup": "マニフェストに載っているファイルを削除する", + "recipe fmt": "レシピを整形して出力する", + "preset": "名前の付いたテストの疑問からファイルセットを作る", + "formats": "このビルドが対応する形式を一覧表示する", + "damage": "このビルドがファイルを意図的に壊す方法を一覧表示する", + "tool": "手元にあるファイル向けの小さなツール", + "version": "ツールのバージョンを表示する", + "license": "ライセンスと、生成ファイルにとっての意味を表示する" + }, + "outcomes": { + "accept": "システムはこのファイルを受け入れるべきです。", + "reject": "システムはこのファイルを拒否するべきです。", + "sanitize": "システムはこのファイルを受け入れ、たとえば名前を変更するなどして無害化するべきです。", + "unspecified": "システムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。" + }, + "damages": { + "zero-head": "ファイルの先頭のバイトをゼロで上書きし、長さは変えません。ほとんどのリーダーはまずそこを見るので、この破損にはほぼどれも気づきます。" + }, + "terms": { + "oracleNone": "該当なし", + "int": "任意の整数", + "choice": "決まった候補のいずれか", + "bool": "真または偽", + "size": "2mbのようなサイズ", + "text": "テキスト", + "pixels": "ピクセル", + "paragraphs": "段落", + "rows": "行", + "columns": "列", + "slides": "スライド", + "hertz": "ヘルツ", + "megapixels": "メガピクセル", + "million cells": "百万セル", + "entries per second": "1秒あたりのエントリ数", + "files": "ファイル", + "sizes separated by commas": "カンマ区切りのサイズ", + "format ids separated by commas": "カンマ区切りの形式ID", + "format ids separated by commas, or all": "カンマ区切りの形式ID、またはall", + "extensions separated by commas": "カンマ区切りの拡張子", + "the id of a format, as tfg formats lists them": "tfg formatsが一覧表示する形式のID", + "the password, in plain text": "パスワード(平文)", + "any text": "任意のテキスト", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "2024-02-29や2024-02-29T13:45:00+02:00のような日付、またはnone" + }, + "faq": [ + { + "q": "ddやfsutil、truncateとは何が違いますか。", + "a": "それらが作るのは、サイズだけ正しい中身のないファイルです。そうして作ったphoto.pngという2MBのファイルはPNGではないため、実際に解析するものはすべて誤った理由で拒否し、あなたのテストも誤った理由で通ります。このツールはちょうど2MBの本物のPNGを作ります。画像ビューアーで開け、システムがどう扱うべきかという宣言も付いてきます。", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "無料ですか。仕事で使えますか。", + "a": "どちらも可能です。GPL-3.0で公開されており、費用はかかりません。アカウントもライセンスキーも有料プランもありません。" + }, + { + "q": "生成したファイルをクローズドソースの製品で使えますか。", + "a": "はい。ライセンスが対象とするのはツールのコードであり、ツールが生成するものではありません。生成されたファイル、レシピ、マニフェストは派生物ではなく出力ですので、コミットして配布しても何の義務も生じません。" + }, + { + "q": "生成されたファイルに実在の個人情報は含まれますか。", + "a": "いいえ。中身はすべてシードから合成されます。データセットは読み込まず、サービスにも接続せず、第三者のコンテンツも埋め込みません。生成されたメールアドレスは、未使用ではなく使用不可と見なしてください。ランダムな文字列がたまたま実在のものと一致することがあるからです。" + }, + { + "q": "別のマシンでもまったく同じファイルになりますか。", + "a": "はい。レシピとシードが同じなら、バイト単位で同じです。プロジェクトは変更のたびにこれをテストしており、破るにはメジャーバージョンを上げる必要があります。だからこそ、大きなバイナリのフィクスチャの代わりに小さなレシピをコミットできます。" + }, + { + "q": "インターネット接続は必要ですか。", + "a": "一切不要です。テレメトリも更新確認もクラウドクライアントもなく、コマンドラインのバイナリにはネットワークスタックがそもそもコンパイルされていません。ネットワークのないマシンでも、閉じた社内環境でも動きます。" + }, + { + "q": "形式が到達できないサイズを要求するとどうなりますか。", + "a": "形式名、可能な最小サイズ、その下限の理由、代わりにすべきことを示すエラーが返り、ファイルは書き込まれません。ツールがサイズを黙って丸めることはありません。各下限は形式ページに載っています。", + "code": "tfg formats png" + }, + { + "q": "意図的に壊れたファイルを生成できますか。", + "a": "はい。--damage zero-headを加えると、ファイルは求めたとおりのサイズで、先頭のバイトがゼロで上書きされて出てきます。そのためリーダーはそれを拒否し、マニフェストにはシステムがそれを拒否すべきことが記録されます。詳細は破損したテストファイルのページにあります。", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "次に対応する形式は何ですか。", + "a": "7z、mp3、mp4です。現在、{{ .Facts.FormatCount }}種類の形式がエンドツーエンドで動作します。" + }, + { + "q": "どのOSで動かせますか。", + "a": "コマンドラインは、WindowsとLinuxのIntelとARM、およびApple SiliconのMacで動作します。デスクトップウィンドウは、WindowsのIntel、LinuxのIntel、Apple SiliconのMac向けに提供されます。IntelのMacは非対応で、ビルドもされません。" + }, + { + "q": "何かインストールする必要はありますか。", + "a": "いいえ。お使いのOS向けのアーカイブをダウンロードして展開し、バイナリを実行するだけです。インストーラーも、追加するランタイムも、解決すべき依存関係もありません。Goをお持ちなら、go installコマンド1つでも動きます。", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "数千ファイルの実行がWindowsで遅いのはなぜですか。", + "a": "Windowsは調べるパス1つあたりのコストが高く、数千ファイルを走査するコマンドは数千のパスを調べるからです。1kBのファイル3000個があるマシンで測定したところ、verifyはWindowsで約0.9秒、コンテナ内のLinuxで約0.2秒かかりました。出力パスを短くするとWindowsの数値は小さくなります。ファイルより上のフォルダーもすべて調べる対象に含まれるためです。" + } + ] +} diff --git a/web/content/ja/use-cases.html b/web/content/ja/use-cases.html new file mode 100644 index 00000000..76cd55bc --- /dev/null +++ b/web/content/ja/use-cases.html @@ -0,0 +1,108 @@ +

何に使われているか

+

+ 人からファイルを受け取るほぼすべてのプロジェクトで出てくる5つの作業と、それぞれを実行するコマンド。以下の例はすべて、書かれたとおりに動きます。 +

+ +
+

アップロード制限

+

ファイルサイズ制限が、言っている位置で適用されているかをテストする

+

+ 制限は1つではなく3つのテストケースです。直前、ちょうど、直後。これを手作業で用意するとバイト数を計算することになり、1つずれていないことを祈るしかありません。代わりにセットを要求します。 +

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

+ 1048575、1048576、1048577バイトの本物のPDFが3つ得られ、マニフェストは、最初の2つを受け入れ、3つ目をsize_limitで拒否すべきだと示します。アサーションを3つ手書きする代わりに、テストは期待値を読みます。制限が変わったら、数値を1つ変えて再実行するだけです。 +

+

+ 1つの境界セットをインラインで用意したいときは、プリセットなしでも同じことができます。 +

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

継続的インテグレーション

+

フィクスチャを失わずに、リポジトリの外に置く

+

+ 大きなバイナリのフィクスチャは、リポジトリのクローンを遅くし、レビューを難しくし、1つが置き換えられても何が変わったのか誰にも分かりません。レシピは数百文字のYAMLで、同一のファイルを再構築します。どのマシンでもバイト単位で同じです。すべてのファイルが実行のシードから導かれるためです。 +

+
- 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
+

+ 終わり方ごとに専用の終了コードがあるため、パイプラインは、誤ったレシピ、ディスク満杯、検証の不一致を区別できます。失敗した実行は標準出力に何も出力しないので、ログパーサーがエラーをデータとして読み取ることもありません。 +

+
+ +
+

規模

+

フォルダーが大きいときに何が起きるかを確かめる

+

+ 取り込み処理、夜間ジョブ、ディレクトリ一覧は、10ファイルのときと1万ファイルのときで挙動が変わります。範囲から決めたサイズを使うと、1万個の同一ファイルではなく実際のトラフィックに近いセットになります。抽選はシードから決まるため、セットは明日も同じです。 +

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

+ 合計がギガバイト単位になるときは特に、何かを書き込む前に実行のコストを確認します。 +

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

+ ディスクの空き容量より大きい実行は、最初の1バイトを書く前に拒否されます。ディスクを埋めて途中で失敗することはありません。 +

+
+ +
+

アーカイブ

+

実際にファイルが入ったアーカイブで、展開処理をテストする

+

+ 拡張子だけ正しい空のアーカイブでは、それを開いて中身をたどるコードについて何も証明できません。中身を宣言すれば、アーカイブは実際にそれを含みます。 +

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

+ ネストの深さ、エントリ数、中身のサイズは、どれも取り込み処理が意見を持つ項目で、これが、その意見を知る方法です。 +

+
+ +
+

パーサーとビューアー

+

自分のコードが、実際のソフトウェアと同じように形式を読めているかを確かめる

+

+ ここにあるすべての形式は、出荷前に独立したリーダーで検証されています。PNGは開かれてピクセルが比較され、DOCXは別のライブラリで読み直され、アーカイブは展開されます。つまり、あなたのパーサーが拒否するファイルは、生成ツールではなくあなたのパーサーに関する発見です。 +

+
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
+

+ 形式ページに、各形式が受け付ける設定と、取りうる最小のファイルを載せています。 +

+
+ +
+

ガイド

+

そのうち2つを詳しく

+ +
+ +
+

誰のためのものか

+

+ QAエンジニア、テスト自動化、そしてコードの先にアップロードフォーム、取り込み処理、パーサー、ストレージの割り当てがあるすべての人のためのものです。ネットワークが一切ないマシンで動くため、ブラウザーベースの生成ツールが使えない閉じた社内環境でも役立ちます。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ko/ci.html b/web/content/ko/ci.html new file mode 100644 index 00000000..46abb85a --- /dev/null +++ b/web/content/ko/ci.html @@ -0,0 +1,176 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

CI 파이프라인에서 테스트 파일을 생성하는 방법

+

+ 저장소의 바이너리 픽스처는 기록에 영원히 남고, diff에서 검토할 수 없으며, 파일이 커지면 아예 불가능해집니다. 대신 파이프라인 안에서 레시피로 파일을 생성하세요. 레시피는 + 텍스트이고, 바이트는 매번 같게 나오며, 마지막 단계가 아무것도 움직이지 않았음을 증명합니다. +

+ +
+

짧은 답

+

+ tfg를 설치하고, 테스트 전에 tfg generate fixtures.yaml --out ./fixtures를, 테스트 후에 + tfg verify ./fixtures/manifest.json을 실행하세요. 두 단계 모두 스스로 빌드를 실패시키며, 이유를 알려 주는 종료 코드를 + 남깁니다. +

+
+ +
+

커밋하지 않는 이유

+

픽스처가 저장소에 있으면 안 되는 이유

+ +

+ 커밋할 것은 레시피입니다. 같은 레시피와 같은 시드는 어느 머신에서나 같은 바이트를 쓰므로, 파이프라인에서 생성한 파일은 노트북에 있던 바로 그 파일입니다. +

+
+ +
+

레시피

+

테스트 옆에 두는 레시피

+

+ 이 레시피는 수락되어야 하는 청구서 25건과 한도를 넘어 거부되어야 하는 이미지 2장을 쓰며, 매니페스트는 두 기대 결과를 모두 기록합니다. +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml은 아무것도 쓰지 않고 레시피를 검사하며 모든 문제를 한 번에 알려 줍니다. +

+
+ +
+

GitHub Actions

+

도구를 설치하고 픽스처를 만드는 워크플로

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 체크섬 줄은 아카이브를 같은 릴리스의 verify-SHA256SUMS.txt와 비교합니다. 버전이 고정되어 있어서 새 릴리스가 손대지 않은 빌드를 바꾸는 + 일은 없습니다. +

+
+ +
+

GitLab CI

+

같은 일을 GitLab 작업으로

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

빨갛게 변했을 때

+

무엇이 단계를 실패시키는지, 그리고 이유

+

+ 끝나는 방식마다 고유한 종료 코드가 있으므로 단계는 스스로 실패하고 로그가 어느 것인지 알려 줍니다. 파이프라인이 만나는 코드는 다음과 같습니다. +

+ +

+ 실패한 실행은 표준 출력에 아무것도 출력하지 않으므로 로그 파서가 오류를 데이터로 착각하는 일이 없습니다. 전체 표는 문서 페이지에 + 있습니다. +

+
+ +
+

PowerShell

+

PowerShell 스크립트에는 한 줄이 더 필요합니다

+

+ PowerShell은 프로그램의 종료 코드를 .ps1 파일 밖으로 전달하지 않습니다. -File로 실행하면 안에 있는 도구가 작업을 + 거부했더라도 스크립트는 0으로 답하므로, 빨갛게 되어야 할 빌드가 초록이 됩니다. 마지막 한 줄이 수정의 전부입니다. +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 이것은 PowerShell의 동작이지 이 도구와는 무관합니다. cmd, bash, zsh에는 따로 필요한 것이 + 없습니다. +

+
+ +
+

여러 작업

+

작업 사이에서 픽스처 공유하기

+

+ 보통은 업로드할 필요가 없습니다. 같은 레시피가 같은 바이트를 쓰므로 각 작업이 자기 tfg generate를 실행할 수 있고, 이것이 업로드 후 + 다운로드보다 빠릅니다. 한 작업이 다른 작업에서 파일을 받아야 한다면 전송 후 매니페스트에 tfg verify를 실행하세요. 도착한 것이 기록된 것과 + 같은지 알려 줍니다. +

+
+ +
+

다음

+

여기서 어디로

+ +
diff --git a/web/content/ko/damage.html b/web/content/ko/damage.html new file mode 100644 index 00000000..e7252779 --- /dev/null +++ b/web/content/ko/damage.html @@ -0,0 +1,156 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

테스트용 손상 파일을 만드는 방법

+

+ 멀쩡한 파일만 본 검증기는 제대로 테스트된 것이 아닙니다. 일부러 망가뜨렸고, 요청한 크기 그대로 나오며, 시스템이 그 파일을 어떻게 다뤄야 하는지 + 알려 주는 매니페스트가 딸려 오는 파일을 얻는 방법을 설명합니다. +

+ +
+

짧은 답

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out은 정확히 2097152바이트이고 첫 + 바이트들이 0인 PNG를 쓰며, 옆의 매니페스트에는 시스템이 그것을 거부해야 한다고 기록됩니다. +

+
+ +
+

흔한 방법

+

손으로 망가뜨린 파일이 좋지 않은 테스트인 이유

+

+ 흔한 방법은 16진 편집기, 임의의 바이트 몇 개를 뒤집는 스크립트, 또는 head나 truncate로 파일을 잘라 내는 것입니다. + 한 번은 통하지만 나중에 대가를 치릅니다. +

+ +
+ +
+

얻는 것

+

손상된 파일도 요청한 크기를 유지합니다

+

+ 파일은 평소대로 생성된 뒤 디스크로 가는 길에 망가집니다. 요청한 크기는 그대로이고, 같은 명령은 같은 바이트를 다시 씁니다. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 설정은 콜론 뒤에 씁니다. 옵션은 반복할 수 있고, 손상은 쓴 순서대로 적용됩니다. {{ .Facts.FormatCount }}개 형식 모두에서 동작합니다. +

+
+ +
+

할 수 있는 것

+

어떤 손상이 있나요?

+

+ 이것은 프로그램이 출력하는 목록이며, 이 페이지를 빌드할 때 프로그램에서 읽어 옵니다. tfg damage는 같은 목록을 출력하고, tfg + damage <id>는 그중 하나가 받는 설정을 알려 줍니다. +

+ {{ template "damagesTable" . }} +

+ zero-head는 파일의 시작 부분을 0으로 덮어씁니다. 대부분의 리더는 파일이 무엇인지 알려 주는 시그니처와 헤더가 있는 그곳을 가장 먼저 봅니다. + 그래서 거의 모든 리더가 알아챕니다. 일반 텍스트와 로그에는 시그니처가 없지만 역시 거부됩니다. 0 바이트의 연속은 텍스트가 아니기 때문입니다. 4바이트 미만에서는 어떤 + 리더도 불평하지 않는 손상이 나오는 형식이 있으며, 설정이 4부터 시작하는 이유가 그것입니다. +

+
+ +
+

매니페스트가 말하는 것

+

무엇이 일어나야 하는지 말해 주는 매니페스트

+

+ 손상된 파일마다 시스템이 그것을 거부해야 한다는 항목이 붙고, 손상 내용이 그 옆에 기록됩니다. +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 두 가지 요청은 무엇이든 쓰기 전에 거부됩니다. 둘 다 매니페스트가 잘못 설명하는 파일을 디스크에 남기게 되기 때문입니다. +

+ +
+ +
+

레시피에서

+

한 번의 실행에 멀쩡한 파일과 망가진 파일을

+

+ 둘을 한 레시피에 넣으면 매니페스트가 파일마다 기대 결과를 가지므로, 테스트에 어느 것이 어느 것인지 알려 주는 목록이 필요 없습니다. +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

테스트에서

+

테스트로 만들기

+

+ 테스트는 매니페스트를 읽고 일어난 일이 선언된 것과 같은지 확인합니다. 파일 이름 목록은 필요 없습니다. +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 좋은 거부는 깔끔한 거부입니다. 무엇이 잘못됐는지 알려 주는 메시지가 원하는 답입니다. 서버 오류, 멈춤, 반쯤 저장된 파일은 이 테스트가 찾아내려고 존재하는 결함입니다. +

+
+ +
+

다음

+

여기서 어디로

+ +
diff --git a/web/content/ko/docs.html b/web/content/ko/docs.html new file mode 100644 index 00000000..26b5ed34 --- /dev/null +++ b/web/content/ko/docs.html @@ -0,0 +1,257 @@ +

문서

+

+ 도구가 하는 모든 일을 사람들이 실제로 가져오는 질문 형태로 정리했습니다. 저장소의 README가 전체 레퍼런스이며, + 내려받은 빌드와 항상 일치합니다. +

+ +
+

어떤 명령이 있나요?

+

각 명령은 한 가지 일만 합니다.

+ {{ template "commandList" . }} +
+ +
+

정확한 크기의 파일 하나는 어떻게 만드나요?

+

+ 형식, 크기, 저장 위치를 지정합니다. 크기는 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>한도 주변의 파일 세 개: 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매니페스트를 표준 출력에 씀
+
+
+ +
+

일부러 망가진 파일은 어떻게 만드나요?

+

+ 이 도구가 쓰는 다른 모든 파일은 구조상 올바르며, 이는 업로드 검증기가 던지는 세 가지 질문 중 두 가지에 답합니다. --damage는 세 번째, 곧 + 파일이 아예 열리는지에 답합니다. 파일은 정상적으로 만들어진 뒤 망가지므로 요청한 크기는 그대로입니다. +

+
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를 받고, 옆에 손상 내용이 기록됩니다. 두 가지는 아무것도 쓰기 전에 거부됩니다. 각각 + 매니페스트가 잘못 설명하는 파일을 디스크에 남기게 되기 때문입니다. +

+ +

+ 세 번째는 미리 알 수 없습니다. 손상이 실행되었는데 한 바이트도 바뀌지 않았다면 그 파일은 쓰이지 않고 버려집니다. 실행은 계속되고, 어떤 파일이었는지 알려 주며, 일부만 완료된 + 종료 코드로 끝납니다. +

+

+ 단계별로, 매니페스트를 읽는 테스트와 함께 설명합니다. 테스트용 손상 파일을 만드는 방법. +

+
+ +
+

레시피는 어떻게 생겼나요?

+

+ 레시피는 실행 전체를 기술하는 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 중 + 정확히 하나가 필요합니다. 둘은 오류이고 하나도 없는 것도 오류입니다. 올바르지 않은 레시피는 파일을 하나도 쓰지 않으며, 첫 번째 문제만이 + 아니라 모든 문제를 한꺼번에 보고하고 각각 해당 설정의 이름을 알려 줍니다. +

+
+ +
+

시스템이 파일을 어떻게 처리해야 하는지는 어떻게 선언하나요?

+

결과만 있으면 충분할 때는 짧은 형식을, 이유가 중요할 때는 긴 형식을 씁니다.

+
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입니다. +

+
+ +
+

매니페스트에는 무엇이 들어 있나요?

+

+ 중단된 실행을 포함해 모든 실행이 끝날 때 파일 옆에 쓰입니다. 파일마다 항목이 하나씩 있습니다. +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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가 레시피를 출력하므로 + 거기서부터 편집할 수 있습니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 + 전용 페이지가 있습니다. +

+ {{ template "presetsList" . }} +
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는 세트를 만들기 전에 비용이 얼마나 드는지 알려 주고, 숫자가 여러분의 한도가 아니라 우리 쪽의 임시값일 때는 분명히 말해 줍니다. +

+
+ +
+

종료 코드는 무엇을 뜻하나요?

+

+ 끝나는 방식마다 고유한 코드가 있고, 기계가 읽을 수 있는 출력은 표준 출력으로 나가며, 실패한 실행은 거기에 아무것도 출력하지 않습니다. 이 표는 고정된 약속이며, 코드의 의미를 + 바꾸려면 메이저 버전을 올려야 합니다. +

+ {{ template "exitCodesTable" . }} +
- 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 파이프라인에서 테스트 파일을 생성하는 + 방법. +

+
+ +
+

데스크톱 창이 있나요?

+

+ 네. 같은 엔진 위에 창을 얹은 것으로, 스크립트로 하지 않는 테스트를 위한 것입니다. 축소판이 아닙니다. 테스트가 두 인터페이스를 기능별로 비교하며, 한쪽만 할 수 있는 것은 + 조용히 벌어지는 대신 선언하고 이유를 밝혀야 합니다. +

+

+ 화면은 단일 배치, 프리셋, 여러 배치 동시 실행, 정보입니다. 무엇이든 쓰기 전에 실행 비용을 보여 주고, 실행 중에는 진행 상황을 알려 주며, 쓰다 만 파일을 남기지 않고 + 도중에 취소할 수 있습니다. 아직 레시피 파일은 열지 못합니다. 지금은 레시피가 명령줄의 몫이고, 창은 양식에서 배치를 구성합니다. +

+
diff --git a/web/content/ko/exact-size.html b/web/content/ko/exact-size.html new file mode 100644 index 00000000..313791dd --- /dev/null +++ b/web/content/ko/exact-size.html @@ -0,0 +1,133 @@ +

정확한 크기의 파일을 만드는 방법

+

+ 모든 시스템에 이를 위한 명령이 있으며, 세 가지 모두 아래에 있습니다. 정확한 바이트 수의 파일을 만들어 주며, 많은 테스트에서는 그것만으로 충분합니다. 이 + 페이지의 모든 명령은 게시하기 전에 해당 시스템에서 실행해 보았습니다. +

+ +
+

짧은 답

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. 크기는 바이트 단위이며, 파일 관리자가 세는 방식의 10MB는 + 10485760입니다. +

+
+ +
+

Windows

+

fsutil, 그리고 추가 도구가 필요 없는 PowerShell 방식

+

+ fsutil은 Windows에 포함되어 있습니다. 크기를 바이트 단위로 받으므로 먼저 숫자를 계산하세요. 10MB는 + 10485760, 100MB는 104857600, 1GB는 1073741824입니다. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11에서 측정했습니다. 관리자 권한이 아닌 일반 프롬프트에서도 동작하며, 파일은 정확히 10485760바이트가 됩니다. +

+

PowerShell은 다른 프로그램을 호출하지 않고도 같은 일을 할 수 있으며 단위를 이해합니다.

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell의 10MB는 탐색기가 쓰는 것과 같은 1024 기준 계산으로 10485760바이트를 뜻하므로, 위의 두 명령은 같은 크기를 만듭니다. +

+
+ +
+

Linux

+

dd, truncate, fallocate, 그리고 사람들이 걸려 넘어지는 차이

+

dd는 누구나 아는 명령입니다. 바이트를 실제로 씁니다.

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate는 즉시 끝나는데, 그것이 함정입니다. Alpine Linux에서 측정해 보면 파일은 10485760바이트로 보고되지만 차지하는 블록은 + 0개로, 희소 파일입니다. 읽는 쪽은 0으로 채워진 10메가바이트를 받지만, 디스크는 공간을 내준 적이 + 없습니다. +

+
truncate -s 10M test10mb.bin
+

+ 업로드 한도를 테스트하기에는 괜찮지만 디스크 할당량을 테스트할 때는 오해를 부릅니다. 공간이 실제여야 할 때는 fallocate를 쓰세요. +

+
fallocate -l 10M test10mb.bin
+

그리고 압축 프로그램이 다시 줄일 수 없도록 내용이 압축 불가능해야 할 때는:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

희소 파일이 아닌 mkfile, 그리고 이미 아시는 두 가지

+

+ macOS에는 mkfile이 포함되어 있습니다. macOS 26.6.2에서 측정하니 10485760바이트에 20480블록이었으므로, 공간은 약속이 아니라 + 실제로 할당됩니다. +

+
mkfile 10m test10mb.bin
+

dd와 truncate도 있으며 Linux와 같게 동작합니다.

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

이 방법이 통하지 않는 곳

+

크기가 맞는 파일이 종류까지 맞는 파일은 아닙니다

+

+ 위의 방법은 모두 0으로 된 덩어리를 줍니다. 테스트 대상이 크기만 본다면, 예를 들어 업로드 한도, 할당량, 전송이라면 충분합니다. 하지만 무엇이든 그 파일을 + 여는 순간 충분하지 않게 됩니다. +

+

+ 직접 측정했으며, 여러분도 해 볼 만합니다. fsutil로 2MB 파일을 만들고 photo.png라고 이름 붙인 다음 이미지 + 라이브러리에 넘겨 보세요. Pillow는 cannot identify image file이라고 답합니다. 그것은 PNG가 아닙니다. 처음부터 + 아니었고, 이름만 그렇게 말했을 뿐입니다. +

+

+ 이는 들리는 것보다 중요합니다. 테스트가 그다음에 어느 쪽으로 실패하는지가 걸려 있기 때문입니다. 업로드 엔드포인트가 파일을 거부하고, 테스트가 + 초록색이 되며, 크기 한도가 동작한다고 결론짓게 됩니다. 하지만 크기 때문에 거부한 것이 아닙니다. 바이트가 이미지가 아니어서 거부한 것이며, 테스트하려던 규칙에는 닿지도 + 않았습니다. +

+ +
+ +
+

다른 방법

+

그 형식의 실제 파일, 요청한 크기 그대로

+

+ 이것이 Testing Files Generator가 하는 일입니다. 파일은 해당 형식의 진짜 파일로, 해당 소프트웨어에서 열리며, 요청한 바이트 수와 정확히 같습니다. +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 형식이 도달할 수 없는 크기를 요청하면 하한과 그 이유를 알려 주는 오류가 나오며, 크기가 틀린 파일은 나오지 않습니다. 형식 + 페이지에 각 형식과 만들 수 있는 가장 작은 파일이 나와 있습니다. +

+

그리고 한도는 하나가 아니라 세 개의 테스트 케이스이므로, 도구가 세 개 모두 만듭니다.

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 10485759, 10485760, 10485761바이트의 파일과, 시스템이 어느 것을 받고 어느 것을 거부해야 하는지 알려 주는 매니페스트를 얻습니다. + 활용 사례 페이지에서 이것과 이 도구가 대상으로 하는 네 가지 다른 작업을 다룹니다. +

+ {{ template "downloadCta" . }} +
+ +
+

그러면 무엇을 써야 할까요?

+ +

+ 둘 다 이 페이지에 있는 이유는 둘 다 때로는 맞기 때문입니다. 피해야 할 실수는 두 번째가 필요한 곳에서 첫 번째를 쓰고 초록색 테스트를 증거로 읽는 것입니다. +

+
diff --git a/web/content/ko/faq.html b/web/content/ko/faq.html new file mode 100644 index 00000000..0fa5cea3 --- /dev/null +++ b/web/content/ko/faq.html @@ -0,0 +1,17 @@ +

자주 묻는 질문

+

+ 라이선스, 개인정보, 재현성, 그리고 사람들이 생성기를 빌드 파이프라인에 넣기 전에 확인하는 것들. 질문이 여기에 없다면 이슈 + 트래커가 열려 있습니다. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

아직 고민 중이신가요?

+

+ 활용 사례 페이지는 이 도구가 대상으로 하는 작업을, 형식 페이지는 각 형식과 + 만들 수 있는 가장 작은 파일을 보여 줍니다. 저장소의 README가 전체 레퍼런스입니다. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ko/formats.html b/web/content/ko/formats.html new file mode 100644 index 00000000..4ab23444 --- /dev/null +++ b/web/content/ko/formats.html @@ -0,0 +1,68 @@ +

파일 형식 {{ .Facts.FormatCount }}가지, 모두 정확한 크기로 생성됩니다

+

+ 이들은 모두 해당 형식의 실제 파일입니다. 해당 소프트웨어에서 열리며 요청한 바이트 수와 정확히 같습니다. 확장자만 붙인 채운 0은 하나도 없습니다. +

+ +{{ template "formatsTable" . }} + +
+

각 열의 의미

+ +

+ 모든 형식은 바이트 단위로 반복되기도 합니다. 같은 레시피와 같은 시드는 어느 컴퓨터에서나 같은 파일을 만들며, 그래서 픽스처 자체 대신 레시피를 커밋해도 안전합니다. +

+
+ +
+

각 형식이 받는 설정

+

+ 대부분의 형식에는 고유한 설정이 있습니다. 이미지 크기, JPEG 품질, PDF 쪽수, 스프레드시트의 행과 열, 아카이브에 들어가는 항목 수 등입니다. 명령줄에서는 + --set key=value로, 레시피에서는 properties: 아래에서 설정합니다. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ 설정이 받는 범위를 벗어난 값은 설정, 허용 범위, 대신 쓸 값을 알려 주는 메시지와 함께 거부됩니다. 알 수 없는 설정도 오류이며 조용히 기본값이 되는 일은 없습니다. 조용히 + 받아들여진 오타는 잘못된 설정의 파일과, 통과하면 안 되는 테스트가 왜 통과하는지 고민하는 한 시간을 낳습니다. +

+

+ 가지고 있는 빌드에서 한 형식이 정확히 무엇을 받는지 보려면 tfg formats <id>를 실행하세요. +

+
+ +
+

아카이브에는 실제 파일이 들어 있습니다

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }}와 {{ end }}{{ $c.ID }}{{ end }}는 빈 + 껍데기로 두지 않고 항목으로 채울 수 있습니다. 생성된 아카이브는 담았다고 하는 문서를 실제로 담고 있으므로, 테스트 중에 이를 푸는 것은 무엇이든 안에서 실제 파일을 + 찾습니다. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/ko/index.html b/web/content/ko/index.html new file mode 100644 index 00000000..ef7acdb1 --- /dev/null +++ b/web/content/ko/index.html @@ -0,0 +1,187 @@ +
+
+

정확한 크기의 실제 테스트 파일을 만드세요

+

+ PDF, PNG, DOCX, ZIP 등 모두 {{ .Facts.FormatCount }}가지 형식이며, 모두 해당 소프트웨어에서 열리는 실제 파일로 + 요청한 크기와 정확히 같습니다. 매 실행마다 애플리케이션이 각 파일을 어떻게 처리해야 하는지도 함께 기록합니다. 명령줄과 데스크톱 창, 무료 + 오픈 소스이며, 모두 여러분의 컴퓨터에서 동작합니다. +

+ + {{ template "downloadCta" . }} +
+ +
+ 테스트 파일 배치를 쓸 준비가 된 Testing Files Generator 데스크톱 창 +
파일 배치를 쓸 준비가 된 데스크톱 창. 명령줄 뒤에서도 같은 엔진이 동작합니다.
+
+
+ + + +
+

문제

+

테스트 파일 하나를 만드는 것은 쉽습니다. 알맞은 천 개를 만드는 것이 번거로운 부분입니다

+

여러분은 사람들에게서 파일을 받는 소프트웨어를 테스트하고 있습니다. 머지않아 다음이 필요해집니다.

+ +

+ 이것이 바로 이 도구가 대체하는 일입니다. QA 엔지니어, 테스트 자동화, 그리고 코드 뒤에 업로드 양식, 가져오기 루틴, 파서, 저장 용량 할당이 있는 모든 분을 위해 + 만들었습니다. +

+
+ +
+

무엇이 다른가

+

다른 생성기는 바이트에서 멈춥니다. 이 도구는 테스트가 실제로 묻는 것에 답합니다

+

+ 파일이 가득한 폴더만으로는 각 파일이 무엇을 증명해야 하는지 여전히 직접 정해야 합니다. 여기서는 실행할 때마다 파일 옆에 manifest.json을 + 씁니다. 만들어진 모든 것의 단순한 목록이며, 항목마다 선언된 기대값이 있습니다. +

+

업로드 엔드포인트가 1MB까지 허용한다고 해 봅시다. 그 경계선 위에 놓인 파일 세 개를 요청합니다.

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
파일바이트시스템의 처리이유
1mb_under_1b.pdf1048575수락한도 안쪽입니다
1mb_at_limit.pdf1048576수락한도 값 자체는 허용됩니다
1mb_over_1b.pdf1048577거부size_limit
+
+ +

파일 세 개, 서로 다른 세 가지 답을 기계가 읽을 수 있는 형태로 줍니다. 어서션을 직접 쓰는 대신 테스트가 매니페스트를 읽습니다.

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

답이 여러분의 정책에 달려 있는 경우, 매니페스트는 그렇다고 말합니다

+

+ 기대값을 지어내지 않고 unspecified를 기록합니다. 추측하는 생성기는 거짓 실패를 만들고, 거짓 경보를 울려 대는 테스트 묶음은 결국 꺼집니다. +

+
+
+ +
+

프리셋

+

질문을 고르면 세트 전체를 얻습니다

+

+ 프리셋은 하나의 테스트 질문을 중심으로 설계한 테스트 파일 세트로, 어떤 파일이 무엇을 증명하는지 직접 따져 볼 필요가 없습니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 + 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 페이지가 있습니다. +

+ {{ template "presetsList" . }} +

모든 프리셋과 레시피와의 관계

+
+ +
+

빠른 시작

+

동작을 확인하는 명령 세 개

+
    +
  1. +

    파일 하나 만들기

    +

    PNG 하나, 정확히 2메가바이트:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    많은 파일 만들기

    +

    + 각각 1KB에서 8KB 사이이고 크기를 시드에서 뽑은 로그 파일 1만 개로, 내일도 같은 세트가 나옵니다. 실행마다 고유한 디렉터리를 쓰세요. + 매니페스트는 실행이 쓴 내용의 유일한 기록이므로, 도구는 그 위에 두 번째 매니페스트를 쓰기를 거부합니다. +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    검사한 뒤 삭제하기

    +

    verify는 아무것도 바뀌지 않았음을 알려 줍니다. cleanup은 쓰인 것만 정확히 삭제하고 다른 것은 건드리지 않습니다.

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 크기는 파일 관리자처럼 1024 단위로 세므로 2mb는 2097152바이트입니다. 바이트 수를 그대로 써도 됩니다. + 문서에서 레시피, 매니페스트, 종료 코드를 다룹니다. +

+
+ +
+

얻는 것

+

무인으로 실행되는 테스트 묶음을 위해 만들었습니다

+ +
+ +
+

다운로드

+

시스템에 맞는 빌드를 고르세요

+

+ 압축 파일을 풀고 실행하세요. tfg는 명령줄이고 tfg-gui는 데스크톱 창입니다. 설치 프로그램은 없으며 컴퓨터에 추가할 것도 + 없습니다. +

+ {{ template "downloadsTable" . }} +
+

서명된 것과 그렇지 않은 것

+

+ Windows와 macOS 다운로드는 서명되어 있어 확인되지 않은 개발자 경고 없이 실행됩니다. Linux용은 데스크톱 Linux에 서명할 수 있는 대응 수단이 없어 서명되어 있지 + 않습니다. 모든 압축 파일은 릴리스 페이지의 verify-SHA256SUMS.txt에 나열되어 있으므로 내려받은 것을 확인할 수 있습니다. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/ko/preset.html b/web/content/ko/preset.html new file mode 100644 index 00000000..9d51b05d --- /dev/null +++ b/web/content/ko/preset.html @@ -0,0 +1,90 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }} 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ +{{ if .Catches }} +
+

보통 무엇을 찾아내나요?

+ +
+{{ end }} + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show {{ .ID }}가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수{{ .Budget.Files }}
레시피의 타깃 수{{ .Budget.Targets }}
총 크기{{ .Bytes }} B
형식{{ join .Budget.Formats ", " }}
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
기대값의미파일 수
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

무엇을 바꿀 수 있나요?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
설정값기본값동작
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} 이 기본값은 우리 쪽의 임시값이며 여러분 시스템의 값이 아닙니다. 직접 값을 지정하세요.{{ end }}
+
+ {{- else }} +

이 프리셋에는 설정이 없습니다. 세트는 매번 같습니다.

+ {{- end }} +
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/ko/presets.html b/web/content/ko/presets.html new file mode 100644 index 00000000..bc5d6fed --- /dev/null +++ b/web/content/ko/presets.html @@ -0,0 +1,26 @@ +

테스트 파일 프리셋, 테스트 질문마다 한 세트

+

+ 프리셋은 하나의 질문을 중심으로 설계한 테스트 파일 세트 전체이며, 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 매니페스트가 함께 제공됩니다. 질문을 고르면 도구가 세트를 + 만듭니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 고유한 페이지가 있습니다. +

+ +{{ template "presetsList" . }} + +
+

프리셋과 레시피는 어떻게 다른가요?

+

+ 내부적으로는 다르지 않습니다. 프리셋은 몇 가지 설정으로 도구가 대신 써 주는 레시피입니다. tfg preset eject가 그 레시피를 출력하므로 테스트 + 옆에 두고 편집할 수 있으며, 직접 만든 레시피는 extends: preset: 뒤에 id를 붙인 한 줄로 프리셋을 바탕으로 할 수 있습니다. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

기본값을 믿어도 되나요?

+

+ 파일에 대해서는 그렇습니다. 업로드 양식의 한도처럼 여러분의 시스템만 아는 숫자라면 기본값은 우리 쪽의 임시값이며, 도구는 임시값을 쓸 때마다 그렇게 알려 줍니다. 각 프리셋의 + 페이지는 그러한 설정을 표시하고, tfg preset show는 무엇이든 쓰기 전에 그 사실을 알려 줍니다. +

+
diff --git a/web/content/ko/site.json b/web/content/ko/site.json new file mode 100644 index 00000000..619bf08c --- /dev/null +++ b/web/content/ko/site.json @@ -0,0 +1,328 @@ +{ + "code": "ko", + "locale": "ko_KR", + "name": "한국어", + "dir": "ko", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "홈", + "title": "테스트 파일 생성기 - 정확한 크기, 실제 형식 {{ .Facts.FormatCount }}종", + "description": "QA를 위한 무료 오픈 소스 테스트 파일 생성기. 정확한 크기의 실제 PDF, DOCX, PNG, ZIP 파일과 시스템이 어떻게 반응해야 하는지 알려 주는 매니페스트를 만듭니다." + }, + { + "key": "formats", + "slug": "formats", + "nav": "형식", + "title": "지원하는 파일 형식 {{ .Facts.FormatCount }}종 - PDF, DOCX, PNG, ZIP 등", + "description": "이 생성기가 만드는 모든 파일 형식, 형식별 가능한 가장 작은 파일, 각 형식이 받는 설정. {{ .Facts.FormatCount }}종 모두 해당 소프트웨어에서 열립니다." + }, + { + "key": "presets", + "slug": "presets", + "nav": "프리셋", + "title": "테스트 파일 프리셋 - QA 질문별 기성 세트", + "description": "기성 테스트 파일 세트로, 각 세트가 하나의 테스트 질문에 답합니다. 업로드 한도, 파일 이름, 인코딩, 표 가져오기, 빈 파일, 업로드 검증." + }, + { + "key": "docs", + "slug": "docs", + "nav": "문서", + "title": "문서 - 명령, 레시피, 매니페스트, 종료 코드", + "description": "명령줄이나 YAML 레시피로 테스트 파일을 만드는 방법, 매니페스트의 내용, CI에서 실행할 때 각 종료 코드가 뜻하는 바를 설명합니다." + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "활용 사례", + "title": "활용 사례 - 업로드 한도, CI 픽스처, 대량 테스트", + "description": "업로드 크기 한도 테스트, CI용 재현 가능한 픽스처 구성, 파일 1만 개 생성, 실제 내용으로 아카이브 채우기." + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "정확한 크기", + "title": "지정한 크기의 파일 만드는 법 - Windows, Linux, macOS", + "description": "fsutil, dd, truncate, mkfile을 각 시스템에서 직접 측정했으며, 테스트에 PDF나 PNG가 필요할 때 이렇게 만든 파일로 부족한 이유도 설명합니다." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - 테스트 파일 생성에 관한 질문", + "description": "dd, fsutil과의 차이, 파일을 커밋해도 안전한지, 실행이 바이트 단위로 재현되는지, 크기에 도달할 수 없을 때 어떻게 되는지." + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "손상 파일", + "title": "손상된 테스트 파일 - 크기가 정확한 망가진 파일", + "description": "일부러 망가뜨린, 크기가 정확한 파일. 시스템이 거부해야 함을 알리는 매니페스트가 딸려 옵니다. 업로드 검증과 파서 테스트용.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "CI의 테스트 파일", + "title": "CI의 테스트 파일 - GitHub Actions, GitLab CI, PowerShell", + "description": "바이너리를 커밋하는 대신 파이프라인에서 테스트 파일을 생성하세요. GitHub Actions 워크플로, GitLab 작업, 종료 코드, PowerShell의 함정.", + "parent": "use-cases" + } + ], + "words": { + "skip": "본문으로 건너뛰기", + "navLabel": "메인 메뉴", + "langLabel": "언어", + "breadcrumbHome": "홈", + "imageAlt": "Testing Files Generator - 정확한 크기의 실제 테스트 파일과 각 파일에 시스템이 어떻게 반응해야 하는지 알려 주는 매니페스트", + "schemaDescription": "QA를 위한 무료 오픈 소스 테스트 파일 생성기입니다. {{ .Facts.FormatCount }}가지 형식의 정확한 크기의 실제 파일을 만들고, 테스트 대상 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 매니페스트를 작성합니다.", + "ctaDownload": "다운로드", + "ctaSource": "소스 코드 보기", + "ctaNote": "무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.", + "colFormat": "형식", + "colName": "이름", + "colExtension": "확장자", + "colSmallest": "가장 작은 파일", + "colFidelity": "완전성", + "colChecked": "검증 도구", + "colSetting": "설정", + "colAccepts": "허용값", + "colSystem": "시스템", + "colCli": "명령줄", + "colWindow": "데스크톱 창", + "noBinary": "아직 바이너리 없음", + "colCode": "코드", + "colMeaning": "의미", + "footerBlurb": "QA를 위한 정확한 크기의 테스트 파일과 각 파일에 시스템이 어떻게 반응해야 하는지 알려 주는 매니페스트.", + "footerProject": "프로젝트", + "footerSource": "GitHub의 소스 코드", + "footerReleases": "다운로드", + "footerIssues": "문제 신고", + "footerSupport": "프로젝트 후원", + "footerPages": "페이지", + "footerLicence": "Copyright (C) 2026 DonislawDev. GNU 일반 공중 사용 허가서 버전 3에 따라 배포됩니다. 생성한 파일은 여러분의 것입니다. 라이선스는 도구에 적용되며 도구의 출력물에는 적용되지 않습니다.", + "footerPrivacy": "이 사이트는 어디에서도 글꼴, 스크립트, 추적기를 불러오지 않습니다. 쿠키도 설정하지 않습니다.", + "notFoundTitle": "이 페이지는 없습니다", + "notFoundLead": "따라오신 주소는 이 사이트의 어떤 페이지와도 일치하지 않습니다.", + "notFoundBack": "홈으로 이동", + "read.format": "세트에 포함된 모든 파일의 형식입니다. 도구 자체의 플래그이며, 프리셋은 기본값만 지정합니다.", + "readTakes.format": "형식 페이지의 형식 id", + "colDamage": "손상", + "colEffect": "바이트에 하는 일", + "colSettings": "설정", + "noSettings": "없음" + }, + "endings": { + "0": "모두 정상적으로 동작했습니다.", + "1": "도구 내부에서 예기치 않은 오류가 발생했습니다.", + "2": "명령 또는 플래그가 잘못되었습니다.", + "3": "레시피가 올바르지 않습니다.", + "4": "해당 형식으로는 요청한 작업을 할 수 없습니다.", + "5": "읽기 또는 쓰기에 실패했습니다.", + "6": "디스크 공간이 부족합니다.", + "7": "verify가 불일치를 발견했습니다.", + "8": "실행은 끝났지만 모든 것이 만들어지지는 않았습니다.", + "130": "Ctrl+C로 중단되었습니다.", + "143": "시그널로 중지되었습니다. CI 시간 초과가 이렇게 보입니다." + }, + "presets": { + "empty-and-minimal": { + "question": "형식이 허용하는 가장 작은 크기의 유효한 파일이 통과할까요?", + "title": "빈 파일과 최소 파일", + "pageTitle": "모든 형식의 가장 작은 유효 파일과 빈 파일", + "description": "이 도구가 {{ .Facts.FormatCount }}가지 형식 각각에서 쓰는 가장 작은 유효 파일과, 형식이 허용하는 경우의 빈 파일. 각각 기대되는 반응이 함께 제공됩니다.", + "catches": [ + "검사가 바이트를 읽지 않고 개수만 세기 때문에 너무 작다며 거부되는 유효한 파일", + "보고되지 않고 읽는 쪽을 비정상 종료시키는 빈 파일", + "썸네일을 만드는 도중 0으로 나누기가 발생하는 너비 1픽셀의 이미지", + "0바이트를 업로드 실패로 보고 계속 재시도하는 스토리지" + ], + "details": { + "formats": "세트를 구성하는 형식입니다. 이 빌드의 모든 형식을 쓰려면 all로 두고, 시스템이 받는 형식만 쓰려면 이름을 지정합니다." + } + }, + "filename-handling": { + "question": "예상하지 못한 파일 이름을 시스템이 저장하고, 보여 주고, 돌려줄 수 있을까요?", + "title": "파일 이름 처리", + "pageTitle": "테스트용 까다로운 파일 이름 - 유니코드와 길이", + "description": "업로드와 저장을 깨뜨리는 이름의 파일. 다른 문자 체계와 이모지, 오른쪽에서 왼쪽 재정의, 보이지 않는 문자, 셸과 SQL 구문, 길이 제한.", + "catches": [ + "화면이나 로그, 목록에서 다른 이름처럼 보이는 이름", + "업로드와 저장 사이에 잘리거나 다듬어지거나 다시 쓰이는 이름", + "스토리지는 바이트로 세는데 문자로 세는 길이 제한" + ], + "details": {} + }, + "size-boundaries": { + "question": "크기 한도가 선언한 바로 그 지점에서 적용되고 있을까요?", + "title": "크기 경계", + "pageTitle": "업로드 크기 한도 테스트 - 경계 바로 위의 파일", + "description": "시스템이 선언한 크기 한도보다 1바이트 작은 파일, 정확히 같은 파일, 1바이트 큰 파일과 양쪽의 더 넓은 간격. 각각 허용해야 하는지 표시합니다.", + "catches": [ + "한도에서 발생하는 하나 차이 오류", + "MB와 MiB를 혼동하는 경우로, 4.8퍼센트 차이이며 통과하면 안 되는 파일을 통과시키기에 충분합니다", + "서버가 아니라 브라우저에서만 적용되는 한도" + ], + "details": { + "limit": "시스템이 선언한 크기 한도입니다. 다른 모든 값은 이 값을 기준으로 측정됩니다.", + "spread": "한도 양쪽으로 얼마나 멀리 갈지를 크기 목록으로 지정합니다." + } + }, + "tabular-import": { + "question": "실제 도구가 내보내는 표를 제 가져오기 기능이 제대로 처리할까요?", + "title": "표 가져오기", + "pageTitle": "CSV와 Excel 가져오기 테스트 파일 - 구분자, 머리글", + "description": "다른 구분자, CR LF 줄 끝, 머리글 없음, 다른 따옴표를 쓴 CSV, 아주 넓은 표, Excel 통합 문서, 여러 구조의 JSON.", + "catches": [ + "구분자를 찾지 않고 가정했기 때문에 한 열로 읽히는 세미콜론 구분 파일", + "각 줄 뒤에 빈 줄이 생기며 행으로 나뉘는 CRLF 파일", + "첫 데이터 행이 열 이름으로 처리되어 사라지는 머리글 없는 표", + "표시할 수 있는 열만 남기고 나머지는 말없이 버리는 가져오기", + "JSON 레코드를 한 줄씩 읽다가 들여쓰기된 첫 문서에서 멈추는 리더" + ], + "details": { + "rows": "스프레드시트에 담길 행 수입니다. 그만큼의 행이 패키징되는 정확한 크기로 파일이 쓰이므로, 위의 예산이 이 값에 따라 움직입니다.", + "columns": "스프레드시트의 각 행에 있는 열 수입니다. 행 수와 열 수의 곱에는 상한이 있으며, 이를 넘는 요청은 아무것도 쓰기 전에 거부됩니다." + } + }, + "text-encoding": { + "question": "제 리더는 파일의 인코딩을 알고 있을까요, 아니면 추측하고 있을까요?", + "title": "텍스트 인코딩", + "pageTitle": "텍스트 인코딩 테스트 파일 - UTF-8, UTF-16, BOM, CRLF", + "description": "같은 텍스트를 UTF-8, UTF-16LE, UTF-16BE로 바이트 순서 표시 유무에 따라, 그리고 CR LF와 LF 줄 끝으로 만들어 리더가 텍스트를 해독하는 방식을 테스트합니다.", + "catches": [ + "UTF-8로 가정하여 UTF-16 파일을 세 글자에 한 글자만, 또는 네모 칸의 행으로 보여 주는 리더", + "바이트 순서 표시를 내용으로 읽어서 가져오기의 첫 필드가 낯선 문자 세 개로 시작하는 문제", + "앞쪽 바이트로 인코딩을 추측하고 더 긴 파일에서는 다르게 추측하는 임포터", + "각 줄 뒤에 빈 줄이 생기며 행으로 나뉘는 CRLF 파일, 또는 마지막 필드에 남는 캐리지 리턴" + ], + "details": { + "sample": "세트에 포함된 각 파일의 크기입니다. UTF-16은 글자당 2바이트를 저장하므로 홀수는 거부됩니다." + } + }, + "upload-validation": { + "question": "제 업로드 양식은 받아야 할 것을 받고 나머지는 거부할까요?", + "title": "업로드 검증", + "pageTitle": "업로드 검증 테스트 파일 - 유형, 크기, 이름", + "description": "업로드 양식을 테스트하는 파일. 허용과 거부 유형, 확장자와 맞지 않는 내용, 크기 한도 전후, 악의적인 이름, 대량 업로드.", + "catches": [ + "서버가 아니라 브라우저에서만 적용되는 한도", + "이미지나 일반 텍스트로 오인되는 SVG 또는 HTML 파일로, 스크립트가 양식 검사를 통과하는 방법이 됩니다", + "확장자로만 검사하고 열어 보지 않아서 .jpg라는 이름의 PDF가 통과하는 파일", + "크기를 확인하기 전에 본문 전체를 메모리로 읽어 들이는 양식", + "photo.jpg는 받으면서 PHOTO.JPG는 거부하거나 그 반대인 업로드", + "공백, 괄호, ASCII 이외의 문자가 든 이름이 그대로 디스크에 쓰이는 문제" + ], + "details": { + "limit": "업로드 양식이 선언한 크기 한도입니다. 이 세트는 한도 양쪽으로 한 단계씩 만듭니다. 모든 거리의 파일이 필요하면 size-boundaries 프리셋을 실행하세요.", + "allow": "양식이 받아야 할 유형입니다. 각 유형이 해당 유형의 실제 파일이 되며, 세트 전체의 양성 대조군이 됩니다.", + "deny": "양식이 거부해야 할 확장자입니다. 이 빌드에 형식이 없는 확장자도 그 이름의 파일이 만들어지며, 내용은 일반 텍스트입니다.", + "far-over": "하나뿐인 큰 파일이 한도를 얼마나 넘는지입니다. 한도의 몇 배를 쓰는 것이 디스크 낭비라면 꺼 두세요.", + "bulk": "대량 업로드에 포함할 파일 수입니다. 0이면 그 그룹은 세트에서 완전히 빠집니다." + } + } + }, + "commands": { + "generate": "레시피나 플래그로 파일을 만든다", + "validate": "레시피를 검사하고 아무것도 쓰지 않는다", + "verify": "디렉터리를 매니페스트와 대조해 검사한다", + "cleanup": "매니페스트에 나열된 파일을 삭제한다", + "recipe fmt": "레시피를 정돈된 형태로 출력한다", + "preset": "이름 붙은 테스트 질문으로 파일 세트를 만든다", + "formats": "이 빌드가 지원하는 형식을 나열한다", + "damage": "이 빌드가 파일을 일부러 망가뜨릴 수 있는 방법을 나열한다", + "tool": "이미 가진 파일을 위한 작은 도구", + "version": "도구 버전을 출력한다", + "license": "라이선스와 생성된 파일에 대한 의미를 출력한다" + }, + "outcomes": { + "accept": "시스템은 이 파일을 받아야 합니다.", + "reject": "시스템은 이 파일을 거부해야 합니다.", + "sanitize": "시스템은 이 파일을 받아서 이름을 바꾸는 등의 방법으로 정리해야 합니다.", + "unspecified": "시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요." + }, + "damages": { + "zero-head": "파일의 첫 바이트들을 길이는 그대로 둔 채 0으로 덮어씁니다. 대부분의 리더가 가장 먼저 그곳을 보므로 거의 모든 것이 이 손상을 알아챕니다." + }, + "terms": { + "oracleNone": "해당 없음", + "int": "임의의 정수", + "choice": "정해진 집합 중 하나", + "bool": "참 또는 거짓", + "size": "2mb와 같은 크기", + "text": "텍스트", + "pixels": "픽셀", + "paragraphs": "단락", + "rows": "행", + "columns": "열", + "slides": "슬라이드", + "hertz": "헤르츠", + "megapixels": "메가픽셀", + "million cells": "백만 셀", + "entries per second": "초당 항목 수", + "files": "파일", + "sizes separated by commas": "쉼표로 구분한 크기", + "format ids separated by commas": "쉼표로 구분한 형식 id", + "format ids separated by commas, or all": "쉼표로 구분한 형식 id 또는 all", + "extensions separated by commas": "쉼표로 구분한 확장자", + "the id of a format, as tfg formats lists them": "tfg formats가 나열하는 형식의 id", + "the password, in plain text": "암호(평문)", + "any text": "임의의 텍스트", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "2024-02-29 또는 2024-02-29T13:45:00+02:00 같은 날짜, 또는 none" + }, + "faq": [ + { + "q": "dd, fsutil, truncate와는 무엇이 다른가요?", + "a": "그 명령들은 크기만 맞고 내용이 텅 빈 파일을 줍니다. 그렇게 만든 2MB짜리 photo.png는 PNG가 아니므로, 실제로 파싱하는 것은 모두 엉뚱한 이유로 거부하고, 여러분의 테스트도 엉뚱한 이유로 통과합니다. 이 도구는 정확히 2MB인 실제 PNG를 만듭니다. 이미지 뷰어에서 열리며, 시스템이 이를 어떻게 다루어야 하는지에 대한 선언도 함께 제공됩니다.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "무료인가요? 업무에서 써도 되나요?", + "a": "둘 다 가능합니다. GPL-3.0으로 배포되며 비용이 들지 않습니다. 계정도, 라이선스 키도, 유료 요금제도 없습니다." + }, + { + "q": "생성한 파일을 클로즈드 소스 제품에 써도 되나요?", + "a": "네. 라이선스는 도구의 코드에 적용되며 도구가 만든 것에는 적용되지 않습니다. 생성된 파일, 레시피, 매니페스트는 파생 저작물이 아니라 출력물이므로, 어떤 의무도 없이 커밋하고 배포할 수 있습니다." + }, + { + "q": "생성된 파일에 실제 개인 정보가 들어 있나요?", + "a": "아니요. 내부의 모든 내용은 시드에서 합성됩니다. 어떤 데이터 세트도 읽지 않고, 어떤 서비스에도 접속하지 않으며, 제3자 콘텐츠도 포함하지 않습니다. 생성된 이메일 주소는 아직 쓰이지 않은 주소가 아니라 쓸 수 없는 주소로 여기세요. 임의의 문자열이 우연히 실제 주소와 같을 수 있기 때문입니다." + }, + { + "q": "다른 컴퓨터에서도 완전히 같은 파일이 나오나요?", + "a": "네. 같은 레시피와 같은 시드라면 바이트 단위로 같습니다. 프로젝트는 변경할 때마다 이를 테스트하며, 이를 깨려면 메이저 버전을 올려야 합니다. 그래서 큰 바이너리 픽스처 대신 작은 레시피를 커밋할 수 있습니다." + }, + { + "q": "인터넷 연결이 필요한가요?", + "a": "전혀 필요 없습니다. 텔레메트리도, 업데이트 확인도, 클라우드 클라이언트도 없으며, 명령줄 바이너리에는 네트워크 스택이 아예 컴파일되어 있지 않습니다. 네트워크가 없는 컴퓨터와 폐쇄된 기업 환경에서도 동작합니다." + }, + { + "q": "형식이 도달할 수 없는 크기를 요청하면 어떻게 되나요?", + "a": "형식, 가능한 가장 작은 크기, 그 하한의 이유, 대신 해야 할 일을 알려 주는 오류가 나오고 파일은 쓰이지 않습니다. 도구는 크기를 조용히 반올림하지 않습니다. 모든 하한은 형식 페이지에 나와 있습니다.", + "code": "tfg formats png" + }, + { + "q": "일부러 망가진 파일도 만들 수 있나요?", + "a": "네. --damage zero-head를 추가하면 파일은 요청한 크기 그대로, 첫 바이트가 0으로 덮어쓰인 채 나오므로 리더가 그것을 거부하고, 매니페스트에는 시스템이 그것을 거부해야 한다고 적힙니다. 자세한 내용은 손상된 테스트 파일 페이지에 있습니다.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "다음에는 어떤 형식이 추가되나요?", + "a": "7z, mp3, mp4입니다. 현재 {{ .Facts.FormatCount }}가지 형식이 처음부터 끝까지 동작합니다." + }, + { + "q": "어떤 시스템에서 실행할 수 있나요?", + "a": "명령줄은 Windows와 Linux의 Intel과 ARM, 그리고 Apple Silicon Mac에서 실행됩니다. 데스크톱 창은 Intel의 Windows, Intel의 Linux, Apple Silicon Mac용으로 제공됩니다. Intel Mac은 지원하지 않으며 빌드도 하지 않습니다." + }, + { + "q": "설치해야 하는 것이 있나요?", + "a": "없습니다. 시스템에 맞는 압축 파일을 내려받아 풀고 바이너리를 실행하면 됩니다. 설치 프로그램도, 추가할 런타임도, 해결할 의존성도 없습니다. Go가 있다면 go install 명령 하나로도 됩니다.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "수천 개의 파일을 처리하는 실행이 Windows에서 더 느린 이유는 무엇인가요?", + "a": "Windows는 살펴보는 경로 하나하나에 더 많은 비용을 치르게 하고, 수천 개의 파일을 훑는 명령은 수천 개의 경로를 살펴보기 때문입니다. 1kB 파일 3000개가 있는 한 컴퓨터에서 측정하니 verify는 Windows에서 약 0.9초, 컨테이너 안의 Linux에서 약 0.2초가 걸렸습니다. 출력 경로를 짧게 하면 Windows 수치가 줄어듭니다. 파일 위의 모든 폴더도 살펴보는 대상에 포함되기 때문입니다." + } + ] +} diff --git a/web/content/ko/use-cases.html b/web/content/ko/use-cases.html new file mode 100644 index 00000000..38882e80 --- /dev/null +++ b/web/content/ko/use-cases.html @@ -0,0 +1,116 @@ +

어떤 일에 쓰나요

+

+ 사람들에게서 파일을 받는 거의 모든 프로젝트에 나오는 다섯 가지 작업과, 각각을 처리하는 명령입니다. 아래의 모든 예제는 쓰인 그대로 실행됩니다. +

+ +
+

업로드 한도

+

파일 크기 한도가 말한 위치에서 적용되는지 테스트하기

+

+ 한도는 하나가 아니라 세 개의 테스트 케이스입니다. 바로 아래, 정확히 그 값, 바로 위입니다. 이를 손으로 만들려면 바이트 수를 계산하고 하나 어긋나지 않았기를 바라야 합니다. + 대신 세트를 요청하세요. +

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

+ 1048575, 1048576, 1048577바이트의 실제 PDF 세 개와, 처음 두 개는 수락하고 세 번째는 size_limit으로 거부해야 한다고 알려 + 주는 매니페스트를 얻습니다. 어서션 세 개를 직접 쓰는 대신 테스트가 기대값을 읽으며, 한도가 바뀌면 숫자 하나를 바꾸고 다시 실행하면 됩니다. +

+

+ 경계 세트 하나를 인라인으로 만들고 싶다면 프리셋 없이도 같은 일을 할 수 있습니다. +

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

지속적 통합

+

픽스처를 잃지 않으면서 저장소 밖에 두기

+

+ 큰 바이너리 픽스처는 저장소 복제를 느리게 하고 리뷰를 불편하게 하며, 하나가 교체되어도 무엇이 바뀌었는지 아무도 알 수 없습니다. 레시피는 똑같은 파일을 다시 만드는 몇백 자의 + YAML입니다. 어느 컴퓨터에서나 바이트 단위로 같습니다. 모든 파일이 실행의 시드에서 파생되기 때문입니다. +

+
- 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
+

+ 끝나는 방식마다 고유한 종료 코드가 있으므로 파이프라인은 잘못된 레시피, 디스크 가득 참, 검증 불일치를 구별할 수 있습니다. 실패한 실행은 표준 출력에 아무것도 출력하지 않아 + 로그 파서가 오류를 데이터로 읽지 않습니다. +

+
+ +
+

규모

+

폴더가 클 때 무슨 일이 일어나는지 알아내기

+

+ 가져오기 루틴, 야간 작업, 디렉터리 목록은 파일이 10개일 때와 1만 개일 때 다르게 동작합니다. 범위에서 뽑은 크기는 똑같은 파일 1만 개가 아니라 실제 트래픽처럼 보이는 + 세트를 만들며, 추첨은 시드에서 나오므로 세트는 내일도 같습니다. +

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

+ 합계가 기가바이트 단위일 때는 특히, 무언가를 쓰기 전에 실행 비용을 확인하세요. +

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

+ 디스크 여유 공간보다 큰 실행은 첫 바이트를 쓰기 전에 거부되며, 디스크를 가득 채운 채 중간에 실패하는 일이 없습니다. +

+
+ +
+

아카이브

+

실제로 파일이 들어 있는 아카이브로 압축 해제 기능 테스트하기

+

+ 확장자만 맞는 빈 아카이브는 이를 열어 내용을 순회하는 코드에 대해 아무것도 증명하지 못합니다. 내용을 선언하면 아카이브가 실제로 그것을 담습니다. +

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

+ 중첩 깊이, 항목 수, 내부 내용의 크기는 모두 가져오기 루틴이 나름의 의견을 가진 것들이며, 이것이 그 의견이 무엇인지 알아내는 방법입니다. +

+
+ +
+

파서와 뷰어

+

내 코드가 실제 소프트웨어처럼 형식을 읽는지 확인하기

+

+ 여기 있는 모든 형식은 출시 전에 독립적인 리더로 검증됩니다. PNG는 열어서 픽셀을 비교하고, DOCX는 별도의 라이브러리로 다시 읽고, 아카이브는 풀어 봅니다. 즉 여러분의 + 파서가 거부하는 파일은 생성기가 아니라 여러분의 파서에 대한 발견입니다. +

+
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
+

+ 형식 페이지에 각 형식이 받는 설정과 각각이 될 수 있는 가장 작은 파일이 나와 있습니다. +

+
+ +
+

가이드

+

그중 두 가지를 자세히

+ +
+ +
+

누구를 위한 것인가

+

+ QA 엔지니어, 테스트 자동화, 그리고 코드 뒤에 업로드 양식, 가져오기 루틴, 파서, 저장 용량 할당이 있는 모든 분을 위한 것입니다. 네트워크가 전혀 없는 컴퓨터에서 + 동작하므로, 브라우저 기반 생성기를 쓸 수 없는 폐쇄된 기업 환경에서 특히 중요합니다. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/nl/ci.html b/web/content/nl/ci.html new file mode 100644 index 00000000..91a4c522 --- /dev/null +++ b/web/content/nl/ci.html @@ -0,0 +1,192 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Hoe genereer je testbestanden in een CI-pipeline

+

+ Een binaire fixture in een repository blijft voorgoed in de geschiedenis, kan niet in een diff + worden beoordeeld en wordt onmogelijk zodra het bestand groot is. Genereer de bestanden in plaats + daarvan in de pipeline uit een recept. Het recept is tekst, de bytes komen elke keer hetzelfde uit + en een laatste stap bewijst dat er niets is veranderd. +

+ +
+

Het korte antwoord

+

+ Installeer tfg, voer vóór de tests tfg generate fixtures.yaml --out + ./fixtures uit en erna tfg verify ./fixtures/manifest.json. Beide stappen + laten de build vanzelf mislukken, met een afsluitcode die zegt waarom. +

+
+ +
+

Waarom niet committen

+

Waarom een fixture niet in de repository hoort

+ +

+ Het recept is wat je commit. Hetzelfde recept en dezelfde seed schrijven op elke machine dezelfde + bytes, dus het bestand dat in de pipeline wordt gegenereerd is het bestand dat je op je laptop + had. +

+
+ +
+

Het recept

+

Een recept dat naast de tests staat

+

+ Dit schrijft vijfentwintig facturen die geaccepteerd moeten worden en twee afbeeldingen boven een + limiet die geweigerd moeten worden, en het manifest legt beide verwachtingen vast: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml controleert het zonder iets te schrijven en noemt alle + problemen tegelijk. +

+
+ +
+

GitHub Actions

+

Een workflow die de tool installeert en de fixtures bouwt

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ De regel met de controlesom vergelijkt het archief met verify-SHA256SUMS.txt uit + dezelfde release. De versie is vastgezet, dus een nieuwe release verandert nooit een build die + je niet hebt aangeraakt. +

+
+ +
+

GitLab CI

+

Hetzelfde als GitLab-job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Wanneer het rood wordt

+

Wat een stap laat mislukken, en waarom

+

+ Elk einde heeft zijn eigen afsluitcode, dus de stap mislukt vanzelf en het log zegt welke. De codes + die een pipeline tegenkomt: +

+ +

+ Een mislukte run drukt niets af op de standaarduitvoer, zodat een logparser een fout nooit voor data + aanziet. De hele tabel staat op de documentatiepagina. +

+
+ +
+

PowerShell

+

Een PowerShell-script heeft nog één regel nodig

+

+ PowerShell neemt de afsluitcode van een programma niet mee uit een .ps1-bestand. Start + er een met -File en het script antwoordt 0, ook als de tool erin het + werk weigerde, waardoor een build die rood hoort te zijn groen wordt. De laatste regel is de + hele oplossing: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Zo gedraagt PowerShell zich, het ligt niet aan deze tool. cmd, bash en + zsh hebben niets extra nodig. +

+
+ +
+

Meerdere jobs

+

De fixtures delen tussen jobs

+

+ Uploaden is meestal niet nodig. Omdat hetzelfde recept dezelfde bytes schrijft, kan elke job zijn + eigen tfg generate uitvoeren, wat sneller is dan uploaden en downloaden. Moet een + job bestanden van een andere ontvangen, voer dan na de overdracht tfg verify uit op + het manifest, en het zegt of wat aankwam is wat werd geschreven. +

+
+ +
+

Verder

+

Waar je vandaar heen kunt

+ +
diff --git a/web/content/nl/damage.html b/web/content/nl/damage.html new file mode 100644 index 00000000..c5d39fc4 --- /dev/null +++ b/web/content/nl/damage.html @@ -0,0 +1,178 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Hoe maak je een beschadigd bestand om mee te testen

+

+ Een validator aan wie alleen gezonde bestanden zijn getoond, is niet echt getest. Zo krijg je een + bestand dat met opzet kapot is, precies de grootte heeft die je vraagt en een + manifest meebrengt dat zegt wat je systeem ermee moet doen. +

+ +
+

Het korte antwoord

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out schrijft een PNG + van precies 2097152 bytes waarvan de eerste bytes nullen zijn, en het manifest ernaast legt vast + dat je systeem het moet weigeren. +

+
+ +
+

De gebruikelijke weg

+

Waarom een met de hand beschadigd bestand een slechte test is

+

+ Gebruikelijk zijn een hexeditor, een script dat een paar willekeurige bytes omgooit, of een bestand + dat met head of truncate wordt ingekort. Het werkt één keer, en daarna + kost het je: +

+ +
+ +
+

Wat je krijgt

+

Een beschadigd bestand heeft nog steeds de grootte die je vroeg

+

+ Het bestand wordt normaal gegenereerd en daarna kapotgemaakt, op weg naar de schijf. Het houdt de + grootte die je vroeg, en hetzelfde commando schrijft opnieuw dezelfde bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Instellingen komen achter een dubbele punt. De optie mag herhaald worden, en de beschadigingen + worden toegepast in de volgorde waarin je ze schrijft. Het werkt met elk van de + {{ .Facts.FormatCount }} formaten. +

+
+ +
+

Wat het kan

+

Welke beschadigingen zijn er?

+

+ Dit is de lijst die het programma afdrukt, uit het programma gelezen op het moment dat deze pagina + wordt gebouwd. tfg damage drukt dezelfde af, en tfg damage <id> + zegt wat één ervan aanneemt. +

+ {{ template "damagesTable" . }} +

+ zero-head schrijft nullen over het begin van het bestand. De meeste lezers kijken daar + eerst, naar de handtekening en de kop die zeggen wat het bestand is, dus bijna elke lezer merkt + het. Platte tekst en logbestanden hebben geen handtekening en worden ook geweigerd, omdat een + reeks nulbytes geen tekst is. Onder vier bytes komen sommige formaten uit met schade waar geen + lezer over klaagt, en daarom begint de instelling bij vier. +

+
+ +
+

Wat het manifest zegt

+

Een manifest dat zegt wat er moet gebeuren

+

+ Elk beschadigd bestand krijgt een regel die zegt dat je systeem het moet weigeren, met de + beschadiging ernaast vastgelegd: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Twee verzoeken worden geweigerd voordat er iets wordt geschreven, omdat elk een bestand op schijf + zou laten staan dat het manifest verkeerd beschrijft: +

+ +
+ +
+

In een recept

+

Gezonde en kapotte bestanden in één run

+

+ Zet beide in één recept, en het manifest draagt de verwachting van elk bestand, zodat de test geen + lijst nodig heeft van welk bestand welk is: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In een test

+

Er een test van maken

+

+ De test leest het manifest en controleert dat wat er gebeurde is wat er werd opgegeven. Hij heeft + geen lijst met bestandsnamen nodig: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Een goede weigering is een schone weigering. Een melding die zegt wat er mis was, is het antwoord + dat je wilt. Een serverfout, een vastloper of een half opgeslagen bestand is het gebrek dat deze + test moet vinden. +

+
+ +
+

Verder

+

Waar je vandaar heen kunt

+ +
diff --git a/web/content/nl/docs.html b/web/content/nl/docs.html new file mode 100644 index 00000000..f6527f34 --- /dev/null +++ b/web/content/nl/docs.html @@ -0,0 +1,285 @@ +

Documentatie

+

+ Alles wat de tool doet, geordend als de vragen waarmee mensen echt komen. De + README in de repository is de volledige referentie en komt altijd + overeen met de build die je hebt gedownload. +

+ +
+

Welke opdrachten zijn er?

+

Elke doet precies één ding:

+ {{ template "commandList" . }} +
+ +
+

Hoe genereer ik één bestand van een exacte grootte?

+

+ Noem het formaat, de grootte en waar het naartoe moet. Groottes tellen in 1024-tallen, dus + 2mb is 2097152 bytes. Een gewoon aantal bytes werkt ook, dus --size + 10485761 vraagt precies zoveel. +

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

De nuttige opties van generate:

+
+ + + + + + + + + + + + + + + + + +
OptieWat het doet
--format <id>formaat van de bestanden, bijvoorbeeld txt
--size <size>exacte grootte van elk bestand, zoals 10mb of een gewoon aantal bytes
--size-range <a-b>een grootte die per bestand uit een bereik wordt getrokken, zoals 1kb-8kb. De trekking komt uit de seed
--boundary <size>drie bestanden rond een limiet: één byte eronder, de limiet, één byte erboven
--count <n>hoeveel bestanden te maken. Standaard 1
--name <template>naamsjabloon, bijvoorbeeld invoice_{index:04}.txt
--out <dir>map om naartoe te schrijven
--seed <n>seed van de run. Dezelfde seed geeft dezelfde bytes
--set <k>=<v>een formaatinstelling, herhaalbaar
--damage <name>de bestanden met opzet beschadigen, herhaalbaar en in volgorde toegepast. Draai tfg damage voor de lijst
--expected <outcome>accept, reject, sanitize of unspecified
--dry-runtellen en tonen, helemaal niets schrijven
--jsonhet manifest naar de standaarduitvoer schrijven
+
+
+ +
+

Hoe maak ik een bestand dat met opzet kapot is?

+

+ Elk ander bestand dat deze tool schrijft is correct per constructie, wat twee van de drie vragen + beantwoordt die een uploadvalidator stelt. --damage beantwoordt de derde - gaat het + bestand überhaupt open. Het bestand wordt normaal gemaakt en daarna beschadigd, dus het heeft + nog steeds de grootte die je vroeg. +

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

+ Instellingen komen na een dubbele punt. De optie herhaalt zich, en de volgorde waarin je ze schrijft + is de volgorde waarin ze worden toegepast. tfg damage toont wat deze build kan en + wat elke variant accepteert. +

+

In een recept is de sleutel een lijst, van namen of van instellingen:

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

+ Een beschadigd bestand krijgt expected: reject in het manifest, met de beschadiging + ernaast vastgelegd. Twee dingen worden geweigerd voordat er iets wordt geschreven, omdat elk + anders een bestand op schijf zou zetten dat het manifest verkeerd beschrijft: +

+ +

+ Een derde is vooraf niet te weten. Als een beschadiging draait en geen enkele byte verschuift, wordt + dat bestand weggegooid in plaats van geschreven - de run gaat door, zegt om welk bestand het + ging en eindigt met de gedeeltelijke afsluitcode. +

+

+ Stap voor stap, met een test die het manifest leest: hoe + maak je een beschadigd bestand om mee te testen. +

+
+ +
+

Hoe ziet een recept eruit?

+

+ Een recept is een YAML-bestand dat een hele run beschrijft. Commit het naast je tests en de fixtures + zijn geen binaries meer in je repository - iedereen kan ze byte voor byte opnieuw opbouwen uit + een bestand van een paar honderd tekens. +

+
# 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
+

+ Elk target heeft precies één van deze sleutels nodig: size, size-range, + boundary of contains. Twee is een fout en geen ook. Een ongeldig + recept schrijft helemaal geen bestanden en meldt alle problemen tegelijk in + plaats van alleen het eerste, elk met de instelling waar het over gaat. +

+
+ +
+

Hoe leg ik vast wat mijn systeem met een bestand moet doen?

+

Korte vorm als de uitkomst genoeg is, lange vorm als de reden ertoe doet:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ De uitkomsten zijn accept, reject, sanitize en + unspecified. De redenen zijn een gesloten lijst zodat een rapport erop kan + groeperen: 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 en + size_zero. +

+

+ Een reden noemt de regel die in het spel is, niet het oordeel. Daarom kan dezelfde + reden onder beide uitkomsten staan - een bestand één byte onder een limiet is + accept, en de regel waar het om gaat is nog steeds size_limit. +

+
+ +
+

Wat staat er in het manifest?

+

+ Het wordt aan het einde van elke run naast de bestanden geschreven, ook bij een onderbroken run. Eén + item per bestand: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Er komt een recipe_hash bij als de run uit een recept kwam, en preset met + overrides als hij uit een preset kwam, zodat een manifest altijd te herleiden is + tot wat het maakte. +

+

+ Elk item draagt ook target_id, de id van het target in het recept dat het bestand + maakte, en summary.by_target telt de bestanden waar elk target op uitkwam. Een + recept met meerdere targets kan zo target voor target worden gecontroleerd zonder bestandsnamen + te lezen. +

+
+ +
+

Wat is een preset?

+

+ Een kant-en-klare set bestanden die een veelvoorkomende testvraag beantwoordt, zodat je de set niet + zelf hoeft te ontwerpen. Presets zijn gewone recepten onder de motorkap, en eject + drukt het recept af zodat je het vanaf daar kunt bewerken. Elke preset heeft + een eigen pagina met wat hij meestal vindt, wat er in de set zit en + welke instellingen hij kent. +

+ {{ template "presetsList" . }} +
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 zegt je wat de set zou kosten voordat je hem bouwt, en zegt zonder omwegen wanneer + een getal een tijdelijke waarde van ons is in plaats van een limiet van jou. +

+
+ +
+

Wat betekenen de afsluitcodes?

+

+ Elk einde heeft zijn eigen code, machineleesbare uitvoer gaat naar de standaarduitvoer, en een + mislukte run drukt daar niets af. De tabel is een bevroren contract - de betekenis van een code + wijzigen vereist een major-versie. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Een run die met Ctrl+C is gestopt laat nog steeds een manifest achter en nooit een half geschreven + bestand, zodat een afgebroken taak door de volgende nog kan worden opgeruimd. +

+

+ Kant-en-klare workflows voor GitHub Actions en GitLab CI: hoe + genereer je testbestanden in een CI-pipeline. +

+
+ +
+

Is er een bureaubladvenster?

+

+ Ja, dezelfde engine met een venster erop, voor het testen dat niet geautomatiseerd is. Het is geen + uitgeklede versie: een test vergelijkt de twee interfaces mogelijkheid voor mogelijkheid, en + alles wat maar één van beide kan moet worden verklaard en gerechtvaardigd in plaats van + ongemerkt uit elkaar te drijven. +

+

+ De schermen zijn één batch, presets, meerdere batches tegelijk en info. Het toont wat een run zou + kosten voordat er iets wordt geschreven, meldt de voortgang terwijl het draait en kan halverwege + worden afgebroken zonder een half geschreven bestand achter te laten. Het opent nog geen + receptbestand - recepten zijn voorlopig iets van de opdrachtregel, en het venster bouwt zijn + batches in het formulier. +

+
diff --git a/web/content/nl/exact-size.html b/web/content/nl/exact-size.html new file mode 100644 index 00000000..b7e86c8f --- /dev/null +++ b/web/content/nl/exact-size.html @@ -0,0 +1,149 @@ +

Hoe maak je een bestand van een exacte grootte

+

+ Elk systeem heeft er een opdracht voor, en alle drie staan hieronder. Ze geven je een bestand met + precies het juiste aantal bytes - en voor veel tests is dat alles wat je nodig hebt. Elke + opdracht op deze pagina is uitgevoerd vóór publicatie, op het systeem waartoe hij + behoort. +

+ +
+

Het korte antwoord

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Groottes zijn in bytes, en 10 MB + geteld zoals je bestandsbeheer telt is 10485760. +

+
+ +
+

Windows

+

fsutil, en een PowerShell-versie die niets extra's nodig heeft

+

+ fsutil wordt met Windows meegeleverd. Het neemt de grootte in bytes, + reken het getal dus eerst uit - 10 MB is 10485760, 100 MB is 104857600, 1 GB is 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Gemeten op Windows 11: het werkt vanaf een gewone prompt en heeft geen verhoogde nodig, en het + bestand komt uit op precies 10485760 bytes. +

+

PowerShell kan hetzelfde zonder een ander programma aan te roepen, en begrijpt eenheden:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB betekent in PowerShell 10485760 bytes, dezelfde telling op basis van 1024 die + Verkenner gebruikt, dus de twee opdrachten hierboven geven dezelfde grootte. +

+
+ +
+

Linux

+

dd, truncate en fallocate, en het verschil dat mensen te pakken neemt

+

dd is degene die iedereen kent. Het schrijft de bytes echt:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate is direct klaar, en dat is de adder onder het gras. Gemeten op Alpine Linux + meldt het bestand 10485760 bytes en neemt het nul blokken in beslag - het is + een sparse bestand. Alles wat het leest krijgt tien megabyte aan nullen, maar + de schijf heeft de ruimte nooit afgestaan: +

+
truncate -s 10M test10mb.bin
+

+ Dat is prima om een uploadlimiet te testen en misleidend om een schijfquotum te testen. + fallocate is degene waar je naar grijpt als de ruimte echt moet zijn: +

+
fallocate -l 10M test10mb.bin
+

En als de inhoud onsamendrukbaar moet zijn, zodat een archiefprogramma hem niet weer kan verkleinen:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, dat niet sparse is, en de twee die je al kent

+

+ macOS levert mkfile mee. Gemeten op macOS 26.6.2: 10485760 bytes en 20480 blokken, dus + de ruimte is echt toegewezen in plaats van beloofd: +

+
mkfile 10m test10mb.bin
+

dd en truncate zijn er ook en gedragen zich zoals op Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Waar dit ophoudt te werken

+

Een bestand van de juiste grootte is geen bestand van het juiste soort

+

+ Alles hierboven geeft je een blok nullen. Dat is genoeg als wat getest wordt alleen naar de grootte + kijkt - een uploadlimiet, een quotum, een overdracht. Het is niet meer genoeg zodra iets het + bestand opent. +

+

+ Gemeten, en het is de moeite waard om het zelf te doen: maak een bestand van 2 MB met + fsutil, noem het photo.png en geef het aan een afbeeldingsbibliotheek. + Pillow antwoordt cannot identify image file. Het is geen PNG. Dat is het ook nooit + geweest - alleen de naam zei het. +

+

+ Dat doet er meer toe dan het klinkt, vanwege de kant waarop de test dan faalt. Je + upload-endpoint weigert het bestand, je test wordt groen en je concludeert dat de groottelimiet + werkt. Het weigerde het niet vanwege de grootte. Het weigerde het omdat de bytes geen afbeelding + waren, en de regel die je wilde testen is nooit bereikt. +

+ +
+ +
+

De andere weg

+

Een echt bestand van dat formaat, in precies de grootte die je vroeg

+

+ Dit is wat Testing Files Generator doet. Het bestand is een echt bestand van zijn formaat - het + opent in het programma waartoe het behoort - en het heeft het exacte aantal bytes dat je vroeg, + tot op de byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Vraag een grootte die een formaat niet kan halen en je krijgt een fout die de ondergrens en de reden + noemt, nooit een bestand van de verkeerde grootte. De pagina met + formaten toont elk formaat met het kleinste bestand dat het kan maken. +

+

En een limiet is drie testgevallen in plaats van één, dus de tool bouwt ze alle drie:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Dat geeft je 10485759, 10485760 en 10485761 bytes, en een manifest dat zegt welke je systeem moet + accepteren en welke het moet weigeren. De pagina met + toepassingen loopt dat en vier andere taken door waarvoor het is gebouwd. +

+ {{ template "downloadCta" . }} +
+ +
+

Dus wat moet je gebruiken?

+ +

+ Beide staan op deze pagina omdat beide soms goed zijn. De fout die je moet vermijden is de eerste + gebruiken waar de tweede nodig is en de groene test als bewijs lezen. +

+
diff --git a/web/content/nl/faq.html b/web/content/nl/faq.html new file mode 100644 index 00000000..901354b5 --- /dev/null +++ b/web/content/nl/faq.html @@ -0,0 +1,20 @@ +

Veelgestelde vragen

+

+ Licentie, privacy, reproduceerbaarheid en de dingen die mensen nagaan voordat ze een generator in + een buildpipeline zetten. Staat je vraag er niet bij, dan staat de + issuetracker open. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Nog aan het twijfelen?

+

+ De pagina met toepassingen toont de taken waarvoor het is gebouwd, + en de pagina met formaten toont elk formaat met het kleinste bestand + dat het kan maken. De README in de repository is de volledige + referentie. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/nl/formats.html b/web/content/nl/formats.html new file mode 100644 index 00000000..688b9410 --- /dev/null +++ b/web/content/nl/formats.html @@ -0,0 +1,81 @@ +

{{ .Facts.FormatCount }} bestandsformaten, elk gegenereerd in een exacte grootte

+

+ Elk daarvan is een echt bestand van dat formaat. Het opent in het programma waartoe + het behoort en is precies het aantal bytes dat je vroeg. Geen enkele is opgevulde nullen met een + extensie eraan geplakt. +

+ +{{ template "formatsTable" . }} + +
+

Wat de kolommen betekenen

+ +

+ Elk formaat herhaalt zich ook tot op de byte: hetzelfde recept en dezelfde seed geven op elke + machine identieke bestanden, en daardoor is het veilig een recept te committen in plaats van de + fixtures zelf. +

+
+ +
+

Instellingen die elk formaat accepteert

+

+ De meeste formaten hebben eigen instellingen - afbeeldingsafmetingen, JPEG-kwaliteit, aantal + PDF-pagina's, rijen en kolommen in een spreadsheet, hoeveel items er in een archief zitten. Stel + ze in met --set key=value op de opdrachtregel, of onder properties: in + een recept. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Een waarde buiten wat een instelling accepteert wordt geweigerd met een melding die de instelling, + het toegestane bereik en het alternatief noemt. Een onbekende instelling is ook een fout, nooit + een stille standaardwaarde - een stilzwijgend geaccepteerde typefout geeft een bestand met de + verkeerde instellingen en een uur zoeken waarom de test slaagt terwijl dat niet zou moeten. +

+

+ Draai tfg formats <id> om precies te zien wat één formaat accepteert in de build + die je hebt. +

+
+ +
+

Archieven bevatten echte bestanden

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} en {{ end }}{{ $c.ID }}{{ end }} + kunnen met items worden gevuld in plaats van als lege huls te blijven. Een gegenereerd archief + bevat echt de documenten die het zegt te bevatten, dus alles wat het tijdens een test uitpakt + vindt er echte bestanden in. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/nl/index.html b/web/content/nl/index.html new file mode 100644 index 00000000..90fe263d --- /dev/null +++ b/web/content/nl/index.html @@ -0,0 +1,196 @@ +
+
+

Genereer echte testbestanden in elke exacte grootte

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formaten in totaal, en elk is een + echt bestand dat opent in het programma waartoe het behoort, in precies de grootte die + je vroeg. Elke run schrijft ook op wat je applicatie met elk bestand moet doen. + Opdrachtregel en bureaubladvenster, gratis en open source, volledig op je eigen machine. +

+ + {{ template "downloadCta" . }} +
+ +
+ Het bureaubladvenster van Testing Files Generator, klaargezet om een reeks testbestanden te schrijven +
Het bureaubladvenster, klaargezet om een reeks bestanden te schrijven. Dezelfde engine draait achter de opdrachtregel.
+
+
+ + + +
+

Het probleem

+

Eén testbestand maken is makkelijk. De juiste duizend maken is het vervelende deel

+

Je test software die bestanden van mensen aanneemt. Vroeg of laat heb je nodig:

+ +

+ Dat is wat dit vervangt. Het is gebouwd voor QA-engineers, testautomatisering en iedereen wiens code + een uploadformulier, een importroutine, een parser of een opslagquotum achter zich heeft. +

+
+ +
+

Wat het anders maakt

+

Andere generatoren stoppen bij de bytes. Deze beantwoordt wat je test werkelijk vraagt

+

+ Een map met bestanden laat je nog steeds beslissen wat elk bestand moet bewijzen. Elke run schrijft + hier een manifest.json naast de bestanden - een eenvoudige lijst van alles wat is + gemaakt, en bij elk item een gedeclareerde verwachting. +

+

Stel dat je upload-endpoint 1 MB toestaat. Vraag de drie bestanden die op die lijn zitten:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
BestandBytesJe systeem moetOmdat
1mb_under_1b.pdf1048575accepterenhet valt binnen de limiet
1mb_at_limit.pdf1048576accepterende limiet zelf is toegestaan
1mb_over_1b.pdf1048577weigerensize_limit
+
+ +

Drie bestanden, drie verschillende antwoorden, in machineleesbare vorm. Je test leest het manifest in plaats van dat jij de asserties met de hand schrijft:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Waar het antwoord van je eigen beleid afhangt, zegt het manifest dat

+

+ Het legt unspecified vast in plaats van een verwachting te verzinnen. Een generator die + gokt levert valse fouten op, en een suite die loos alarm slaat wordt uitgezet. +

+
+
+ +
+

Presets

+

Kies de vraag, krijg de hele set

+

+ Een preset is een set testbestanden ontworpen rond één testvraag, zodat je zelf niet hoeft uit te + zoeken welke bestanden wat bewijzen. Elke heeft een pagina die zegt wat hij meestal vindt, wat + er in de set zit en welke instellingen hij kent. +

+ {{ template "presetsList" . }} +

Alle presets, en hoe ze zich tot recepten verhouden

+
+ +
+

Snel starten

+

Drie opdrachten om het te zien werken

+
    +
  1. +

    Maak een bestand

    +

    Eén PNG, precies twee megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Maak veel bestanden

    +

    + Tienduizend logbestanden, elk tussen één en acht kilobyte, met groottes getrokken uit de seed zodat + morgen dezelfde set oplevert. Geef elke run een eigen map - het manifest is + het enige verslag van wat een run schreef, dus de tool weigert er een tweede overheen te + schrijven: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Controleer ze en verwijder ze dan

    +

    verify zegt je dat er niets verschoven is. cleanup verwijdert precies wat is geschreven en niets anders:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Groottes tellen in 1024-tallen, zoals je bestandsbeheer doet, dus 2mb betekent 2097152 + bytes. Een gewoon aantal bytes werkt ook. De documentatie + behandelt recepten, het manifest en de afsluitcodes. +

+
+ +
+

Wat je krijgt

+

Gebouwd voor een suite die onbeheerd draait

+ +
+ +
+

Download

+

Kies de build voor je systeem

+

+ Pak het archief uit en start het. tfg is de opdrachtregel en tfg-gui is + het bureaubladvenster. Er is geen installatieprogramma en niets om aan je machine toe te voegen. +

+ {{ template "downloadsTable" . }} +
+

Wat is ondertekend, en wat niet

+

+ De downloads voor Windows en macOS zijn ondertekend, dus ze starten zonder waarschuwing over een + onbekende ontwikkelaar. Die voor Linux niet, omdat desktop-Linux niets vergelijkbaars heeft om + ze mee te ondertekenen. Elk archief staat in verify-SHA256SUMS.txt op de + releasepagina, zodat je kunt controleren wat je hebt gedownload. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/nl/preset.html b/web/content/nl/preset.html new file mode 100644 index 00000000..723dbfb0 --- /dev/null +++ b/web/content/nl/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ De preset {{ .ID }} bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ +{{ if .Catches }} +
+

Wat vindt hij meestal?

+ +
+{{ end }} + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show {{ .ID }} het meldt:

+
+ + + + + + + +
Bestanden{{ .Budget.Files }}
Targets in het recept{{ .Budget.Targets }}
Totale grootte{{ .Bytes }} B
Formaten{{ join .Budget.Formats ", " }}
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
VerwachtBetekenisBestanden
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Wat kun je wijzigen?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
InstellingAccepteertStandaardWat het doet
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Deze standaardwaarde is onze tijdelijke waarde, niet de waarde van je systeem. Geef je eigen op.{{ end }}
+
+ {{- else }} +

Deze preset heeft geen instellingen. De set is elke keer dezelfde.

+ {{- end }} +
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/nl/presets.html b/web/content/nl/presets.html new file mode 100644 index 00000000..ebfabce3 --- /dev/null +++ b/web/content/nl/presets.html @@ -0,0 +1,31 @@ +

Presets voor testbestanden, een set voor elke testvraag

+

+ Een preset is een hele set testbestanden ontworpen rond één vraag, met een manifest dat zegt hoe je + systeem op elk bestand moet reageren. Jij kiest de vraag, de tool bouwt de set. Elke preset heeft + een eigen pagina met wat hij meestal vindt, wat er in de set zit en welke instellingen hij kent. +

+ +{{ template "presetsList" . }} + +
+

Hoe verschilt een preset van een recept?

+

+ Eronder niet. Een preset is een recept dat de tool voor je schrijft uit een paar instellingen. + tfg preset eject drukt dat recept af zodat je het naast je tests kunt bewaren en + bewerken, en een eigen recept kan met één regel op een preset voortbouwen, extends: + preset: gevolgd door zijn id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Kan ik de standaardwaarden vertrouwen?

+

+ Voor de bestanden wel. Voor een getal dat alleen je systeem kent, zoals de limiet van een + uploadformulier, is een standaardwaarde een tijdelijke waarde van ons, en de tool zegt dat elke + keer dat hij er een gebruikt. De pagina van elke preset markeert die instellingen, en tfg + preset show zegt het voordat er iets wordt geschreven. +

+
diff --git a/web/content/nl/site.json b/web/content/nl/site.json new file mode 100644 index 00000000..93c57e0b --- /dev/null +++ b/web/content/nl/site.json @@ -0,0 +1,328 @@ +{ + "code": "nl", + "locale": "nl_NL", + "name": "Nederlands", + "dir": "nl", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Home", + "title": "Testbestanden genereren - exacte grootte, {{ .Facts.FormatCount }} echte formaten", + "description": "Gratis open source generator van testbestanden voor QA. Echte PDF-, DOCX-, PNG- en ZIP-bestanden in exacte grootte, met een manifest over de verwachte reactie." + }, + { + "key": "formats", + "slug": "formaten", + "nav": "Formaten", + "title": "{{ .Facts.FormatCount }} ondersteunde bestandsformaten - PDF, DOCX, PNG, ZIP en meer", + "description": "Alle bestandsformaten die deze generator maakt, het kleinst mogelijke bestand per formaat en hun instellingen. Alle {{ .Facts.FormatCount }} openen in hun eigen programma." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Presets", + "title": "Presets voor testbestanden - kant-en-klare sets voor QA", + "description": "Kant-en-klare sets testbestanden, elk beantwoordt een testvraag: uploadlimieten, bestandsnamen, tekencoderingen, tabelimport, lege bestanden en uploadvalidatie." + }, + { + "key": "docs", + "slug": "documentatie", + "nav": "Documentatie", + "title": "Documentatie - opdrachten, recepten, manifest, afsluitcodes", + "description": "Hoe je testbestanden genereert vanaf de opdrachtregel of met een YAML-recept, wat het manifest bevat en wat elke afsluitcode betekent wanneer de tool in CI draait." + }, + { + "key": "use-cases", + "slug": "toepassingen", + "nav": "Toepassingen", + "title": "Toepassingen - uploadlimieten, CI-fixtures, massatests", + "description": "Een uploadlimiet testen, reproduceerbare fixtures voor CI bouwen, tienduizend bestanden genereren en archieven vullen met echte inhoud." + }, + { + "key": "exact-size", + "slug": "bestand-met-exacte-grootte-maken", + "nav": "Exacte grootte", + "title": "Een bestand van een exacte grootte maken - Windows, Linux, macOS", + "description": "fsutil, dd, truncate en mkfile, elk gemeten op het systeem waarvoor het bedoeld is, en waarom zo'n bestand geen PDF of PNG is wanneer een test dat nodig heeft." + }, + { + "key": "faq", + "slug": "veelgestelde-vragen", + "nav": "FAQ", + "title": "FAQ - vragen over het genereren van testbestanden", + "description": "Hoe dit verschilt van dd en fsutil, of je de bestanden kunt committen, of runs byte voor byte herhaalbaar zijn en wat er gebeurt als een grootte onhaalbaar is." + }, + { + "key": "damage", + "slug": "beschadigde-testbestanden", + "nav": "Beschadigde bestanden", + "title": "Beschadigde testbestanden - kapotte bestanden op exacte grootte", + "description": "Een bestand dat met opzet kapot is, op exacte grootte, met een manifest dat zegt dat je systeem het moet weigeren. Voor het testen van uploadvalidatie en parsers.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "testbestanden-in-ci", + "nav": "Testbestanden in CI", + "title": "Testbestanden in CI - GitHub Actions, GitLab CI en PowerShell", + "description": "Genereer testbestanden in de pipeline in plaats van binaire bestanden te committen: GitHub Actions-workflow, GitLab-job, afsluitcodes en de PowerShell-valkuil.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Direct naar de inhoud", + "navLabel": "Hoofdmenu", + "langLabel": "Taal", + "breadcrumbHome": "Home", + "imageAlt": "Testing Files Generator - echte testbestanden in elke exacte grootte, met een manifest dat zegt hoe je systeem op elk bestand moet reageren", + "schemaDescription": "Een gratis open source generator van testbestanden voor QA. Hij maakt echte bestanden in {{ .Facts.FormatCount }} formaten in elke exacte grootte en schrijft een manifest dat zegt hoe het geteste systeem op elk bestand moet reageren.", + "ctaDownload": "Downloaden", + "ctaSource": "Bekijk de broncode", + "ctaNote": "Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.", + "colFormat": "Formaat", + "colName": "Naam", + "colExtension": "Extensie", + "colSmallest": "Kleinste bestand", + "colFidelity": "Volledigheid", + "colChecked": "Gecontroleerd met", + "colSetting": "Instelling", + "colAccepts": "Accepteert", + "colSystem": "Systeem", + "colCli": "Opdrachtregel", + "colWindow": "Bureaubladvenster", + "noBinary": "nog geen binary", + "colCode": "Code", + "colMeaning": "Betekenis", + "footerBlurb": "Testbestanden voor QA, in elke exacte grootte, met een manifest dat zegt hoe je systeem op elk bestand moet reageren.", + "footerProject": "Project", + "footerSource": "Broncode op GitHub", + "footerReleases": "Downloads", + "footerIssues": "Een probleem melden", + "footerSupport": "Steun het project", + "footerPages": "Pagina's", + "footerLicence": "Copyright (C) 2026 DonislawDev. Uitgebracht onder de GNU General Public License, versie 3. De bestanden die je genereert zijn van jou - de licentie geldt voor de tool, niet voor de uitvoer.", + "footerPrivacy": "Deze site laadt nergens vandaan lettertypen, scripts of trackers. Hij plaatst geen cookies.", + "notFoundTitle": "Die pagina bestaat niet", + "notFoundLead": "Het adres dat je volgde komt met geen enkele pagina op deze site overeen.", + "notFoundBack": "Naar de startpagina", + "read.format": "Het formaat van elk bestand in de set. Het is een optie van de tool zelf, en de preset geeft er alleen een standaardwaarde aan.", + "readTakes.format": "een formaat-id van de pagina met formaten", + "colDamage": "Beschadiging", + "colEffect": "Wat het met de bytes doet", + "colSettings": "Instellingen", + "noSettings": "geen" + }, + "endings": { + "0": "Alles werkte.", + "1": "Een onverwachte fout in de tool.", + "2": "Verkeerde opdracht of optie.", + "3": "Het recept is niet geldig.", + "4": "Het formaat kan niet wat er gevraagd werd.", + "5": "Een lees- of schrijfactie is mislukt.", + "6": "Niet genoeg schijfruimte.", + "7": "verify vond een afwijking.", + "8": "De run is klaar, maar niet alles is gemaakt.", + "130": "Onderbroken met Ctrl+C.", + "143": "Gestopt door een signaal, zo ziet een CI-timeout eruit." + }, + "presets": { + "empty-and-minimal": { + "question": "Komt een geldig bestand dat zo klein is als het formaat toestaat door de controle?", + "title": "Leeg en minimaal", + "pageTitle": "Kleinste geldige en lege testbestanden in elk formaat", + "description": "Het kleinste geldige bestand dat deze tool schrijft in elk van zijn {{ .Facts.FormatCount }} formaten, plus een leeg bestand waar het formaat dat toestaat, elk met de verwachte reactie.", + "catches": [ + "een geldig bestand dat als te klein wordt geweigerd, omdat de controle bytes telt in plaats van ze te lezen", + "een leeg bestand dat de lezer laat crashen in plaats van gemeld te worden", + "een afbeelding van één pixel breed die op weg naar het miniatuur door nul deelt", + "opslag die nul bytes als een mislukte upload leest en blijft opnieuw proberen" + ], + "details": { + "formats": "Uit welke formaten de set is opgebouwd. Laat het op all staan voor elk formaat van deze build, of noem de formaten die je systeem accepteert." + } + }, + "filename-handling": { + "question": "Slaat mijn systeem een bestandsnaam op, toont en geeft het die terug, ook als het die niet verwachtte?", + "title": "Omgaan met bestandsnamen", + "pageTitle": "Lastige bestandsnamen om te testen - Unicode en lengte", + "description": "Testbestanden met namen die uploads en opslag laten haperen: andere schriften, emoji, omgekeerde schrijfrichting, onzichtbare tekens, shell- en SQL-syntaxis.", + "catches": [ + "een naam die er op het scherm, in een log of in een lijst als een andere uitziet", + "een naam die tussen upload en opslag wordt afgekapt, ingekort of herschreven", + "een lengtelimiet die in tekens wordt geteld waar de opslag bytes telt" + ], + "details": {} + }, + "size-boundaries": { + "question": "Wordt een groottelimiet precies afgedwongen waar hij is opgegeven?", + "title": "Groottegrenzen", + "pageTitle": "Een uploadlimiet testen - bestanden precies op de grens", + "description": "Bestanden één byte onder, precies op en één byte boven de limiet van je systeem, plus bredere stappen aan beide kanten, elk gemarkeerd of het geaccepteerd moet worden.", + "catches": [ + "off-by-one-fouten bij de limiet", + "MB verward met MiB, wat 4,8 procent is en genoeg om een bestand door te laten dat niet door zou mogen", + "een limiet die in de browser wordt afgedwongen en niet op de server" + ], + "details": { + "limit": "De groottelimiet die je systeem opgeeft. Al het andere wordt hiervan afgemeten.", + "spread": "Hoe ver aan beide kanten van de limiet te gaan, als een lijst met groottes." + } + }, + "tabular-import": { + "question": "Overleeft mijn tabelimport wat echte tools exporteren?", + "title": "Tabelimport", + "pageTitle": "Testbestanden voor CSV- en Excel-import - scheidingstekens", + "description": "CSV met andere scheidingstekens, CR LF-regeleinden, zonder koprij en met andere aanhalingstekens, een heel brede tabel, een Excel-werkmap en JSON in meerdere lay-outs.", + "catches": [ + "een bestand met puntkomma's dat als één kolom wordt gelezen, omdat het scheidingsteken is aangenomen in plaats van gezocht", + "een CRLF-bestand dat in rijen wordt gesplitst met na elke rij een lege rij", + "een tabel zonder koprij waarvan de eerste gegevensrij als kolomnamen wordt opgegeten", + "een import die de kolommen houdt die hij kan tonen en de rest zonder een woord weggooit", + "een lezer die JSON-records regel voor regel leest en stopt bij het eerste ingesprongen document" + ], + "details": { + "rows": "Hoeveel rijen de spreadsheet bevat. Het bestand wordt precies zo groot geschreven als zoveel rijen verpakt worden, dus het budget hierboven verschuift met deze waarde.", + "columns": "Hoeveel kolommen elke rij van de spreadsheet heeft. Rijen maal kolommen heeft een plafond, en erboven vragen wordt geweigerd voordat er iets geschreven wordt." + } + }, + "text-encoding": { + "question": "Weet mijn lezer in welke codering een bestand staat, of gokt hij?", + "title": "Tekencodering", + "pageTitle": "Testbestanden voor tekencodering - UTF-8, UTF-16, BOM, CRLF", + "description": "Dezelfde tekst in UTF-8, UTF-16LE en UTF-16BE, met en zonder byte order mark, en regeleinden in CR LF en LF, om te testen hoe een lezer tekst decodeert.", + "catches": [ + "een lezer die UTF-8 aanneemt en een UTF-16-bestand toont als één teken op de drie, of als rijen vakjes", + "een byte order mark die als inhoud wordt gelezen, zodat het eerste veld van een import met drie vreemde tekens begint", + "een importeur die de codering uit de eerste bytes raadt en bij een langer bestand anders raadt", + "een CRLF-bestand dat in rijen wordt gesplitst met na elke rij een lege rij, of een regelterugloop die in het laatste veld blijft staan" + ], + "details": { + "sample": "Hoe groot elk bestand van de set is. UTF-16 slaat twee bytes per teken op, dus een oneven getal wordt geweigerd." + } + }, + "upload-validation": { + "question": "Neemt mijn uploadformulier aan wat het moet en weigert het de rest?", + "title": "Uploadvalidatie", + "pageTitle": "Testbestanden voor uploadvalidatie - type, grootte en naam", + "description": "Bestanden om een uploadformulier te testen: toegestane en geweigerde typen, inhoud die niet bij de extensie past, groottelimiet, vijandige namen en een bulkupload.", + "catches": [ + "een limiet die in de browser wordt afgedwongen en niet op de server", + "een SVG- of HTML-bestand dat voor een afbeelding of platte tekst wordt aangezien, een manier om een script langs een formulier te smokkelen", + "een bestand dat op extensie wordt gecontroleerd en nooit geopend, zodat een PDF met de naam .jpg erdoor komt", + "een formulier dat de hele body in het geheugen leest voordat het kijkt hoe groot hij is", + "een upload met de naam PHOTO.JPG die wordt geweigerd terwijl photo.jpg wordt aangenomen, of andersom", + "een naam met spaties, haakjes of tekens buiten ASCII die ongewijzigd naar schijf wordt geschreven" + ], + "details": { + "limit": "De groottelimiet die je uploadformulier opgeeft. Deze set zet één stap aan beide kanten - voor een bestand op elke afstand draai je de preset size-boundaries.", + "allow": "Welke typen je formulier moet accepteren. Elk wordt een echt bestand van dat type, en ze vormen de positieve controle van de hele set.", + "deny": "Welke extensies je formulier moet weigeren. Een extensie waarvoor deze build geen formaat heeft, krijgt toch een bestand met die naam, met platte tekst erin.", + "far-over": "Hoe ver boven de limiet het ene grote bestand komt. Zet het uit waar het schrijven van een veelvoud van de limiet de schijfruimte niet waard is.", + "bulk": "Hoeveel bestanden de bulkupload bevat. Nul laat die groep helemaal uit de set." + } + } + }, + "commands": { + "generate": "bestanden maken, uit een recept of met opties", + "validate": "een recept controleren en niets schrijven", + "verify": "een map controleren tegen een manifest", + "cleanup": "de bestanden verwijderen die een manifest opsomt", + "recipe fmt": "een recept in zijn vaste vorm afdrukken", + "preset": "een set bestanden bouwen uit een benoemde testvraag", + "formats": "de formaten opsommen die deze build ondersteunt", + "damage": "de manieren opsommen waarop deze build een bestand met opzet kan beschadigen", + "tool": "kleine hulpmiddelen voor bestanden die je al hebt", + "version": "de versie van de tool tonen", + "license": "de licentie tonen en wat die betekent voor gegenereerde bestanden" + }, + "outcomes": { + "accept": "Je systeem moet het bestand aannemen.", + "reject": "Je systeem moet het bestand weigeren.", + "sanitize": "Je systeem moet het bestand aannemen en opschonen, bijvoorbeeld door het te hernoemen.", + "unspecified": "Het hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde." + }, + "damages": { + "zero-head": "Overschrijft de eerste bytes van het bestand met nullen en laat de lengte ongemoeid. De meeste lezers kijken daar eerst, dus bijna alles merkt deze beschadiging." + }, + "terms": { + "oracleNone": "niet van toepassing", + "int": "elk geheel getal", + "choice": "een uit een vaste verzameling", + "bool": "waar of onwaar", + "size": "een grootte zoals 2mb", + "text": "tekst", + "pixels": "pixels", + "paragraphs": "alinea's", + "rows": "rijen", + "columns": "kolommen", + "slides": "dia's", + "hertz": "hertz", + "megapixels": "megapixels", + "million cells": "miljoen cellen", + "entries per second": "items per seconde", + "files": "bestanden", + "sizes separated by commas": "groottes gescheiden door komma's", + "format ids separated by commas": "formaat-id's gescheiden door komma's", + "format ids separated by commas, or all": "formaat-id's gescheiden door komma's, of all", + "extensions separated by commas": "extensies gescheiden door komma's", + "the id of a format, as tfg formats lists them": "de id van een formaat, zoals tfg formats ze opsomt", + "the password, in plain text": "het wachtwoord, als platte tekst", + "any text": "willekeurige tekst", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "een datum zoals 2024-02-29 of 2024-02-29T13:45:00+02:00, of none" + }, + "faq": [ + { + "q": "Waarin verschilt dit van dd, fsutil of truncate?", + "a": "Die geven je een bestand van de juiste grootte vol met niets. Een bestand van 2 MB met de naam photo.png dat zo is gemaakt is geen PNG, dus alles wat het echt parset weigert het om de verkeerde reden, en je test slaagt dan ook om de verkeerde reden. Dit maakt een echte PNG van precies 2 MB die opent in een afbeeldingsviewer, en komt met een verklaring over hoe je systeem ermee om moet gaan.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Is het gratis, en mag ik het op het werk gebruiken?", + "a": "Ja op beide. Het is uitgebracht onder de GPL-3.0 en kost niets. Er is geen account, geen licentiesleutel en geen betaalde variant." + }, + { + "q": "Mag ik de gegenereerde bestanden in een closed source product gebruiken?", + "a": "Ja. De licentie geldt voor de code van de tool, niet voor wat de tool produceert. Gegenereerde bestanden, recepten en manifesten zijn uitvoer en geen afgeleide werken, dus je kunt ze committen en verspreiden zonder enige verplichting." + }, + { + "q": "Bevatten de gegenereerde bestanden echte persoonsgegevens?", + "a": "Nee. Alles erin wordt gesynthetiseerd uit een seed. Er wordt geen dataset gelezen, geen dienst benaderd en geen inhoud van derden ingebed. Behandel een gegenereerd e-mailadres als onbruikbaar in plaats van als ongebruikt, want elke willekeurige tekenreeks kan bij toeval samenvallen met een echte." + }, + { + "q": "Krijg ik op een andere machine precies dezelfde bestanden?", + "a": "Ja, byte voor byte, bij hetzelfde recept en dezelfde seed. Het project test dat bij elke wijziging, en het breken ervan vereist een major-versie. Daardoor kun je een klein recept committen in plaats van grote binaire fixtures." + }, + { + "q": "Heeft het een internetverbinding nodig?", + "a": "Nooit. Er is geen telemetrie, geen updatecontrole en geen cloudclient, en in de opdrachtregel-binary is helemaal geen netwerkstack gecompileerd. Het werkt op een machine zonder netwerk en binnen een afgesloten bedrijfsomgeving." + }, + { + "q": "Wat gebeurt er als ik een grootte vraag die een formaat niet kan halen?", + "a": "Je krijgt een fout die het formaat noemt, de kleinst mogelijke grootte, de reden voor die ondergrens en wat je in plaats daarvan kunt doen, en er wordt geen bestand geschreven. De tool rondt een grootte nooit stilzwijgend af. Elke ondergrens staat op de pagina met formaten.", + "code": "tfg formats png" + }, + { + "q": "Kan ik een bewust kapot bestand genereren?", + "a": "Ja. Voeg --damage zero-head toe en het bestand komt uit op precies de gevraagde grootte, met de eerste bytes overschreven door nullen, zodat een lezer het weigert, en het manifest zegt dat je systeem het moet weigeren. De details staan op de pagina over beschadigde testbestanden.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Welke formaten komen er nog?", + "a": "7z, mp3 en mp4. Vandaag werken {{ .Facts.FormatCount }} formaten van begin tot eind." + }, + { + "q": "Op welke systemen kan ik het draaien?", + "a": "De opdrachtregel draait op Windows en Linux, zowel op Intel als op ARM, en op Macs met Apple Silicon. Het bureaubladvenster wordt geleverd voor Windows op Intel, Linux op Intel en Macs met Apple Silicon. Intel-Macs worden niet ondersteund en daar wordt niets voor gebouwd." + }, + { + "q": "Moet ik iets installeren?", + "a": "Nee. Download het archief voor je systeem, pak het uit en start de binary. Er is geen installatieprogramma, geen runtime om toe te voegen en geen afhankelijkheid om op te lossen. Als je Go hebt, werkt ook één enkele go install-opdracht.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Waarom is een run over duizenden bestanden trager op Windows?", + "a": "Omdat Windows meer rekent voor elk pad dat het bekijkt, en een opdracht die over duizenden bestanden gaat bekijkt duizenden paden. Gemeten op één machine met 3000 bestanden van 1 kB doet verify er ongeveer 0,9 seconde over op Windows en ongeveer 0,2 seconde op Linux in een container. Een korter uitvoerpad maakt het cijfer voor Windows kleiner, omdat elke map boven de bestanden deel uitmaakt van wat wordt bekeken." + } + ] +} diff --git a/web/content/nl/use-cases.html b/web/content/nl/use-cases.html new file mode 100644 index 00000000..53be7d02 --- /dev/null +++ b/web/content/nl/use-cases.html @@ -0,0 +1,132 @@ +

Waar mensen het voor gebruiken

+

+ Vijf taken die in bijna elk project voorkomen dat bestanden van mensen aanneemt, en de opdracht die + elk doet. Elk voorbeeld hieronder werkt zoals het is geschreven. +

+ +
+

Uploadlimieten

+

Testen of een limiet voor bestandsgrootte wordt afgedwongen waar hij zegt dat hij dat doet

+

+ Een limiet is drie testgevallen, niet één: net eronder, precies erop en net erboven. Die met de hand + maken betekent bytetellingen uitrekenen en hopen dat je er niet één naast zit. Vraag in plaats + daarvan de set: +

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

+ Je krijgt drie echte PDF's van 1048575, 1048576 en 1048577 bytes, en een manifest dat zegt dat de + eerste twee geaccepteerd moeten worden en de derde geweigerd wegens size_limit. Je + test leest de verwachting in plaats van dat jij drie asserties met de hand schrijft - en als de + limiet verandert, wijzig je één getal en draai je opnieuw. +

+

+ Hetzelfde werkt zonder preset als je één set grenzen inline wilt: +

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

Continuous integration

+

Fixtures uit de repository houden zonder ze kwijt te raken

+

+ Grote binaire fixtures maken een repository traag om te klonen en lastig te reviewen, en niemand kan + zien wat er veranderde toen er een werd vervangen. Een recept is een paar honderd tekens YAML + die de identieke bestanden opnieuw opbouwen - byte voor byte, op elke machine - + omdat elk bestand is afgeleid van de seed van de run. +

+
- 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
+

+ Elk einde heeft zijn eigen afsluitcode, dus een pipeline kan een slecht recept onderscheiden van een + volle schijf en van een afwijking bij verificatie. Een mislukte run drukt niets af op de + standaarduitvoer, waardoor een logparser een fout niet als gegevens leest. +

+
+ +
+

Schaal

+

Uitzoeken wat er gebeurt als de map groot is

+

+ Importroutines, nachtelijke taken en maplijsten gedragen zich anders bij tienduizend bestanden dan + bij tien. Groottes getrokken uit een bereik laten de set op echt verkeer lijken in plaats van op + tienduizend identieke bestanden, en de trekking komt uit de seed, dus de set is morgen dezelfde. +

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

+ Bekijk wat een run zou kosten voordat hij iets schrijft, wat telt als het totaal in gigabytes wordt + gemeten: +

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

+ Een run die groter is dan de vrije ruimte op de schijf wordt geweigerd voordat de eerste byte is + geschreven, in plaats van de schijf te vullen en halverwege te falen. +

+
+ +
+

Archieven

+

Een uitpakprogramma testen met een archief dat echt bestanden bevat

+

+ Een leeg archief met de juiste extensie bewijst niets over code die het opent en doorloopt wat erin + zit. Declareer de inhoud en het archief bevat die echt: +

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

+ Nestdiepte, aantal items en de grootte van wat erin zit zijn allemaal dingen waar een importroutine + een mening over heeft, en zo kom je erachter wat die meningen zijn. +

+
+ +
+

Parsers en viewers

+

Controleren dat je eigen code een formaat leest zoals echte software dat doet

+

+ Elk formaat hier wordt vóór levering gecontroleerd met een onafhankelijke lezer - een PNG wordt + geopend en de pixels worden vergeleken, een DOCX wordt teruggelezen door aparte bibliotheken, + een archief wordt uitgepakt. Dat betekent dat een bestand dat je parser weigert een bevinding is + over je parser, niet over de 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
+

+ De pagina met formaten toont de instellingen die elk accepteert en het + kleinste bestand dat elk kan zijn. +

+
+ +
+

Handleidingen

+

Twee hiervan in detail

+ +
+ +
+

Voor wie dit is

+

+ QA-engineers, testautomatisering en iedereen wiens code een uploadformulier, een importroutine, een + parser of een opslagquotum achter zich heeft. Het draait op een machine zonder enig netwerk, wat + telt in een afgesloten bedrijfsomgeving waar een generator in de browser geen optie is. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/pl/ci.html b/web/content/pl/ci.html new file mode 100644 index 00000000..ccdf7f2c --- /dev/null +++ b/web/content/pl/ci.html @@ -0,0 +1,188 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Jak generować pliki testowe w potoku CI

+

+ Binarny plik testowy w repozytorium zostaje w jego historii na zawsze, nie da się go ocenić w + różnicach i przestaje być możliwy, gdy plik jest duży. Zamiast tego generuj pliki w potoku z + przepisu. Przepis jest tekstem, bajty wychodzą za każdym razem takie same, a ostatni krok dowodzi, + że nic się nie ruszyło. +

+ +
+

Krótka odpowiedź

+

+ Zainstaluj tfg, uruchom tfg generate fixtures.yaml --out ./fixtures przed + testami, a tfg verify ./fixtures/manifest.json po nich. Oba kroki same przerywają + build, z kodem wyjścia mówiącym dlaczego. +

+
+ +
+

Dlaczego nie commitować

+

Dlaczego pliku testowego nie powinno być w repozytorium

+ +

+ Commitować trzeba przepis. Ten sam przepis i ziarno zapisują te same bajty na każdej maszynie, więc + plik wygenerowany w potoku jest tym plikiem, który miałeś na laptopie. +

+
+ +
+

Przepis

+

Przepis, który leży obok testów

+

+ Ten zapisuje dwadzieścia pięć faktur, które powinny zostać przyjęte, i dwa obrazy ponad limitem, + które powinny zostać odrzucone, a manifest zapisuje oba oczekiwania: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml sprawdza go, nic nie zapisując, i od razu wymienia każdy + problem. +

+
+ +
+

GitHub Actions

+

Workflow, który instaluje narzędzie i buduje pliki testowe

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Wiersz z sumą kontrolną porównuje archiwum z verify-SHA256SUMS.txt z tego samego + wydania. Wersja jest przypięta, więc nowe wydanie nigdy nie zmieni buildu, którego nie ruszałeś. +

+
+ +
+

GitLab CI

+

To samo jako zadanie GitLaba

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Gdy robi się czerwono

+

Co przerywa krok i dlaczego

+

+ Każde zakończenie ma własny kod wyjścia, więc krok sam się przerywa, a log mówi, który to był. Te, + które spotyka potok: +

+ +

+ Nieudany przebieg nie wypisuje niczego na standardowe wyjście, więc parser logów nigdy nie weźmie + błędu za dane. Cała tabela jest na stronie dokumentacji. +

+
+ +
+

PowerShell

+

Skrypt PowerShella potrzebuje jeszcze jednej linii

+

+ PowerShell nie wynosi kodu wyjścia programu poza plik .ps1. Uruchom go z + -File, a skrypt odpowie 0, nawet gdy narzędzie w środku odmówiło + pracy, więc build, który powinien być czerwony, robi się zielony. Ostatnia linia to cała + poprawka: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Tak zachowuje się PowerShell, a nie to narzędzie. cmd, bash i + zsh nie potrzebują niczego więcej. +

+
+ +
+

Kilka zadań

+

Przekazywanie plików testowych między zadaniami

+

+ Zwykle nie trzeba ich wysyłać. Skoro ten sam przepis zapisuje te same bajty, każde zadanie może + uruchomić własne tfg generate, co jest szybsze niż wysyłanie i pobieranie. Gdy + zadanie musi dostać pliki z innego, uruchom tfg verify na manifeście po przesłaniu, + a powie, czy to, co dotarło, jest tym, co zapisano. +

+
+ +
+

Dalej

+

Dokąd pójść stąd

+ +
diff --git a/web/content/pl/damage.html b/web/content/pl/damage.html new file mode 100644 index 00000000..cd5ff132 --- /dev/null +++ b/web/content/pl/damage.html @@ -0,0 +1,174 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Jak zrobić uszkodzony plik do testów

+

+ Walidator, któremu pokazywano tylko zdrowe pliki, nie został naprawdę przetestowany. Oto jak dostać + plik zepsuty celowo, o dokładnie takim rozmiarze, jaki podasz, z manifestem + mówiącym, co system ma z nim zrobić. +

+ +
+

Krótka odpowiedź

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out zapisuje PNG o + dokładnie 2097152 bajtach, którego pierwsze bajty są zerami, a manifest obok zapisuje, że system + powinien go odrzucić. +

+
+ +
+

Zwykła droga

+

Dlaczego plik uszkodzony ręcznie to kiepski test

+

+ Zwykle używa się edytora szesnastkowego, skryptu zmieniającego kilka losowych bajtów albo ucięcia + pliku przez head lub truncate. Za pierwszym razem działa, a potem + kosztuje: +

+ +
+ +
+

Co dostajesz

+

Uszkodzony plik ma nadal rozmiar, o który prosiłeś

+

+ Plik jest generowany normalnie, a psuty dopiero w drodze na dysk. Zachowuje rozmiar, który podałeś, + a to samo polecenie zapisuje znowu te same bajty. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Ustawienia podaje się po dwukropku. Flagę można powtarzać, a uszkodzenia są stosowane w kolejności, + w jakiej je zapiszesz. Działa z każdym z {{ .Facts.FormatCount }} formatów. +

+
+ +
+

Co potrafi

+

Jakie są uszkodzenia?

+

+ To lista, którą wypisuje program, odczytana z niego w chwili budowania tej strony. tfg + damage wypisuje to samo, a tfg damage <id> mówi, co przyjmuje jedno z + nich. +

+ {{ template "damagesTable" . }} +

+ zero-head zapisuje zera na początku pliku. Większość czytników zagląda tam najpierw, w + sygnaturę i nagłówek mówiące, czym jest plik, więc zauważy to prawie każdy czytnik. Zwykły tekst + i logi nie mają sygnatury i też są odrzucane, bo ciąg zerowych bajtów nie jest tekstem. Poniżej + czterech bajtów niektóre formaty wychodzą z uszkodzeniem, na które nie skarży się żaden czytnik, + dlatego ustawienie zaczyna się od czterech. +

+
+ +
+

Co mówi manifest

+

Manifest, który mówi, co ma się stać

+

+ Każdy uszkodzony plik dostaje wpis mówiący, że system powinien go odrzucić, a obok zapisane jest + uszkodzenie: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dwie prośby są odrzucane, zanim cokolwiek powstanie, bo każda zostawiłaby na dysku plik, który + manifest opisuje błędnie: +

+ +
+ +
+

W przepisie

+

Zdrowe i zepsute pliki w jednym przebiegu

+

+ Włóż jedno i drugie do jednego przepisu, a manifest niesie oczekiwanie każdego pliku, więc test nie + potrzebuje listy, który jest który: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

W teście

+

Zamiana tego w test

+

+ Test czyta manifest i sprawdza, czy to, co się stało, jest tym, co zadeklarowano. Nie potrzebuje + listy nazw plików: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Dobre odrzucenie jest czyste. Komunikat mówiący, co było nie tak, to odpowiedź, o którą chodzi. Błąd + serwera, zawieszenie albo plik zapisany do połowy to wada, którą ten test ma znaleźć. +

+
+ +
+

Dalej

+

Dokąd pójść stąd

+ +
diff --git a/web/content/pl/docs.html b/web/content/pl/docs.html index bfa728a9..82bf9869 100644 --- a/web/content/pl/docs.html +++ b/web/content/pl/docs.html @@ -85,6 +85,9 @@

Jak zrobić plik celowo zepsuty?

jednego bajtu, taki plik zostaje odrzucony zamiast zapisany - przebieg idzie dalej, mówi, którego pliku to dotyczyło, i kończy się kodem częściowego wyniku.

+

+ Krok po kroku, z testem czytającym manifest: jak zrobić uszkodzony plik do testów. +

@@ -255,6 +258,9 @@

Co znaczą kody wyjścia?

Przebieg zatrzymany przez Ctrl+C i tak zostawia manifest i nigdy nie zostawia pliku zapisanego w połowie, więc anulowane zadanie da się posprzątać następnym.

+

+ Gotowe workflow dla GitHub Actions i GitLab CI: jak generować pliki testowe w potoku CI. +

diff --git a/web/content/pl/site.json b/web/content/pl/site.json index fbfaebd4..f2310c87 100644 --- a/web/content/pl/site.json +++ b/web/content/pl/site.json @@ -1,5 +1,6 @@ { "code": "pl", + "locale": "pl_PL", "name": "Polski", "dir": "pl", "pages": [ @@ -51,11 +52,28 @@ "nav": "FAQ", "title": "FAQ - pytania o generowanie plików testowych", "description": "Czym to się różni od dd i fsutil, czy pliki można commitować, czy przebieg powtarza się co do bajta i co się dzieje, gdy rozmiar jest nieosiągalny." + }, + { + "key": "damage", + "slug": "uszkodzone-pliki-testowe", + "nav": "Uszkodzone pliki", + "title": "Uszkodzone pliki testowe - zepsute pliki o dokładnym rozmiarze", + "description": "Zrób plik zepsuty celowo, o dokładnie takim rozmiarze, jaki podasz, z manifestem mówiącym, że system powinien go odrzucić. Do testów walidacji uploadu i parserów.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "pliki-testowe-w-ci", + "nav": "Pliki testowe w CI", + "title": "Pliki testowe w CI - GitHub Actions, GitLab CI i PowerShell", + "description": "Generuj pliki testowe w potoku zamiast commitować binaria: workflow GitHub Actions, zadanie GitLaba, kody wyjścia przerywające build i pułapka PowerShella.", + "parent": "use-cases" } ], "words": { "skip": "Przejdź do treści", "navLabel": "Główna", + "langLabel": "Język", "breadcrumbHome": "Start", "imageAlt": "Testing Files Generator - prawdziwe pliki testowe o dokładnym rozmiarze, z manifestem mówiącym, jak system ma na nie zareagować", "schemaDescription": "Darmowy generator plików testowych dla QA o otwartym kodzie. Tworzy prawdziwe pliki w {{ .Facts.FormatCount }} formatach o dokładnie zadanym rozmiarze i zapisuje manifest mówiący, jak testowany system ma na każdy z nich zareagować.", @@ -89,7 +107,11 @@ "notFoundLead": "Adres, którym tu trafiłeś, nie pasuje do żadnej strony w tym serwisie.", "notFoundBack": "Wróć na stronę główną", "read.format": "Format każdego pliku w zestawie. To flaga samego narzędzia, a preset daje jej tylko wartość domyślną.", - "readTakes.format": "identyfikator formatu ze strony formatów" + "readTakes.format": "identyfikator formatu ze strony formatów", + "colDamage": "Uszkodzenie", + "colEffect": "Co robi z bajtami", + "colSettings": "Ustawienia", + "noSettings": "brak" }, "endings": { "0": "Wszystko się udało.", @@ -279,7 +301,8 @@ }, { "q": "Czy mogę wygenerować plik celowo uszkodzony?", - "a": "Jeszcze nie. Pliki uszkodzone i niepoprawne są zaplanowaną funkcją. Dziś każdy plik, który narzędzie zapisuje, jest poprawnym plikiem swojego formatu." + "a": "Tak. Dodaj --damage zero-head, a plik wyjdzie dokładnie o podanym rozmiarze, z pierwszymi bajtami nadpisanymi zerami, więc czytnik go odrzuci, a manifest powie, że system powinien go odrzucić. Szczegóły są na stronie o uszkodzonych plikach testowych.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" }, { "q": "Jakie formaty są następne w kolejce?", @@ -298,5 +321,8 @@ "q": "Dlaczego przebieg po tysiącach plików jest wolniejszy na Windows?", "a": "Bo Windows liczy sobie więcej za każdą ścieżkę, na którą patrzy, a polecenie chodzące po tysiącach plików patrzy na tysiące ścieżek. Zmierzone na jednej maszynie przy 3000 plików po 1 kB: verify trwa około 0,9 sekundy na Windows i około 0,2 sekundy na Linuksie w kontenerze. Krótsza ścieżka katalogu wyjściowego zmniejsza wynik na Windows, bo każdy katalog nad plikami też jest częścią tego, na co system patrzy." } - ] + ], + "damages": { + "zero-head": "Nadpisuje pierwsze bajty pliku zerami, nie zmieniając jego długości. Większość czytników zagląda tam najpierw, więc to uszkodzenie zauważy prawie wszystko." + } } diff --git a/web/content/pl/use-cases.html b/web/content/pl/use-cases.html index 9a1baa89..8b652b6e 100644 --- a/web/content/pl/use-cases.html +++ b/web/content/pl/use-cases.html @@ -104,6 +104,19 @@

Sprawdzenie, czy Twój kod czyta format tak jak prawdziwe oprogramowanie

+
+

Poradniki

+

Dwa z tych zastosowań dokładniej

+ +
+

Dla kogo to jest

diff --git a/web/content/pt-BR/ci.html b/web/content/pt-BR/ci.html new file mode 100644 index 00000000..826b511e --- /dev/null +++ b/web/content/pt-BR/ci.html @@ -0,0 +1,191 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Como gerar arquivos de teste em um pipeline de CI

+

+ Uma fixture binária em um repositório fica para sempre no histórico, não pode ser revisada em um + diff e deixa de ser viável quando o arquivo é grande. Gere os arquivos dentro do pipeline a partir + de uma receita. A receita é texto, os bytes saem iguais a cada vez e um último passo prova que + nada mudou. +

+ +
+

A resposta curta

+

+ Instale o tfg, rode tfg generate fixtures.yaml --out ./fixtures antes dos + testes e tfg verify ./fixtures/manifest.json depois. Os dois passos fazem o build + falhar sozinhos, com um código de saída que diz o motivo. +

+
+ +
+

Por que não commitar

+

Por que uma fixture não deve morar no repositório

+ +

+ O que se commita é a receita. A mesma receita e a mesma semente gravam os mesmos bytes em qualquer + máquina, então o arquivo gerado no pipeline é o arquivo que você tinha no notebook. +

+
+ +
+

A receita

+

Uma receita que mora junto dos testes

+

+ Esta grava vinte e cinco faturas que devem ser aceitas e duas imagens acima de um limite que devem + ser recusadas, e o manifesto registra as duas expectativas: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml verifica a receita sem gravar nada e nomeia todos os + problemas de uma vez. +

+
+ +
+

GitHub Actions

+

Um workflow que instala a ferramenta e constrói as fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ A linha da soma de verificação compara o arquivo com verify-SHA256SUMS.txt da mesma + versão. A versão está fixada, então uma versão nova nunca altera um build que você não mexeu. +

+
+ +
+

GitLab CI

+

A mesma coisa como job do GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quando fica vermelho

+

O que faz um passo falhar, e por quê

+

+ Cada final tem o seu próprio código de saída, então o passo falha sozinho e o log diz qual foi. Os + que um pipeline encontra: +

+ +

+ Uma execução que falhou não imprime nada na saída padrão, então um analisador de logs nunca toma um + erro por dado. A tabela completa está na página de + documentação. +

+
+ +
+

PowerShell

+

Um script PowerShell precisa de mais uma linha

+

+ O PowerShell não leva o código de saída de um programa para fora de um arquivo .ps1. + Rode um com -File e o script responde 0 mesmo quando a ferramenta lá + dentro recusou o trabalho, então um build que deveria ficar vermelho fica verde. A última linha + é a correção inteira: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ É assim que o PowerShell se comporta, não algo desta ferramenta. cmd, bash + e zsh não precisam de mais nada. +

+
+ +
+

Vários jobs

+

Compartilhando as fixtures entre jobs

+

+ Em geral não é preciso enviá-las. Como a mesma receita grava os mesmos bytes, cada job pode rodar o + seu próprio tfg generate, que é mais rápido que um upload e um download. Quando um + job precisa receber arquivos de outro, rode tfg verify no manifesto depois da + transferência, e ele diz se o que chegou é o que foi gravado. +

+
+ +
+

A seguir

+

Para onde ir daqui

+ +
diff --git a/web/content/pt-BR/damage.html b/web/content/pt-BR/damage.html new file mode 100644 index 00000000..cfa96876 --- /dev/null +++ b/web/content/pt-BR/damage.html @@ -0,0 +1,175 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Como criar um arquivo corrompido para testes

+

+ Um validador que só viu arquivos saudáveis não foi realmente testado. Veja como obter um arquivo + quebrado de propósito, que sai com exatamente o tamanho que você pede e traz um + manifesto dizendo o que o seu sistema deve fazer com ele. +

+ +
+

A resposta curta

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out grava um PNG de + exatamente 2097152 bytes cujos primeiros bytes são zeros, e o manifesto ao lado registra que o + seu sistema deve rejeitá-lo. +

+
+ +
+

O jeito de sempre

+

Por que um arquivo corrompido à mão é um teste ruim

+

+ O jeito de sempre é um editor hexadecimal, um script que troca alguns bytes aleatórios ou cortar um + arquivo com head ou truncate. Funciona uma vez, e depois sai caro: +

+ +
+ +
+

O que você recebe

+

Um arquivo danificado continua com o tamanho que você pediu

+

+ O arquivo é gerado normalmente e quebrado depois, a caminho do disco. Ele mantém o tamanho pedido, e + o mesmo comando grava os mesmos bytes outra vez. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ As configurações vão depois de dois-pontos. A opção pode ser repetida, e os danos são aplicados na + ordem em que você os escreve. Funciona com cada um dos {{ .Facts.FormatCount }} formatos. +

+
+ +
+

O que ele sabe fazer

+

Quais danos existem?

+

+ Esta é a lista que o programa imprime, lida dele quando esta página é construída. tfg + damage imprime a mesma, e tfg damage <id> diz o que cada um aceita. +

+ {{ template "damagesTable" . }} +

+ zero-head grava zeros sobre o início do arquivo. A maioria dos leitores olha ali + primeiro, para a assinatura e o cabeçalho que dizem o que o arquivo é, então quase todo leitor + percebe. Texto simples e logs não têm assinatura e também são recusados, porque uma sequência de + bytes zero não é texto. Abaixo de quatro bytes, alguns formatos saem com um dano de que nenhum + leitor reclama, e por isso a configuração começa em quatro. +

+
+ +
+

O que o manifesto diz

+

Um manifesto que diz o que deve acontecer

+

+ Cada arquivo danificado recebe uma entrada dizendo que o seu sistema deve rejeitá-lo, com o dano + registrado ao lado: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dois pedidos são recusados antes de qualquer coisa ser gravada, porque cada um deixaria no disco um + arquivo que o manifesto descreve errado: +

+ +
+ +
+

Em uma receita

+

Arquivos saudáveis e quebrados em uma execução

+

+ Ponha os dois em uma receita, e o manifesto leva a expectativa de cada arquivo, então o teste não + precisa de uma lista de qual é qual: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Em um teste

+

Transformando em um teste

+

+ O teste lê o manifesto e confere se o que aconteceu é o que foi declarado. Não precisa de uma lista + de nomes de arquivo: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Uma boa recusa é uma recusa limpa. Uma mensagem que diz o que estava errado é a resposta que você + quer. Um erro de servidor, uma trava ou um arquivo salvo pela metade é o defeito que este teste + existe para achar. +

+
+ +
+

A seguir

+

Para onde ir daqui

+ +
diff --git a/web/content/pt-BR/docs.html b/web/content/pt-BR/docs.html new file mode 100644 index 00000000..f0ddb4d8 --- /dev/null +++ b/web/content/pt-BR/docs.html @@ -0,0 +1,280 @@ +

Documentação

+

+ Tudo o que a ferramenta faz, organizado como as perguntas com que as pessoas realmente chegam. O + README do repositório é a referência completa e sempre corresponde + à versão que você baixou. +

+ +
+

Quais comandos existem?

+

Cada um faz uma única coisa:

+ {{ template "commandList" . }} +
+ +
+

Como gero um único arquivo de tamanho exato?

+

+ Informe o formato, o tamanho e o destino. Os tamanhos contam de 1024 em 1024, então 2mb + são 2097152 bytes. Uma contagem simples de bytes também funciona, então --size + 10485761 pede exatamente essa quantidade. +

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

As opções úteis de generate:

+
+ + + + + + + + + + + + + + + + + +
OpçãoO que faz
--format <id>formato dos arquivos, por exemplo txt
--size <size>tamanho exato de cada arquivo, como 10mb ou uma contagem simples de bytes
--size-range <a-b>um tamanho sorteado por arquivo dentro de um intervalo, como 1kb-8kb. O sorteio vem do seed
--boundary <size>três arquivos ao redor de um limite: um byte abaixo, o limite, um byte acima
--count <n>quantos arquivos produzir. Padrão 1
--name <template>modelo de nome, por exemplo invoice_{index:04}.txt
--out <dir>diretório onde escrever
--seed <n>seed da execução. O mesmo seed dá os mesmos bytes
--set <k>=<v>uma configuração de formato, repetível
--damage <name>quebrar os arquivos de propósito, repetível e aplicado em ordem. Rode tfg damage para ver a lista
--expected <outcome>accept, reject, sanitize ou unspecified
--dry-runcontar e mostrar, sem escrever absolutamente nada
--jsonescrever o manifesto na saída padrão
+
+
+ +
+

Como faço um arquivo quebrado de propósito?

+

+ Todo outro arquivo que esta ferramenta escreve é correto por construção, o que responde a duas das + três perguntas que um validador de upload faz. --damage responde à terceira - se o + arquivo abre, afinal. O arquivo é produzido normalmente e depois quebrado, então continua com o + tamanho que você pediu. +

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

+ As configurações vão depois de dois-pontos. A opção se repete, e a ordem em que você as escreve é a + ordem em que são aplicadas. tfg damage lista o que esta versão pode fazer e o que + cada uma aceita. +

+

Em uma receita a chave é uma lista, de nomes ou de configurações:

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

+ Um arquivo danificado recebe expected: reject no manifesto, com o dano registrado ao + lado. Duas coisas são recusadas antes de escrever qualquer coisa, porque cada uma deixaria no + disco um arquivo que o manifesto descreve errado: +

+ +

+ Uma terceira não pode ser conhecida de antemão. Se um dano roda e não move nenhum byte, esse arquivo + é descartado em vez de escrito - a execução continua, diz qual arquivo foi e termina com o + código de saída parcial. +

+

+ Passo a passo, com um teste que lê o manifesto: como + criar um arquivo corrompido para testes. +

+
+ +
+

Como é uma receita?

+

+ Uma receita é um arquivo YAML que descreve uma execução inteira. Versione-a ao lado dos seus testes + e as fixtures deixam de ser binários no seu repositório - qualquer pessoa pode reconstruí-las, + byte a byte, a partir de um arquivo de algumas centenas de caracteres. +

+
# 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
+

+ Cada target precisa de exatamente uma destas chaves: size, size-range, + boundary ou contains. Duas é um erro e nenhuma também. Uma receita + inválida escreve nenhum arquivo e relata todos os problemas de uma vez em vez + de só o primeiro, cada um nomeando a configuração a que se refere. +

+
+ +
+

Como declaro o que meu sistema deve fazer com um arquivo?

+

Forma curta quando o resultado basta, forma longa quando o motivo importa:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Os resultados são accept, reject, sanitize e + unspecified. Os motivos são uma lista fechada para que um relatório possa agrupar + por eles: 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 e size_zero. +

+

+ Um motivo nomeia a regra em jogo, não o veredito. Por isso o mesmo motivo pode + ficar sob qualquer um dos resultados - um arquivo um byte abaixo de um limite é + accept, e a regra de que se trata continua sendo size_limit. +

+
+ +
+

O que há no manifesto?

+

+ Ele é escrito ao lado dos arquivos no fim de cada execução, inclusive de uma execução interrompida. + Uma entrada por arquivo: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Um recipe_hash é adicionado quando a execução veio de uma receita, e + preset com overrides quando veio de um preset, de modo que um + manifesto sempre pode ser rastreado até o que o produziu. +

+

+ Cada entrada também traz target_id, o id do target da receita que produziu o arquivo, e + summary.by_target conta os arquivos a que cada target chegou. Uma receita com + vários targets pode assim ser verificada target por target sem ler nomes de arquivo. +

+
+ +
+

O que é um preset?

+

+ Um conjunto de arquivos pronto que responde a uma pergunta de teste comum, para que você não precise + desenhar o conjunto. Presets são receitas comuns por baixo, e eject imprime a + receita para você editá-la a partir dali. Cada preset tem uma página + própria com o que costuma encontrar, o que há no conjunto e cada configuração que aceita. +

+ {{ template "presetsList" . }} +
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 diz quanto o conjunto custaria antes de você montá-lo, e diz abertamente quando um + número é um valor provisório nosso, e não um limite seu. +

+
+ +
+

O que significam os códigos de saída?

+

+ Cada término tem seu próprio código, a saída legível por máquina vai para a saída padrão, e uma + execução com falha não imprime nada lá. A tabela é um contrato congelado - mudar o que um código + significa exige uma versão maior. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Uma execução parada com Ctrl+C ainda deixa um manifesto e nunca deixa um arquivo pela metade, então + um job cancelado ainda pode ser limpo pelo seguinte. +

+

+ Workflows prontos para GitHub Actions e GitLab CI: como + gerar arquivos de teste em um pipeline de CI. +

+
+ +
+

Existe uma janela de desktop?

+

+ Sim, o mesmo motor com uma janela por cima, para o teste que não é automatizado. Não é uma versão + reduzida: um teste compara as duas interfaces capacidade por capacidade, e tudo que só uma delas + pode fazer precisa ser declarado e justificado em vez de divergir em silêncio. +

+

+ As telas são um lote, presets, vários lotes de uma vez e Sobre. Ela mostra quanto uma execução + custaria antes de escrever qualquer coisa, informa o progresso enquanto roda e pode ser + cancelada no meio sem deixar um arquivo pela metade. Ainda não abre um arquivo de receita - por + enquanto receitas são coisa de linha de comando, e a janela monta seus lotes no formulário. +

+
diff --git a/web/content/pt-BR/exact-size.html b/web/content/pt-BR/exact-size.html new file mode 100644 index 00000000..0106f24d --- /dev/null +++ b/web/content/pt-BR/exact-size.html @@ -0,0 +1,145 @@ +

Como criar um arquivo de tamanho exato

+

+ Todo sistema tem um comando para isso, e os três estão abaixo. Eles dão um arquivo com exatamente o + número certo de bytes - e para muito teste isso é tudo de que você precisa. Todo comando + desta página foi executado antes de ser publicado, no sistema a que pertence. +

+ +
+

A resposta curta

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Os tamanhos são em bytes, e 10 MB + contados como o seu gerenciador de arquivos conta são 10485760. +

+
+ +
+

Windows

+

fsutil, e uma versão em PowerShell que não precisa de nada extra

+

+ O fsutil vem com o Windows. Ele recebe o tamanho em bytes, então + calcule o número antes - 10 MB são 10485760, 100 MB são 104857600, 1 GB é 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Medido no Windows 11: funciona em um prompt comum, sem precisar de um elevado, e o arquivo sai com + exatamente 10485760 bytes. +

+

O PowerShell faz o mesmo sem chamar outro programa, e entende unidades:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB no PowerShell significa 10485760 bytes, a mesma contagem em base 1024 que o + Explorer usa, então os dois comandos acima produzem o mesmo tamanho. +

+
+ +
+

Linux

+

dd, truncate e fallocate, e a diferença que pega as pessoas

+

O dd é o que todo mundo conhece. Ele escreve os bytes de verdade:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ O truncate é instantâneo, e essa é a pegadinha. Medido no Alpine Linux, o arquivo + informa 10485760 bytes e ocupa zero blocos - é um arquivo + esparso. Qualquer coisa que o leia recebe dez megabytes de zeros, mas o disco nunca + cedeu o espaço: +

+
truncate -s 10M test10mb.bin
+

+ Isso serve para testar um limite de upload e engana para testar uma cota de disco. O + fallocate é o que se deve usar quando o espaço precisa ser real: +

+
fallocate -l 10M test10mb.bin
+

E quando o conteúdo precisa ser incompressível, para que um compactador não consiga comprimi-lo de volta:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, que não é esparso, e os dois que você já conhece

+

+ O macOS traz o mkfile. Medido no macOS 26.6.2: 10485760 bytes e 20480 blocos, então o + espaço é realmente alocado em vez de prometido: +

+
mkfile 10m test10mb.bin
+

dd e truncate também estão lá e se comportam como no Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Onde isso deixa de funcionar

+

Um arquivo do tamanho certo não é um arquivo do tipo certo

+

+ Tudo acima dá um bloco de zeros. Isso basta quando o que está sob teste olha só o tamanho - um + limite de upload, uma cota, uma transferência. Deixa de bastar no momento em que qualquer coisa + abre o arquivo. +

+

+ Medido, e vale a pena fazer você mesmo: crie um arquivo de 2 MB com fsutil, chame-o de + photo.png e entregue a uma biblioteca de imagens. O Pillow responde cannot + identify image file. Não é um PNG. Nunca foi - só o nome dizia que era. +

+

+ Isso importa mais do que parece, por causa de o jeito como o teste então falha. Seu + endpoint de upload recusa o arquivo, seu teste fica verde e você conclui que o limite de tamanho + funciona. Ele não recusou pelo tamanho. Recusou porque os bytes não eram uma imagem, e a regra + que você queria testar nunca foi alcançada. +

+ +
+ +
+

O outro caminho

+

Um arquivo real desse formato, exatamente no tamanho que você pediu

+

+ É isso que o Testing Files Generator faz. O arquivo é um genuíno do seu formato - abre no programa a + que pertence - e tem o número exato de bytes que você pediu, ao byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Peça um tamanho que um formato não alcança e você recebe um erro que nomeia o piso e o motivo, nunca + um arquivo de tamanho errado. A página de formatos lista cada + formato com o menor arquivo que ele pode produzir. +

+

E um limite são três casos de teste em vez de um, então a ferramenta monta os três:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Isso dá 10485759, 10485760 e 10485761 bytes, e um manifesto dizendo quais deles seu sistema deve + aceitar e quais deve rejeitar. A página de casos de uso + percorre isso e outras quatro tarefas para as quais foi feito. +

+ {{ template "downloadCta" . }} +
+ +
+

Então qual usar?

+ +

+ Os dois estão nesta página porque os dois estão certos parte do tempo. O erro a evitar é usar o + primeiro onde o segundo é necessário e ler o teste verde como prova. +

+
diff --git a/web/content/pt-BR/faq.html b/web/content/pt-BR/faq.html new file mode 100644 index 00000000..100b4989 --- /dev/null +++ b/web/content/pt-BR/faq.html @@ -0,0 +1,20 @@ +

Perguntas frequentes

+

+ Licença, privacidade, reprodutibilidade e o que as pessoas conferem antes de colocar um gerador em + um pipeline de build. Se a sua pergunta não está aqui, o rastreador + de issues está aberto. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Ainda decidindo?

+

+ A página de casos de uso mostra as tarefas para as quais foi + feito, e a página de formatos lista cada formato com o menor + arquivo que ele pode produzir. O README do repositório é a + referência completa. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/pt-BR/formats.html b/web/content/pt-BR/formats.html new file mode 100644 index 00000000..c5a6315b --- /dev/null +++ b/web/content/pt-BR/formats.html @@ -0,0 +1,80 @@ +

{{ .Facts.FormatCount }} formatos de arquivo, cada um gerado em um tamanho exato

+

+ Cada um é um arquivo real daquele formato. Abre no programa a que pertence e tem + exatamente o número de bytes que você pediu. Nenhum é preenchimento de zeros com uma extensão + colada. +

+ +{{ template "formatsTable" . }} + +
+

O que as colunas significam

+ +

+ Todo formato também se repete ao byte: a mesma receita e o mesmo seed produzem arquivos idênticos em + qualquer máquina, o que torna seguro versionar uma receita no lugar das próprias fixtures. +

+
+ +
+

Configurações que cada formato aceita

+

+ A maioria dos formatos tem configurações próprias - dimensões de imagem, qualidade JPEG, número de + páginas do PDF, linhas e colunas de uma planilha, quantas entradas vão dentro de um arquivo + compactado. Defina-as com --set key=value na linha de comando, ou em + properties: numa receita. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Um valor fora do que uma configuração aceita é recusado com uma mensagem que nomeia a configuração, + o intervalo permitido e o que usar no lugar. Uma configuração desconhecida também é um erro, + nunca um padrão silencioso - um erro de digitação aceito em silêncio dá um arquivo com as + configurações erradas e uma hora se perguntando por que o teste passa quando não deveria. +

+

+ Rode tfg formats <id> para ver exatamente o que um formato aceita na versão que + você tem. +

+
+ +
+

Arquivos compactados contêm arquivos reais

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} e {{ end }}{{ $c.ID }}{{ end }} + podem ser preenchidos com entradas em vez de ficarem como uma casca vazia. Um arquivo compactado + gerado realmente contém os documentos que diz conter, então qualquer coisa que o descompacte + durante um teste encontra arquivos reais dentro. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/pt-BR/index.html b/web/content/pt-BR/index.html new file mode 100644 index 00000000..942b00e8 --- /dev/null +++ b/web/content/pt-BR/index.html @@ -0,0 +1,199 @@ +
+
+

Gere arquivos de teste reais no tamanho exato

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formatos no total, e cada um é um + arquivo real que abre no programa a que pertence, com exatamente o tamanho que você + pediu. Cada execução também registra o que sua aplicação deve fazer com cada arquivo. + Linha de comando e janela de desktop, gratuito e de código aberto, funcionando inteiramente na + sua máquina. +

+ + {{ template "downloadCta" . }} +
+ +
+ A janela de desktop do Testing Files Generator, pronta para escrever um lote de arquivos de teste +
A janela de desktop, pronta para escrever um lote de arquivos. O mesmo motor roda por trás da linha de comando.
+
+
+ + + +
+

O problema

+

Fazer um arquivo de teste é fácil. Fazer os mil certos é a parte tediosa

+

Você está testando um software que aceita arquivos de pessoas. Mais cedo ou mais tarde, você precisa de:

+ +

+ É isso que isto substitui. Foi feito para engenheiros de QA, automação de testes e qualquer pessoa + cujo código tenha atrás um formulário de upload, uma rotina de importação, um parser ou uma cota + de armazenamento. +

+
+ +
+

O que o torna diferente

+

Outros geradores param nos bytes. Este responde ao que o seu teste realmente pergunta

+

+ Uma pasta de arquivos ainda deixa você decidindo o que cada um deve provar. Cada execução aqui + escreve um manifest.json ao lado dos arquivos - uma lista simples de tudo que foi + produzido e, para cada entrada, uma expectativa declarada. +

+

Digamos que seu endpoint de upload permita 1 MB. Peça os três arquivos que ficam nessa linha:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ArquivoBytesSeu sistema devePorque
1mb_under_1b.pdf1048575aceitarestá dentro do limite
1mb_at_limit.pdf1048576aceitaro próprio limite é permitido
1mb_over_1b.pdf1048577rejeitarsize_limit
+
+ +

Três arquivos, três respostas diferentes, em forma legível por máquina. Seu teste lê o manifesto em vez de você escrever as asserções à mão:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Onde a resposta depende da sua própria política, o manifesto diz isso

+

+ Ele registra unspecified em vez de inventar uma expectativa. Um gerador que adivinha + produz falhas falsas, e uma suíte que dá alarme falso acaba desligada. +

+
+
+ +
+

Presets

+

Escolha a pergunta, receba o conjunto inteiro

+

+ Um preset é um conjunto de arquivos de teste desenhado em torno de uma pergunta de teste, para que + você não precise descobrir quais arquivos provam o quê. Cada um tem uma página dizendo o que + costuma encontrar, o que há no conjunto e cada configuração que aceita. +

+ {{ template "presetsList" . }} +

Todos os presets, e como eles se relacionam com receitas

+
+ +
+

Início rápido

+

Três comandos para ver funcionando

+
    +
  1. +

    Faça um arquivo

    +

    Um PNG, exatamente dois megabytes:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Faça muitos arquivos

    +

    + Dez mil arquivos de log, cada um entre um e oito kilobytes, com os tamanhos sorteados a partir do + seed para que amanhã dê o mesmo conjunto. Dê a cada execução o seu próprio + diretório - o manifesto é o único registro do que uma execução escreveu, então a + ferramenta se recusa a escrever um segundo por cima: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Verifique e depois remova

    +

    verify diz que nada mudou. cleanup remove exatamente o que foi escrito e mais nada:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Os tamanhos contam de 1024 em 1024, como o seu gerenciador de arquivos faz, então 2mb + significa 2097152 bytes. Uma contagem simples de bytes também funciona. A + documentação cobre receitas, o manifesto e os códigos de + saída. +

+
+ +
+

O que você recebe

+

Feito para uma suíte que roda sem supervisão

+ +
+ +
+

Download

+

Escolha a versão para o seu sistema

+

+ Descompacte o arquivo e execute. tfg é a linha de comando e tfg-gui é a + janela de desktop. Não há instalador e nada para adicionar à sua máquina. +

+ {{ template "downloadsTable" . }} +
+

O que é assinado e o que não é

+

+ Os downloads de Windows e macOS são assinados, então iniciam sem aviso de desenvolvedor + desconhecido. Os de Linux não são, porque o Linux de desktop não tem equivalente para + assiná-los. Cada arquivo está listado em verify-SHA256SUMS.txt na página de + releases, para que você possa conferir o que baixou. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/pt-BR/preset.html b/web/content/pt-BR/preset.html new file mode 100644 index 00000000..2dcd4caf --- /dev/null +++ b/web/content/pt-BR/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ O preset {{ .ID }} monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ +{{ if .Catches }} +
+

O que ele costuma encontrar?

+ +
+{{ end }} + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show {{ .ID }} informa:

+
+ + + + + + + +
Arquivos{{ .Budget.Files }}
Targets na sua receita{{ .Budget.Targets }}
Tamanho total{{ .Bytes }} B
Formatos{{ join .Budget.Formats ", " }}
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
EsperadoSignificadoArquivos
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

O que você pode mudar?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
ConfiguraçãoAceitaPadrãoO que faz
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Este valor padrão é o nosso provisório, não o valor do seu sistema. Passe o seu.{{ end }}
+
+ {{- else }} +

Este preset não tem configurações. O conjunto é o mesmo toda vez.

+ {{- end }} +
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/pt-BR/presets.html b/web/content/pt-BR/presets.html new file mode 100644 index 00000000..88b48d84 --- /dev/null +++ b/web/content/pt-BR/presets.html @@ -0,0 +1,32 @@ +

Presets de arquivos de teste, um conjunto para cada pergunta de teste

+

+ Um preset é um conjunto inteiro de arquivos de teste desenhado em torno de uma pergunta, com um + manifesto dizendo como seu sistema deve reagir a cada arquivo. Você escolhe a pergunta, a + ferramenta monta o conjunto. Cada preset tem sua própria página com o que costuma encontrar, o que + há no conjunto e cada configuração que aceita. +

+ +{{ template "presetsList" . }} + +
+

Como um preset é diferente de uma receita?

+

+ Por baixo, não é. Um preset é uma receita que a ferramenta escreve para você a partir de algumas + configurações. tfg preset eject imprime essa receita para você guardá-la ao lado + dos seus testes e editá-la, e uma receita sua pode se basear em um preset com uma linha, + extends: preset: seguido do id dele. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Posso confiar nos valores padrão?

+

+ Para os arquivos, sim. Para um número que só o seu sistema conhece, como o limite de um formulário + de upload, um valor padrão é um provisório nosso, e a ferramenta diz isso toda vez que usa um. A + página de cada preset marca essas configurações, e tfg preset show diz isso antes + de qualquer coisa ser escrita. +

+
diff --git a/web/content/pt-BR/site.json b/web/content/pt-BR/site.json new file mode 100644 index 00000000..1e613f43 --- /dev/null +++ b/web/content/pt-BR/site.json @@ -0,0 +1,328 @@ +{ + "code": "pt-BR", + "locale": "pt_BR", + "name": "Português (Brasil)", + "dir": "pt-br", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Início", + "title": "Gerador de arquivos de teste - tamanho exato, {{ .Facts.FormatCount }} formatos reais", + "description": "Gerador gratuito e de código aberto de arquivos de teste para QA. PDF, DOCX, PNG e ZIP reais no tamanho exato, com um manifesto de como seu sistema deve reagir." + }, + { + "key": "formats", + "slug": "formatos", + "nav": "Formatos", + "title": "{{ .Facts.FormatCount }} formatos de arquivo - PDF, DOCX, PNG, ZIP e mais", + "description": "Todos os formatos que o gerador produz, o menor arquivo possível de cada um e as configurações que aceita. Os {{ .Facts.FormatCount }} abrem no programa a que pertencem." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Presets", + "title": "Presets de arquivos de teste - conjuntos prontos para QA", + "description": "Conjuntos prontos de arquivos de teste, cada um responde a uma pergunta: limites de upload, nomes, codificações, importação, arquivos vazios e validação." + }, + { + "key": "docs", + "slug": "documentacao", + "nav": "Documentação", + "title": "Documentação - comandos, receitas, manifesto, códigos de saída", + "description": "Como gerar arquivos de teste pela linha de comando ou com uma receita YAML, o que o manifesto contém e o que cada código de saída significa no CI." + }, + { + "key": "use-cases", + "slug": "casos-de-uso", + "nav": "Casos de uso", + "title": "Casos de uso - limites de upload, fixtures de CI, testes em massa", + "description": "Testar um limite de tamanho de upload, montar fixtures reproduzíveis para o CI, gerar dez mil arquivos e encher arquivos compactados com conteúdo real." + }, + { + "key": "exact-size", + "slug": "criar-arquivo-de-tamanho-exato", + "nav": "Tamanho exato", + "title": "Criar um arquivo de tamanho exato - Windows, Linux, macOS", + "description": "fsutil, dd, truncate e mkfile, cada um medido no seu sistema, e por que um arquivo feito assim não é um PDF nem um PNG quando um teste precisa de um." + }, + { + "key": "faq", + "slug": "perguntas-frequentes", + "nav": "FAQ", + "title": "FAQ - perguntas sobre gerar arquivos de teste", + "description": "Como isso difere de dd e fsutil, se os arquivos podem ir para o repositório, se as execuções se repetem byte a byte e o que acontece quando um tamanho é inalcançável." + }, + { + "key": "damage", + "slug": "arquivos-de-teste-corrompidos", + "nav": "Arquivos corrompidos", + "title": "Arquivos de teste corrompidos - arquivos quebrados, tamanho exato", + "description": "Um arquivo quebrado de propósito, com o tamanho exato que você pede e um manifesto dizendo que o seu sistema deve rejeitá-lo. Para testar validação de upload e parsers.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "arquivos-de-teste-no-ci", + "nav": "Arquivos de teste no CI", + "title": "Arquivos de teste no CI - GitHub Actions, GitLab CI e PowerShell", + "description": "Gere arquivos de teste no pipeline em vez de commitar binários: workflow do GitHub Actions, job do GitLab, códigos de saída e a pegadinha do PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Ir para o conteúdo", + "navLabel": "Principal", + "langLabel": "Idioma", + "breadcrumbHome": "Início", + "imageAlt": "Testing Files Generator - arquivos de teste reais no tamanho exato, com um manifesto que diz como seu sistema deve reagir a cada um", + "schemaDescription": "Um gerador gratuito e de código aberto de arquivos de teste para QA. Produz arquivos reais de {{ .Facts.FormatCount }} formatos no tamanho exato e escreve um manifesto que diz como o sistema sob teste deve reagir a cada um.", + "ctaDownload": "Baixar", + "ctaSource": "Ver o código-fonte", + "ctaNote": "Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.", + "colFormat": "Formato", + "colName": "Nome", + "colExtension": "Extensão", + "colSmallest": "Menor arquivo", + "colFidelity": "Fidelidade", + "colChecked": "Verificado com", + "colSetting": "Configuração", + "colAccepts": "Aceita", + "colSystem": "Sistema", + "colCli": "Linha de comando", + "colWindow": "Janela de desktop", + "noBinary": "ainda sem binário", + "colCode": "Código", + "colMeaning": "Significado", + "footerBlurb": "Arquivos de teste para QA, no tamanho exato, com um manifesto que diz como seu sistema deve reagir a cada um.", + "footerProject": "Projeto", + "footerSource": "Código no GitHub", + "footerReleases": "Downloads", + "footerIssues": "Relatar um problema", + "footerSupport": "Apoiar o projeto", + "footerPages": "Páginas", + "footerLicence": "Copyright (C) 2026 DonislawDev. Distribuído sob a Licença Pública Geral GNU, versão 3. Os arquivos que você gera são seus - a licença cobre a ferramenta, não a sua saída.", + "footerPrivacy": "Este site não carrega fontes, scripts nem rastreadores de lugar nenhum. Não usa cookies.", + "notFoundTitle": "Essa página não está aqui", + "notFoundLead": "O endereço que você seguiu não corresponde a nenhuma página deste site.", + "notFoundBack": "Ir para o início", + "read.format": "O formato de cada arquivo do conjunto. É uma opção da própria ferramenta, e o preset apenas dá a ela um valor padrão.", + "readTakes.format": "um id de formato da página de formatos", + "colDamage": "Dano", + "colEffect": "O que faz com os bytes", + "colSettings": "Configurações", + "noSettings": "nenhuma" + }, + "endings": { + "0": "Tudo funcionou.", + "1": "Um erro inesperado dentro da ferramenta.", + "2": "Comando ou opção incorretos.", + "3": "A receita não é válida.", + "4": "O formato não consegue fazer o que foi pedido.", + "5": "Uma leitura ou escrita falhou.", + "6": "Espaço em disco insuficiente.", + "7": "verify encontrou uma divergência.", + "8": "A execução terminou, mas nem tudo foi produzido.", + "130": "Interrompido com Ctrl+C.", + "143": "Encerrado por um sinal, que é a cara de um timeout de CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Um arquivo válido e tão pequeno quanto o formato permite passa?", + "title": "Vazio e mínimo", + "pageTitle": "Menores arquivos de teste válidos e vazios em cada formato", + "description": "O menor arquivo válido que a ferramenta escreve em cada um dos seus {{ .Facts.FormatCount }} formatos, mais um arquivo vazio onde o formato permite, cada um com a reação esperada.", + "catches": [ + "um arquivo válido recusado por ser pequeno demais, porque a verificação conta bytes em vez de lê-los", + "um arquivo vazio que derruba o leitor em vez de ser reportado", + "uma imagem de um pixel de largura que divide por zero a caminho da miniatura", + "um armazenamento que lê zero byte como upload com falha e fica tentando de novo" + ], + "details": { + "formats": "De quais formatos o conjunto é feito. Deixe em all para todos os formatos desta versão, ou nomeie os que o seu sistema aceita." + } + }, + "filename-handling": { + "question": "Meu sistema vai guardar, mostrar e devolver um nome de arquivo que ele não esperava?", + "title": "Tratamento de nomes de arquivo", + "pageTitle": "Nomes de arquivo problemáticos para testar - Unicode e tamanho", + "description": "Arquivos com nomes que quebram uploads e armazenamento: outros alfabetos, emoji, inversão de direção, caracteres invisíveis, sintaxe de shell e SQL, tamanho.", + "catches": [ + "um nome que parece outro na tela, em um log ou em uma lista", + "um nome cortado, aparado ou reescrito entre o upload e o armazenamento", + "um limite de tamanho contado em caracteres onde o armazenamento conta bytes" + ], + "details": {} + }, + "size-boundaries": { + "question": "Um limite de tamanho é aplicado exatamente onde foi declarado?", + "title": "Limites de tamanho", + "pageTitle": "Testar um limite de tamanho de upload - arquivos no limite exato", + "description": "Arquivos um byte abaixo, exatamente no e um byte acima do limite que seu sistema declara, mais degraus maiores dos dois lados, cada um marcado se deve ser aceito.", + "catches": [ + "erros de um a mais ou a menos no limite", + "MB confundido com MiB, que dá 4,8 por cento e basta para deixar passar um arquivo que não deveria passar", + "um limite aplicado no navegador e não no servidor" + ], + "details": { + "limit": "O limite de tamanho que seu sistema declara. Todo o resto é medido a partir dele.", + "spread": "Até onde ir de cada lado do limite, como uma lista de tamanhos." + } + }, + "tabular-import": { + "question": "A minha importação de tabelas sobrevive ao que ferramentas reais exportam?", + "title": "Importação de tabelas", + "pageTitle": "Arquivos de teste para importar CSV e Excel - delimitadores", + "description": "CSV com outros delimitadores, quebras de linha CR LF, sem cabeçalho e com outras aspas, uma tabela larga demais, uma planilha Excel e JSON em vários formatos.", + "catches": [ + "um arquivo com ponto e vírgula lido como uma coluna só, porque o delimitador foi presumido em vez de procurado", + "um arquivo CRLF dividido em linhas com uma linha vazia depois de cada uma", + "uma tabela sem cabeçalho cuja primeira linha de dados é engolida como nomes de coluna", + "uma importação que mantém as colunas que consegue mostrar e descarta o resto sem dizer nada", + "um leitor que lê registros JSON uma linha por vez e para no primeiro documento indentado" + ], + "details": { + "rows": "Quantas linhas a planilha tem. Ela é escrita exatamente no tamanho que essas linhas ocupam, então o orçamento acima muda com este valor.", + "columns": "Quantas colunas cada linha da planilha tem. Linhas vezes colunas tem um teto, e pedir além disso é recusado antes de escrever qualquer coisa." + } + }, + "text-encoding": { + "question": "Meu leitor sabe em que codificação um arquivo está, ou está adivinhando?", + "title": "Codificação de texto", + "pageTitle": "Arquivos de teste de codificação - UTF-8, UTF-16, BOM, CRLF", + "description": "O mesmo texto em UTF-8, UTF-16LE e UTF-16BE, com e sem marca de ordem de bytes, e quebras de linha CR LF e LF, para testar como um leitor decodifica texto.", + "catches": [ + "um leitor que presume UTF-8 e mostra um arquivo UTF-16 com um caractere a cada três, ou como fileiras de quadradinhos", + "uma marca de ordem de bytes lida como conteúdo, de modo que o primeiro campo de uma importação começa com três caracteres estranhos", + "um importador que adivinha a codificação pelos primeiros bytes e adivinha diferente num arquivo mais longo", + "um arquivo CRLF dividido em linhas com uma linha vazia depois de cada uma, ou um retorno de carro que sobra dentro do último campo" + ], + "details": { + "sample": "O tamanho de cada arquivo do conjunto. UTF-16 guarda dois bytes por caractere, então um número ímpar é recusado." + } + }, + "upload-validation": { + "question": "Meu formulário de upload aceita o que deve e recusa o resto?", + "title": "Validação de upload", + "pageTitle": "Arquivos de teste de validação de upload - tipo, tamanho e nome", + "description": "Arquivos para testar um formulário de upload: tipos permitidos e negados, conteúdo que não bate com a extensão, limite de tamanho, nomes hostis e upload em massa.", + "catches": [ + "um limite aplicado no navegador e não no servidor", + "um SVG ou HTML tomado por imagem ou por texto simples, que é um jeito de passar um script por um formulário", + "um arquivo verificado pela extensão e nunca aberto, de modo que um PDF chamado .jpg passa", + "um formulário que lê o corpo inteiro na memória antes de olhar o tamanho", + "um upload chamado PHOTO.JPG recusado onde photo.jpg é aceito, ou o contrário", + "um nome com espaços, parênteses ou caracteres fora do ASCII gravado em disco sem alteração" + ], + "details": { + "limit": "O limite de tamanho que seu formulário de upload declara. Este conjunto dá um passo para cada lado - para um arquivo em cada distância, rode o preset size-boundaries.", + "allow": "Quais tipos seu formulário deve aceitar. Cada um vira um arquivo real desse tipo, e eles são o controle positivo do conjunto todo.", + "deny": "Quais extensões seu formulário deve recusar. Uma extensão para a qual esta versão não tem formato ainda recebe um arquivo com esse nome, com texto simples.", + "far-over": "O quanto acima do limite vai o único arquivo grande. Desligue onde escrever várias vezes o limite não vale o disco.", + "bulk": "Quantos arquivos o upload em massa contém. Zero deixa esse grupo totalmente fora do conjunto." + } + } + }, + "commands": { + "generate": "produzir arquivos, a partir de uma receita ou de opções", + "validate": "verificar uma receita sem escrever nada", + "verify": "verificar um diretório contra um manifesto", + "cleanup": "remover os arquivos que um manifesto lista", + "recipe fmt": "imprimir uma receita na sua forma normalizada", + "preset": "montar um conjunto de arquivos a partir de uma pergunta de teste nomeada", + "formats": "listar os formatos que esta versão suporta", + "damage": "listar as formas como esta versão pode quebrar um arquivo de propósito", + "tool": "pequenas utilidades para arquivos que você já tem", + "version": "imprimir a versão da ferramenta", + "license": "imprimir a licença e o que ela significa para os arquivos gerados" + }, + "outcomes": { + "accept": "Seu sistema deve aceitar o arquivo.", + "reject": "Seu sistema deve recusar o arquivo.", + "sanitize": "Seu sistema deve aceitar o arquivo e limpá-lo, por exemplo renomeando-o.", + "unspecified": "Depende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria." + }, + "damages": { + "zero-head": "Sobrescreve os primeiros bytes do arquivo com zeros, sem mexer no comprimento. A maioria dos leitores olha ali primeiro, então quase tudo percebe este dano." + }, + "terms": { + "oracleNone": "não se aplica", + "int": "qualquer número inteiro", + "choice": "um de um conjunto fixo", + "bool": "verdadeiro ou falso", + "size": "um tamanho como 2mb", + "text": "texto", + "pixels": "pixels", + "paragraphs": "parágrafos", + "rows": "linhas", + "columns": "colunas", + "slides": "slides", + "hertz": "hertz", + "megapixels": "megapixels", + "million cells": "milhões de células", + "entries per second": "entradas por segundo", + "files": "arquivos", + "sizes separated by commas": "tamanhos separados por vírgulas", + "format ids separated by commas": "ids de formato separados por vírgulas", + "format ids separated by commas, or all": "ids de formato separados por vírgulas, ou all", + "extensions separated by commas": "extensões separadas por vírgulas", + "the id of a format, as tfg formats lists them": "o id de um formato, como o tfg formats lista", + "the password, in plain text": "a senha, em texto simples", + "any text": "qualquer texto", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "uma data como 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none" + }, + "faq": [ + { + "q": "Como isso é diferente de dd, fsutil ou truncate?", + "a": "Esses comandos dão um arquivo do tamanho certo cheio de nada. Um arquivo de 2 MB chamado photo.png feito assim não é um PNG, então qualquer coisa que realmente o interprete o recusa pelo motivo errado, e o seu teste também passa pelo motivo errado. Isto produz um PNG real de exatamente 2 MB que abre em um visualizador de imagens e vem com uma declaração de como o seu sistema deve tratá-lo.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "É gratuito, e posso usar no trabalho?", + "a": "Sim para os dois. É distribuído sob a GPL-3.0 e não custa nada. Não há conta, chave de licença nem plano pago." + }, + { + "q": "Posso usar os arquivos gerados em um produto de código fechado?", + "a": "Sim. A licença cobre o código da ferramenta, não o que ela produz. Arquivos, receitas e manifestos gerados são saída e não obras derivadas, então você pode versioná-los e distribuí-los sem nenhuma obrigação." + }, + { + "q": "Os arquivos gerados contêm dados pessoais reais?", + "a": "Não. Tudo dentro deles é sintetizado a partir de um seed. Nenhum conjunto de dados é lido, nenhum serviço é contatado e nenhum conteúdo de terceiros é embutido. Trate um endereço de e-mail gerado como inutilizável em vez de não usado, porque qualquer texto aleatório pode coincidir por acaso com um real." + }, + { + "q": "Vou obter exatamente os mesmos arquivos em outra máquina?", + "a": "Sim, byte a byte, com a mesma receita e o mesmo seed. O projeto testa isso a cada mudança, e quebrá-lo exige uma versão maior. É isso que permite versionar uma receita pequena em vez de fixtures binárias grandes." + }, + { + "q": "Precisa de conexão com a internet?", + "a": "Nunca. Não há telemetria, verificação de atualizações nem cliente de nuvem, e o binário da linha de comando não tem pilha de rede compilada nele. Funciona em uma máquina sem rede e dentro de um ambiente corporativo fechado." + }, + { + "q": "O que acontece se eu pedir um tamanho que um formato não consegue alcançar?", + "a": "Você recebe um erro que nomeia o formato, o menor tamanho possível, o motivo desse piso e o que fazer em vez disso, e nenhum arquivo é escrito. A ferramenta nunca arredonda um tamanho em silêncio. Cada piso está listado na página de formatos.", + "code": "tfg formats png" + }, + { + "q": "Posso gerar um arquivo deliberadamente quebrado?", + "a": "Sim. Adicione --damage zero-head e o arquivo sai com exatamente o tamanho pedido, com os primeiros bytes sobrescritos por zeros, de modo que um leitor o recusa, e o manifesto diz que o seu sistema deve rejeitá-lo. A página sobre arquivos de teste corrompidos traz os detalhes.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Quais formatos vêm a seguir?", + "a": "7z, mp3 e mp4. Hoje {{ .Facts.FormatCount }} formatos funcionam de ponta a ponta." + }, + { + "q": "Em quais sistemas posso rodar?", + "a": "A linha de comando roda em Windows e Linux, tanto em Intel quanto em ARM, e em Macs com Apple Silicon. A janela de desktop é distribuída para Windows em Intel, Linux em Intel e Macs com Apple Silicon. Macs Intel não são suportados e nada é compilado para eles." + }, + { + "q": "Preciso instalar alguma coisa?", + "a": "Não. Baixe o arquivo do seu sistema, descompacte e execute o binário. Não há instalador, runtime para adicionar nem dependência para resolver. Se você tem Go, um único comando go install também funciona.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Por que uma execução sobre milhares de arquivos é mais lenta no Windows?", + "a": "Porque o Windows cobra mais por cada caminho que examina, e um comando que percorre milhares de arquivos examina milhares de caminhos. Medido em uma máquina com 3000 arquivos de 1 kB, o verify leva cerca de 0,9 segundo no Windows e cerca de 0,2 segundo no Linux em um contêiner. Um caminho de saída mais curto reduz o valor do Windows, porque cada pasta acima dos arquivos faz parte do que é examinado." + } + ] +} diff --git a/web/content/pt-BR/use-cases.html b/web/content/pt-BR/use-cases.html new file mode 100644 index 00000000..620c8413 --- /dev/null +++ b/web/content/pt-BR/use-cases.html @@ -0,0 +1,135 @@ +

Para que as pessoas usam

+

+ Cinco tarefas que aparecem em quase todo projeto que aceita arquivos de pessoas, e o comando que faz + cada uma. Todo exemplo abaixo roda como está escrito. +

+ +
+

Limites de upload

+

Testar se um limite de tamanho de arquivo é aplicado onde diz que é

+

+ Um limite são três casos de teste, não um: logo abaixo, exatamente nele e logo acima. Conseguir + esses à mão significa calcular contagens de bytes e torcer para não ter errado por um. Peça o + conjunto no lugar: +

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

+ Você recebe três PDFs reais com 1048575, 1048576 e 1048577 bytes, e um manifesto dizendo que os dois + primeiros devem ser aceitos e o terceiro rejeitado por size_limit. Seu teste lê a + expectativa em vez de você escrever três asserções à mão - e quando o limite muda, você muda um + número e roda de novo. +

+

+ O mesmo funciona sem preset quando você quer um único conjunto de limites embutido: +

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

Integração contínua

+

Manter fixtures fora do repositório sem perdê-las

+

+ Fixtures binárias grandes deixam um repositório lento de clonar e chato de revisar, e ninguém sabe + dizer o que mudou quando uma é substituída. Uma receita são algumas centenas de caracteres de + YAML que reconstroem os arquivos idênticos - byte a byte, em qualquer máquina - + porque cada arquivo é derivado do seed da execução. +

+
- 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
+

+ Cada término tem seu próprio código de saída, então um pipeline consegue distinguir uma receita ruim + de um disco cheio e de uma divergência de verificação. Uma execução com falha não imprime nada + na saída padrão, o que impede um parser de logs de ler um erro como dado. +

+
+ +
+

Escala

+

Descobrir o que acontece quando a pasta é grande

+

+ Rotinas de importação, jobs noturnos e listagens de diretório se comportam diferente com dez mil + arquivos do que com dez. Tamanhos sorteados de um intervalo fazem o conjunto parecer tráfego + real em vez de dez mil arquivos idênticos, e o sorteio vem do seed, então o conjunto é o mesmo + amanhã. +

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

+ Confira quanto uma execução custaria antes de ela escrever qualquer coisa, o que importa quando o + total é medido em gigabytes: +

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

+ Uma execução maior que o espaço livre no disco é recusada antes de o primeiro byte ser escrito, em + vez de encher o disco e falhar no meio. +

+
+ +
+

Arquivos compactados

+

Testar um descompactador com um arquivo compactado que realmente contém arquivos

+

+ Um arquivo compactado vazio com a extensão certa não prova nada sobre o código que o abre e percorre + o que há dentro. Declare o conteúdo e o arquivo compactado realmente o contém: +

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

+ Profundidade de aninhamento, contagem de entradas e tamanho do que há dentro são coisas sobre as + quais uma rotina de importação tem opinião, e é assim que você descobre quais são. +

+
+ +
+

Parsers e visualizadores

+

Conferir se o seu próprio código lê um formato como o software real

+

+ Todo formato aqui é verificado com um leitor independente antes de ser liberado - um PNG é aberto e + seus pixels comparados, um DOCX é relido por bibliotecas separadas, um arquivo compactado é + extraído. Isso significa que um arquivo que o seu parser recusa é uma descoberta sobre o seu + parser, não sobre o gerador. +

+
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
+

+ A página de formatos lista as configurações que cada um aceita e o + menor arquivo que cada um pode ser. +

+
+ +
+

Guias

+

Dois deles em detalhe

+ +
+ +
+

Para quem é

+

+ Engenheiros de QA, automação de testes e qualquer pessoa cujo código tenha atrás um formulário de + upload, uma rotina de importação, um parser ou uma cota de armazenamento. Roda em uma máquina + sem rede nenhuma, o que importa em um ambiente corporativo fechado onde um gerador baseado em + navegador não é opção. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ro/ci.html b/web/content/ro/ci.html new file mode 100644 index 00000000..1a52e87b --- /dev/null +++ b/web/content/ro/ci.html @@ -0,0 +1,192 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cum generezi fișiere de test într-un pipeline CI

+

+ Un fixture binar într-un repository rămâne pentru totdeauna în istoricul lui, nu poate fi revizuit + într-un diff și devine imposibil când fișierul este mare. Generează în schimb fișierele în + pipeline, dintr-o rețetă. Rețeta este text, octeții ies la fel de fiecare dată, iar un ultim pas + dovedește că nimic nu s-a mișcat. +

+ +
+

Răspunsul scurt

+

+ Instalează tfg, rulează tfg generate fixtures.yaml --out ./fixtures + înaintea testelor și tfg verify ./fixtures/manifest.json după ele. Ambii pași fac + singuri build-ul să eșueze, cu un cod de ieșire care spune de ce. +

+
+ +
+

De ce să nu le comiți

+

De ce un fixture nu trebuie să stea în repository

+ +

+ Ce trebuie comis este rețeta. Aceeași rețetă și același seed scriu aceiași octeți pe orice mașină, + deci fișierul generat în pipeline este fișierul pe care l-ai avut pe laptop. +

+
+ +
+

Rețeta

+

O rețetă care stă lângă teste

+

+ Aceasta scrie douăzeci și cinci de facturi care trebuie acceptate și două imagini peste o limită + care trebuie respinse, iar manifestul notează ambele așteptări: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml o verifică fără să scrie nimic și numește toate problemele + deodată. +

+
+ +
+

GitHub Actions

+

Un workflow care instalează instrumentul și construiește fixture-urile

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Linia cu suma de control compară arhiva cu verify-SHA256SUMS.txt din aceeași versiune. + Versiunea este fixată, așa că o versiune nouă nu schimbă niciodată un build pe care nu l-ai + atins. +

+
+ +
+

GitLab CI

+

Același lucru ca job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Când se face roșu

+

Ce face un pas să eșueze, și de ce

+

+ Fiecare final are propriul cod de ieșire, deci pasul eșuează singur, iar jurnalul spune care a fost. + Cele pe care le întâlnește un pipeline: +

+ +

+ O rulare eșuată nu afișează nimic la ieșirea standard, așa că un parser de jurnale nu ia niciodată o + eroare drept date. Tabelul complet este pe pagina de + documentație. +

+
+ +
+

PowerShell

+

Un script PowerShell mai are nevoie de o linie

+

+ PowerShell nu scoate codul de ieșire al unui program dintr-un fișier .ps1. Rulează unul + cu -File și scriptul răspunde 0 chiar și când instrumentul dinăuntru a + refuzat lucrul, așa că un build care ar trebui să fie roșu devine verde. Ultima linie este toată + soluția: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Așa se comportă PowerShell, nu este ceva legat de acest instrument. cmd, + bash și zsh nu au nevoie de nimic în plus. +

+
+ +
+

Mai multe joburi

+

Împărțirea fixture-urilor între joburi

+

+ De obicei nu e nevoie să le încarci. Fiindcă aceeași rețetă scrie aceiași octeți, fiecare job își + poate rula propriul tfg generate, ceea ce e mai rapid decât o încărcare și o + descărcare. Când un job trebuie să primească fișiere de la altul, rulează tfg + verify pe manifest după transfer, și îți spune dacă ce a ajuns este ce s-a scris. +

+
+ +
+

Mai departe

+

Unde să mergi de aici

+ +
diff --git a/web/content/ro/damage.html b/web/content/ro/damage.html new file mode 100644 index 00000000..381ce3ea --- /dev/null +++ b/web/content/ro/damage.html @@ -0,0 +1,177 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cum faci un fișier corupt pentru teste

+

+ Un validator căruia i s-au arătat doar fișiere sănătoase nu a fost cu adevărat testat. Iată cum + obții un fișier stricat intenționat, care iese cu exact mărimea pe care o ceri și + vine cu un manifest care spune ce trebuie să facă sistemul tău cu el. +

+ +
+

Răspunsul scurt

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out scrie un PNG de + exact 2097152 de octeți ai cărui primi octeți sunt zerouri, iar manifestul de lângă el notează + că sistemul tău trebuie să îl respingă. +

+
+ +
+

Calea obișnuită

+

De ce un fișier corupt de mână face un test prost

+

+ Căile obișnuite sunt un editor hexazecimal, un script care schimbă câțiva octeți la întâmplare sau + un fișier scurtat cu head ori truncate. Merg o dată, apoi te costă: +

+ +
+ +
+

Ce primești

+

Un fișier deteriorat are în continuare mărimea cerută

+

+ Fișierul este generat normal și stricat după aceea, pe drumul spre disc. Păstrează mărimea cerută, + iar aceeași comandă scrie din nou aceiași octeți. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Setările se scriu după două puncte. Opțiunea poate fi repetată, iar deteriorările se aplică în + ordinea în care le scrii. Funcționează cu fiecare dintre cele {{ .Facts.FormatCount }} formate. +

+
+ +
+

Ce poate face

+

Ce deteriorări există?

+

+ Aceasta este lista pe care o afișează programul, citită din el când se construiește pagina. + tfg damage o afișează pe aceeași, iar tfg damage <id> spune ce + primește una dintre ele. +

+ {{ template "damagesTable" . }} +

+ zero-head scrie zerouri peste începutul fișierului. Majoritatea cititorilor se uită + întâi acolo, la semnătura și antetul care spun ce este fișierul, așa că aproape orice cititor + observă. Textul simplu și jurnalele nu au semnătură și sunt respinse și ele, pentru că un șir de + octeți nuli nu este text. Sub patru octeți, unele formate ies cu o deteriorare de care nu se + plânge niciun cititor, de aceea setarea începe de la patru. +

+
+ +
+

Ce spune manifestul

+

Un manifest care spune ce trebuie să se întâmple

+

+ Fiecare fișier deteriorat primește o intrare care spune că sistemul tău trebuie să îl respingă, cu + deteriorarea notată alături: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Două cereri sunt refuzate înainte să se scrie ceva, pentru că fiecare ar lăsa pe disc un fișier pe + care manifestul îl descrie greșit: +

+ +
+ +
+

Într-o rețetă

+

Fișiere sănătoase și stricate într-o singură rulare

+

+ Pune-le pe amândouă într-o rețetă, iar manifestul poartă așteptarea fiecărui fișier, deci testul nu + are nevoie de o listă cu care este care: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Într-un test

+

Transformarea într-un test

+

+ Testul citește manifestul și verifică dacă ce s-a întâmplat este ce s-a declarat. Nu are nevoie de o + listă de nume de fișiere: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ O respingere bună este una curată. Un mesaj care spune ce a fost greșit este răspunsul pe care îl + vrei. O eroare de server, o blocare sau un fișier salvat pe jumătate este defectul pe care acest + test există ca să îl găsească. +

+
+ +
+

Mai departe

+

Unde să mergi de aici

+ +
diff --git a/web/content/ro/docs.html b/web/content/ro/docs.html new file mode 100644 index 00000000..b7e04504 --- /dev/null +++ b/web/content/ro/docs.html @@ -0,0 +1,281 @@ +

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:

+ {{ template "commandList" . }} +
+ +
+

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țiuneCe 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-runnumără și arată, nu scrie absolut nimic
--jsonscrie 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: +

+ +

+ 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": "{{ .Facts.Version }}" },
+  "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ă. +

+ {{ template "presetsList" . }} +
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ă. +

+ {{ template "exitCodesTable" . }} +
- 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. +

+
diff --git a/web/content/ro/exact-size.html b/web/content/ro/exact-size.html new file mode 100644 index 00000000..aca2dbb7 --- /dev/null +++ b/web/content/ro/exact-size.html @@ -0,0 +1,145 @@ +

Cum creezi un fișier de dimensiune exactă

+

+ Fiecare sistem are o comandă pentru asta, iar toate trei sunt mai jos. Îți dau un fișier cu exact + numărul potrivit de octeți - și pentru multe teste atât îți trebuie. Fiecare comandă de pe + această pagină a fost rulată înainte de publicare, pe sistemul căruia îi aparține. +

+ +
+

Răspunsul scurt

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Dimensiunile sunt în octeți, iar 10 + MB numărați cum numără managerul tău de fișiere sunt 10485760. +

+
+ +
+

Windows

+

fsutil și o variantă PowerShell care nu are nevoie de nimic în plus

+

+ fsutil vine cu Windows. Primește dimensiunea în octeți, așa că + calculează mai întâi numărul - 10 MB sunt 10485760, 100 MB sunt 104857600, 1 GB este 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Măsurat pe Windows 11: merge dintr-un prompt obișnuit, fără să ceară unul cu privilegii ridicate, + iar fișierul iese de exact 10485760 de octeți. +

+

PowerShell poate face același lucru fără să cheme alt program și înțelege unitățile:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB în PowerShell înseamnă 10485760 de octeți, aceeași numărare în baza 1024 pe care o + folosește Explorer, deci cele două comenzi de mai sus produc aceeași dimensiune. +

+
+ +
+

Linux

+

dd, truncate și fallocate, și diferența care îi prinde pe oameni

+

dd este cel pe care îl știe toată lumea. Scrie într-adevăr octeții:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate e instantaneu și asta e capcana. Măsurat pe Alpine Linux, fișierul raportează + 10485760 de octeți și ocupă zero blocuri - este un fișier rar + (sparse). Tot ce îl citește primește zece megaocteți de zerouri, dar discul nu a cedat niciodată + spațiul: +

+
truncate -s 10M test10mb.bin
+

+ E bine pentru a testa o limită de încărcare și înșelător pentru a testa o cotă de disc. + fallocate este cel de folosit când spațiul trebuie să fie real: +

+
fallocate -l 10M test10mb.bin
+

Și când conținutul trebuie să fie incompresibil, ca un arhivator să nu-l poată strânge la loc:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, care nu e rar, și cele două pe care le știi deja

+

+ macOS vine cu mkfile. Măsurat pe macOS 26.6.2: 10485760 de octeți și 20480 de blocuri, + deci spațiul este alocat cu adevărat, nu doar promis: +

+
mkfile 10m test10mb.bin
+

dd și truncate sunt și ele acolo și se comportă ca pe Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Unde nu mai merge asta

+

Un fișier de dimensiunea potrivită nu este un fișier de tipul potrivit

+

+ Tot ce e mai sus îți dă un bloc de zerouri. Asta ajunge când ce se testează se uită doar la + dimensiune - o limită de încărcare, o cotă, un transfer. Nu mai ajunge din clipa în care ceva + deschide fișierul. +

+

+ Măsurat, și merită să încerci singur: fă un fișier de 2 MB cu fsutil, numește-l + photo.png și dă-l unei biblioteci de imagini. Pillow răspunde cannot identify + image file. Nu e un PNG. N-a fost niciodată - doar numele o spunea. +

+

+ Contează mai mult decât pare, din cauza direcției în care eșuează testul. + Endpointul tău de încărcare respinge fișierul, testul tău devine verde și tragi concluzia că + limita de dimensiune funcționează. Nu l-a respins pentru dimensiune. L-a respins pentru că + octeții nu erau o imagine, iar regula pe care voiai s-o testezi n-a fost niciodată atinsă. +

+ +
+ +
+

Cealaltă cale

+

Un fișier real de acel format, la exact dimensiunea cerută

+

+ Asta face Testing Files Generator. Fișierul este unul autentic al formatului său - se deschide în + programul căruia îi aparține - și are numărul exact de octeți pe care l-ai cerut, la octet: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Cere o dimensiune pe care un format nu o poate atinge și primești o eroare care numește pragul și + motivul lui, niciodată un fișier de dimensiune greșită. Pagina de + formate listează fiecare format cu cel mai mic fișier pe care îl poate produce. +

+

Iar o limită înseamnă trei cazuri de test, nu unul, așa că instrumentul le construiește pe toate trei:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Asta îți dă 10485759, 10485760 și 10485761 de octeți și un manifest care spune pe care sistemul tău + trebuie să le accepte și pe care să le respingă. Pagina de + cazuri de utilizare parcurge asta și alte patru sarcini pentru care a fost făcut. +

+ {{ template "downloadCta" . }} +
+ +
+

Deci pe care să-l folosești?

+ +

+ Ambele sunt pe această pagină pentru că ambele au dreptate o parte din timp. Greșeala de evitat este + să-l folosești pe primul unde îl trebuie pe al doilea și să citești testul verde drept dovadă. +

+
diff --git a/web/content/ro/faq.html b/web/content/ro/faq.html new file mode 100644 index 00000000..d1dcf5d8 --- /dev/null +++ b/web/content/ro/faq.html @@ -0,0 +1,20 @@ +

Întrebări frecvente

+

+ Licență, confidențialitate, reproductibilitate și lucrurile pe care oamenii le verifică înainte să + pună un generator într-un pipeline de build. Dacă întrebarea ta nu e aici, + sistemul de issue-uri este deschis. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Încă te decizi?

+

+ Pagina de cazuri de utilizare arată sarcinile pentru care a + fost făcut, iar pagina de formate listează fiecare format cu cel mai + mic fișier pe care îl poate produce. README-ul din repository + este referința completă. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ro/formats.html b/web/content/ro/formats.html new file mode 100644 index 00000000..a6d2dd6f --- /dev/null +++ b/web/content/ro/formats.html @@ -0,0 +1,80 @@ +

{{ .Facts.FormatCount }} formate de fișiere, fiecare generat la o dimensiune exactă

+

+ Fiecare este un fișier real al acelui format. Se deschide în programul căruia îi + aparține și are exact numărul de octeți pe care l-ai cerut. Niciunul nu e umplutură de zerouri cu + o extensie lipită. +

+ +{{ template "formatsTable" . }} + +
+

Ce înseamnă coloanele

+ +

+ Fiecare format se și repetă la octet: aceeași rețetă și același seed produc fișiere identice pe + orice mașină, ceea ce face sigur să comiți o rețetă în locul fixture-urilor înseși. +

+
+ +
+

Setările pe care le acceptă fiecare format

+

+ Majoritatea formatelor au setări proprii - dimensiunile imaginii, calitatea JPEG, numărul de pagini + PDF, rândurile și coloanele dintr-o foaie de calcul, câte intrări intră într-o arhivă. + Setează-le cu --set key=value în linia de comandă sau sub properties: + într-o rețetă. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ O valoare în afara a ce acceptă o setare este refuzată cu un mesaj care numește setarea, intervalul + permis și ce să folosești în loc. O setare necunoscută este și ea o eroare, niciodată o valoare + implicită tăcută - o greșeală de scriere acceptată pe tăcute dă un fișier cu setările greșite și + o oră de întrebări de ce trece testul când n-ar trebui. +

+

+ Rulează tfg formats <id> ca să vezi exact ce acceptă un format în versiunea pe + care o ai. +

+
+ +
+

Arhivele conțin fișiere reale

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} și {{ end }}{{ $c.ID }}{{ end }} pot + fi umplute cu intrări, nu lăsate ca o carcasă goală. O arhivă generată conține cu adevărat + documentele pe care spune că le conține, așa că tot ce o dezarhivează în timpul unui test + găsește înăuntru fișiere reale. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/ro/index.html b/web/content/ro/index.html new file mode 100644 index 00000000..1e57acb9 --- /dev/null +++ b/web/content/ro/index.html @@ -0,0 +1,197 @@ +
+
+

Generează fișiere de test reale la dimensiunea exactă

+

+ PDF, PNG, DOCX, ZIP - {{ .Facts.FormatCount }} formate în total, și fiecare este un + fișier real care se deschide în programul căruia îi aparține, la exact dimensiunea pe + care ai cerut-o. Fiecare rulare notează și ce trebuie să facă aplicația ta cu fiecare + fișier. Linie de comandă și fereastră desktop, gratuit și open source, funcționând în întregime + pe mașina ta. +

+ + {{ template "downloadCta" . }} +
+ +
+ Fereastra desktop Testing Files Generator, pregătită să scrie un lot de fișiere de test +
Fereastra desktop, pregătită să scrie un lot de fișiere. Același motor rulează în spatele liniei de comandă.
+
+
+ + + +
+

Problema

+

Să faci un fișier de test e ușor. Să faci cele o mie potrivite e partea plictisitoare

+

Testezi software care primește fișiere de la oameni. Mai devreme sau mai târziu ai nevoie de:

+ +

+ Asta înlocuiește acesta. Este construit pentru ingineri QA, automatizarea testelor și oricine are în + spatele codului un formular de încărcare, o rutină de import, un parser sau o cotă de stocare. +

+
+ +
+

Ce îl face diferit

+

Alte generatoare se opresc la octeți. Acesta răspunde la ce întreabă de fapt testul tău

+

+ Un folder de fișiere te lasă tot pe tine să hotărăști ce trebuie să demonstreze fiecare. Fiecare + rulare scrie aici un manifest.json lângă fișiere - o listă simplă a tot ce s-a + produs și, pentru fiecare intrare, o așteptare declarată. +

+

Să zicem că endpointul tău de încărcare permite 1 MB. Cere cele trei fișiere de pe acea linie:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FișierOctețiSistemul tău trebuie săPentru că
1mb_under_1b.pdf1048575acceptee în interiorul limitei
1mb_at_limit.pdf1048576acceptelimita însăși este permisă
1mb_over_1b.pdf1048577respingăsize_limit
+
+ +

Trei fișiere, trei răspunsuri diferite, în formă citibilă de mașină. Testul tău citește manifestul în loc să scrii tu asertările de mână:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Acolo unde răspunsul depinde de propria ta politică, manifestul spune asta

+

+ Înregistrează unspecified în loc să inventeze o așteptare. Un generator care ghicește + produce eșecuri false, iar o suită care dă alarme false ajunge oprită. +

+
+
+ +
+

Presetări

+

Alege întrebarea, primești setul întreg

+

+ O presetare este un set de fișiere de test conceput în jurul unei întrebări de test, ca să nu fie + nevoie să afli tu ce fișiere dovedesc ce. Fiecare are o pagină care spune ce găsește de obicei, + ce este în set și fiecare setare pe care o acceptă. +

+ {{ template "presetsList" . }} +

Toate presetările și cum se leagă de rețete

+
+ +
+

Pornire rapidă

+

Trei comenzi ca să-l vezi funcționând

+
    +
  1. +

    Fă un fișier

    +

    Un PNG, exact doi megaocteți:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Fă multe fișiere

    +

    + Zece mii de fișiere de jurnal, fiecare între unu și opt kiloocteți, cu dimensiunile extrase din seed + ca mâine să dea același set. Dă fiecărei rulări propriul director - + manifestul este singura evidență a ce a scris o rulare, așa că instrumentul refuză să scrie + un al doilea peste el: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Verifică-le, apoi șterge-le

    +

    verify îți spune că nimic nu s-a mișcat. cleanup șterge exact ce s-a scris și nimic altceva:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Dimensiunile se numără din 1024 în 1024, cum o face managerul tău de fișiere, deci 2mb + înseamnă 2097152 octeți. Merge și un simplu număr de octeți. + Documentația acoperă rețetele, manifestul și codurile de ieșire. +

+
+ +
+

Ce primești

+

Construit pentru o suită care rulează nesupravegheată

+ +
+ +
+

Descărcare

+

Alege versiunea pentru sistemul tău

+

+ Dezarhivează arhiva și rulează-o. tfg este linia de comandă și tfg-gui + este fereastra desktop. Nu există instalator și nimic de adăugat pe mașina ta. +

+ {{ template "downloadsTable" . }} +
+

Ce este semnat și ce nu

+

+ Descărcările pentru Windows și macOS sunt semnate, așa că pornesc fără avertisment despre un + dezvoltator necunoscut. Cele pentru Linux nu sunt, pentru că Linux pe desktop nu are un + echivalent cu care să le semnezi. Fiecare arhivă este listată în + verify-SHA256SUMS.txt pe pagina de versiuni, ca să poți verifica ce ai descărcat. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/ro/preset.html b/web/content/ro/preset.html new file mode 100644 index 00000000..7c4c596d --- /dev/null +++ b/web/content/ro/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Presetarea {{ .ID }} construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ +{{ if .Catches }} +
+

Ce găsește de obicei?

+ +
+{{ end }} + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show {{ .ID }}:

+
+ + + + + + + +
Fișiere{{ .Budget.Files }}
Targeturi în rețeta lui{{ .Budget.Targets }}
Dimensiune totală{{ .Bytes }} B
Formate{{ join .Budget.Formats ", " }}
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
AșteptatSemnificațieFișiere
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Ce poți schimba?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
SetarePrimeșteImplicitCe face
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Această valoare implicită este valoarea noastră provizorie, nu valoarea sistemului tău. Dă-o pe a ta.{{ end }}
+
+ {{- else }} +

Această presetare nu are setări. Setul este același de fiecare dată.

+ {{- end }} +
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/ro/presets.html b/web/content/ro/presets.html new file mode 100644 index 00000000..017f703b --- /dev/null +++ b/web/content/ro/presets.html @@ -0,0 +1,32 @@ +

Presetări de fișiere de test, câte un set pentru fiecare întrebare de test

+

+ O presetare este un set întreg de fișiere de test conceput în jurul unei întrebări, cu un manifest + care spune cum trebuie să reacționeze sistemul tău la fiecare fișier. Tu alegi întrebarea, + instrumentul construiește setul. Fiecare presetare are propria pagină cu ce găsește de obicei, ce + este în set și fiecare setare pe care o acceptă. +

+ +{{ template "presetsList" . }} + +
+

Prin ce diferă o presetare de o rețetă?

+

+ Pe dedesubt, prin nimic. O presetare este o rețetă pe care instrumentul o scrie pentru tine din + câteva setări. tfg preset eject afișează acea rețetă ca s-o poți păstra lângă + testele tale și s-o editezi, iar o rețetă proprie se poate sprijini pe o presetare cu o singură + linie, extends: preset: urmat de id-ul ei. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Pot avea încredere în valorile implicite?

+

+ Pentru fișiere, da. Pentru un număr pe care îl știe doar sistemul tău, precum limita unui formular + de încărcare, o valoare implicită este o valoare provizorie de-a noastră, iar instrumentul o + spune de fiecare dată când folosește una. Pagina fiecărei presetări marchează acele setări, iar + tfg preset show o spune înainte să se scrie ceva. +

+
diff --git a/web/content/ro/site.json b/web/content/ro/site.json new file mode 100644 index 00000000..8b011671 --- /dev/null +++ b/web/content/ro/site.json @@ -0,0 +1,328 @@ +{ + "code": "ro", + "locale": "ro_RO", + "name": "Română", + "dir": "ro", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Acasă", + "title": "Generator de fișiere de test - dimensiune exactă, {{ .Facts.FormatCount }} formate reale", + "description": "Generator gratuit și open source de fișiere de test pentru QA. PDF, DOCX, PNG și ZIP reale, la dimensiunea exactă, cu un manifest despre reacția așteptată." + }, + { + "key": "formats", + "slug": "formate", + "nav": "Formate", + "title": "{{ .Facts.FormatCount }} formate de fișiere - PDF, DOCX, PNG, ZIP și altele", + "description": "Toate formatele generate, cel mai mic fișier posibil pentru fiecare și setările acceptate. Toate cele {{ .Facts.FormatCount }} se deschid în programul căruia îi aparțin." + }, + { + "key": "presets", + "slug": "presetari", + "nav": "Presetări", + "title": "Presetări de fișiere de test - seturi gata făcute pentru QA", + "description": "Seturi gata făcute de fișiere de test, fiecare răspunde unei întrebări: limite de încărcare, nume de fișiere, codări, import de tabele, fișiere goale și validare." + }, + { + "key": "docs", + "slug": "documentatie", + "nav": "Documentație", + "title": "Documentație - comenzi, rețete, manifest, coduri de ieșire", + "description": "Cum generezi fișiere de test din linia de comandă sau dintr-o rețetă YAML, ce conține manifestul și ce înseamnă fiecare cod de ieșire în CI." + }, + { + "key": "use-cases", + "slug": "cazuri-de-utilizare", + "nav": "Cazuri de utilizare", + "title": "Cazuri de utilizare - limite de încărcare, fixture-uri, teste", + "description": "Testarea unei limite de dimensiune la încărcare, fixture-uri reproductibile pentru CI, zece mii de fișiere generate și arhive umplute cu conținut real." + }, + { + "key": "exact-size", + "slug": "creare-fisier-de-dimensiune-exacta", + "nav": "Dimensiune exactă", + "title": "Cum creezi un fișier de dimensiune exactă - Windows, Linux, macOS", + "description": "fsutil, dd, truncate și mkfile, fiecare măsurat pe sistemul lui, și de ce un fișier făcut așa nu e un PDF sau un PNG când un test are nevoie de unul." + }, + { + "key": "faq", + "slug": "intrebari-frecvente", + "nav": "FAQ", + "title": "FAQ - întrebări despre generarea fișierelor de test", + "description": "Prin ce diferă de dd și fsutil, dacă fișierele pot fi comise, dacă rulările se repetă octet cu octet și ce se întâmplă când o dimensiune nu poate fi atinsă." + }, + { + "key": "damage", + "slug": "fisiere-de-test-corupte", + "nav": "Fișiere corupte", + "title": "Fișiere de test corupte - fișiere stricate de mărime exactă", + "description": "Un fișier stricat intenționat, de mărime exactă, cu un manifest care spune că sistemul tău trebuie să îl respingă. Pentru validarea încărcărilor și parsere.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "fisiere-de-test-in-ci", + "nav": "Fișiere de test în CI", + "title": "Fișiere de test în CI - GitHub Actions, GitLab CI și PowerShell", + "description": "Generează fișiere de test în pipeline în loc să comiți binare: workflow GitHub Actions, job GitLab, coduri de ieșire și capcana PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Sari la conținut", + "navLabel": "Principal", + "langLabel": "Limba", + "breadcrumbHome": "Acasă", + "imageAlt": "Testing Files Generator - fișiere de test reale la dimensiunea exactă, cu un manifest care spune cum trebuie să reacționeze sistemul tău la fiecare", + "schemaDescription": "Un generator gratuit și open source de fișiere de test pentru QA. Produce fișiere reale în {{ .Facts.FormatCount }} formate, la dimensiunea exactă, și scrie un manifest care spune cum trebuie să reacționeze sistemul testat la fiecare.", + "ctaDownload": "Descarcă", + "ctaSource": "Vezi codul sursă", + "ctaNote": "Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.", + "colFormat": "Format", + "colName": "Nume", + "colExtension": "Extensie", + "colSmallest": "Cel mai mic fișier", + "colFidelity": "Fidelitate", + "colChecked": "Verificat cu", + "colSetting": "Setare", + "colAccepts": "Acceptă", + "colSystem": "Sistem", + "colCli": "Linie de comandă", + "colWindow": "Fereastră desktop", + "noBinary": "încă fără binar", + "colCode": "Cod", + "colMeaning": "Semnificație", + "footerBlurb": "Fișiere de test pentru QA, la dimensiunea exactă, cu un manifest care spune cum trebuie să reacționeze sistemul tău la fiecare.", + "footerProject": "Proiect", + "footerSource": "Cod sursă pe GitHub", + "footerReleases": "Descărcări", + "footerIssues": "Raportează o problemă", + "footerSupport": "Susține proiectul", + "footerPages": "Pagini", + "footerLicence": "Copyright (C) 2026 DonislawDev. Publicat sub Licența Publică Generală GNU, versiunea 3. Fișierele pe care le generezi sunt ale tale - licența acoperă instrumentul, nu rezultatul lui.", + "footerPrivacy": "Acest site nu încarcă fonturi, scripturi sau trackere de nicăieri. Nu setează cookie-uri.", + "notFoundTitle": "Pagina aceasta nu există", + "notFoundLead": "Adresa pe care ai urmat-o nu corespunde niciunei pagini de pe acest site.", + "notFoundBack": "Mergi la pagina principală", + "read.format": "Formatul fiecărui fișier din set. Este o opțiune a instrumentului însuși, iar presetarea îi dă doar o valoare implicită.", + "readTakes.format": "un id de format din pagina de formate", + "colDamage": "Deteriorare", + "colEffect": "Ce face cu octeții", + "colSettings": "Setări", + "noSettings": "niciuna" + }, + "endings": { + "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." + }, + "presets": { + "empty-and-minimal": { + "question": "Trece un fișier valid, cât de mic permite formatul?", + "title": "Gol și minimal", + "pageTitle": "Cele mai mici fișiere de test valide și goale, în fiecare format", + "description": "Cel mai mic fișier valid scris în fiecare dintre cele {{ .Facts.FormatCount }} formate, plus un fișier gol acolo unde formatul permite, fiecare cu reacția așteptată.", + "catches": [ + "un fișier valid respins pentru că e prea mic, când verificarea numără octeți în loc să îi citească", + "un fișier gol care prăbușește cititorul în loc să fie raportat", + "o imagine lată de un pixel care împarte la zero pe drumul spre miniatură", + "un depozit care citește zero octeți ca pe o încărcare eșuată și tot reîncearcă" + ], + "details": { + "formats": "Din ce formate este alcătuit setul. Lasă all pentru toate formatele acestei versiuni sau numește-le pe cele pe care le acceptă sistemul tău." + } + }, + "filename-handling": { + "question": "Va stoca, va afișa și va returna sistemul meu un nume de fișier la care nu se aștepta?", + "title": "Gestionarea numelor de fișiere", + "pageTitle": "Nume de fișiere problematice pentru teste - Unicode și lungime", + "description": "Fișiere cu nume care strică încărcarea și stocarea: alte alfabete și emoji, inversarea direcției, caractere invizibile, sintaxă shell și SQL, limite de lungime.", + "catches": [ + "un nume care arată ca altul pe ecran, într-un jurnal sau într-o listă", + "un nume tăiat, scurtat sau rescris între încărcare și stocare", + "o limită de lungime numărată în caractere acolo unde depozitul numără octeți" + ], + "details": {} + }, + "size-boundaries": { + "question": "Este o limită de dimensiune aplicată exact acolo unde este declarată?", + "title": "Limite de dimensiune", + "pageTitle": "Testarea unei limite de încărcare - fișiere exact la limită", + "description": "Fișiere cu un octet sub, exact la și cu un octet peste limita declarată de sistemul tău, plus trepte mai largi de ambele părți, fiecare marcat dacă trebuie acceptat.", + "catches": [ + "erori de unu în plus sau în minus la limită", + "MB confundat cu MiB, adică 4,8 la sută, suficient cât să treacă un fișier care n-ar trebui să treacă", + "o limită aplicată în browser și nu pe server" + ], + "details": { + "limit": "Limita de dimensiune declarată de sistemul tău. Tot restul se măsoară pornind de la ea.", + "spread": "Cât de departe să se meargă de ambele părți ale limitei, ca listă de dimensiuni." + } + }, + "tabular-import": { + "question": "Supraviețuiește importul meu de tabele la ce exportă instrumentele reale?", + "title": "Import de tabele", + "pageTitle": "Fișiere de test pentru import CSV și Excel - delimitatori", + "description": "CSV cu alți delimitatori, sfârșituri de linie CR LF, fără antet și cu alte ghilimele, un tabel foarte lat, un registru Excel și JSON în mai multe forme.", + "catches": [ + "un fișier cu punct și virgulă citit ca o singură coloană, pentru că delimitatorul a fost presupus în loc să fie căutat", + "un fișier CRLF împărțit în rânduri cu un rând gol după fiecare", + "un tabel fără antet al cărui prim rând de date este înghițit drept nume de coloane", + "un import care păstrează coloanele pe care le poate arăta și aruncă restul fără o vorbă", + "un cititor care ia înregistrările JSON câte o linie și se oprește la primul document indentat" + ], + "details": { + "rows": "Câte rânduri are foaia de calcul. Se scrie exact la dimensiunea pe care o ocupă atâtea rânduri, așa că bugetul de mai sus se mută odată cu această valoare.", + "columns": "Câte coloane are fiecare rând al foii de calcul. Rânduri înmulțit cu coloane are un plafon, iar cererea peste el este refuzată înainte de a se scrie ceva." + } + }, + "text-encoding": { + "question": "Știe cititorul meu în ce codare este un fișier sau doar ghicește?", + "title": "Codarea textului", + "pageTitle": "Fișiere de test pentru codarea textului - UTF-8, UTF-16, BOM, CRLF", + "description": "Același text în UTF-8, UTF-16LE și UTF-16BE, cu și fără marcă de ordine a octeților, și sfârșituri de linie CR LF și LF, pentru a testa cum decodează un cititor textul.", + "catches": [ + "un cititor care presupune UTF-8 și arată un fișier UTF-16 cu un caracter din trei sau ca rânduri de pătrățele", + "o marcă de ordine a octeților citită ca și conținut, astfel încât primul câmp al unui import începe cu trei caractere străine", + "un importator care ghicește codarea din primii octeți și ghicește altfel pentru un fișier mai lung", + "un fișier CRLF împărțit în rânduri cu un rând gol după fiecare sau un retur de car rămas în ultimul câmp" + ], + "details": { + "sample": "Cât de mare este fiecare fișier din set. UTF-16 stochează doi octeți pentru fiecare caracter, așa că un număr impar este refuzat." + } + }, + "upload-validation": { + "question": "Acceptă formularul meu de încărcare ce trebuie și respinge restul?", + "title": "Validarea încărcării", + "pageTitle": "Fișiere de test pentru validarea încărcării - tip și nume", + "description": "Fișiere pentru testarea unui formular de încărcare: tipuri permise și interzise, conținut ce nu se potrivește cu extensia, limită de dimensiune, nume ostile.", + "catches": [ + "o limită aplicată în browser și nu pe server", + "un SVG sau un HTML luat drept imagine sau text simplu, o cale de a strecura un script printr-un formular", + "un fișier verificat după extensie și niciodată deschis, așa că un PDF numit .jpg trece", + "un formular care citește tot corpul în memorie înainte să vadă cât de mare e", + "o încărcare numită PHOTO.JPG respinsă acolo unde photo.jpg e acceptată, sau invers", + "un nume cu spații, paranteze sau caractere în afara ASCII scris pe disc neschimbat" + ], + "details": { + "limit": "Limita de dimensiune declarată de formularul tău de încărcare. Acest set face câte un pas de fiecare parte - pentru un fișier la orice distanță rulează presetarea size-boundaries.", + "allow": "Ce tipuri trebuie să accepte formularul tău. Fiecare devine un fișier real de acel tip și ele formează controlul pozitiv al întregului set.", + "deny": "Ce extensii trebuie să respingă formularul tău. O extensie pentru care această versiune nu are format primește totuși un fișier cu acel nume, conținând text simplu.", + "far-over": "Cât de mult peste limită ajunge singurul fișier mare. Oprește-l unde scrierea de mai multe ori limita nu merită discul.", + "bulk": "Câte fișiere conține încărcarea în masă. Zero scoate acel grup complet din set." + } + } + }, + "commands": { + "generate": "produce fișiere, dintr-o rețetă sau din opțiuni", + "validate": "verifică o rețetă fără a scrie nimic", + "verify": "verifică un director față de un manifest", + "cleanup": "șterge fișierele pe care le listează un manifest", + "recipe fmt": "afișează o rețetă în forma ei normalizată", + "preset": "construiește un set de fișiere dintr-o întrebare de test cu nume", + "formats": "listează formatele acceptate de această versiune", + "damage": "listează modurile în care această versiune poate strica un fișier intenționat", + "tool": "mici unelte pentru fișiere pe care le ai deja", + "version": "afișează versiunea instrumentului", + "license": "afișează licența și ce înseamnă ea pentru fișierele generate" + }, + "outcomes": { + "accept": "Sistemul tău trebuie să accepte fișierul.", + "reject": "Sistemul tău trebuie să respingă fișierul.", + "sanitize": "Sistemul tău trebuie să accepte fișierul și să îl curețe, de exemplu redenumindu-l.", + "unspecified": "Depinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut." + }, + "damages": { + "zero-head": "Suprascrie cu zerouri primii octeți ai fișierului, fără să îi schimbe lungimea. Majoritatea cititorilor se uită întâi acolo, deci aproape orice observă această deteriorare." + }, + "terms": { + "oracleNone": "nu se aplică", + "int": "orice număr întreg", + "choice": "unul dintr-un set fix", + "bool": "adevărat sau fals", + "size": "o dimensiune precum 2mb", + "text": "text", + "pixels": "pixeli", + "paragraphs": "paragrafe", + "rows": "rânduri", + "columns": "coloane", + "slides": "diapozitive", + "hertz": "herți", + "megapixels": "megapixeli", + "million cells": "milioane de celule", + "entries per second": "intrări pe secundă", + "files": "fișiere", + "sizes separated by commas": "dimensiuni separate prin virgule", + "format ids separated by commas": "id-uri de format separate prin virgule", + "format ids separated by commas, or all": "id-uri de format separate prin virgule, sau all", + "extensions separated by commas": "extensii separate prin virgule", + "the id of a format, as tfg formats lists them": "id-ul unui format, așa cum îl listează tfg formats", + "the password, in plain text": "parola, în text simplu", + "any text": "orice text", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "o dată precum 2024-02-29 sau 2024-02-29T13:45:00+02:00, sau none" + }, + "faq": [ + { + "q": "Prin ce diferă de dd, fsutil sau truncate?", + "a": "Acelea îți dau un fișier de dimensiunea potrivită, plin de nimic. Un fișier de 2 MB numit photo.png făcut așa nu este un PNG, deci tot ce îl analizează cu adevărat îl respinge din motivul greșit, iar testul tău trece apoi tot din motivul greșit. Acesta produce un PNG real de exact 2 MB care se deschide într-un vizualizator de imagini și vine cu o declarație despre cum trebuie să îl trateze sistemul tău.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Este gratuit și îl pot folosi la serviciu?", + "a": "Da la amândouă. Este publicat sub GPL-3.0 și nu costă nimic. Nu există cont, cheie de licență sau nivel plătit." + }, + { + "q": "Pot folosi fișierele generate într-un produs cu cod închis?", + "a": "Da. Licența acoperă codul instrumentului, nu ce produce el. Fișierele, rețetele și manifestele generate sunt rezultat și nu lucrări derivate, deci le poți comite și distribui fără nicio obligație." + }, + { + "q": "Conțin fișierele generate date personale reale?", + "a": "Nu. Tot ce se află în ele este sintetizat dintr-un seed. Nu se citește niciun set de date, nu se contactează niciun serviciu și nu se încorporează conținut de la terți. Tratează o adresă de e-mail generată ca inutilizabilă, nu ca neutilizată, pentru că orice șir aleatoriu poate coincide din întâmplare cu una reală." + }, + { + "q": "Voi obține exact aceleași fișiere pe altă mașină?", + "a": "Da, octet cu octet, cu aceeași rețetă și același seed. Proiectul testează asta la fiecare modificare, iar încălcarea ei cere o versiune majoră. Asta îți permite să comiți o rețetă mică în loc de fixture-uri binare mari." + }, + { + "q": "Are nevoie de conexiune la internet?", + "a": "Niciodată. Nu există telemetrie, verificare de actualizări sau client cloud, iar binarul liniei de comandă nu are compilat în el niciun stack de rețea. Funcționează pe o mașină fără rețea și într-un mediu corporativ închis." + }, + { + "q": "Ce se întâmplă dacă cer o dimensiune pe care un format nu o poate atinge?", + "a": "Primești o eroare care numește formatul, cea mai mică dimensiune posibilă, motivul acelui prag și ce să faci în loc, și nu se scrie niciun fișier. Instrumentul nu rotunjește niciodată o dimensiune pe tăcute. Fiecare prag este listat în pagina de formate.", + "code": "tfg formats png" + }, + { + "q": "Pot genera un fișier stricat în mod deliberat?", + "a": "Da. Adaugă --damage zero-head și fișierul iese cu exact mărimea cerută, cu primii octeți suprascriși cu zerouri, așa că un cititor îl respinge, iar manifestul spune că sistemul tău trebuie să îl respingă. Detaliile sunt pe pagina despre fișierele de test corupte.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Ce formate urmează?", + "a": "7z, mp3 și mp4. Azi funcționează de la un capăt la altul {{ .Facts.FormatCount }} formate." + }, + { + "q": "Pe ce sisteme îl pot rula?", + "a": "Linia de comandă rulează pe Windows și Linux, atât pe Intel, cât și pe ARM, și pe Mac-uri cu Apple Silicon. Fereastra desktop este livrată pentru Windows pe Intel, Linux pe Intel și Mac-uri cu Apple Silicon. Mac-urile Intel nu sunt acceptate și nu se construiește nimic pentru ele." + }, + { + "q": "Trebuie să instalez ceva?", + "a": "Nu. Descarcă arhiva pentru sistemul tău, dezarhiveaz-o și rulează binarul. Nu există instalator, mediu de execuție de adăugat sau dependență de rezolvat. Dacă ai Go, funcționează și o singură comandă go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "De ce o rulare peste mii de fișiere este mai lentă pe Windows?", + "a": "Pentru că Windows cere mai mult pentru fiecare cale pe care o examinează, iar o comandă care parcurge mii de fișiere examinează mii de căi. Măsurat pe o mașină cu 3000 de fișiere de 1 kB, verify durează aproximativ 0,9 secunde pe Windows și aproximativ 0,2 secunde pe Linux într-un container. O cale de ieșire mai scurtă micșorează cifra de pe Windows, pentru că fiecare folder de deasupra fișierelor face parte din ce se examinează." + } + ] +} diff --git a/web/content/ro/use-cases.html b/web/content/ro/use-cases.html new file mode 100644 index 00000000..196dfb85 --- /dev/null +++ b/web/content/ro/use-cases.html @@ -0,0 +1,133 @@ +

Pentru ce îl folosesc oamenii

+

+ Cinci sarcini care apar în aproape orice proiect care primește fișiere de la oameni și comanda care + face fiecare. Fiecare exemplu de mai jos rulează așa cum e scris. +

+ +
+

Limite de încărcare

+

Testarea dacă o limită de dimensiune a fișierelor este aplicată acolo unde spune că este

+

+ O limită înseamnă trei cazuri de test, nu unul: puțin sub, exact pe ea și puțin peste. Să le faci de + mână înseamnă să calculezi numere de octeți și să speri că n-ai greșit cu unu. Cere în schimb + setul: +

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

+ Primești trei PDF-uri reale de 1048575, 1048576 și 1048577 de octeți și un manifest care spune că + primele două trebuie acceptate, iar al treilea respins pentru size_limit. Testul + tău citește așteptarea în loc să scrii tu trei asertări de mână - iar când limita se schimbă, + schimbi un număr și rulezi din nou. +

+

+ La fel merge fără presetare când vrei un singur set de limite inline: +

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

Integrare continuă

+

Ținerea fixture-urilor în afara repository-ului fără a le pierde

+

+ Fixture-urile binare mari fac un repository lent la clonare și incomod la revizuire, și nimeni nu + poate spune ce s-a schimbat când una e înlocuită. O rețetă este câteva sute de caractere de YAML + care reconstruiesc fișierele identice - octet cu octet, pe orice mașină - + pentru că fiecare fișier derivă din seed-ul rulării. +

+
- 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
+

+ Fiecare final are propriul cod de ieșire, așa că un pipeline poate deosebi o rețetă proastă de un + disc plin și de o nepotrivire la verificare. O rulare eșuată nu tipărește nimic la ieșirea + standard, ceea ce împiedică un parser de jurnale să citească o eroare drept date. +

+
+ +
+

Scară

+

Aflarea a ce se întâmplă când folderul e mare

+

+ Rutinele de import, joburile de noapte și listările de directoare se comportă altfel la zece mii de + fișiere decât la zece. Dimensiunile extrase dintr-un interval fac setul să semene cu trafic + real, nu cu zece mii de fișiere identice, iar extragerea vine din seed, deci setul e același + mâine. +

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

+ Verifică cât ar costa o rulare înainte să scrie ceva, ceea ce contează când totalul se măsoară în + gigaocteți: +

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

+ O rulare mai mare decât spațiul liber de pe disc este refuzată înainte de a se scrie primul octet, + în loc să umple discul și să eșueze pe la jumătate. +

+
+ +
+

Arhive

+

Testarea unui dezarhivator cu o arhivă care conține cu adevărat fișiere

+

+ O arhivă goală cu extensia potrivită nu dovedește nimic despre codul care o deschide și parcurge ce + e înăuntru. Declară conținutul și arhiva îl conține cu adevărat: +

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

+ Adâncimea de imbricare, numărul de intrări și dimensiunea a ce e înăuntru sunt toate lucruri despre + care o rutină de import are păreri, iar așa afli care sunt acele păreri. +

+
+ +
+

Parsere și vizualizatoare

+

Verificarea că propriul tău cod citește un format cum o face software-ul real

+

+ Fiecare format de aici este verificat cu un cititor independent înainte de livrare - un PNG este + deschis și pixelii lui comparați, un DOCX este recitit de biblioteci separate, o arhivă este + extrasă. Asta înseamnă că un fișier pe care parserul tău îl respinge este o constatare despre + parserul tău, nu despre 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
+

+ Pagina de formate listează setările pe care le acceptă fiecare format și + cel mai mic fișier posibil pentru fiecare. +

+
+ +
+

Ghiduri

+

Două dintre ele mai în detaliu

+ +
+ +
+

Pentru cine este

+

+ Ingineri QA, automatizarea testelor și oricine are în spatele codului un formular de încărcare, o + rutină de import, un parser sau o cotă de stocare. Rulează pe o mașină fără nicio rețea, ceea ce + contează într-un mediu corporativ închis unde un generator din browser nu e o opțiune. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ru/ci.html b/web/content/ru/ci.html new file mode 100644 index 00000000..1983c0bc --- /dev/null +++ b/web/content/ru/ci.html @@ -0,0 +1,190 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Как генерировать тестовые файлы в конвейере CI

+

+ Двоичная фикстура в репозитории остаётся в его истории навсегда, её нельзя проверить в диффе, и она + перестаёт быть возможной, когда файл велик. Генерируйте файлы внутри конвейера из рецепта. Рецепт + - это текст, байты каждый раз выходят одинаковыми, а последний шаг доказывает, что ничего не + сдвинулось. +

+ +
+

Короткий ответ

+

+ Установите tfg, запустите tfg generate fixtures.yaml --out ./fixtures + перед тестами и tfg verify ./fixtures/manifest.json после них. Оба шага сами роняют + сборку, с кодом завершения, который говорит почему. +

+
+ +
+

Почему не коммитить

+

Почему фикстуре не место в репозитории

+ +

+ Коммитить нужно рецепт. Один и тот же рецепт с тем же зерном записывает одни и те же байты на любой + машине, поэтому файл, созданный в конвейере, - это файл, который был у вас на ноутбуке. +

+
+ +
+

Рецепт

+

Рецепт, который лежит рядом с тестами

+

+ Этот записывает двадцать пять счетов, которые должны быть приняты, и два изображения сверх лимита, + которые должны быть отклонены, а манифест фиксирует оба ожидания: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml проверяет его, ничего не записывая, и называет сразу все + проблемы. +

+
+ +
+

GitHub Actions

+

Workflow, который устанавливает инструмент и собирает фикстуры

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Строка с контрольной суммой сверяет архив с verify-SHA256SUMS.txt из того же выпуска. + Версия зафиксирована, так что новый выпуск никогда не изменит сборку, которой вы не касались. +

+
+ +
+

GitLab CI

+

То же самое как задание GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Когда становится красно

+

Что роняет шаг и почему

+

+ У каждого завершения свой код, так что шаг падает сам, а журнал говорит, какой именно. Те, что + встречает конвейер: +

+ +

+ Неудачный запуск ничего не печатает в стандартный вывод, поэтому разборщик журналов никогда не + примет ошибку за данные. Вся таблица на странице документации. +

+
+ +
+

PowerShell

+

Скрипту PowerShell нужна ещё одна строка

+

+ PowerShell не выносит код завершения программы из файла .ps1. Запустите такой файл с + -File, и скрипт ответит 0, даже когда инструмент внутри отказался + работать, так что сборка, которая должна быть красной, становится зелёной. Последняя строка - + это всё исправление: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Так ведёт себя PowerShell, а не этот инструмент. cmd, bash и + zsh ничего лишнего не требуют. +

+
+ +
+

Несколько заданий

+

Как делиться фикстурами между заданиями

+

+ Обычно загружать их не нужно. Поскольку один и тот же рецепт записывает одни и те же байты, каждое + задание может запустить собственный tfg generate, что быстрее загрузки и + скачивания. Когда задание должно получить файлы от другого, запустите после передачи tfg + verify на манифесте, и он скажет, совпадает ли полученное с записанным. +

+
+ +
+

Дальше

+

Куда идти отсюда

+ +
diff --git a/web/content/ru/damage.html b/web/content/ru/damage.html new file mode 100644 index 00000000..8fc7fbbe --- /dev/null +++ b/web/content/ru/damage.html @@ -0,0 +1,176 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Как сделать повреждённый файл для тестов

+

+ Валидатор, которому показывали только здоровые файлы, на самом деле не проверен. Вот как получить + файл, намеренно испорченный, выходящий точно того размера, который вы просите, и + несущий манифест с указанием, что ваша система должна с ним сделать. +

+ +
+

Короткий ответ

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out записывает PNG + ровно в 2097152 байта, первые байты которого нули, а манифест рядом фиксирует, что ваша система + должна его отклонить. +

+
+ +
+

Обычный путь

+

Почему файл, испорченный вручную, - плохой тест

+

+ Обычно берут шестнадцатеричный редактор, скрипт, переворачивающий несколько случайных байтов, или + укорачивают файл через head либо truncate. Один раз это работает, а + потом обходится дорого: +

+ +
+ +
+

Что вы получаете

+

Повреждённый файл остаётся нужного размера

+

+ Файл создаётся как обычно и портится потом, по пути на диск. Он сохраняет заданный размер, а та же + команда снова записывает те же байты. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Настройки пишутся после двоеточия. Параметр можно повторять, а повреждения применяются в том + порядке, в каком вы их записали. Это работает с каждым из {{ .Facts.FormatCount }} форматов. +

+
+ +
+

Что он умеет

+

Какие бывают повреждения?

+

+ Это список, который печатает программа, прочитанный из неё при сборке этой страницы. tfg + damage печатает тот же список, а tfg damage <id> говорит, что + принимает одно из них. +

+ {{ template "damagesTable" . }} +

+ zero-head записывает нули поверх начала файла. Большинство программ чтения смотрят + сначала туда, на сигнатуру и заголовок, которые говорят, что это за файл, поэтому замечает почти + любая. У простого текста и журналов сигнатуры нет, и их тоже отклоняют, потому что + последовательность нулевых байтов не является текстом. Меньше четырёх байтов у некоторых + форматов получается повреждение, на которое не жалуется ни одна программа чтения, поэтому + настройка начинается с четырёх. +

+
+ +
+

Что говорит манифест

+

Манифест, который говорит, что должно произойти

+

+ Каждый повреждённый файл получает запись о том, что ваша система должна его отклонить, а рядом + записано повреждение: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Два запроса отклоняются до того, как что-либо записано, потому что каждый оставил бы на диске файл, + который манифест описывает неверно: +

+ +
+ +
+

В рецепте

+

Здоровые и сломанные файлы за один запуск

+

+ Положите оба вида в один рецепт, и манифест несёт ожидание для каждого файла, так что тесту не нужен + список, какой файл какой: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

В тесте

+

Превращаем это в тест

+

+ Тест читает манифест и проверяет, что произошедшее совпадает с заявленным. Список имён файлов ему не + нужен: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Хороший отказ - это чистый отказ. Сообщение, говорящее, что было не так, - тот ответ, который вам + нужен. Ошибка сервера, зависание или наполовину сохранённый файл - тот дефект, ради которого + этот тест и существует. +

+
+ +
+

Дальше

+

Куда идти отсюда

+ +
diff --git a/web/content/ru/docs.html b/web/content/ru/docs.html new file mode 100644 index 00000000..371ed003 --- /dev/null +++ b/web/content/ru/docs.html @@ -0,0 +1,281 @@ +

Документация

+

+ Всё, что делает инструмент, разложено по вопросам, с которыми люди действительно приходят. + README в репозитории - полный справочник, и он всегда + соответствует скачанной вами сборке. +

+ +
+

Какие есть команды?

+

Каждая делает одно дело:

+ {{ template "commandList" . }} +
+ +
+

Как создать один файл точного размера?

+

+ Укажите формат, размер и место назначения. Размеры считаются по 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. Выбор идёт от seed
--boundary <size>три файла вокруг лимита: на байт меньше, сам лимит, на байт больше
--count <n>сколько файлов создать. По умолчанию 1
--name <template>шаблон имени, например invoice_{index:04}.txt
--out <dir>каталог, в который записывать
--seed <n>seed запуска. Один и тот же seed даёт те же байты
--set <k>=<v>настройка формата, можно повторять
--damage <name>намеренно испортить файлы, можно повторять, применяется по порядку. Список выводит tfg damage
--expected <outcome>accept, reject, sanitize или unspecified
--dry-runпосчитать и показать, ничего не записывая
--jsonзаписать манифест в стандартный вывод
+
+
+ +
+

Как сделать намеренно сломанный файл?

+

+ Любой другой файл, который записывает этот инструмент, корректен по построению, и это отвечает на + два из трёх вопросов, которые задаёт проверка загрузки. --damage отвечает на третий + - открывается ли файл вообще. Файл создаётся как обычно, а затем портится, поэтому у него + остаётся запрошенный размер. +

+
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 с записанным рядом + повреждением. Две вещи отклоняются до записи чего-либо, потому что каждая оставила бы на диске + файл, неверно описанный манифестом: +

+ +

+ Третье заранее узнать нельзя. Если повреждение выполняется и не меняет ни одного байта, такой файл + отбрасывается, а не записывается - запуск продолжается, сообщает, что это был за файл, и + завершается кодом частичного завершения. +

+

+ Шаг за шагом, с тестом, который читает манифест: как сделать + повреждённый файл для тестов. +

+
+ +
+

Как выглядит рецепт?

+

+ Рецепт - это файл 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. Два - это ошибка, и ни одного - тоже. + Недопустимый рецепт записывает ни одного файла и сообщает обо всех проблемах + сразу, а не только о первой, называя каждый раз настройку, к которой она относится. +

+
+ +
+

Как объявить, что моя система должна делать с файлом?

+

Краткая форма, когда достаточно исхода, и длинная, когда важна причина:

+
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. +

+

+ Причина называет действующее правило, а не вердикт. Поэтому одна и та же причина + может стоять под любым исходом - файл на байт меньше лимита получает accept, а + правило, о котором речь, всё равно size_limit. +

+
+ +
+

Что в манифесте?

+

+ Он записывается рядом с файлами в конце каждого запуска, в том числе прерванного. Одна запись на + файл: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 - если по пресету, так что манифест всегда можно отследить до того, что + его создало. +

+

+ Каждая запись также содержит target_id - id цели рецепта, которая создала файл, а + summary.by_target считает файлы каждой цели. Рецепт с несколькими целями можно + поэтому проверить цель за целью, не читая имена файлов. +

+
+ +
+

Что такое пресет?

+

+ Готовый набор файлов, отвечающий на распространённый тестовый вопрос, чтобы вам не приходилось + проектировать набор самостоятельно. Пресеты - обычные рецепты внутри, а eject + выводит рецепт, чтобы вы могли отредактировать его. У каждого пресета есть + отдельная страница о том, что он обычно находит, что входит в набор и + какие настройки принимает. +

+ {{ template "presetsList" . }} +
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 сообщает, чего стоил бы набор, прежде чем вы его соберёте, и прямо говорит, когда + число - наша временная подстановка, а не ваш лимит. +

+
+ +
+

Что означают коды завершения?

+

+ У каждого исхода свой код, машиночитаемый вывод идёт в стандартный вывод, а неудачный запуск ничего + туда не печатает. Таблица - замороженный контракт: смена значения кода требует повышения + мажорной версии. +

+ {{ template "exitCodesTable" . }} +
- 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, всё равно оставляет манифест и никогда не оставляет + наполовину записанный файл, поэтому отменённое задание может быть убрано следующим. +

+

+ Готовые workflow для GitHub Actions и GitLab CI: как генерировать + тестовые файлы в конвейере CI. +

+
+ +
+

Есть ли десктопное окно?

+

+ Да, тот же движок с окном сверху, для тестирования, которое не автоматизируется. Это не урезанная + версия: тест сравнивает два интерфейса возможность за возможностью, и всё, что умеет только один + из них, должно быть объявлено и обосновано, а не тихо расходиться. +

+

+ Экраны: одна партия, пресеты, несколько партий одновременно и о программе. Окно показывает, чего + стоил бы запуск, прежде чем что-либо записать, отображает ход работы и может быть отменено на + полпути без наполовину записанного файла. Файл рецепта оно пока не открывает - рецепты пока дело + командной строки, а окно собирает свои партии в форме. +

+
diff --git a/web/content/ru/exact-size.html b/web/content/ru/exact-size.html new file mode 100644 index 00000000..2ac130c5 --- /dev/null +++ b/web/content/ru/exact-size.html @@ -0,0 +1,145 @@ +

Как создать файл точного размера

+

+ В каждой системе для этого есть команда, и все три приведены ниже. Они дают файл с точным числом + байт, а для многих тестов этого достаточно. Каждая команда на этой странице была выполнена + до публикации в той системе, к которой она относится. +

+ +
+

Короткий ответ

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Размеры указываются в байтах, а 10 + МБ, посчитанные так, как считает ваш файловый менеджер, - это 10485760. +

+
+ +
+

Windows

+

fsutil и вариант на PowerShell, которому ничего дополнительного не нужно

+

+ fsutil входит в Windows. Он принимает размер в байтах, поэтому сначала + посчитайте число: 10 МБ - это 10485760, 100 МБ - 104857600, 1 ГБ - 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Измерено в Windows 11: работает из обычной командной строки без повышенных прав, и файл получается + ровно в 10485760 байт. +

+

PowerShell может сделать то же самое, не вызывая другую программу, и понимает единицы:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB в PowerShell означает 10485760 байт, тот же счёт по основанию 1024, что использует + Проводник, поэтому две команды выше дают один и тот же размер. +

+
+ +
+

Linux

+

dd, truncate и fallocate, и разница, которая ловит людей

+

dd знают все. Он действительно записывает байты:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate срабатывает мгновенно, и в этом подвох. Измерено в Alpine Linux: файл сообщает + 10485760 байт и занимает ноль блоков - это разреженный файл. + Всё, что его читает, получает десять мегабайт нулей, но диск место так и не отдал: +

+
truncate -s 10M test10mb.bin
+

+ Для проверки лимита загрузки это нормально, а для проверки дисковой квоты вводит в заблуждение. + fallocate - то, к чему стоит обратиться, когда место должно быть настоящим: +

+
fallocate -l 10M test10mb.bin
+

А когда содержимое должно быть несжимаемым, чтобы архиватор не мог снова его ужать:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, который не разреженный, и две команды, которые вы уже знаете

+

+ В macOS есть mkfile. Измерено в macOS 26.6.2: 10485760 байт и 20480 блоков, то есть + место действительно выделено, а не обещано: +

+
mkfile 10m test10mb.bin
+

dd и truncate тоже есть и ведут себя как в Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Где это перестаёт работать

+

Файл правильного размера - не файл правильного вида

+

+ Всё сказанное выше даёт блок нулей. Этого достаточно, когда тестируемое смотрит только на размер: + лимит загрузки, квота, передача. Этого перестаёт хватать, как только что-либо + открывает файл. +

+

+ Измерено, и стоит проверить самому: сделайте файл на 2 МБ командой fsutil, назовите его + photo.png и передайте библиотеке работы с изображениями. Pillow ответит + cannot identify image file. Это не PNG. Он им никогда и не был, так говорило лишь + имя. +

+

+ Это важнее, чем кажется, из-за того, в какую сторону тест тогда проваливается. Ваша + точка загрузки отклоняет файл, ваш тест зеленеет, и вы заключаете, что лимит размера работает. + Она отклонила его не из-за размера. Она отклонила его потому, что байты не были изображением, и + правило, которое вы хотели проверить, так и не было достигнуто. +

+ +
+ +
+

Другой путь

+

Настоящий файл этого формата точно того размера, который вы запросили

+

+ Именно это делает Testing Files Generator. Файл - настоящий файл своего формата, он открывается в + своей программе, и в нём ровно то число байт, которое вы запросили, с точностью до байта: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Запросите размер, которого формат не может достичь, и вы получите ошибку с названием минимума и + причиной, а не файл неверного размера. Страница форматов перечисляет + каждый формат с наименьшим файлом, который он может создать. +

+

А лимит - это три тестовых случая, а не один, поэтому инструмент собирает все три:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Вы получите 10485759, 10485760 и 10485761 байт и манифест, который говорит, какие из них ваша + система должна принять, а какие отклонить. Страница сценариев + разбирает это и ещё четыре задачи, для которых инструмент создан. +

+ {{ template "downloadCta" . }} +
+ +
+

Так что же использовать?

+ +

+ Обе есть на этой странице, потому что обе бывают правы. Ошибка, которой стоит избегать, - + использовать первую там, где нужна вторая, и принимать зелёный тест за доказательство. +

+
diff --git a/web/content/ru/faq.html b/web/content/ru/faq.html new file mode 100644 index 00000000..ae0de5c2 --- /dev/null +++ b/web/content/ru/faq.html @@ -0,0 +1,20 @@ +

Часто задаваемые вопросы

+

+ Лицензия, приватность, воспроизводимость и то, что люди проверяют, прежде чем включать генератор в + конвейер сборки. Если вашего вопроса здесь нет, трекер задач + открыт. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Всё ещё выбираете?

+

+ Страница сценариев показывает задачи, для которых инструмент создан, а + страница форматов перечисляет каждый формат с наименьшим файлом, + который он может создать. README в репозитории - полный + справочник. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/ru/formats.html b/web/content/ru/formats.html new file mode 100644 index 00000000..0fd9cb6f --- /dev/null +++ b/web/content/ru/formats.html @@ -0,0 +1,79 @@ +

{{ .Facts.FormatCount }} форматов файлов, каждый создаётся точного размера

+

+ Каждый из них - настоящий файл этого формата. Он открывается в своей программе и + имеет ровно то число байт, которое вы запросили. Ни один не является нулями-заполнителями с + приклеенным расширением. +

+ +{{ template "formatsTable" . }} + +
+

Что означают столбцы

+ +

+ Каждый формат к тому же повторяется до байта: тот же рецепт и тот же seed дают одинаковые файлы на + любой машине, и именно это делает безопасным коммит рецепта вместо самих фикстур. +

+
+ +
+

Настройки, которые принимает каждый формат

+

+ У большинства форматов есть свои настройки - размеры изображения, качество JPEG, число страниц PDF, + строки и столбцы в таблице, сколько записей входит в архив. Задайте их через --set + key=value в командной строке или в разделе properties: рецепта. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Значение вне допустимого для настройки отклоняется сообщением с названием настройки, допустимым + диапазоном и тем, что использовать вместо этого. Неизвестная настройка тоже ошибка, а не + молчаливое значение по умолчанию - опечатка, принятая молча, даёт файл с неверными настройками и + час раздумий, почему тест проходит, хотя не должен. +

+

+ Выполните tfg formats <id>, чтобы увидеть, что именно принимает один формат в + вашей сборке. +

+
+ +
+

Архивы содержат настоящие файлы

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} и {{ end }}{{ $c.ID }}{{ end }} + можно наполнить записями, а не оставлять пустой оболочкой. Созданный архив действительно + содержит документы, которые заявляет, поэтому всё, что распаковывает его во время теста, находит + внутри настоящие файлы. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/ru/index.html b/web/content/ru/index.html new file mode 100644 index 00000000..229bbf77 --- /dev/null +++ b/web/content/ru/index.html @@ -0,0 +1,197 @@ +
+
+

Создавайте настоящие тестовые файлы точного размера

+

+ PDF, PNG, DOCX, ZIP - всего {{ .Facts.FormatCount }} форматов, и каждый из них + настоящий файл, который открывается в своей программе, точно того размера, который вы + запросили. Каждый запуск ещё и записывает, что ваше приложение должно делать с каждым + файлом. Командная строка и десктопное окно, бесплатно и с открытым кодом, всё работает на вашей + машине. +

+ + {{ template "downloadCta" . }} +
+ +
+ Десктопное окно Testing Files Generator, подготовленное к записи партии тестовых файлов +
Десктопное окно, подготовленное к записи партии файлов. За командной строкой работает тот же движок.
+
+
+ + + +
+

Проблема

+

Сделать один тестовый файл легко. Сделать нужную тысячу - вот утомительная часть

+

Вы тестируете программу, принимающую файлы от людей. Рано или поздно вам понадобятся:

+ +

+ Именно это он заменяет. Он создан для QA-инженеров, автоматизации тестирования и всех, за чьим кодом + стоит форма загрузки, процедура импорта, парсер или квота хранилища. +

+
+ +
+

Чем он отличается

+

Другие генераторы останавливаются на байтах. Этот отвечает на то, о чём на самом деле спрашивает ваш тест

+

+ Папка с файлами всё равно оставляет вам решать, что должен доказывать каждый из них. Каждый запуск + здесь записывает рядом с файлами manifest.json - простой список всего созданного и + для каждой записи заявленное ожидание. +

+

Допустим, ваша точка загрузки допускает 1 МБ. Запросите три файла, лежащие на этой границе:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ФайлБайтВаша система должнаПотому что
1mb_under_1b.pdf1048575принятьон в пределах лимита
1mb_at_limit.pdf1048576принятьсам лимит допустим
1mb_over_1b.pdf1048577отклонитьsize_limit
+
+ +

Три файла, три разных ответа, в машиночитаемом виде. Ваш тест читает манифест, вместо того чтобы вы писали проверки вручную:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Там, где ответ зависит от вашей собственной политики, манифест так и говорит

+

+ Он записывает unspecified, а не придумывает ожидание. Генератор, который гадает, даёт + ложные сбои, а набор тестов, который кричит «волки», в итоге отключают. +

+
+
+ +
+

Пресеты

+

Выберите вопрос, получите весь набор

+

+ Пресет - это набор тестовых файлов, продуманный вокруг одного тестового вопроса, чтобы вам не + пришлось выяснять, какие файлы что доказывают. У каждого есть страница о том, что он обычно + находит, что входит в набор и какие настройки принимает. +

+ {{ template "presetsList" . }} +

Все пресеты и как они связаны с рецептами

+
+ +
+

Быстрый старт

+

Три команды, чтобы увидеть работу

+
    +
  1. +

    Создайте файл

    +

    Один PNG, ровно два мегабайта:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Создайте много файлов

    +

    + Десять тысяч файлов журнала, каждый от одного до восьми килобайт, с размерами из seed, чтобы завтра + получился тот же набор. Давайте каждому запуску свой каталог - манифест + остаётся единственной записью о том, что записал запуск, поэтому инструмент отказывается + записывать второй поверх него: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Проверьте их, затем удалите

    +

    verify сообщает, что ничего не сдвинулось. cleanup удаляет ровно то, что было записано, и ничего больше:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Размеры считаются по 1024, как в вашем файловом менеджере, поэтому 2mb означает 2097152 + байта. Подойдёт и простое число байт. Документация охватывает рецепты, + манифест и коды завершения. +

+
+ +
+

Что вы получаете

+

Создан для набора тестов, работающего без присмотра

+ +
+ +
+

Скачать

+

Выберите сборку для вашей системы

+

+ Распакуйте архив и запустите. tfg - это командная строка, а tfg-gui - + десктопное окно. Нет установщика и ничего, что нужно добавлять на вашу машину. +

+ {{ template "downloadsTable" . }} +
+

Что подписано, а что нет

+

+ Сборки для Windows и macOS подписаны, поэтому запускаются без предупреждения о неизвестном + разработчике. Сборки для Linux не подписаны, потому что у десктопного Linux нет эквивалента, + которым их можно подписать. Каждый архив указан в verify-SHA256SUMS.txt на + странице релиза, так что вы можете проверить, что скачали. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/ru/preset.html b/web/content/ru/preset.html new file mode 100644 index 00000000..c1a09a5c --- /dev/null +++ b/web/content/ru/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Пресет {{ .ID }} одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ +{{ if .Catches }} +
+

Что он обычно находит?

+ +
+{{ end }} + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show {{ .ID }}:

+
+ + + + + + + +
Файлов{{ .Budget.Files }}
Целей в его рецепте{{ .Budget.Targets }}
Общий размер{{ .Bytes }} B
Форматы{{ join .Budget.Formats ", " }}
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
ОжидаетсяЗначениеФайлов
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Что можно изменить?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
НастройкаПринимаетПо умолчаниюЧто делает
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Это значение по умолчанию - наша временная подстановка, а не значение вашей системы. Передайте своё.{{ end }}
+
+ {{- else }} +

У этого пресета нет настроек. Набор каждый раз одинаков.

+ {{- end }} +
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/ru/presets.html b/web/content/ru/presets.html new file mode 100644 index 00000000..b5c1bae0 --- /dev/null +++ b/web/content/ru/presets.html @@ -0,0 +1,32 @@ +

Пресеты тестовых файлов, по набору на каждый тестовый вопрос

+

+ Пресет - это целый набор тестовых файлов, продуманный вокруг одного вопроса, с манифестом об + ожидаемой реакции вашей системы на каждый файл. Вы выбираете вопрос, инструмент собирает набор. У + каждого пресета своя страница о том, что он обычно находит, что входит в набор и какие настройки + принимает. +

+ +{{ template "presetsList" . }} + +
+

Чем пресет отличается от рецепта?

+

+ По сути ничем. Пресет - это рецепт, который инструмент пишет для вас из нескольких настроек. + tfg preset eject выводит этот рецепт, чтобы вы могли хранить его рядом с тестами и + править, а ваш собственный рецепт может опираться на пресет одной строкой: extends: + preset: и его id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Можно ли доверять значениям по умолчанию?

+

+ Для файлов - да. Для числа, которое знает только ваша система, например лимита формы загрузки, + значение по умолчанию - наша временная подстановка, и инструмент говорит об этом каждый раз, + когда её использует. Страница каждого пресета отмечает такие настройки, а tfg preset + show сообщает об этом до записи чего-либо. +

+
diff --git a/web/content/ru/site.json b/web/content/ru/site.json new file mode 100644 index 00000000..e898c8fe --- /dev/null +++ b/web/content/ru/site.json @@ -0,0 +1,328 @@ +{ + "code": "ru", + "locale": "ru_RU", + "name": "Русский", + "dir": "ru", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Главная", + "title": "Генератор тестовых файлов для QA - точный размер, {{ .Facts.FormatCount }} форматов", + "description": "Бесплатный генератор тестовых файлов для QA с открытым кодом. Настоящие PDF, DOCX, PNG и ZIP точного размера и манифест с ожидаемой реакцией вашей системы." + }, + { + "key": "formats", + "slug": "formats", + "nav": "Форматы", + "title": "{{ .Facts.FormatCount }} форматов файлов - PDF, DOCX, PNG, ZIP и другие", + "description": "Все форматы, которые создаёт генератор, самый маленький возможный файл каждого и допустимые настройки. Все {{ .Facts.FormatCount }} открываются в своих программах." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Пресеты", + "title": "Пресеты тестовых файлов - готовые наборы для QA", + "description": "Готовые наборы тестовых файлов, каждый отвечает на один вопрос: лимиты загрузки, имена файлов, кодировки, импорт таблиц, пустые файлы и проверка загрузки." + }, + { + "key": "docs", + "slug": "docs", + "nav": "Документация", + "title": "Документация - команды, рецепты, манифест, коды завершения", + "description": "Как создавать тестовые файлы из командной строки или рецепта YAML, что содержит манифест и что означает каждый код завершения при запуске в CI." + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "Сценарии", + "title": "Сценарии - лимиты загрузки, фикстуры для CI, массовые тесты", + "description": "Проверка лимита размера загрузки, воспроизводимые фикстуры для CI, десять тысяч файлов за один запуск и архивы с настоящим содержимым." + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "Точный размер", + "title": "Как создать файл точного размера - Windows, Linux, macOS", + "description": "fsutil, dd, truncate и mkfile, каждая команда измерена в своей системе, и почему такой файл не является PDF или PNG, когда тесту нужен настоящий." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - вопросы о создании тестовых файлов", + "description": "Чем это отличается от dd и fsutil, можно ли коммитить файлы, повторяются ли запуски байт в байт и что будет, если размер недостижим." + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "Повреждённые файлы", + "title": "Повреждённые тестовые файлы - сломанные файлы точного размера", + "description": "Намеренно испорченный файл точного размера с манифестом, который говорит, что ваша система должна его отклонить. Для проверки валидации загрузки и парсеров.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "Тестовые файлы в CI", + "title": "Тестовые файлы в CI - GitHub Actions, GitLab CI и PowerShell", + "description": "Генерируйте тестовые файлы в конвейере, а не коммитьте бинарники: workflow GitHub Actions, задание GitLab, коды завершения и ловушка PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Перейти к содержимому", + "navLabel": "Основное", + "langLabel": "Язык", + "breadcrumbHome": "Главная", + "imageAlt": "Testing Files Generator - настоящие тестовые файлы точного размера и манифест с ожидаемой реакцией вашей системы на каждый из них", + "schemaDescription": "Бесплатный генератор тестовых файлов для QA с открытым кодом. Создаёт настоящие файлы в {{ .Facts.FormatCount }} форматах точного размера и записывает манифест с ожидаемой реакцией тестируемой системы на каждый из них.", + "ctaDownload": "Скачать", + "ctaSource": "Исходный код", + "ctaNote": "Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.", + "colFormat": "Формат", + "colName": "Название", + "colExtension": "Расширение", + "colSmallest": "Наименьший файл", + "colFidelity": "Полнота", + "colChecked": "Проверяется с помощью", + "colSetting": "Настройка", + "colAccepts": "Допускает", + "colSystem": "Система", + "colCli": "Командная строка", + "colWindow": "Десктопное окно", + "noBinary": "пока без сборки", + "colCode": "Код", + "colMeaning": "Значение", + "footerBlurb": "Тестовые файлы для QA точного размера и манифест с ожидаемой реакцией вашей системы на каждый из них.", + "footerProject": "Проект", + "footerSource": "Исходный код на GitHub", + "footerReleases": "Загрузки", + "footerIssues": "Сообщить о проблеме", + "footerSupport": "Поддержать проект", + "footerPages": "Страницы", + "footerLicence": "Copyright (C) 2026 DonislawDev. Распространяется по лицензии GNU General Public License версии 3. Файлы, которые вы создаёте, принадлежат вам - лицензия охватывает инструмент, а не его результат.", + "footerPrivacy": "Этот сайт не загружает шрифты, скрипты и трекеры ниоткуда. Он не устанавливает куки.", + "notFoundTitle": "Такой страницы нет", + "notFoundLead": "Адрес, по которому вы перешли, не соответствует ни одной странице этого сайта.", + "notFoundBack": "На главную", + "read.format": "Формат каждого файла набора. Это флаг самого инструмента, а пресет лишь задаёт ему значение по умолчанию.", + "readTakes.format": "id формата со страницы форматов", + "colDamage": "Повреждение", + "colEffect": "Что оно делает с байтами", + "colSettings": "Настройки", + "noSettings": "нет" + }, + "endings": { + "0": "Всё сработало.", + "1": "Непредвиденная ошибка внутри инструмента.", + "2": "Неверная команда или флаг.", + "3": "Рецепт недопустим.", + "4": "Формат не может сделать то, что запрошено.", + "5": "Не удалось прочитать или записать.", + "6": "Недостаточно места на диске.", + "7": "verify обнаружил расхождение.", + "8": "Запуск завершён, но создано не всё.", + "130": "Прерван с помощью Ctrl+C.", + "143": "Остановлен сигналом, так выглядит тайм-аут в CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Пройдёт ли корректный файл, настолько маленький, насколько позволяет формат?", + "title": "Пустые и минимальные", + "pageTitle": "Минимальные корректные и пустые тестовые файлы в каждом формате", + "description": "Самый маленький корректный файл, который инструмент записывает в каждом из {{ .Facts.FormatCount }} форматов, и пустой файл там, где формат это допускает, с ожидаемой реакцией для каждого.", + "catches": [ + "корректный файл, отклонённый как слишком маленький, потому что проверка считает байты, а не читает их", + "пустой файл, который роняет читающий код вместо того, чтобы быть замеченным", + "картинка шириной в один пиксель, которая делит на ноль на пути к миниатюре", + "хранилище, которое воспринимает ноль байт как неудачную загрузку и бесконечно повторяет попытки" + ], + "details": { + "formats": "Из каких форматов состоит набор. Оставьте all для всех форматов этой сборки или перечислите те, которые принимает ваша система." + } + }, + "filename-handling": { + "question": "Сохранит, покажет и вернёт ли моя система имя файла, которого не ожидала?", + "title": "Обработка имён файлов", + "pageTitle": "Проблемные имена файлов для тестов - Unicode и длина", + "description": "Файлы с именами, ломающими загрузку и хранение: другие письменности и эмодзи, смена направления письма, невидимые символы, синтаксис shell и SQL, лимиты длины.", + "catches": [ + "имя, которое на экране, в журнале или в списке выглядит как другое", + "имя, обрезанное, укороченное или переписанное между загрузкой и хранением", + "лимит длины, который считается в символах там, где хранилище считает байты" + ], + "details": {} + }, + "size-boundaries": { + "question": "Применяется ли лимит размера ровно там, где он объявлен?", + "title": "Границы размера", + "pageTitle": "Проверка лимита размера загрузки - файлы на самой границе", + "description": "Файлы на байт меньше, ровно по лимиту и на байт больше лимита вашей системы, плюс более широкие шаги в обе стороны, с пометкой, нужно ли принять каждый.", + "catches": [ + "ошибки на единицу на границе лимита", + "МБ, перепутанные с МиБ, то есть 4,8 процента, чего достаточно, чтобы пропустить файл, который не должен проходить", + "лимит, который применяется в браузере, а не на сервере" + ], + "details": { + "limit": "Лимит размера, который объявляет ваша система. Всё остальное отмеряется от него.", + "spread": "Как далеко отходить от лимита в обе стороны, списком размеров." + } + }, + "tabular-import": { + "question": "Переживёт ли мой импорт таблиц то, что экспортируют настоящие инструменты?", + "title": "Импорт таблиц", + "pageTitle": "Тестовые файлы для импорта CSV и Excel - разделители и заголовки", + "description": "CSV с другими разделителями, концами строк CR LF, без заголовка и с иными кавычками, очень широкая таблица, книга Excel и JSON в нескольких видах.", + "catches": [ + "файл с точкой с запятой, прочитанный как один столбец, потому что разделитель предположили, а не искали", + "файл CRLF, разбитый на строки с пустой строкой после каждой", + "таблица без заголовка, первая строка данных которой съедается как имена столбцов", + "импорт, который оставляет столбцы, что может показать, и молча отбрасывает остальные", + "читатель, который берёт записи JSON по одной строке и останавливается на первом документе с отступами" + ], + "details": { + "rows": "Сколько строк в таблице. Файл записывается ровно того размера, в который упаковывается столько строк, поэтому бюджет выше меняется вместе с этим значением.", + "columns": "Сколько столбцов в каждой строке таблицы. У произведения строк на столбцы есть потолок, и запрос сверх него отклоняется до записи чего-либо." + } + }, + "text-encoding": { + "question": "Знает ли мой читатель, в какой кодировке файл, или угадывает?", + "title": "Кодировка текста", + "pageTitle": "Тестовые файлы кодировки текста - UTF-8, UTF-16, BOM, CRLF", + "description": "Один и тот же текст в UTF-8, UTF-16LE и UTF-16BE, с меткой порядка байтов и без неё, и концы строк CR LF и LF, чтобы проверить, как читатель декодирует текст.", + "catches": [ + "читатель, который предполагает UTF-8 и показывает файл UTF-16 с одним символом из трёх или рядами квадратиков", + "метка порядка байтов, прочитанная как содержимое, из-за чего первое поле импорта начинается с трёх лишних символов", + "импортёр, который угадывает кодировку по первым байтам и угадывает иначе для более длинного файла", + "файл CRLF, разбитый на строки с пустой строкой после каждой, или возврат каретки, оставшийся в последнем поле" + ], + "details": { + "sample": "Размер каждого файла набора. UTF-16 хранит по два байта на символ, поэтому нечётное число отклоняется." + } + }, + "upload-validation": { + "question": "Принимает ли моя форма загрузки то, что должна, и отклоняет ли остальное?", + "title": "Проверка загрузки", + "pageTitle": "Тестовые файлы проверки загрузки - тип, размер и имя", + "description": "Файлы для проверки формы загрузки: разрешённые и запрещённые типы, содержимое не по расширению, лимит размера, враждебные имена и массовая загрузка.", + "catches": [ + "лимит, который применяется в браузере, а не на сервере", + "SVG или HTML, принятый за картинку или простой текст, что позволяет провести скрипт через форму", + "файл, проверенный по расширению и ни разу не открытый, так что PDF с именем .jpg проходит", + "форма, которая читает всё тело в память, прежде чем посмотреть, насколько оно велико", + "загрузка с именем PHOTO.JPG отклонена там, где photo.jpg принимается, или наоборот", + "имя с пробелами, скобками или символами вне ASCII, записанное на диск без изменений" + ], + "details": { + "limit": "Лимит размера, который объявляет ваша форма загрузки. Этот набор делает по одному шагу в обе стороны - для файла на любом расстоянии запустите пресет size-boundaries.", + "allow": "Какие типы должна принимать ваша форма. Каждый становится настоящим файлом этого типа, и вместе они служат положительным контролем всего набора.", + "deny": "Какие расширения должна отклонять ваша форма. Расширение, для которого в этой сборке нет формата, всё равно получает файл с таким именем и простым текстом внутри.", + "far-over": "Насколько далеко за лимит заходит единственный большой файл. Отключите, если запись нескольких лимитов не стоит места на диске.", + "bulk": "Сколько файлов в массовой загрузке. Ноль полностью убирает эту группу из набора." + } + } + }, + "commands": { + "generate": "создать файлы по рецепту или по флагам", + "validate": "проверить рецепт, ничего не записывая", + "verify": "сверить каталог с манифестом", + "cleanup": "удалить файлы, перечисленные в манифесте", + "recipe fmt": "вывести рецепт в устоявшемся виде", + "preset": "собрать набор файлов по именованному тестовому вопросу", + "formats": "перечислить форматы этой сборки", + "damage": "перечислить способы, которыми эта сборка может намеренно испортить файл", + "tool": "небольшие инструменты для уже имеющихся файлов", + "version": "вывести версию инструмента", + "license": "вывести лицензию и что она означает для созданных файлов" + }, + "outcomes": { + "accept": "Ваша система должна принять файл.", + "reject": "Ваша система должна отклонить файл.", + "sanitize": "Ваша система должна принять файл и очистить его, например переименовав.", + "unspecified": "Зависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду." + }, + "damages": { + "zero-head": "Перезаписывает первые байты файла нулями, не меняя его длину. Большинство программ чтения смотрят сначала туда, поэтому это повреждение замечает почти всё." + }, + "terms": { + "oracleNone": "не применимо", + "int": "любое целое число", + "choice": "одно значение из фиксированного набора", + "bool": "истина или ложь", + "size": "размер, например 2mb", + "text": "текст", + "pixels": "пикселей", + "paragraphs": "абзацев", + "rows": "строк", + "columns": "столбцов", + "slides": "слайдов", + "hertz": "герц", + "megapixels": "мегапикселей", + "million cells": "миллионов ячеек", + "entries per second": "записей в секунду", + "files": "файлов", + "sizes separated by commas": "размеры через запятую", + "format ids separated by commas": "id форматов через запятую", + "format ids separated by commas, or all": "id форматов через запятую или all", + "extensions separated by commas": "расширения через запятую", + "the id of a format, as tfg formats lists them": "id формата в том виде, как его выводит tfg formats", + "the password, in plain text": "пароль открытым текстом", + "any text": "любой текст", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "дата вида 2024-02-29 или 2024-02-29T13:45:00+02:00, либо none" + }, + "faq": [ + { + "q": "Чем это отличается от dd, fsutil или truncate?", + "a": "Они дают файл нужного размера, набитый пустотой. Файл photo.png на 2 МБ, сделанный так, не является PNG, поэтому всё, что действительно его разбирает, отклоняет его по неверной причине, и ваш тест тоже проходит по неверной причине. Этот инструмент создаёт настоящий PNG ровно на 2 МБ, который открывается в просмотрщике изображений, и сопровождает его заявлением о том, как ваша система должна с ним поступать.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Это бесплатно, и можно ли использовать на работе?", + "a": "Да в обоих случаях. Инструмент выпущен под GPL-3.0 и ничего не стоит. Нет ни учётной записи, ни лицензионного ключа, ни платного тарифа." + }, + { + "q": "Можно ли использовать созданные файлы в продукте с закрытым кодом?", + "a": "Да. Лицензия охватывает код инструмента, а не то, что он создаёт. Созданные файлы, рецепты и манифесты являются результатом, а не производными произведениями, поэтому их можно коммитить и поставлять без каких-либо обязательств." + }, + { + "q": "Содержат ли созданные файлы настоящие персональные данные?", + "a": "Нет. Всё внутри синтезируется из seed. Никакой набор данных не читается, ни к какому сервису не обращаются и никакое стороннее содержимое не встраивается. Считайте созданный адрес электронной почты непригодным, а не неиспользованным, потому что любая случайная строка может случайно совпасть с настоящим адресом." + }, + { + "q": "Получу ли я точно такие же файлы на другой машине?", + "a": "Да, байт в байт, при том же рецепте и том же seed. Проект проверяет это при каждом изменении, а нарушить это можно только повышением мажорной версии. Именно поэтому вы можете коммитить небольшой рецепт вместо больших бинарных фикстур." + }, + { + "q": "Нужно ли подключение к интернету?", + "a": "Никогда. Нет ни телеметрии, ни проверки обновлений, ни облачного клиента, а в бинарный файл командной строки вообще не скомпилирован сетевой стек. Он работает на машине без сети и в закрытой корпоративной среде." + }, + { + "q": "Что будет, если запросить размер, которого формат не может достичь?", + "a": "Вы получите ошибку с названием формата, наименьшим возможным размером, причиной этого минимума и тем, что делать вместо этого, а файл записан не будет. Инструмент никогда не округляет размер молча. Каждый минимум указан на странице форматов.", + "code": "tfg formats png" + }, + { + "q": "Можно ли создать намеренно сломанный файл?", + "a": "Да. Добавьте --damage zero-head, и файл выйдет точно заданного размера, с первыми байтами, перезаписанными нулями, так что программа чтения его отклонит, а манифест скажет, что ваша система должна его отклонить. Подробности на странице о повреждённых тестовых файлах.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Какие форматы появятся дальше?", + "a": "7z, mp3 и mp4. Сегодня полностью работают {{ .Facts.FormatCount }} форматов." + }, + { + "q": "На каких системах это можно запускать?", + "a": "Командная строка работает в Windows и Linux на Intel и ARM, а также на Mac с Apple Silicon. Десктопное окно поставляется для Windows на Intel, Linux на Intel и Mac с Apple Silicon. Mac на Intel не поддерживаются, и для них ничего не собирается." + }, + { + "q": "Нужно ли что-нибудь устанавливать?", + "a": "Нет. Скачайте архив для своей системы, распакуйте и запустите бинарный файл. Нет установщика, среды выполнения, которую нужно добавлять, и зависимостей, которые нужно разрешать. Если у вас есть Go, подойдёт и одна команда go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Почему запуск на тысячах файлов в Windows медленнее?", + "a": "Потому что Windows берёт больше за каждый просматриваемый путь, а команда, обходящая тысячи файлов, просматривает тысячи путей. Измерено на одной машине с 3000 файлов по 1 КБ: verify занимает около 0,9 секунды в Windows и около 0,2 секунды в Linux в контейнере. Более короткий путь вывода уменьшает цифру для Windows, потому что каждая папка над файлами входит в то, что просматривается." + } + ] +} diff --git a/web/content/ru/use-cases.html b/web/content/ru/use-cases.html new file mode 100644 index 00000000..3f9d79d0 --- /dev/null +++ b/web/content/ru/use-cases.html @@ -0,0 +1,131 @@ +

Для чего это используют

+

+ Пять задач, которые возникают почти в каждом проекте, принимающем файлы от людей, и команда, + решающая каждую. Каждый пример ниже запускается как написано. +

+ +
+

Лимиты загрузки

+

Проверка того, что лимит размера файла применяется там, где заявлено

+

+ Лимит - это три тестовых случая, а не один: чуть ниже, ровно по лимиту и чуть выше. Получить их + вручную значит считать числа байт и надеяться, что вы не ошиблись на единицу. Запросите вместо + этого набор: +

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

+ Вы получите три настоящих PDF по 1048575, 1048576 и 1048577 байт и манифест, который говорит, что + первые два нужно принять, а третий отклонить по size_limit. Ваш тест читает + ожидание, вместо того чтобы вы писали три проверки вручную, а когда лимит меняется, вы меняете + одно число и запускаете заново. +

+

+ То же работает и без пресета, когда нужен один набор границ прямо в команде: +

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

Непрерывная интеграция

+

Держать фикстуры вне репозитория, не теряя их

+

+ Большие бинарные фикстуры замедляют клонирование репозитория и мешают ревью, а при замене никто не + может сказать, что изменилось. Рецепт - это несколько сотен символов YAML, которые пересоздают + те же файлы - байт в байт, на любой машине - потому что каждый файл выводится + из 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
+

+ У каждого исхода свой код завершения, поэтому конвейер отличает плохой рецепт от полного диска и от + расхождения при проверке. Неудачный запуск ничего не печатает в стандартный вывод, и разборщик + журналов не принимает ошибку за данные. +

+
+ +
+

Масштаб

+

Выяснить, что происходит, когда папка велика

+

+ Процедуры импорта, ночные задания и списки каталогов ведут себя иначе при десяти тысячах файлов, чем + при десяти. Размеры, выбранные из диапазона, делают набор похожим на настоящий трафик, а не на + десять тысяч одинаковых файлов, и выбор идёт от seed, так что завтра набор будет тем же. +

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

+ Проверьте, чего стоил бы запуск, до того как он что-либо запишет, это важно, когда итог измеряется + гигабайтами: +

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

+ Запуск больше свободного места на диске отклоняется до записи первого байта, а не заполняет диск и + не падает на полпути. +

+
+ +
+

Архивы

+

Проверка распаковщика на архиве, который действительно содержит файлы

+

+ Пустой архив с правильным расширением ничего не доказывает о коде, который его открывает и обходит + содержимое. Объявите содержимое, и архив действительно его содержит: +

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

+ Глубина вложенности, число записей и размер содержимого - это то, о чём у процедуры импорта есть + своё мнение, и так вы узнаёте, каково оно. +

+
+ +
+

Парсеры и просмотрщики

+

Проверка того, что ваш собственный код читает формат так же, как настоящее ПО

+

+ Каждый формат здесь проверяется независимым читателем до выпуска: PNG открывается и сравниваются его + пиксели, DOCX перечитывается отдельными библиотеками, архив распаковывается. Это значит, что + файл, который отклоняет ваш парсер, - находка о вашем парсере, а не о генераторе. +

+
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
+

+ Страница форматов перечисляет настройки каждого формата и наименьший + файл, каким он может быть. +

+
+ +
+

Руководства

+

Два из них подробнее

+ +
+ +
+

Для кого это

+

+ QA-инженеры, автоматизация тестирования и все, за чьим кодом стоит форма загрузки, процедура + импорта, парсер или квота хранилища. Работает на машине вообще без сети, что важно в закрытой + корпоративной среде, где генератор в браузере - не вариант. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/th/ci.html b/web/content/th/ci.html new file mode 100644 index 00000000..48ae49f1 --- /dev/null +++ b/web/content/th/ci.html @@ -0,0 +1,185 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

วิธีสร้างไฟล์ทดสอบในไปป์ไลน์ CI

+

+ ฟิกซ์เจอร์ไบนารีในรีโพซิทอรีจะค้างอยู่ในประวัติตลอดไป รีวิวใน diff ไม่ได้ + และเป็นไปไม่ได้เลยเมื่อไฟล์ใหญ่ ให้สร้างไฟล์ในไปป์ไลน์จากสูตรแทน สูตรเป็นข้อความ + ไบต์ออกมาเหมือนกันทุกครั้ง และขั้นสุดท้ายพิสูจน์ว่าไม่มีอะไรขยับ +

+ +
+

คำตอบสั้นๆ

+

+ ติดตั้ง tfg รัน tfg generate fixtures.yaml --out ./fixtures ก่อนการทดสอบ + และ tfg verify ./fixtures/manifest.json หลังการทดสอบ + ทั้งสองขั้นทำให้บิลด์ล้มเหลวได้เอง พร้อมรหัสออกที่บอกเหตุผล +

+
+ +
+

ทำไมไม่คอมมิต

+

ทำไมฟิกซ์เจอร์ไม่ควรอยู่ในรีโพซิทอรี

+ +

+ สิ่งที่ควรคอมมิตคือสูตร สูตรเดียวกันกับซีดเดียวกันเขียนไบต์เดียวกันบนทุกเครื่อง + ไฟล์ที่สร้างในไปป์ไลน์จึงเป็นไฟล์เดียวกับที่คุณมีบนแล็ปท็อป +

+
+ +
+

สูตร

+

สูตรที่อยู่ข้างๆ การทดสอบ

+

+ สูตรนี้เขียนใบแจ้งหนี้ยี่สิบห้าใบที่ควรถูกรับ และรูปสองรูปที่เกินขีดจำกัดซึ่งควรถูกปฏิเสธ + และแมนิเฟสต์บันทึกสิ่งที่คาดหวังทั้งสองอย่าง: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml ตรวจสูตรโดยไม่เขียนอะไร และบอกทุกปัญหาในครั้งเดียว +

+
+ +
+

GitHub Actions

+

เวิร์กโฟลว์ที่ติดตั้งเครื่องมือและสร้างฟิกซ์เจอร์

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ บรรทัดผลรวมตรวจสอบเทียบไฟล์เก็บถาวรกับ verify-SHA256SUMS.txt จากรุ่นเดียวกัน + เวอร์ชันถูกตรึงไว้ รุ่นใหม่จึงไม่มีวันเปลี่ยนบิลด์ที่คุณไม่ได้แตะ +

+
+ +
+

GitLab CI

+

เรื่องเดียวกันในรูปแบบงานของ GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

เมื่อกลายเป็นสีแดง

+

อะไรทำให้ขั้นหนึ่งล้มเหลว และเพราะอะไร

+

+ ทุกการจบมีรหัสออกของตัวเอง ขั้นจึงล้มเหลวได้เอง และล็อกบอกว่าเป็นรหัสไหน รหัสที่ไปป์ไลน์พบ: +

+ +

+ การรันที่ล้มเหลวไม่พิมพ์อะไรออกทางเอาต์พุตมาตรฐาน + ตัวแยกวิเคราะห์ล็อกจึงไม่มีวันเข้าใจผิดว่าข้อผิดพลาดเป็นข้อมูล + ตารางทั้งหมดอยู่ในหน้าเอกสาร +

+
+ +
+

PowerShell

+

สคริปต์ PowerShell ต้องการอีกหนึ่งบรรทัด

+

+ PowerShell ไม่นำรหัสออกของโปรแกรมออกมานอกไฟล์ .ps1 รันสคริปต์ด้วย -File + แล้วสคริปต์จะตอบ 0 แม้เครื่องมือข้างในปฏิเสธงาน + ทำให้บิลด์ที่ควรเป็นสีแดงกลายเป็นสีเขียว บรรทัดสุดท้ายคือวิธีแก้ทั้งหมด: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ นี่คือวิธีที่ PowerShell ทำงาน ไม่ใช่เรื่องของเครื่องมือนี้ cmd bash และ + zsh ไม่ต้องการอะไรเพิ่ม +

+
+ +
+

หลายงาน

+

แบ่งปันฟิกซ์เจอร์ระหว่างงาน

+

+ โดยปกติไม่จำเป็นต้องอัปโหลด เพราะสูตรเดียวกันเขียนไบต์เดียวกัน แต่ละงานจึงรัน tfg + generate ของตัวเองได้ ซึ่งเร็วกว่าการอัปโหลดแล้วดาวน์โหลด + เมื่องานหนึ่งต้องรับไฟล์จากอีกงานหนึ่ง ให้รัน tfg verify กับแมนิเฟสต์หลังการถ่ายโอน + แล้วมันจะบอกว่าสิ่งที่มาถึงตรงกับที่เขียนไว้หรือไม่ +

+
+ +
+

ถัดไป

+

จากตรงนี้ไปไหนต่อ

+ +
diff --git a/web/content/th/damage.html b/web/content/th/damage.html new file mode 100644 index 00000000..7c2d680f --- /dev/null +++ b/web/content/th/damage.html @@ -0,0 +1,168 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

วิธีทำไฟล์เสียหายสำหรับการทดสอบ

+

+ ตัวตรวจสอบที่เคยเห็นแต่ไฟล์ปกติยังไม่ถือว่าผ่านการทดสอบจริง นี่คือวิธีได้ไฟล์ที่ตั้งใจทำให้เสีย + ออกมาขนาดตรงตามที่ขอเป๊ะ + และมาพร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรทำอะไรกับไฟล์นั้น +

+ +
+

คำตอบสั้นๆ

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out เขียน PNG ขนาด + 2097152 ไบต์พอดี โดยไบต์แรกๆ เป็นศูนย์ และแมนิเฟสต์ที่อยู่ข้างๆ + บันทึกว่าระบบของคุณควรปฏิเสธไฟล์นี้ +

+
+ +
+

วิธีที่ทำกันทั่วไป

+

ทำไมไฟล์ที่ทำให้เสียด้วยมือจึงเป็นการทดสอบที่แย่

+

+ วิธีทั่วไปคือใช้โปรแกรมแก้ไขเลขฐานสิบหก สคริปต์ที่สลับไบต์สุ่มไม่กี่ตัว หรือตัดไฟล์ให้สั้นลงด้วย + head หรือ truncate ใช้ได้ครั้งเดียว แล้วจะเสียเวลาในภายหลัง: +

+ +
+ +
+

สิ่งที่คุณได้

+

ไฟล์ที่เสียหายยังมีขนาดตามที่คุณขอ

+

+ ไฟล์ถูกสร้างตามปกติแล้วค่อยทำให้เสียระหว่างทางไปยังดิสก์ ขนาดยังเป็นไปตามที่ขอ + และคำสั่งเดิมเขียนไบต์เดิมซ้ำอีกครั้ง +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ การตั้งค่าเขียนหลังเครื่องหมายทวิภาค ตัวเลือกนี้ใส่ซ้ำได้ + และความเสียหายจะถูกนำมาใช้ตามลำดับที่คุณเขียน ใช้ได้กับทั้ง {{ .Facts.FormatCount }} รูปแบบ +

+
+ +
+

มันทำอะไรได้

+

มีความเสียหายแบบไหนบ้าง

+

+ นี่คือรายการที่โปรแกรมพิมพ์ออกมา อ่านจากตัวโปรแกรมเองตอนสร้างหน้านี้ tfg damage + พิมพ์รายการเดียวกัน และ tfg damage <id> บอกว่าแบบหนึ่งรับอะไรบ้าง +

+ {{ template "damagesTable" . }} +

+ zero-head เขียนศูนย์ทับส่วนต้นของไฟล์ ตัวอ่านส่วนใหญ่มองตรงนั้นก่อน + คือลายเซ็นและส่วนหัวที่บอกว่าไฟล์คืออะไร ตัวอ่านเกือบทุกตัวจึงสังเกตเห็น + ข้อความธรรมดาและล็อกไม่มีลายเซ็นและก็ถูกปฏิเสธเช่นกัน เพราะไบต์ศูนย์ต่อกันไม่ใช่ข้อความ + ต่ำกว่าสี่ไบต์ บางรูปแบบออกมาพร้อมความเสียหายที่ไม่มีตัวอ่านใดบ่น + นั่นคือเหตุผลที่การตั้งค่าเริ่มที่สี่ +

+
+ +
+

แมนิเฟสต์บอกอะไร

+

แมนิเฟสต์ที่บอกว่าควรเกิดอะไรขึ้น

+

+ ไฟล์ที่เสียหายทุกไฟล์ได้รายการที่บอกว่าระบบของคุณควรปฏิเสธ โดยบันทึกความเสียหายไว้ข้างๆ: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ คำขอสองแบบถูกปฏิเสธก่อนที่จะมีอะไรถูกเขียน เพราะแต่ละแบบจะทิ้งไฟล์ไว้บนดิสก์ที่แมนิเฟสต์อธิบายผิด: +

+ +
+ +
+

ในสูตร

+

ไฟล์ปกติและไฟล์เสียในการรันเดียว

+

+ ใส่ทั้งสองอย่างในสูตรเดียว แล้วแมนิเฟสต์จะมีสิ่งที่คาดหวังของแต่ละไฟล์ + การทดสอบจึงไม่ต้องมีรายการบอกว่าไฟล์ไหนเป็นไฟล์ไหน: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

ในการทดสอบ

+

เปลี่ยนให้เป็นการทดสอบ

+

+ การทดสอบอ่านแมนิเฟสต์แล้วตรวจว่าสิ่งที่เกิดขึ้นตรงกับที่ประกาศไว้ ไม่ต้องมีรายชื่อไฟล์: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ การปฏิเสธที่ดีคือการปฏิเสธที่สะอาด ข้อความที่บอกว่าผิดตรงไหนคือคำตอบที่คุณต้องการ + ส่วนข้อผิดพลาดของเซิร์ฟเวอร์ การค้าง + หรือไฟล์ที่บันทึกไว้ครึ่งเดียวคือข้อบกพร่องที่การทดสอบนี้มีไว้หา +

+
+ +
+

ถัดไป

+

จากตรงนี้ไปไหนต่อ

+ +
diff --git a/web/content/th/docs.html b/web/content/th/docs.html new file mode 100644 index 00000000..16dc89c8 --- /dev/null +++ b/web/content/th/docs.html @@ -0,0 +1,272 @@ +

เอกสาร

+

+ ทุกอย่างที่เครื่องมือทำได้ จัดเรียงตามคำถามที่ผู้คนมาถามจริงๆ README + ในรีโพซิทอรีเป็นข้อมูลอ้างอิงฉบับสมบูรณ์และตรงกับบิลด์ที่คุณดาวน์โหลดเสมอ +

+ +
+

มีคำสั่งอะไรบ้าง

+

แต่ละคำสั่งทำสิ่งเดียว:

+ {{ template "commandList" . }} +
+ +
+

สร้างไฟล์เดียวที่ขนาดแม่นยำได้อย่างไร

+

+ ระบุรูปแบบ ขนาด และปลายทาง ขนาดนับเป็นทีละ 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>สามไฟล์รอบขีดจำกัด: น้อยกว่าหนึ่งไบต์ เท่ากับขีดจำกัด และมากกว่าหนึ่งไบต์
--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เขียนแมนิเฟสต์ไปยังเอาต์พุตมาตรฐาน
+
+
+ +
+

ทำไฟล์ที่เสียโดยตั้งใจได้อย่างไร

+

+ ไฟล์อื่นทุกไฟล์ที่เครื่องมือนี้เขียนถูกต้องโดยโครงสร้าง + ซึ่งตอบสองในสามคำถามที่ตัวตรวจสอบการอัปโหลดถาม --damage ตอบข้อที่สาม - + ไฟล์เปิดได้หรือไม่ ไฟล์ถูกสร้างตามปกติแล้วจึงถูกทำให้เสีย จึงยังคงมีขนาดที่คุณขอ +

+
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 ในแมนิเฟสต์ พร้อมบันทึกความเสียหายไว้ข้างๆ + สองอย่างถูกปฏิเสธก่อนจะเขียนอะไร เพราะแต่ละอย่างจะวางไฟล์ที่แมนิเฟสต์อธิบายผิดไว้บนดิสก์: +

+ +

+ ข้อที่สามรู้ล่วงหน้าไม่ได้ ถ้าความเสียหายทำงานแล้วไม่ขยับไบต์ใดเลย ไฟล์นั้นจะถูกทิ้งแทนที่จะถูกเขียน + - การรันดำเนินต่อ บอกว่าเป็นไฟล์ไหน และจบด้วยรหัสออกแบบบางส่วน +

+

+ ทีละขั้น พร้อมการทดสอบที่อ่านแมนิเฟสต์: + วิธีทำไฟล์เสียหายสำหรับการทดสอบ +

+
+ +
+

สูตรหน้าตาเป็นอย่างไร

+

+ สูตรคือไฟล์ 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
+

+ แต่ละ target ต้องมี size, size-range, boundary หรือ + contains อย่างใดอย่างหนึ่งพอดี มีสองอย่างคือข้อผิดพลาด ไม่มีเลยก็เป็นข้อผิดพลาด + สูตรที่ไม่ถูกต้องไม่เขียนไฟล์ใดเลย + และรายงานปัญหาทั้งหมดพร้อมกันแทนที่จะรายงานแค่ข้อแรก โดยแต่ละข้อระบุการตั้งค่าที่เกี่ยวข้อง +

+
+ +
+

ประกาศอย่างไรว่าระบบของฉันควรทำอะไรกับไฟล์

+

ใช้รูปแบบสั้นเมื่อผลลัพธ์เพียงพอ ใช้รูปแบบยาวเมื่อเหตุผลสำคัญ:

+
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 +

+

+ เหตุผลระบุกฎที่เกี่ยวข้อง ไม่ใช่คำตัดสิน + ด้วยเหตุนี้เหตุผลเดียวกันจึงอยู่ใต้ผลลัพธ์ใดก็ได้ - ไฟล์ที่น้อยกว่าขีดจำกัดหนึ่งไบต์คือ + accept และกฎที่เกี่ยวข้องก็ยังเป็น size_limit +

+
+ +
+

แมนิเฟสต์มีอะไรบ้าง

+

+ ถูกเขียนไว้ข้างไฟล์เมื่อจบทุกการรัน รวมถึงการรันที่ถูกขัดจังหวะ หนึ่งรายการต่อไฟล์: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 เมื่อมาจากพรีเซ็ต แมนิเฟสต์จึงสืบย้อนไปถึงสิ่งที่สร้างมันได้เสมอ +

+

+ ทุกรายการยังมี target_id ซึ่งเป็นรหัสของ target ในสูตรที่สร้างไฟล์ และ + summary.by_target นับจำนวนไฟล์ที่แต่ละ target สร้างได้ สูตรที่มีหลาย target + จึงตรวจทีละ target ได้โดยไม่ต้องอ่านชื่อไฟล์ +

+
+ +
+

พรีเซ็ตคืออะไร

+

+ ชุดไฟล์สำเร็จรูปที่ตอบคำถามการทดสอบที่พบบ่อย คุณจึงไม่ต้องออกแบบชุดเอง + พรีเซ็ตเป็นสูตรธรรมดาอยู่ข้างใน และ eject + พิมพ์สูตรออกมาเพื่อให้คุณแก้ไขต่อจากตรงนั้น + แต่ละพรีเซ็ตมีหน้าของตัวเองที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร + และรับการตั้งค่าใดบ้าง +

+ {{ template "presetsList" . }} +
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 บอกว่าชุดจะมีต้นทุนเท่าไรก่อนที่คุณจะสร้าง และบอกตรงๆ + เมื่อตัวเลขใดเป็นค่าชั่วคราวของเรา ไม่ใช่ขีดจำกัดของคุณ +

+
+ +
+

รหัสออกมีความหมายอย่างไร

+

+ ทุกการจบมีรหัสของตัวเอง เอาต์พุตที่เครื่องอ่านได้ไปที่เอาต์พุตมาตรฐาน + และการรันที่ล้มเหลวไม่พิมพ์อะไรที่นั่น ตารางนี้เป็นสัญญาที่ตรึงไว้ - + การเปลี่ยนความหมายของรหัสต้องเลื่อนเวอร์ชันหลัก +

+ {{ template "exitCodesTable" . }} +
- 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 +

+
+ +
+

มีหน้าต่างเดสก์ท็อปไหม

+

+ มี เป็นเอนจินเดียวกันที่มีหน้าต่างครอบอยู่ สำหรับการทดสอบที่ไม่ได้เขียนสคริปต์ ไม่ใช่ฉบับตัดทอน: + มีการทดสอบเปรียบเทียบสองอินเทอร์เฟซทีละความสามารถ + และสิ่งที่ทำได้เพียงฝั่งเดียวต้องถูกประกาศและให้เหตุผล แทนที่จะแยกจากกันไปอย่างเงียบๆ +

+

+ หน้าจอมีชุดเดียว พรีเซ็ต หลายชุดพร้อมกัน และเกี่ยวกับ แสดงต้นทุนของการรันก่อนเขียนอะไร + รายงานความคืบหน้าขณะรัน และยกเลิกกลางคันได้โดยไม่ทิ้งไฟล์ที่เขียนค้างครึ่งหนึ่ง + ยังเปิดไฟล์สูตรไม่ได้ - ตอนนี้สูตรเป็นเรื่องของบรรทัดคำสั่ง และหน้าต่างสร้างชุดในฟอร์ม +

+
diff --git a/web/content/th/exact-size.html b/web/content/th/exact-size.html new file mode 100644 index 00000000..33def3e5 --- /dev/null +++ b/web/content/th/exact-size.html @@ -0,0 +1,142 @@ +

วิธีสร้างไฟล์ขนาดแม่นยำ

+

+ ทุกระบบมีคำสั่งสำหรับเรื่องนี้ และทั้งสามอยู่ด้านล่าง คำสั่งเหล่านี้ให้ไฟล์ที่มีจำนวนไบต์ถูกต้องพอดี + - และสำหรับการทดสอบจำนวนมากนั่นคือทั้งหมดที่ต้องการ + ทุกคำสั่งในหน้านี้ถูกรันก่อนเผยแพร่ บนระบบที่มันเป็นของ +

+ +
+

คำตอบสั้นๆ

+

+ Windows: fsutil file createnew name 10485760 Linux: dd if=/dev/zero of=name bs=1M + count=10 macOS: mkfile 10m name ขนาดเป็นไบต์ และ 10 MB + ตามวิธีนับของตัวจัดการไฟล์คือ 10485760 +

+
+ +
+

Windows

+

fsutil และเวอร์ชัน PowerShell ที่ไม่ต้องใช้อะไรเพิ่ม

+

+ fsutil มาพร้อม Windows รับขนาดเป็นไบต์ จึงคำนวณตัวเลขก่อน - 10 MB คือ + 10485760, 100 MB คือ 104857600, 1 GB คือ 1073741824 +

+
fsutil file createnew test10mb.bin 10485760
+

+ วัดบน Windows 11: ทำงานจากพรอมต์ธรรมดาโดยไม่ต้องใช้พรอมต์ที่ยกระดับสิทธิ์ และไฟล์ออกมาที่ 10485760 + ไบต์พอดี +

+

PowerShell ทำสิ่งเดียวกันได้โดยไม่ต้องเรียกโปรแกรมอื่น และเข้าใจหน่วย:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB ใน PowerShell หมายถึง 10485760 ไบต์ ซึ่งเป็นการนับฐาน 1024 เดียวกับที่ Explorer + ใช้ ดังนั้นสองคำสั่งข้างต้นให้ขนาดเดียวกัน +

+
+ +
+

Linux

+

dd, truncate และ fallocate และความต่างที่ทำให้คนพลาด

+

dd คือคำสั่งที่ทุกคนรู้จัก มันเขียนไบต์จริงๆ:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate เสร็จทันที และนั่นคือกับดัก วัดบน Alpine Linux ไฟล์รายงาน 10485760 + ไบต์และกินที่ ศูนย์บล็อก - เป็นไฟล์แบบกระจาย + สิ่งที่อ่านไฟล์ได้ศูนย์สิบเมกะไบต์ แต่ดิสก์ไม่เคยสละพื้นที่: +

+
truncate -s 10M test10mb.bin
+

+ ใช้ทดสอบขีดจำกัดการอัปโหลดได้ แต่ทำให้เข้าใจผิดเมื่อทดสอบโควตาดิสก์ fallocate + คือสิ่งที่ควรใช้เมื่อพื้นที่ต้องเป็นของจริง: +

+
fallocate -l 10M test10mb.bin
+

และเมื่อเนื้อหาต้องบีบอัดไม่ได้ เพื่อไม่ให้ตัวเก็บถาวรบีบกลับลงไปอีก:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile ซึ่งไม่ใช่ไฟล์แบบกระจาย และอีกสองคำสั่งที่คุณรู้จักอยู่แล้ว

+

+ macOS มี mkfile มาให้ วัดบน macOS 26.6.2: 10485760 ไบต์ และ 20480 บล็อก + ดังนั้นพื้นที่ถูกจัดสรรจริง ไม่ใช่แค่สัญญา: +

+
mkfile 10m test10mb.bin
+

dd และ truncate ก็มีเช่นกันและทำงานเหมือนบน Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

ตรงที่วิธีนี้เลิกได้ผล

+

ไฟล์ขนาดถูกต้องไม่ใช่ไฟล์ชนิดที่ถูกต้อง

+

+ ทุกวิธีข้างต้นให้บล็อกของศูนย์ นั่นเพียงพอเมื่อสิ่งที่ทดสอบดูแค่ขนาด เช่น ขีดจำกัดอัปโหลด โควตา + หรือการถ่ายโอน และเลิกเพียงพอทันทีที่มีอะไรเปิดไฟล์ +

+

+ วัดแล้ว และควรลองด้วยตัวเอง: สร้างไฟล์ 2 MB ด้วย fsutil ตั้งชื่อว่า + photo.png แล้วส่งให้ไลบรารีรูปภาพ Pillow ตอบว่า cannot identify image + file มันไม่ใช่ PNG และไม่เคยเป็น - มีแต่ชื่อที่บอกเช่นนั้น +

+

+ เรื่องนี้สำคัญกว่าที่ฟังดู เพราะการทดสอบล้มเหลวไปทางไหนต่อจากนั้น + เอนด์พอยต์อัปโหลดของคุณปฏิเสธไฟล์ การทดสอบเป็นสีเขียว และคุณสรุปว่าขีดจำกัดขนาดใช้ได้ + แต่มันไม่ได้ปฏิเสธเพราะขนาด มันปฏิเสธเพราะไบต์ไม่ใช่รูปภาพ + และกฎที่คุณตั้งใจทดสอบไม่เคยถูกแตะต้องเลย +

+ +
+ +
+

อีกทางหนึ่ง

+

ไฟล์จริงของรูปแบบนั้น ขนาดตรงตามที่คุณขอพอดี

+

+ นี่คือสิ่งที่ Testing Files Generator ทำ ไฟล์เป็นของแท้ของรูปแบบนั้น - เปิดได้ในซอฟต์แวร์ของมัน - + และมีจำนวนไบต์ตรงตามที่คุณขอ ถึงระดับไบต์: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ ขอขนาดที่รูปแบบไปไม่ถึง แล้วคุณจะได้ข้อผิดพลาดที่ระบุขีดล่างและเหตุผล ไม่ใช่ไฟล์ขนาดผิด + หน้ารูปแบบไฟล์แสดงทุกรูปแบบพร้อมไฟล์เล็กที่สุดที่ทำได้ +

+

และขีดจำกัดหนึ่งค่าคือกรณีทดสอบสามกรณี ไม่ใช่หนึ่ง เครื่องมือจึงสร้างทั้งสาม:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ ได้ไฟล์ 10485759, 10485760 และ 10485761 ไบต์ + พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรยอมรับไฟล์ไหนและปฏิเสธไฟล์ไหน + หน้ากรณีการใช้งานอธิบายเรื่องนี้และงานอื่นอีกสี่อย่างที่เครื่องมือนี้สร้างมาเพื่อ +

+ {{ template "downloadCta" . }} +
+ +
+

แล้วควรใช้อะไร

+ +

+ ทั้งสองอยู่ในหน้านี้เพราะทั้งสองถูกต้องในบางครั้ง + ข้อผิดพลาดที่ควรเลี่ยงคือการใช้อันแรกในที่ที่ต้องใช้อันที่สอง แล้วอ่านการทดสอบสีเขียวเป็นหลักฐาน +

+
diff --git a/web/content/th/faq.html b/web/content/th/faq.html new file mode 100644 index 00000000..6897f733 --- /dev/null +++ b/web/content/th/faq.html @@ -0,0 +1,18 @@ +

คำถามที่พบบ่อย

+

+ ใบอนุญาต ความเป็นส่วนตัว การทำซ้ำได้ และสิ่งที่ผู้คนตรวจสอบก่อนนำตัวสร้างไปไว้ในไปป์ไลน์บิลด์ + ถ้าคำถามของคุณไม่อยู่ที่นี่ ตัวติดตามปัญหาเปิดอยู่ +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

ยังตัดสินใจอยู่หรือ

+

+ หน้ากรณีการใช้งานแสดงงานที่เครื่องมือนี้สร้างมาเพื่อ + และหน้ารูปแบบไฟล์แสดงทุกรูปแบบพร้อมไฟล์เล็กที่สุดที่ทำได้ + README ในรีโพซิทอรีเป็นข้อมูลอ้างอิงฉบับสมบูรณ์ +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/th/formats.html b/web/content/th/formats.html new file mode 100644 index 00000000..a693b412 --- /dev/null +++ b/web/content/th/formats.html @@ -0,0 +1,75 @@ +

{{ .Facts.FormatCount }} รูปแบบไฟล์ แต่ละรูปแบบสร้างที่ขนาดแม่นยำ

+

+ ทุกรูปแบบเป็นไฟล์จริงของรูปแบบนั้น เปิดได้ในซอฟต์แวร์ของมัน + และมีจำนวนไบต์ตรงตามที่คุณขอพอดี ไม่มีรูปแบบใดเป็นศูนย์เติมเต็มที่แปะนามสกุลเข้าไป +

+ +{{ template "formatsTable" . }} + +
+

ความหมายของคอลัมน์

+ +

+ ทุกรูปแบบยังทำซ้ำได้ถึงระดับไบต์ด้วย: สูตรและซีดเดียวกันสร้างไฟล์เหมือนกันทุกประการบนเครื่องใดก็ตาม + และนี่คือสิ่งที่ทำให้การคอมมิตสูตรแทนตัวฟิกซ์เจอร์ปลอดภัย +

+
+ +
+

การตั้งค่าที่แต่ละรูปแบบรับ

+

+ ส่วนใหญ่ของรูปแบบมีการตั้งค่าของตัวเอง - ขนาดภาพ คุณภาพ JPEG จำนวนหน้า PDF + จำนวนแถวและคอลัมน์ในสเปรดชีต จำนวนรายการในไฟล์บีบอัด ตั้งค่าด้วย --set key=value + ในบรรทัดคำสั่ง หรือใต้ properties: ในสูตร +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ ค่านอกขอบเขตที่การตั้งค่ารับถูกปฏิเสธด้วยข้อความที่ระบุการตั้งค่า ช่วงที่อนุญาต และสิ่งที่ควรใช้แทน + การตั้งค่าที่ไม่รู้จักก็เป็นข้อผิดพลาดเช่นกัน ไม่ใช่ค่าเริ่มต้นเงียบๆ - + ตัวพิมพ์ผิดที่ถูกยอมรับเงียบๆ + ให้ไฟล์ที่ตั้งค่าผิดและหนึ่งชั่วโมงของการสงสัยว่าทำไมการทดสอบจึงผ่านทั้งที่ไม่ควร +

+

+ รัน tfg formats <id> เพื่อดูว่ารูปแบบหนึ่งรับอะไรบ้างในบิลด์ที่คุณมี +

+
+ +
+

ไฟล์บีบอัดมีไฟล์จริงอยู่ข้างใน

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} และ {{ end }}{{ $c.ID }}{{ end }} + ใส่รายการลงไปได้ แทนที่จะปล่อยเป็นเปลือกว่าง ไฟล์บีบอัดที่สร้างขึ้นมีเอกสารที่อ้างว่ามีจริงๆ + ดังนั้นสิ่งใดที่แตกไฟล์นั้นระหว่างการทดสอบจะพบไฟล์จริงอยู่ข้างใน +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/th/index.html b/web/content/th/index.html new file mode 100644 index 00000000..ac0d156a --- /dev/null +++ b/web/content/th/index.html @@ -0,0 +1,195 @@ +
+
+

สร้างไฟล์ทดสอบจริงที่ขนาดแม่นยำ

+

+ PDF, PNG, DOCX, ZIP - รวม {{ .Facts.FormatCount }} รูปแบบ + และทุกไฟล์เป็นไฟล์จริงที่เปิดได้ในซอฟต์แวร์ของมัน ด้วยขนาดตรงตามที่คุณขอพอดี + ทุกครั้งที่รันยังจดด้วยว่าแอปพลิเคชันของคุณควรทำอย่างไรกับแต่ละไฟล์ + มีทั้งบรรทัดคำสั่งและหน้าต่างเดสก์ท็อป ฟรีและโอเพนซอร์ส ทำงานทั้งหมดบนเครื่องของคุณ +

+ + {{ template "downloadCta" . }} +
+ +
+ หน้าต่างเดสก์ท็อปของ Testing Files Generator ที่ตั้งค่าพร้อมเขียนไฟล์ทดสอบเป็นชุด +
หน้าต่างเดสก์ท็อปที่ตั้งค่าพร้อมเขียนไฟล์เป็นชุด เอนจินเดียวกันทำงานอยู่เบื้องหลังบรรทัดคำสั่ง
+
+
+ + + +
+

ปัญหา

+

การทำไฟล์ทดสอบหนึ่งไฟล์เป็นเรื่องง่าย การทำหนึ่งพันไฟล์ที่ถูกต้องคือส่วนที่น่าเบื่อ

+

คุณกำลังทดสอบซอฟต์แวร์ที่รับไฟล์จากผู้คน ไม่ช้าก็เร็วคุณจะต้องการ:

+ +

+ นี่คือสิ่งที่เครื่องมือนี้เข้ามาแทนที่ สร้างขึ้นสำหรับวิศวกร QA งานทดสอบอัตโนมัติ + และทุกคนที่โค้ดมีฟอร์มอัปโหลด ขั้นตอนนำเข้า ตัวแยกวิเคราะห์ + หรือโควตาพื้นที่จัดเก็บอยู่เบื้องหลัง +

+
+ +
+

อะไรที่ทำให้ต่างออกไป

+

ตัวสร้างอื่นหยุดที่ไบต์ ตัวนี้ตอบสิ่งที่การทดสอบของคุณถามจริงๆ

+

+ โฟลเดอร์ที่เต็มไปด้วยไฟล์ยังปล่อยให้คุณตัดสินเองว่าแต่ละไฟล์ควรพิสูจน์อะไร + ที่นี่ทุกครั้งที่รันจะเขียน manifest.json ไว้ข้างไฟล์ + เป็นรายการธรรมดาของทุกอย่างที่สร้างขึ้น และแต่ละรายการมีความคาดหวังที่ประกาศไว้ +

+

สมมติว่าเอนด์พอยต์อัปโหลดของคุณอนุญาต 1 MB ขอไฟล์สามไฟล์ที่อยู่บนเส้นนั้น:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ไฟล์ไบต์ระบบของคุณควรเพราะ
1mb_under_1b.pdf1048575ยอมรับอยู่ภายในขีดจำกัด
1mb_at_limit.pdf1048576ยอมรับตัวขีดจำกัดเองได้รับอนุญาต
1mb_over_1b.pdf1048577ปฏิเสธsize_limit
+
+ +

ไฟล์สามไฟล์ คำตอบสามแบบที่ต่างกัน ในรูปแบบที่เครื่องอ่านได้ การทดสอบของคุณอ่านแมนิเฟสต์แทนที่คุณจะเขียนการยืนยันด้วยมือ:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

เมื่อคำตอบขึ้นอยู่กับนโยบายของคุณเอง แมนิเฟสต์จะบอกอย่างนั้น

+

+ มันบันทึก unspecified แทนที่จะแต่งความคาดหวังขึ้นมา + ตัวสร้างที่เดาทำให้เกิดความล้มเหลวเท็จ และชุดทดสอบที่ร้องหมาป่ามาจะถูกปิดไป +

+
+
+ +
+

พรีเซ็ต

+

เลือกคำถาม แล้วรับทั้งชุด

+

+ พรีเซ็ตคือชุดไฟล์ทดสอบที่ออกแบบรอบคำถามการทดสอบข้อเดียว คุณจึงไม่ต้องหาเองว่าไฟล์ไหนพิสูจน์อะไร + แต่ละชุดมีหน้าที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร และรับการตั้งค่าใดบ้าง +

+ {{ template "presetsList" . }} +

พรีเซ็ตทั้งหมด และความสัมพันธ์กับสูตร

+
+ +
+

เริ่มต้นอย่างรวดเร็ว

+

สามคำสั่งเพื่อดูว่ามันทำงานอย่างไร

+
    +
  1. +

    สร้างไฟล์หนึ่งไฟล์

    +

    PNG หนึ่งไฟล์ สองเมกะไบต์พอดี:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    สร้างไฟล์จำนวนมาก

    +

    + ไฟล์บันทึกหนึ่งหมื่นไฟล์ แต่ละไฟล์ขนาดระหว่าง 1 ถึง 8 กิโลไบต์ + โดยสุ่มขนาดจากซีดเพื่อให้พรุ่งนี้ได้ชุดเดิม + ให้แต่ละการรันมีไดเรกทอรีของตัวเอง - + แมนิเฟสต์เป็นบันทึกเดียวของสิ่งที่การรันเขียนไว้ เครื่องมือจึงไม่ยอมเขียนฉบับที่สองทับ: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    ตรวจสอบ แล้วลบ

    +

    verify บอกว่าไม่มีอะไรขยับ cleanup ลบเฉพาะสิ่งที่ถูกเขียนไว้และไม่ลบอย่างอื่น:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ ขนาดนับเป็นทีละ 1024 เหมือนตัวจัดการไฟล์ของคุณ ดังนั้น 2mb หมายถึง 2097152 ไบต์ + ใช้จำนวนไบต์ธรรมดาก็ได้ เอกสารครอบคลุมสูตร แมนิเฟสต์ และรหัสออก +

+
+ +
+

สิ่งที่คุณได้รับ

+

สร้างมาสำหรับชุดทดสอบที่รันโดยไม่มีคนเฝ้า

+ +
+ +
+

ดาวน์โหลด

+

เลือกบิลด์สำหรับระบบของคุณ

+

+ แตกไฟล์บีบอัดแล้วรัน tfg คือบรรทัดคำสั่ง และ tfg-gui คือหน้าต่างเดสก์ท็อป + ไม่มีตัวติดตั้ง และไม่มีอะไรต้องเพิ่มลงในเครื่องของคุณ +

+ {{ template "downloadsTable" . }} +
+

อะไรลงนามแล้ว และอะไรยังไม่ได้ลงนาม

+

+ ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้ว จึงเริ่มทำงานโดยไม่มีคำเตือนเรื่องผู้พัฒนาที่ไม่รู้จัก + ส่วนของ Linux ไม่ได้ลงนาม เพราะ Linux เดสก์ท็อปไม่มีสิ่งเทียบเท่าที่ใช้ลงนามได้ + ทุกไฟล์บีบอัดอยู่ใน verify-SHA256SUMS.txt บนหน้าเผยแพร่ + เพื่อให้คุณตรวจสอบสิ่งที่ดาวน์โหลดได้ +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/th/preset.html b/web/content/th/preset.html new file mode 100644 index 00000000..da67c77b --- /dev/null +++ b/web/content/th/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ พรีเซ็ต {{ .ID }} สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ +{{ if .Catches }} +
+

โดยทั่วไปมันพบอะไร

+ +
+{{ end }} + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show {{ .ID }} รายงาน:

+
+ + + + + + + +
ไฟล์{{ .Budget.Files }}
target ในสูตรของมัน{{ .Budget.Targets }}
ขนาดรวม{{ .Bytes }} B
รูปแบบ{{ join .Budget.Formats ", " }}
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
ที่คาดหวังความหมายไฟล์
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} ค่าเริ่มต้นนี้เป็นค่าชั่วคราวของเรา ไม่ใช่ค่าของระบบคุณ ให้ใส่ค่าของคุณเอง{{ end }}
+
+ {{- else }} +

พรีเซ็ตนี้ไม่มีการตั้งค่า ชุดเป็นแบบเดิมทุกครั้ง

+ {{- end }} +
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/th/presets.html b/web/content/th/presets.html new file mode 100644 index 00000000..24563e8c --- /dev/null +++ b/web/content/th/presets.html @@ -0,0 +1,31 @@ +

พรีเซ็ตไฟล์ทดสอบ หนึ่งชุดสำหรับทุกคำถามการทดสอบ

+

+ พรีเซ็ตคือชุดไฟล์ทดสอบทั้งชุดที่ออกแบบรอบคำถามข้อเดียว + พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร คุณเลือกคำถาม เครื่องมือสร้างชุด + แต่ละพรีเซ็ตมีหน้าของตัวเองที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร และรับการตั้งค่าใดบ้าง +

+ +{{ template "presetsList" . }} + +
+

พรีเซ็ตต่างจากสูตรอย่างไร

+

+ ข้างใต้แล้วไม่ต่าง พรีเซ็ตคือสูตรที่เครื่องมือเขียนให้คุณจากการตั้งค่าไม่กี่อย่าง tfg preset + eject พิมพ์สูตรนั้นออกมาเพื่อให้คุณเก็บไว้ข้างการทดสอบและแก้ไขได้ + และสูตรของคุณเองสร้างต่อยอดจากพรีเซ็ตได้ด้วยบรรทัดเดียว คือ extends: preset: + ตามด้วยรหัสของมัน +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

เชื่อค่าเริ่มต้นได้ไหม

+

+ สำหรับไฟล์ ได้ สำหรับตัวเลขที่มีแต่ระบบของคุณที่รู้ เช่น ขีดจำกัดของฟอร์มอัปโหลด + ค่าเริ่มต้นเป็นค่าชั่วคราวของเรา และเครื่องมือบอกเช่นนั้นทุกครั้งที่ใช้ค่าดังกล่าว + หน้าของแต่ละพรีเซ็ตทำเครื่องหมายการตั้งค่าเหล่านั้น และ tfg preset show + บอกก่อนจะเขียนอะไร +

+
diff --git a/web/content/th/site.json b/web/content/th/site.json new file mode 100644 index 00000000..2054e952 --- /dev/null +++ b/web/content/th/site.json @@ -0,0 +1,328 @@ +{ + "code": "th", + "locale": "th_TH", + "name": "ไทย", + "dir": "th", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "หน้าแรก", + "title": "ตัวสร้างไฟล์ทดสอบสำหรับ QA - ขนาดแม่นยำ {{ .Facts.FormatCount }} รูปแบบจริง", + "description": "ตัวสร้างไฟล์ทดสอบสำหรับ QA ฟรีและโอเพนซอร์ส ได้ไฟล์ PDF, DOCX, PNG และ ZIP จริงขนาดแม่นยำ พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรตอบสนองอย่างไร" + }, + { + "key": "formats", + "slug": "formats", + "nav": "รูปแบบไฟล์", + "title": "{{ .Facts.FormatCount }} รูปแบบไฟล์ที่รองรับ - PDF, DOCX, PNG, ZIP และอื่นๆ", + "description": "รูปแบบไฟล์ทั้งหมดที่ตัวสร้างทำได้ ไฟล์เล็กที่สุดที่เป็นไปได้ของแต่ละรูปแบบ และการตั้งค่าที่รองรับ ทั้ง {{ .Facts.FormatCount }} รูปแบบเปิดได้ในซอฟต์แวร์ของมัน" + }, + { + "key": "presets", + "slug": "presets", + "nav": "พรีเซ็ต", + "title": "พรีเซ็ตไฟล์ทดสอบ - ชุดสำเร็จรูปสำหรับคำถามของ QA", + "description": "ชุดไฟล์ทดสอบสำเร็จรูป แต่ละชุดตอบคำถามการทดสอบข้อเดียว ได้แก่ ขีดจำกัดการอัปโหลด ชื่อไฟล์ การเข้ารหัส การนำเข้าตาราง ไฟล์ว่าง และการตรวจสอบการอัปโหลด" + }, + { + "key": "docs", + "slug": "docs", + "nav": "เอกสาร", + "title": "เอกสาร - คำสั่ง สูตร แมนิเฟสต์ รหัสออก", + "description": "วิธีสร้างไฟล์ทดสอบจากบรรทัดคำสั่งหรือสูตร YAML แมนิเฟสต์มีอะไรบ้าง และรหัสออกแต่ละตัวมีความหมายอย่างไรเมื่อรันใน CI" + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "กรณีการใช้งาน", + "title": "กรณีการใช้งาน - ขีดจำกัดอัปโหลด ฟิกซ์เจอร์ CI ทดสอบจำนวนมาก", + "description": "ทดสอบขีดจำกัดขนาดอัปโหลด สร้างฟิกซ์เจอร์ที่ทำซ้ำได้สำหรับ CI สร้างไฟล์หมื่นไฟล์ และใส่เนื้อหาจริงลงในไฟล์บีบอัด" + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "ขนาดแม่นยำ", + "title": "วิธีสร้างไฟล์ขนาดที่กำหนด - Windows, Linux, macOS", + "description": "fsutil, dd, truncate และ mkfile วัดผลบนระบบของแต่ละคำสั่ง และเหตุผลที่ไฟล์ที่สร้างวิธีนี้ใช้ไม่ได้เมื่อการทดสอบต้องการ PDF หรือ PNG" + }, + { + "key": "faq", + "slug": "faq", + "nav": "คำถามที่พบบ่อย", + "title": "คำถามที่พบบ่อย - เรื่องการสร้างไฟล์ทดสอบ", + "description": "ต่างจาก dd และ fsutil อย่างไร คอมมิตไฟล์ได้ปลอดภัยไหม การรันซ้ำได้ไบต์ต่อไบต์ไหม และเกิดอะไรขึ้นเมื่อไปถึงขนาดที่ต้องการไม่ได้" + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "ไฟล์เสียหาย", + "title": "ไฟล์ทดสอบที่เสียหาย - ไฟล์เสียขนาดตรงเป๊ะ", + "description": "ไฟล์ที่ตั้งใจทำให้เสีย ขนาดตรงเป๊ะ พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรปฏิเสธ สำหรับทดสอบการตรวจสอบการอัปโหลดและตัวแยกวิเคราะห์", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "ไฟล์ทดสอบใน CI", + "title": "ไฟล์ทดสอบใน CI - GitHub Actions, GitLab CI และ PowerShell", + "description": "สร้างไฟล์ทดสอบในไปป์ไลน์แทนการคอมมิตไบนารี: เวิร์กโฟลว์ GitHub Actions งาน GitLab รหัสออก และกับดักของ PowerShell", + "parent": "use-cases" + } + ], + "words": { + "skip": "ข้ามไปยังเนื้อหา", + "navLabel": "เมนูหลัก", + "langLabel": "ภาษา", + "breadcrumbHome": "หน้าแรก", + "imageAlt": "Testing Files Generator - ไฟล์ทดสอบจริงขนาดแม่นยำ พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร", + "schemaDescription": "ตัวสร้างไฟล์ทดสอบสำหรับ QA ฟรีและโอเพนซอร์ส สร้างไฟล์จริงใน {{ .Facts.FormatCount }} รูปแบบด้วยขนาดแม่นยำ และเขียนแมนิเฟสต์ที่บอกว่าระบบที่ถูกทดสอบควรตอบสนองต่อแต่ละไฟล์อย่างไร", + "ctaDownload": "ดาวน์โหลด", + "ctaSource": "ดูซอร์สโค้ด", + "ctaNote": "ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน", + "colFormat": "รูปแบบ", + "colName": "ชื่อ", + "colExtension": "นามสกุล", + "colSmallest": "ไฟล์เล็กที่สุด", + "colFidelity": "ความสมบูรณ์", + "colChecked": "ตรวจสอบด้วย", + "colSetting": "การตั้งค่า", + "colAccepts": "ค่าที่รับ", + "colSystem": "ระบบ", + "colCli": "บรรทัดคำสั่ง", + "colWindow": "หน้าต่างเดสก์ท็อป", + "noBinary": "ยังไม่มีไฟล์ไบนารี", + "colCode": "รหัส", + "colMeaning": "ความหมาย", + "footerBlurb": "ไฟล์ทดสอบสำหรับ QA ขนาดแม่นยำ พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร", + "footerProject": "โครงการ", + "footerSource": "ซอร์สโค้ดบน GitHub", + "footerReleases": "ดาวน์โหลด", + "footerIssues": "แจ้งปัญหา", + "footerSupport": "สนับสนุนโครงการ", + "footerPages": "หน้าเว็บ", + "footerLicence": "Copyright (C) 2026 DonislawDev เผยแพร่ภายใต้ GNU General Public License เวอร์ชัน 3 ไฟล์ที่คุณสร้างเป็นของคุณ - ใบอนุญาตครอบคลุมตัวเครื่องมือ ไม่ใช่ผลลัพธ์ของมัน", + "footerPrivacy": "เว็บไซต์นี้ไม่โหลดฟอนต์ สคริปต์ หรือตัวติดตามจากที่ใดเลย และไม่ตั้งค่าคุกกี้", + "notFoundTitle": "ไม่พบหน้านี้", + "notFoundLead": "ที่อยู่ที่คุณเปิดไม่ตรงกับหน้าใดในเว็บไซต์นี้", + "notFoundBack": "ไปที่หน้าแรก", + "read.format": "รูปแบบของทุกไฟล์ในชุด เป็นแฟลกของตัวเครื่องมือเอง และพรีเซ็ตเพียงกำหนดค่าเริ่มต้นให้", + "readTakes.format": "รหัสรูปแบบจากหน้ารูปแบบไฟล์", + "colDamage": "ความเสียหาย", + "colEffect": "สิ่งที่ทำกับไบต์", + "colSettings": "การตั้งค่า", + "noSettings": "ไม่มี" + }, + "endings": { + "0": "ทุกอย่างทำงานได้", + "1": "เกิดข้อผิดพลาดที่ไม่คาดคิดภายในเครื่องมือ", + "2": "คำสั่งหรือแฟลกไม่ถูกต้อง", + "3": "สูตรไม่ถูกต้อง", + "4": "รูปแบบนี้ทำสิ่งที่ขอไม่ได้", + "5": "การอ่านหรือเขียนล้มเหลว", + "6": "พื้นที่ดิสก์ไม่พอ", + "7": "verify พบความไม่ตรงกัน", + "8": "การรันเสร็จสิ้น แต่สร้างไม่ครบทุกอย่าง", + "130": "ถูกขัดจังหวะด้วย Ctrl+C", + "143": "ถูกหยุดด้วยสัญญาณ ซึ่งเป็นหน้าตาของการหมดเวลาใน CI" + }, + "presets": { + "empty-and-minimal": { + "question": "ไฟล์ที่ถูกต้องและเล็กเท่าที่รูปแบบอนุญาตจะผ่านไหม", + "title": "ไฟล์ว่างและขั้นต่ำ", + "pageTitle": "ไฟล์ทดสอบที่ถูกต้องเล็กที่สุดและไฟล์ว่างในทุกรูปแบบ", + "description": "ไฟล์ที่ถูกต้องเล็กที่สุดที่เครื่องมือเขียนได้ในทั้ง {{ .Facts.FormatCount }} รูปแบบ พร้อมไฟล์ว่างในรูปแบบที่อนุญาต โดยแต่ละไฟล์มาพร้อมปฏิกิริยาที่คาดหวัง", + "catches": [ + "ไฟล์ที่ถูกต้องแต่ถูกปฏิเสธว่าเล็กเกินไป เพราะการตรวจนับไบต์แทนที่จะอ่านไฟล์", + "ไฟล์ว่างที่ทำให้ตัวอ่านล่มแทนที่จะถูกรายงาน", + "ภาพกว้างหนึ่งพิกเซลที่หารด้วยศูนย์ระหว่างทางไปสร้างภาพขนาดย่อ", + "ที่เก็บข้อมูลที่ถือว่าศูนย์ไบต์คืออัปโหลดล้มเหลวแล้วลองซ้ำไม่หยุด" + ], + "details": { + "formats": "ชุดนี้สร้างจากรูปแบบใดบ้าง ปล่อยเป็น all เพื่อใช้ทุกรูปแบบของบิลด์นี้ หรือระบุเฉพาะรูปแบบที่ระบบของคุณรับ" + } + }, + "filename-handling": { + "question": "ระบบของฉันจะเก็บ แสดง และส่งคืนชื่อไฟล์ที่ไม่ได้คาดไว้ได้ไหม", + "title": "การจัดการชื่อไฟล์", + "pageTitle": "ชื่อไฟล์ที่เป็นปัญหาสำหรับการทดสอบ - Unicode และความยาว", + "description": "ไฟล์ที่มีชื่อซึ่งทำให้การอัปโหลดและการจัดเก็บพัง ได้แก่ ตัวอักษรระบบอื่นและอีโมจิ การกลับทิศทางข้อความ อักขระที่มองไม่เห็น ไวยากรณ์ shell และ SQL และขีดจำกัดความยาว", + "catches": [ + "ชื่อที่บนหน้าจอ ในบันทึก หรือในรายการ ดูเหมือนเป็นอีกชื่อหนึ่ง", + "ชื่อที่ถูกตัด ถูกเล็ม หรือถูกเขียนใหม่ระหว่างอัปโหลดกับจัดเก็บ", + "ขีดจำกัดความยาวที่นับเป็นอักขระ ทั้งที่ที่เก็บข้อมูลนับเป็นไบต์" + ], + "details": {} + }, + "size-boundaries": { + "question": "ขีดจำกัดขนาดถูกบังคับใช้ตรงจุดที่ประกาศไว้พอดีหรือไม่", + "title": "ขอบเขตขนาด", + "pageTitle": "ทดสอบขีดจำกัดขนาดอัปโหลด - ไฟล์ที่ขอบเขตพอดี", + "description": "ไฟล์ที่น้อยกว่า เท่ากับ และมากกว่าขีดจำกัดที่ระบบของคุณประกาศหนึ่งไบต์ พร้อมช่วงห่างที่กว้างขึ้นทั้งสองข้าง โดยแต่ละไฟล์ระบุว่าควรถูกยอมรับหรือไม่", + "catches": [ + "ข้อผิดพลาดคลาดเคลื่อนหนึ่งที่ขีดจำกัด", + "สับสนระหว่าง MB กับ MiB ซึ่งต่างกัน 4.8 เปอร์เซ็นต์ และมากพอที่จะปล่อยไฟล์ที่ไม่ควรผ่านให้ผ่านไป", + "ขีดจำกัดที่บังคับใช้ในเบราว์เซอร์แต่ไม่ได้บังคับที่เซิร์ฟเวอร์" + ], + "details": { + "limit": "ขีดจำกัดขนาดที่ระบบของคุณประกาศ ทุกอย่างที่เหลือวัดจากค่านี้", + "spread": "จะขยายออกไปไกลแค่ไหนทั้งสองข้างของขีดจำกัด เป็นรายการขนาด" + } + }, + "tabular-import": { + "question": "การนำเข้าตารางของฉันรับมือกับสิ่งที่เครื่องมือจริงส่งออกได้ไหม", + "title": "การนำเข้าตาราง", + "pageTitle": "ไฟล์ทดสอบนำเข้า CSV และ Excel - ตัวคั่น และส่วนหัว", + "description": "CSV ที่มีตัวคั่นอื่น ท้ายบรรทัดแบบ CR LF ไม่มีส่วนหัว และเครื่องหมายคำพูดอื่น ตารางที่กว้างมาก เวิร์กบุ๊ก Excel และ JSON หลายรูปแบบ", + "catches": [ + "ไฟล์ที่ใช้อัฒภาคถูกอ่านเป็นคอลัมน์เดียว เพราะสันนิษฐานตัวคั่นแทนที่จะค้นหา", + "ไฟล์ CRLF ที่ถูกแบ่งเป็นแถวพร้อมแถวว่างหลังทุกแถว", + "ตารางที่ไม่มีส่วนหัวซึ่งแถวข้อมูลแรกถูกกลืนไปเป็นชื่อคอลัมน์", + "การนำเข้าที่เก็บคอลัมน์เท่าที่แสดงได้แล้วทิ้งส่วนที่เหลือโดยไม่บอกสักคำ", + "ตัวอ่านที่รับระเบียน JSON ทีละบรรทัดและหยุดที่เอกสารแรกที่มีการเยื้อง" + ], + "details": { + "rows": "สเปรดชีตมีกี่แถว ไฟล์ถูกเขียนที่ขนาดพอดีกับจำนวนแถวนั้น ดังนั้นงบประมาณด้านบนจึงเลื่อนไปตามค่านี้", + "columns": "แต่ละแถวของสเปรดชีตมีกี่คอลัมน์ จำนวนแถวคูณคอลัมน์มีเพดาน และการขอเกินจะถูกปฏิเสธก่อนที่จะเขียนอะไรลงไป" + } + }, + "text-encoding": { + "question": "ตัวอ่านของฉันรู้ไหมว่าไฟล์ใช้การเข้ารหัสอะไร หรือกำลังเดาอยู่", + "title": "การเข้ารหัสข้อความ", + "pageTitle": "ไฟล์ทดสอบการเข้ารหัสข้อความ - UTF-8, UTF-16, BOM, CRLF", + "description": "ข้อความเดียวกันใน UTF-8, UTF-16LE และ UTF-16BE มีและไม่มีเครื่องหมายลำดับไบต์ พร้อมท้ายบรรทัด CR LF และ LF เพื่อทดสอบว่าตัวอ่านถอดรหัสข้อความอย่างไร", + "catches": [ + "ตัวอ่านที่สมมติว่าเป็น UTF-8 แล้วแสดงไฟล์ UTF-16 เป็นหนึ่งอักขระในทุกสามอักขระ หรือเป็นแถวของกล่องสี่เหลี่ยม", + "เครื่องหมายลำดับไบต์ที่ถูกอ่านเป็นเนื้อหา ทำให้ช่องแรกของการนำเข้าขึ้นต้นด้วยอักขระแปลกปลอมสามตัว", + "ตัวนำเข้าที่เดาการเข้ารหัสจากไบต์แรกๆ และเดาต่างออกไปกับไฟล์ที่ยาวกว่า", + "ไฟล์ CRLF ที่ถูกแบ่งเป็นแถวพร้อมแถวว่างหลังทุกแถว หรือตัวอักขระขึ้นต้นบรรทัดที่ค้างอยู่ในช่องสุดท้าย" + ], + "details": { + "sample": "แต่ละไฟล์ในชุดมีขนาดเท่าไร UTF-16 เก็บสองไบต์ต่ออักขระ ดังนั้นเลขคี่จะถูกปฏิเสธ" + } + }, + "upload-validation": { + "question": "ฟอร์มอัปโหลดของฉันรับสิ่งที่ควรรับและปฏิเสธที่เหลือหรือไม่", + "title": "การตรวจสอบการอัปโหลด", + "pageTitle": "ไฟล์ทดสอบการตรวจสอบอัปโหลด - ประเภท ขนาด และชื่อ", + "description": "ไฟล์สำหรับทดสอบฟอร์มอัปโหลด ได้แก่ ประเภทที่อนุญาตและไม่อนุญาต เนื้อหาที่ไม่ตรงกับนามสกุล ขีดจำกัดขนาดทั้งสองด้าน ชื่อที่เป็นอันตราย และการอัปโหลดเป็นกลุ่ม", + "catches": [ + "ขีดจำกัดที่บังคับใช้ในเบราว์เซอร์แต่ไม่ได้บังคับที่เซิร์ฟเวอร์", + "ไฟล์ SVG หรือ HTML ที่ถูกเข้าใจว่าเป็นรูปภาพหรือข้อความธรรมดา ซึ่งเป็นวิธีหนึ่งในการลอบส่งสคริปต์ผ่านฟอร์ม", + "ไฟล์ที่ตรวจจากนามสกุลโดยไม่เคยเปิดดู ทำให้ PDF ที่ตั้งชื่อ .jpg ผ่านไปได้", + "ฟอร์มที่อ่านเนื้อหาทั้งหมดเข้าหน่วยความจำก่อนจะดูว่าใหญ่แค่ไหน", + "การอัปโหลดชื่อ PHOTO.JPG ที่ถูกปฏิเสธขณะที่ photo.jpg ถูกรับ หรือกลับกัน", + "ชื่อที่มีช่องว่าง วงเล็บ หรืออักขระนอก ASCII ที่ถูกเขียนลงดิสก์โดยไม่เปลี่ยนแปลง" + ], + "details": { + "limit": "ขีดจำกัดขนาดที่ฟอร์มอัปโหลดของคุณประกาศ ชุดนี้ก้าวไปข้างละหนึ่งขั้น - หากต้องการไฟล์ที่ทุกระยะ ให้รันพรีเซ็ต size-boundaries", + "allow": "ประเภทที่ฟอร์มของคุณควรรับ แต่ละประเภทจะกลายเป็นไฟล์จริงของประเภทนั้น และเป็นตัวควบคุมเชิงบวกของทั้งชุด", + "deny": "นามสกุลที่ฟอร์มของคุณควรปฏิเสธ นามสกุลที่บิลด์นี้ไม่มีรูปแบบรองรับก็ยังได้ไฟล์ชื่อนั้นที่มีข้อความธรรมดา", + "far-over": "ไฟล์ใหญ่ไฟล์เดียวเกินขีดจำกัดไปไกลแค่ไหน ปิดไว้หากการเขียนหลายเท่าของขีดจำกัดไม่คุ้มกับพื้นที่ดิสก์", + "bulk": "การอัปโหลดเป็นกลุ่มมีกี่ไฟล์ ศูนย์จะตัดกลุ่มนั้นออกจากชุดทั้งหมด" + } + } + }, + "commands": { + "generate": "สร้างไฟล์จากสูตรหรือจากแฟลก", + "validate": "ตรวจสอบสูตรโดยไม่เขียนอะไร", + "verify": "ตรวจสอบไดเรกทอรีเทียบกับแมนิเฟสต์", + "cleanup": "ลบไฟล์ที่แมนิเฟสต์ระบุไว้", + "recipe fmt": "พิมพ์สูตรในรูปแบบมาตรฐาน", + "preset": "สร้างชุดไฟล์จากคำถามทดสอบที่มีชื่อ", + "formats": "แสดงรายการรูปแบบที่บิลด์นี้รองรับ", + "damage": "แสดงรายการวิธีที่บิลด์นี้ทำให้ไฟล์เสียหายโดยตั้งใจ", + "tool": "เครื่องมือเล็กๆ สำหรับไฟล์ที่คุณมีอยู่แล้ว", + "version": "พิมพ์เวอร์ชันของเครื่องมือ", + "license": "พิมพ์ใบอนุญาตและความหมายสำหรับไฟล์ที่สร้างขึ้น" + }, + "outcomes": { + "accept": "ระบบของคุณควรยอมรับไฟล์นี้", + "reject": "ระบบของคุณควรปฏิเสธไฟล์นี้", + "sanitize": "ระบบของคุณควรยอมรับไฟล์นี้แล้วทำความสะอาด เช่น ด้วยการเปลี่ยนชื่อ", + "unspecified": "ขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ" + }, + "damages": { + "zero-head": "เขียนทับไบต์แรกๆ ของไฟล์ด้วยศูนย์ โดยไม่แตะความยาว ตัวอ่านส่วนใหญ่มองตรงนั้นก่อน เกือบทุกอย่างจึงสังเกตเห็นความเสียหายนี้" + }, + "terms": { + "oracleNone": "ไม่เกี่ยวข้อง", + "int": "จำนวนเต็มใดก็ได้", + "choice": "หนึ่งในชุดค่าที่กำหนดไว้", + "bool": "จริงหรือเท็จ", + "size": "ขนาด เช่น 2mb", + "text": "ข้อความ", + "pixels": "พิกเซล", + "paragraphs": "ย่อหน้า", + "rows": "แถว", + "columns": "คอลัมน์", + "slides": "สไลด์", + "hertz": "เฮิรตซ์", + "megapixels": "เมกะพิกเซล", + "million cells": "ล้านเซลล์", + "entries per second": "รายการต่อวินาที", + "files": "ไฟล์", + "sizes separated by commas": "ขนาดที่คั่นด้วยจุลภาค", + "format ids separated by commas": "รหัสรูปแบบที่คั่นด้วยจุลภาค", + "format ids separated by commas, or all": "รหัสรูปแบบที่คั่นด้วยจุลภาค หรือ all", + "extensions separated by commas": "นามสกุลที่คั่นด้วยจุลภาค", + "the id of a format, as tfg formats lists them": "รหัสของรูปแบบ ตามที่ tfg formats แสดง", + "the password, in plain text": "รหัสผ่านในรูปข้อความธรรมดา", + "any text": "ข้อความใดก็ได้", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "วันที่ เช่น 2024-02-29 หรือ 2024-02-29T13:45:00+02:00 หรือ none" + }, + "faq": [ + { + "q": "ต่างจาก dd, fsutil หรือ truncate อย่างไร", + "a": "คำสั่งเหล่านั้นให้ไฟล์ที่ขนาดถูกต้องแต่เต็มไปด้วยความว่างเปล่า ไฟล์ photo.png ขนาด 2 MB ที่ทำแบบนั้นไม่ใช่ PNG ดังนั้นสิ่งใดที่แยกวิเคราะห์ไฟล์จริงๆ ก็จะปฏิเสธด้วยเหตุผลที่ผิด และการทดสอบของคุณก็ผ่านด้วยเหตุผลที่ผิดเช่นกัน เครื่องมือนี้สร้าง PNG จริงขนาด 2 MB พอดีที่เปิดได้ในโปรแกรมดูภาพ และมาพร้อมคำประกาศว่าระบบของคุณควรปฏิบัติต่อไฟล์นั้นอย่างไร", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "ฟรีไหม และใช้ที่ทำงานได้หรือไม่", + "a": "ได้ทั้งสองอย่าง เผยแพร่ภายใต้ GPL-3.0 และไม่มีค่าใช้จ่าย ไม่มีบัญชี ไม่มีคีย์ใบอนุญาต และไม่มีแพ็กเกจเสียเงิน" + }, + { + "q": "ใช้ไฟล์ที่สร้างในผลิตภัณฑ์ซอร์สปิดได้ไหม", + "a": "ได้ ใบอนุญาตครอบคลุมโค้ดของเครื่องมือ ไม่ใช่สิ่งที่เครื่องมือสร้างขึ้น ไฟล์ สูตร และแมนิเฟสต์ที่สร้างขึ้นเป็นผลลัพธ์ ไม่ใช่งานดัดแปลง คุณจึงคอมมิตและแจกจ่ายได้โดยไม่มีข้อผูกมัดใดๆ" + }, + { + "q": "ไฟล์ที่สร้างมีข้อมูลส่วนบุคคลจริงหรือไม่", + "a": "ไม่มี ทุกอย่างข้างในถูกสังเคราะห์จากซีด ไม่มีการอ่านชุดข้อมูล ไม่มีการติดต่อบริการใด และไม่มีการฝังเนื้อหาของบุคคลที่สาม ให้ถือว่าอีเมลที่สร้างขึ้นเป็นที่ใช้ไม่ได้ ไม่ใช่ที่ยังไม่ได้ใช้ เพราะสตริงสุ่มใดๆ อาจบังเอิญตรงกับของจริงได้" + }, + { + "q": "ได้ไฟล์เหมือนกันทุกประการบนเครื่องอื่นไหม", + "a": "ได้ ไบต์ต่อไบต์ เมื่อใช้สูตรและซีดเดียวกัน โครงการทดสอบเรื่องนี้ในทุกการเปลี่ยนแปลง และการทำลายต้องเลื่อนเวอร์ชันหลัก นี่คือสิ่งที่ทำให้คุณคอมมิตสูตรเล็กๆ แทนฟิกซ์เจอร์ไบนารีขนาดใหญ่ได้" + }, + { + "q": "ต้องใช้อินเทอร์เน็ตไหม", + "a": "ไม่เลย ไม่มีเทเลเมทรี ไม่มีการตรวจสอบอัปเดต ไม่มีไคลเอนต์คลาวด์ และไบนารีบรรทัดคำสั่งไม่ได้คอมไพล์สแตกเครือข่ายไว้เลย ทำงานได้บนเครื่องที่ไม่มีเครือข่ายและในสภาพแวดล้อมองค์กรที่ปิด" + }, + { + "q": "จะเกิดอะไรขึ้นถ้าขอขนาดที่รูปแบบนั้นไปไม่ถึง", + "a": "คุณจะได้ข้อผิดพลาดที่ระบุรูปแบบ ขนาดเล็กที่สุดที่เป็นไปได้ เหตุผลของขีดล่างนั้น และสิ่งที่ควรทำแทน และจะไม่มีไฟล์ถูกเขียน เครื่องมือไม่เคยปัดเศษขนาดอย่างเงียบๆ ขีดล่างทุกค่าแสดงไว้ในหน้ารูปแบบไฟล์", + "code": "tfg formats png" + }, + { + "q": "สร้างไฟล์ที่เสียหายโดยตั้งใจได้ไหม", + "a": "ได้ เพิ่ม --damage zero-head แล้วไฟล์จะออกมาขนาดตรงตามที่ขอ โดยไบต์แรกๆ ถูกเขียนทับด้วยศูนย์ ตัวอ่านจึงปฏิเสธ และแมนิเฟสต์บอกว่าระบบของคุณควรปฏิเสธ รายละเอียดอยู่ในหน้าเกี่ยวกับไฟล์ทดสอบที่เสียหาย", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "รูปแบบใดจะมาต่อไป", + "a": "7z, mp3 และ mp4 ตอนนี้ {{ .Facts.FormatCount }} รูปแบบทำงานได้ครบตั้งแต่ต้นจนจบ" + }, + { + "q": "รันบนระบบใดได้บ้าง", + "a": "บรรทัดคำสั่งทำงานบน Windows และ Linux ทั้ง Intel และ ARM และบน Mac ที่ใช้ Apple Silicon หน้าต่างเดสก์ท็อปมีให้สำหรับ Windows บน Intel, Linux บน Intel และ Mac ที่ใช้ Apple Silicon ไม่รองรับ Mac แบบ Intel และไม่มีการสร้างบิลด์สำหรับเครื่องเหล่านั้น" + }, + { + "q": "ต้องติดตั้งอะไรไหม", + "a": "ไม่ ดาวน์โหลดไฟล์บีบอัดสำหรับระบบของคุณ แตกไฟล์ แล้วรันไบนารี ไม่มีตัวติดตั้ง ไม่มีรันไทม์ที่ต้องเพิ่ม และไม่มีไลบรารีที่ต้องแก้ ถ้าคุณมี Go คำสั่ง go install เพียงคำสั่งเดียวก็ใช้ได้เช่นกัน", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "ทำไมการรันกับไฟล์นับพันจึงช้ากว่าบน Windows", + "a": "เพราะ Windows คิดค่าใช้จ่ายมากกว่าสำหรับทุกพาธที่มันดู และคำสั่งที่วนผ่านไฟล์นับพันก็ดูพาธนับพัน วัดบนเครื่องหนึ่งที่มีไฟล์ขนาด 1 kB จำนวน 3000 ไฟล์ verify ใช้เวลาประมาณ 0.9 วินาทีบน Windows และประมาณ 0.2 วินาทีบน Linux ในคอนเทนเนอร์ พาธเอาต์พุตที่สั้นลงทำให้ตัวเลขบน Windows น้อยลง เพราะทุกโฟลเดอร์เหนือไฟล์เป็นส่วนหนึ่งของสิ่งที่ถูกดู" + } + ] +} diff --git a/web/content/th/use-cases.html b/web/content/th/use-cases.html new file mode 100644 index 00000000..21d54fe0 --- /dev/null +++ b/web/content/th/use-cases.html @@ -0,0 +1,130 @@ +

คนใช้มันทำอะไร

+

+ ห้างานที่เกิดขึ้นในเกือบทุกโครงการที่รับไฟล์จากผู้คน และคำสั่งที่ทำแต่ละงาน + ทุกตัวอย่างด้านล่างรันได้ตามที่เขียน +

+ +
+

ขีดจำกัดการอัปโหลด

+

ทดสอบว่าขีดจำกัดขนาดไฟล์ถูกบังคับใช้ตรงที่บอกไว้หรือไม่

+

+ ขีดจำกัดหนึ่งค่าคือกรณีทดสอบสามกรณี ไม่ใช่หนึ่ง: ต่ำกว่าเล็กน้อย ตรงพอดี และสูงกว่าเล็กน้อย + การทำด้วยมือหมายถึงคำนวณจำนวนไบต์และหวังว่าจะไม่พลาดไปหนึ่ง ขอเป็นชุดแทน: +

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

+ คุณได้ PDF จริงสามไฟล์ขนาด 1048575, 1048576 และ 1048577 ไบต์ + พร้อมแมนิเฟสต์ที่บอกว่าสองไฟล์แรกควรถูกยอมรับและไฟล์ที่สามถูกปฏิเสธด้วย size_limit + การทดสอบของคุณอ่านความคาดหวังแทนที่คุณจะเขียนการยืนยันสามอันด้วยมือ - และเมื่อขีดจำกัดเปลี่ยน + คุณเปลี่ยนตัวเลขเดียวแล้วรันใหม่ +

+

+ ทำแบบเดียวกันได้โดยไม่ใช้พรีเซ็ตเมื่อต้องการชุดขอบเขตเดียวในบรรทัด: +

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

การรวมระบบต่อเนื่อง

+

เก็บฟิกซ์เจอร์ไว้นอกรีโพซิทอรีโดยไม่ทำหาย

+

+ ฟิกซ์เจอร์ไบนารีขนาดใหญ่ทำให้รีโพซิทอรีโคลนช้าและตรวจทานยาก + และไม่มีใครบอกได้ว่าอะไรเปลี่ยนเมื่อมีการเปลี่ยนไฟล์หนึ่ง สูตรคือ YAML + ไม่กี่ร้อยอักขระที่สร้างไฟล์เหมือนเดิมขึ้นใหม่ - ไบต์ต่อไบต์ บนเครื่องใดก็ตาม - + เพราะทุกไฟล์ได้มาจากซีดของการรัน +

+
- 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
+

+ ทุกการจบมีรหัสออกของตัวเอง + ไปป์ไลน์จึงแยกสูตรที่ไม่ดีออกจากดิสก์เต็มและจากความไม่ตรงกันในการตรวจสอบได้ + การรันที่ล้มเหลวไม่พิมพ์อะไรบนเอาต์พุตมาตรฐาน + ทำให้ตัวแยกวิเคราะห์บันทึกไม่อ่านข้อผิดพลาดเป็นข้อมูล +

+
+ +
+

ขนาดใหญ่

+

ค้นหาว่าเกิดอะไรขึ้นเมื่อโฟลเดอร์ใหญ่

+

+ ขั้นตอนนำเข้า งานกลางคืน และรายการไดเรกทอรีทำงานต่างกันเมื่อมีหนึ่งหมื่นไฟล์เทียบกับสิบไฟล์ + ขนาดที่สุ่มจากช่วงทำให้ชุดดูเหมือนทราฟฟิกจริงแทนที่จะเป็นไฟล์เหมือนกันหนึ่งหมื่นไฟล์ + และการสุ่มมาจากซีด ชุดจึงเหมือนเดิมในวันพรุ่งนี้ +

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

+ ตรวจต้นทุนของการรันก่อนที่มันจะเขียนอะไร ซึ่งสำคัญเมื่อยอดรวมวัดเป็นกิกะไบต์: +

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

+ การรันที่ใหญ่กว่าพื้นที่ว่างบนดิสก์ถูกปฏิเสธก่อนจะเขียนไบต์แรก + แทนที่จะเติมดิสก์จนเต็มแล้วล้มเหลวกลางคัน +

+
+ +
+

ไฟล์บีบอัด

+

ทดสอบตัวแตกไฟล์ด้วยไฟล์บีบอัดที่มีไฟล์อยู่ข้างในจริงๆ

+

+ ไฟล์บีบอัดว่างที่มีนามสกุลถูกต้องไม่พิสูจน์อะไรเกี่ยวกับโค้ดที่เปิดและไล่ดูสิ่งที่อยู่ข้างใน + ประกาศเนื้อหา แล้วไฟล์บีบอัดจะมีมันอยู่จริง: +

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

+ ความลึกของการซ้อน จำนวนรายการ และขนาดของสิ่งที่อยู่ข้างใน ล้วนเป็นสิ่งที่ขั้นตอนนำเข้ามีความเห็น + และนี่คือวิธีที่คุณจะรู้ว่าความเห็นเหล่านั้นคืออะไร +

+
+ +
+

ตัวแยกวิเคราะห์และโปรแกรมดู

+

ตรวจสอบว่าโค้ดของคุณเองอ่านรูปแบบได้เหมือนซอฟต์แวร์จริง

+

+ ทุกรูปแบบที่นี่ถูกตรวจด้วยตัวอ่านอิสระก่อนปล่อย - PNG ถูกเปิดและเทียบพิกเซล DOCX + ถูกอ่านกลับด้วยไลบรารีแยกต่างหาก ไฟล์บีบอัดถูกแตกไฟล์ + นั่นหมายความว่าไฟล์ที่ตัวแยกวิเคราะห์ของคุณปฏิเสธเป็นข้อค้นพบเกี่ยวกับตัวแยกวิเคราะห์ของคุณ + ไม่ใช่เกี่ยวกับตัวสร้าง +

+
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
+

+ หน้ารูปแบบไฟล์แสดงการตั้งค่าที่แต่ละรูปแบบรับและไฟล์เล็กที่สุดที่แต่ละรูปแบบเป็นได้ +

+
+ +
+

คู่มือ

+

สองเรื่องนี้ในรายละเอียด

+ +
+ +
+

เหมาะกับใคร

+

+ วิศวกร QA งานทดสอบอัตโนมัติ และทุกคนที่โค้ดมีฟอร์มอัปโหลด ขั้นตอนนำเข้า ตัวแยกวิเคราะห์ + หรือโควตาพื้นที่จัดเก็บอยู่เบื้องหลัง ทำงานบนเครื่องที่ไม่มีเครือข่ายเลย + ซึ่งสำคัญในสภาพแวดล้อมองค์กรที่ปิดซึ่งตัวสร้างบนเบราว์เซอร์ไม่ใช่ทางเลือก +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/tr/ci.html b/web/content/tr/ci.html new file mode 100644 index 00000000..7f54b3cc --- /dev/null +++ b/web/content/tr/ci.html @@ -0,0 +1,188 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

CI hattında test dosyaları nasıl üretilir

+

+ Bir depodaki ikili fixture sonsuza dek geçmişinde kalır, bir diff'te incelenemez ve dosya + büyüdüğünde olanaksız hale gelir. Bunun yerine dosyaları hat içinde bir tariften üretin. Tarif + metindir, baytlar her seferinde aynı çıkar ve son bir adım hiçbir şeyin kaymadığını kanıtlar. +

+ +
+

Kısa yanıt

+

+ tfg'yi kurun, testlerden önce tfg generate fixtures.yaml --out ./fixtures, + sonra tfg verify ./fixtures/manifest.json çalıştırın. Her iki adım da derlemeyi + kendiliğinden başarısız kılar ve nedenini söyleyen bir çıkış koduyla bunu yapar. +

+
+ +
+

Neden commit edilmez

+

Bir fixture neden depoda durmamalı

+ +

+ Commit edilecek olan tariftir. Aynı tarif ve aynı tohum her makinede aynı baytları yazar, bu yüzden + hatta üretilen dosya dizüstünüzde sahip olduğunuz dosyadır. +

+
+ +
+

Tarif

+

Testlerin yanında duran bir tarif

+

+ Bu tarif, kabul edilmesi gereken yirmi beş fatura ile bir sınırın üzerinde olup reddedilmesi gereken + iki görüntü yazar ve bildirim iki beklentiyi de kaydeder: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml onu hiçbir şey yazmadan denetler ve tüm sorunları tek + seferde adlandırır. +

+
+ +
+

GitHub Actions

+

Aracı kuran ve fixture'ları oluşturan bir iş akışı

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Sağlama toplamı satırı arşivi aynı sürümdeki verify-SHA256SUMS.txt ile karşılaştırır. + Sürüm sabitlenmiştir, bu yüzden yeni bir sürüm dokunmadığınız bir derlemeyi asla değiştirmez. +

+
+ +
+

GitLab CI

+

Aynısı bir GitLab işi olarak

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Kırmızıya döndüğünde

+

Bir adımı ne başarısız kılar ve neden

+

+ Her sonun kendi çıkış kodu vardır, bu yüzden adım kendiliğinden başarısız olur ve günlük hangisi + olduğunu söyler. Bir hattın karşılaştıkları: +

+ +

+ Başarısız bir çalıştırma standart çıktıya hiçbir şey yazmaz, bu yüzden bir günlük ayrıştırıcısı + hatayı asla veri sanmaz. Tablonun tamamı belgeler + sayfasında. +

+
+ +
+

PowerShell

+

Bir PowerShell betiği bir satır daha ister

+

+ PowerShell, bir programın çıkış kodunu bir .ps1 dosyasının dışına taşımaz. Birini + -File ile çalıştırın. İçindeki araç işi reddetse bile betik 0 yanıtı + verir ve kırmızı olması gereken bir derleme yeşile döner. Son satır düzeltmenin tamamıdır: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell böyle davranır, bu aracla ilgili bir şey değildir. cmd, bash ve + zsh fazladan hiçbir şeye gerek duymaz. +

+
+ +
+

Birkaç iş

+

Fixture'ları işler arasında paylaşmak

+

+ Genellikle yüklemeye gerek yoktur. Aynı tarif aynı baytları yazdığı için her iş kendi tfg + generate komutunu çalıştırabilir ve bu, yükleyip indirmekten daha hızlıdır. Bir işin + başka bir işten dosya alması gerekiyorsa, aktarımdan sonra bildirim üzerinde tfg + verify çalıştırın. Gelenin yazılanla aynı olup olmadığını söyler. +

+
+ +
+

Sonraki

+

Buradan nereye gidilir

+ +
diff --git a/web/content/tr/damage.html b/web/content/tr/damage.html new file mode 100644 index 00000000..df1d5aad --- /dev/null +++ b/web/content/tr/damage.html @@ -0,0 +1,174 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Test için bozuk dosya nasıl yapılır

+

+ Yalnızca sağlam dosyalar gösterilmiş bir doğrulayıcı gerçekten sınanmış sayılmaz. İşte kasıtlı + bozulmuş, tam istediğiniz boyutta çıkan ve sisteminizin onunla ne yapması + gerektiğini söyleyen bir bildirimle gelen bir dosyayı nasıl elde edeceğiniz. +

+ +
+

Kısa yanıt

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out tam 2097152 bayt + boyutunda, ilk baytları sıfır olan bir PNG yazar ve yanındaki bildirim sisteminizin onu + reddetmesi gerektiğini kaydeder. +

+
+ +
+

Olağan yol

+

Elle bozulmuş bir dosya neden kötü bir testtir

+

+ Olağan yollar bir onaltılık düzenleyici, birkaç rastgele baytı çeviren bir betik ya da bir dosyayı + head veya truncate ile kısaltmaktır. Bir kez işe yarar, sonra size + pahalıya mal olur: +

+ +
+ +
+

Ne elde edersiniz

+

Hasarlı bir dosya yine istediğiniz boyuttadır

+

+ Dosya normal üretilir, sonra diske giderken bozulur. İstediğiniz boyutu korur ve aynı komut yine + aynı baytları yazar. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Ayarlar iki noktadan sonra yazılır. Seçenek tekrarlanabilir ve hasarlar yazdığınız sırayla + uygulanır. {{ .Facts.FormatCount }} biçimin her biriyle çalışır. +

+
+ +
+

Neler yapabilir

+

Hangi hasarlar var?

+

+ Bu, programın yazdırdığı listedir ve bu sayfa oluşturulurken programdan okunur. tfg + damage aynısını yazdırır, tfg damage <id> ise birinin neyi kabul + ettiğini söyler. +

+ {{ template "damagesTable" . }} +

+ zero-head dosyanın başına sıfırlar yazar. Okuyucuların çoğu önce oraya bakar, dosyanın + ne olduğunu söyleyen imzaya ve başlığa, bu yüzden hemen her okuyucu fark eder. Düz metin ve + günlüklerin imzası yoktur ve onlar da reddedilir, çünkü bir sıfır baytı dizisi metin değildir. + Dört baytın altında bazı biçimler hiçbir okuyucunun şikâyet etmediği bir hasarla çıkar, ayarın + dörtten başlamasının nedeni budur. +

+
+ +
+

Bildirim ne söyler

+

Ne olması gerektiğini söyleyen bir bildirim

+

+ Hasarlı her dosya, sisteminizin onu reddetmesi gerektiğini söyleyen bir kayıt alır ve hasar yanına + yazılır: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ İki istek, bir şey yazılmadan önce reddedilir, çünkü her biri diskte bildirimin yanlış tarif ettiği + bir dosya bırakırdı: +

+ +
+ +
+

Bir tarifte

+

Tek çalıştırmada sağlam ve bozuk dosyalar

+

+ İkisini de tek bir tarife koyun, bildirim her dosyanın beklentisini taşır. Böylece testin hangisinin + hangisi olduğuna dair bir listeye ihtiyacı kalmaz: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Bir testte

+

Bunu bir teste dönüştürmek

+

+ Test bildirimi okur ve olanın bildirilenle aynı olup olmadığına bakar. Dosya adı listesine ihtiyacı + yoktur: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ İyi bir ret temiz bir rettir. Neyin yanlış olduğunu söyleyen bir ileti istediğiniz yanıttır. Sunucu + hatası, takılma ya da yarım kaydedilmiş dosya, bu testin bulmak için var olduğu kusurdur. +

+
+ +
+

Sonraki

+

Buradan nereye gidilir

+ +
diff --git a/web/content/tr/docs.html b/web/content/tr/docs.html new file mode 100644 index 00000000..1e299277 --- /dev/null +++ b/web/content/tr/docs.html @@ -0,0 +1,278 @@ +

Dokümantasyon

+

+ Aracın yaptığı her şey, insanların gerçekten geldiği sorular şeklinde düzenlendi. + Depodaki README tam başvurudur ve her zaman indirdiğiniz sürümle + eşleşir. +

+ +
+

Hangi komutlar var?

+

Her biri tek bir iş yapar:

+ {{ template "commandList" . }} +
+ +
+

Tam boyutta tek bir dosyayı nasıl üretirim?

+

+ Biçimi, boyutu ve nereye gideceğini söyleyin. Boyutlar 1024'lerle sayılır, yani 2mb + 2097152 bayttır. Düz bir bayt sayısı da olur, yani --size 10485761 tam o kadarını + ister. +

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

generate için işe yarar bayraklar:

+
+ + + + + + + + + + + + + + + + + +
BayrakNe yapar
--format <id>dosyaların biçimi, örneğin txt
--size <size>her dosyanın tam boyutu, 10mb gibi veya düz bir bayt sayısı
--size-range <a-b>bir aralıktan dosya başına çekilen boyut, 1kb-8kb gibi. Çekiliş seed'den gelir
--boundary <size>bir sınırın çevresinde üç dosya: bir bayt altı, sınırın kendisi, bir bayt üstü
--count <n>kaç dosya üretileceği. Varsayılan 1
--name <template>ad şablonu, örneğin invoice_{index:04}.txt
--out <dir>yazılacak dizin
--seed <n>çalıştırmanın seed'i. Aynı seed aynı baytları verir
--set <k>=<v>bir biçim ayarı, tekrarlanabilir
--damage <name>dosyaları kasıtlı bozar, tekrarlanabilir ve sırayla uygulanır. Liste için tfg damage çalıştırın
--expected <outcome>accept, reject, sanitize veya unspecified
--dry-runsay ve göster, hiçbir şey yazma
--jsonmanifesti standart çıktıya yaz
+
+
+ +
+

Kasıtlı bozuk bir dosyayı nasıl yaparım?

+

+ Bu aracın yazdığı diğer her dosya yapısı gereği doğrudur ve bu, bir yükleme doğrulayıcısının sorduğu + üç sorudan ikisini yanıtlar. --damage üçüncüsünü yanıtlar - dosya hiç açılıyor mu. + Dosya normal üretilir, sonra bozulur, böylece hâlâ istediğiniz boyuttadır. +

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

+ Ayarlar iki noktadan sonra gelir. Bayrak tekrarlanır ve yazdığınız sıra uygulanma sırasıdır. + tfg damage bu sürümün neler yapabildiğini ve her birinin ne aldığını listeler. +

+

Bir tarifte anahtar, adlardan veya ayarlardan oluşan bir listedir:

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

+ Hasarlı bir dosya manifestte expected: reject alır, hasar yanında kaydedilir. İki şey + bir şey yazılmadan önce reddedilir, çünkü her biri aksi hâlde diske manifestin yanlış tarif + ettiği bir dosya koyardı: +

+ +

+ Üçüncüsü önceden bilinemez. Bir hasar çalışıp hiçbir baytı oynatmazsa o dosya yazılmak yerine atılır + - çalıştırma sürer, hangi dosya olduğunu söyler ve kısmi çıkış koduyla biter. +

+

+ Adım adım, bildirimi okuyan bir testle: test için bozuk dosya + nasıl yapılır. +

+
+ +
+

Bir tarif nasıl görünür?

+

+ Tarif, tüm bir çalıştırmayı anlatan bir YAML dosyasıdır. Testlerinizin yanına commit edin, + fixture'lar deponuzda ikili dosya olmaktan çıkar - herkes onları birkaç yüz karakterlik bir + dosyadan bayt bayt yeniden kurabilir. +

+
# 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
+

+ Her target, size, size-range, boundary veya + contains anahtarlarından tam birine ihtiyaç duyar. İkisi hatadır, hiçbiri de öyle. + Geçersiz bir tarif hiç dosya yazmaz ve yalnızca ilkini değil tüm sorunları bir + seferde bildirir, her biri ilgili ayarı adlandırır. +

+
+ +
+

Sistemimin bir dosyayla ne yapması gerektiğini nasıl bildiririm?

+

Sonuç yeterliyse kısa biçim, neden önemliyse uzun biçim:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Sonuçlar accept, reject, sanitize ve + unspecified. Nedenler, bir rapor onlara göre gruplayabilsin diye kapalı bir + listedir: 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 ve + size_zero. +

+

+ Bir neden söz konusu kuralı adlandırır, hükmü değil. Bu yüzden aynı neden iki + sonucun altında da durabilir - sınırın bir bayt altındaki dosya accept olur ve söz + konusu kural yine size_limit kalır. +

+
+ +
+

Manifestte ne var?

+

+ Her çalıştırmanın sonunda, kesilen çalıştırma dahil, dosyaların yanına yazılır. Dosya başına bir + girdi: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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"
+      }
+    }
+  ]
+}
+

+ Çalıştırma bir tariften geldiyse bir recipe_hash, bir hazır ayardan geldiyse + overrides ile birlikte preset eklenir, böylece bir manifest her zaman + onu üreten şeye kadar izlenebilir. +

+

+ Her girdi ayrıca dosyayı üreten tarifteki hedefin kimliği olan target_id taşır ve + summary.by_target her hedefin kaç dosyaya vardığını sayar. Birkaç hedefli bir tarif + böylece dosya adlarını okumadan hedef hedef denetlenebilir. +

+
+ +
+

Hazır ayar nedir?

+

+ Yaygın bir test sorusunu yanıtlayan hazır bir dosya seti, böylece seti kendiniz tasarlamanız + gerekmez. Hazır ayarlar altta sıradan tariflerdir ve eject tarifi yazdırır, oradan + düzenleyebilirsiniz. Her hazır ayarın genelde ne bulduğunu, sette ne olduğunu ve kabul ettiği + her ayarı anlatan kendi sayfası vardır. +

+ {{ template "presetsList" . }} +
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, seti kurmadan önce neye mal olacağını söyler ve bir sayının sizin sınırınız değil + bizim geçici değerimiz olduğunu açıkça belirtir. +

+
+ +
+

Çıkış kodları ne anlama gelir?

+

+ Her sonun kendi kodu vardır, makine tarafından okunabilir çıktı standart çıktıya gider ve başarısız + bir çalıştırma orada hiçbir şey yazdırmaz. Tablo dondurulmuş bir sözleşmedir - bir kodun + anlamını değiştirmek büyük sürüm artışı gerektirir. +

+ {{ template "exitCodesTable" . }} +
- 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 ile durdurulan bir çalıştırma yine bir manifest bırakır ve asla yarım yazılmış bir dosya + bırakmaz, böylece iptal edilen bir işi bir sonraki temizleyebilir. +

+

+ GitHub Actions ve GitLab CI için hazır iş akışları: CI + hattında test dosyaları nasıl üretilir. +

+
+ +
+

Masaüstü penceresi var mı?

+

+ Evet, betiklenmeyen test için üzerine bir pencere konmuş aynı motor. Kırpılmış bir sürüm değildir: + bir test iki arayüzü yetenek yetenek karşılaştırır ve yalnızca birinin yapabildiği her şey + sessizce ayrışmak yerine bildirilip gerekçelendirilmelidir. +

+

+ Ekranlar tek bir grup, hazır ayarlar, aynı anda birkaç grup ve hakkında. Bir çalıştırmanın neye mal + olacağını bir şey yazmadan önce gösterir, çalışırken ilerlemeyi bildirir ve yarım yazılmış dosya + bırakmadan yarıda iptal edilebilir. Henüz bir tarif dosyası açmaz - tarifler şimdilik komut + satırının işidir ve pencere gruplarını formda kurar. +

+
diff --git a/web/content/tr/exact-size.html b/web/content/tr/exact-size.html new file mode 100644 index 00000000..5548df50 --- /dev/null +++ b/web/content/tr/exact-size.html @@ -0,0 +1,144 @@ +

Tam boyutta dosya nasıl oluşturulur

+

+ Her sistemin bunun için bir komutu var ve üçü de aşağıda. Size tam doğru bayt sayısında bir dosya + verirler - ve birçok test için gereken tek şey budur. Bu sayfadaki her komut, + yayımlanmadan önce ait olduğu sistemde çalıştırıldı. +

+ +
+

Kısa yanıt

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Boyutlar bayt cinsindendir ve dosya + yöneticinizin saydığı gibi 10 MB, 10485760'tır. +

+
+ +
+

Windows

+

fsutil ve fazladan hiçbir şey gerektirmeyen bir PowerShell sürümü

+

+ fsutil Windows ile gelir. Boyutu bayt cinsinden alır, bu yüzden sayıyı + önce hesaplayın - 10 MB 10485760, 100 MB 104857600, 1 GB 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11'de ölçüldü: sıradan bir istemden çalışır, yükseltilmiş bir istem gerektirmez ve dosya tam + 10485760 bayt çıkar. +

+

PowerShell aynı şeyi başka bir programı çağırmadan yapabilir ve birimleri anlar:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell'de 10MB, Gezgin'in kullandığı aynı 1024 tabanlı sayımla 10485760 bayt + demektir, yani yukarıdaki iki komut aynı boyutu üretir. +

+
+ +
+

Linux

+

dd, truncate ve fallocate ve insanları yakalayan fark

+

dd herkesin bildiğidir. Baytları gerçekten yazar:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate anlıktır ve tuzak da budur. Alpine Linux'ta ölçüldü: dosya 10485760 bayt + bildirir ve sıfır blok kaplar - bir seyrek dosyadır. Onu + okuyan her şey on megabayt sıfır alır ama disk alanı hiç vermemiştir: +

+
truncate -s 10M test10mb.bin
+

+ Bu, yükleme sınırını sınamak için iyidir ve disk kotasını sınamak için yanıltıcıdır. Alan gerçek + olmalıysa başvurulacak olan fallocate'tir: +

+
fallocate -l 10M test10mb.bin
+

Ve içerik, bir arşivleyici onu yeniden sıkıştıramasın diye sıkıştırılamaz olmalıysa:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

seyrek olmayan mkfile ve zaten bildiğiniz iki komut

+

+ macOS mkfile ile gelir. macOS 26.6.2'de ölçüldü: 10485760 bayt ve 20480 blok, yani alan + söz verilmek yerine gerçekten ayrılır: +

+
mkfile 10m test10mb.bin
+

dd ve truncate da var ve Linux'taki gibi davranır:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Bunun işe yaramadığı yer

+

Doğru boyutta bir dosya doğru türde bir dosya değildir

+

+ Yukarıdakilerin hepsi size bir sıfır bloğu verir. Test edilen şey yalnızca boyuta bakıyorsa - + yükleme sınırı, kota, aktarım - bu yeterlidir. Bir şey dosyayı açtığı anda + yeterli olmaktan çıkar. +

+

+ Ölçüldü ve kendiniz yapmaya değer: fsutil ile 2 MB'lık bir dosya yapın, adını + photo.png koyun ve bir görüntü kitaplığına verin. Pillow cannot identify + image file yanıtını verir. PNG değil. Hiç de olmadı - yalnızca adı öyle diyordu. +

+

+ Bu, göründüğünden daha önemlidir, çünkü testin bundan sonra hangi yönde başarısız + olduğu belirleyicidir. Yükleme endpoint'iniz dosyayı reddeder, testiniz yeşile döner ve + boyut sınırının çalıştığı sonucuna varırsınız. Onu boyut yüzünden reddetmedi. Baytlar resim + olmadığı için reddetti ve sınamak istediğiniz kurala hiç ulaşılmadı. +

+ +
+ +
+

Öbür yol

+

O biçimden gerçek bir dosya, tam istediğiniz boyutta

+

+ Testing Files Generator'ın yaptığı budur. Dosya biçiminin gerçek bir örneğidir - ait olduğu + programda açılır - ve istediğiniz tam bayt sayısındadır, bayta kadar: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Bir biçimin ulaşamayacağı bir boyut isteyin, alt sınırı ve nedenini adlandıran bir hata alırsınız, + asla yanlış boyutta bir dosya değil. Biçimler sayfası her biçimi + üretebildiği en küçük dosyayla listeler. +

+

Ve bir sınır bir değil üç test durumudur, bu yüzden araç üçünü de kurar:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Bu size 10485759, 10485760 ve 10485761 bayt ile hangilerini sisteminizin kabul etmesi, hangilerini + reddetmesi gerektiğini söyleyen bir manifest verir. Kullanım + senaryoları sayfası bunu ve aracın yapıldığı dört işi daha anlatır. +

+ {{ template "downloadCta" . }} +
+ +
+

Peki hangisini kullanmalı?

+ +

+ İkisi de bu sayfada çünkü ikisi de zamanın bir kısmında haklı. Kaçınılması gereken hata, ikincisinin + gerektiği yerde birincisini kullanmak ve yeşil testi kanıt saymaktır. +

+
diff --git a/web/content/tr/faq.html b/web/content/tr/faq.html new file mode 100644 index 00000000..4f268e89 --- /dev/null +++ b/web/content/tr/faq.html @@ -0,0 +1,18 @@ +

Sık sorulan sorular

+

+ Lisans, gizlilik, tekrarlanabilirlik ve insanların bir üreticiyi derleme hattına koymadan önce + denetlediği şeyler. Sorunuz burada yoksa sorun takipçisi açık. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Hâlâ karar vermediniz mi?

+

+ Kullanım senaryoları sayfası aracın yapıldığı işleri + gösterir, biçimler sayfası her biçimi üretebildiği en küçük dosyayla + listeler. Depodaki README tam başvurudur. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/tr/formats.html b/web/content/tr/formats.html new file mode 100644 index 00000000..714e8c39 --- /dev/null +++ b/web/content/tr/formats.html @@ -0,0 +1,79 @@ +

{{ .Facts.FormatCount }} dosya biçimi, her biri tam boyutta üretilir

+

+ Bunların her biri o biçimde gerçek bir dosyadır. Ait olduğu programda açılır ve tam + istediğiniz bayt sayısındadır. Hiçbiri yapıştırılmış uzantılı dolgu sıfırları değildir. +

+ +{{ template "formatsTable" . }} + +
+

Sütunların anlamı

+ +

+ Her biçim ayrıca bayta kadar tekrarlanır: aynı tarif ve aynı seed her makinede özdeş dosyalar üretir + ve bir tarifi fixture'ların kendisi yerine commit etmeyi güvenli kılan budur. +

+
+ +
+

Her biçimin kabul ettiği ayarlar

+

+ Çoğu biçimin kendi ayarları vardır - görüntü boyutları, JPEG kalitesi, PDF sayfa sayısı, bir + elektronik tablodaki satır ve sütunlar, bir arşivin içine kaç girdi gireceği. Bunları komut + satırında --set key=value ile veya bir tarifte properties: altında + ayarlayın. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Bir ayarın kabul ettiğinin dışındaki değer, ayarı, izin verilen aralığı ve onun yerine ne + kullanılacağını söyleyen bir iletiyle reddedilir. Bilinmeyen bir ayar da hatadır, asla sessiz + bir varsayılan değil - sessizce kabul edilen bir yazım hatası yanlış ayarlı bir dosya ve testin + geçmemesi gerekirken neden geçtiğini merak ederek geçen bir saat verir. +

+

+ Elinizdeki sürümde bir biçimin tam olarak ne kabul ettiğini görmek için tfg formats + <id> çalıştırın. +

+
+ +
+

Arşivler gerçek dosyalar içerir

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} ve {{ end }}{{ $c.ID }}{{ end }} boş + bir kabuk olarak bırakılmak yerine girdilerle doldurulabilir. Üretilmiş bir arşiv, içerdiğini + söylediği belgeleri gerçekten içerir, bu yüzden bir test sırasında onu açan her şey içinde + gerçek dosyalar bulur. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/tr/index.html b/web/content/tr/index.html new file mode 100644 index 00000000..b1ad743c --- /dev/null +++ b/web/content/tr/index.html @@ -0,0 +1,196 @@ +
+
+

Tam boyutta gerçek test dosyaları üretin

+

+ PDF, PNG, DOCX, ZIP - toplam {{ .Facts.FormatCount }} biçim ve her biri ait olduğu + programda açılan, tam istediğiniz boyutta gerçek bir dosya. Her çalıştırma + ayrıca uygulamanızın her dosyayla ne yapması gerektiğini de yazar. Komut satırı ve masaüstü + penceresi, ücretsiz ve açık kaynak, tamamen makinenizde çalışır. +

+ + {{ template "downloadCta" . }} +
+ +
+ Bir grup test dosyası yazmaya hazırlanmış Testing Files Generator masaüstü penceresi +
Bir dosya grubu yazmaya hazırlanmış masaüstü penceresi. Aynı motor komut satırının arkasında çalışır.
+
+
+ + + +
+

Sorun

+

Bir test dosyası yapmak kolay. Doğru bini yapmak sıkıcı kısım

+

İnsanlardan dosya kabul eden bir yazılımı test ediyorsunuz. Er ya da geç şunlara ihtiyacınız olur:

+ +

+ Bunun yerini alan şey bu. QA mühendisleri, test otomasyonu ve kodunun arkasında bir yükleme formu, + içe aktarma rutini, ayrıştırıcı veya depolama kotası olan herkes için yapıldı. +

+
+ +
+

Onu farklı kılan

+

Diğer üreticiler baytlarda durur. Bu, testinizin gerçekte ne sorduğunu yanıtlar

+

+ Bir dosya klasörü, her birinin neyi kanıtlaması gerektiğine yine sizin karar vermenize bırakır. + Burada her çalıştırma dosyaların yanına bir manifest.json yazar - üretilen her + şeyin düz bir listesi ve her girdi için bir bildirilmiş beklenti. +

+

Yükleme endpoint'inizin 1 MB'a izin verdiğini varsayalım. O çizgideki üç dosyayı isteyin:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
DosyaBaytSisteminizÇünkü
1mb_under_1b.pdf1048575kabul etmelisınırın içinde
1mb_at_limit.pdf1048576kabul etmelisınırın kendisine izin verilir
1mb_over_1b.pdf1048577reddetmelisize_limit
+
+ +

Üç dosya, üç farklı yanıt, makine tarafından okunabilir biçimde. Testiniz, sizin elle assertion yazmanız yerine manifesti okur:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Yanıt kendi politikanıza bağlıysa manifest bunu söyler

+

+ Bir beklenti uydurmak yerine unspecified kaydeder. Tahmin yürüten bir üretici yanlış + hatalar üretir ve sürekli yalancı alarm veren bir test takımı kapatılır. +

+
+
+ +
+

Hazır ayarlar

+

Soruyu seçin, setin tamamını alın

+

+ Hazır ayar, hangi dosyanın neyi kanıtladığını sizin çözmeniz gerekmesin diye tek bir test sorusu + etrafında tasarlanmış bir test dosyası setidir. Her birinin, genelde ne bulduğunu, sette ne + olduğunu ve kabul ettiği her ayarı anlatan bir sayfası vardır. +

+ {{ template "presetsList" . }} +

Tüm hazır ayarlar ve tariflerle ilişkileri

+
+ +
+

Hızlı başlangıç

+

Çalıştığını görmek için üç komut

+
    +
  1. +

    Bir dosya üretin

    +

    Bir PNG, tam iki megabayt:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Çok sayıda dosya üretin

    +

    + Her biri bir ile sekiz kilobayt arasında on bin günlük dosyası, boyutlar seed'den çekilir ki yarın + aynı seti versin. Her çalıştırmaya kendi dizinini verin - manifest bir + çalıştırmanın ne yazdığının tek kaydıdır, bu yüzden araç üzerine ikincisini yazmayı + reddeder: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Denetleyin, sonra silin

    +

    verify hiçbir şeyin kımıldamadığını söyler. cleanup yazılanı tam olarak ve başka hiçbir şeyi silmez:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Boyutlar, dosya yöneticinizin yaptığı gibi 1024'lerle sayılır, yani 2mb 2097152 bayt + demektir. Düz bir bayt sayısı da olur. Dokümantasyon tarifleri, + manifesti ve çıkış kodlarını kapsar. +

+
+ +
+

Neler elde edersiniz

+

Gözetimsiz çalışan bir test takımı için yapıldı

+ +
+ +
+

İndirme

+

Sisteminiz için derlemeyi seçin

+

+ Arşivi açın ve çalıştırın. tfg komut satırı, tfg-gui masaüstü + penceresidir. Yükleyici yok ve makinenize eklenecek hiçbir şey yok. +

+ {{ template "downloadsTable" . }} +
+

Neler imzalı, neler değil

+

+ Windows ve macOS indirmeleri imzalıdır, bu yüzden bilinmeyen geliştirici uyarısı olmadan başlar. + Linux olanlar değildir, çünkü masaüstü Linux'ta onları imzalayacak bir karşılık yoktur. Her + arşiv sürüm sayfasındaki verify-SHA256SUMS.txt içinde listelenir, böylece + indirdiğinizi doğrulayabilirsiniz. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/tr/preset.html b/web/content/tr/preset.html new file mode 100644 index 00000000..d624c721 --- /dev/null +++ b/web/content/tr/preset.html @@ -0,0 +1,92 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }} hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ +{{ if .Catches }} +
+

Genelde ne bulur?

+ +
+{{ end }} + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show {{ .ID }} çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya{{ .Budget.Files }}
Tarifindeki hedefler{{ .Budget.Targets }}
Toplam boyut{{ .Bytes }} B
Biçimler{{ join .Budget.Formats ", " }}
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
BeklenenAnlamıDosya
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Neyi değiştirebilirsiniz?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
AyarAldığıVarsayılanNe yapar
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Bu varsayılan sizin sisteminizin değeri değil, bizim geçici değerimizdir. Kendinizinkini verin.{{ end }}
+
+ {{- else }} +

Bu hazır ayarın ayarı yok. Set her seferinde aynıdır.

+ {{- end }} +
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/tr/presets.html b/web/content/tr/presets.html new file mode 100644 index 00000000..c1fae63e --- /dev/null +++ b/web/content/tr/presets.html @@ -0,0 +1,32 @@ +

Test dosyası hazır ayarları, her test sorusu için bir set

+

+ Hazır ayar, tek bir soru etrafında tasarlanmış, sisteminizin her dosyaya nasıl tepki vermesi + gerektiğini söyleyen bir manifestle gelen bütün bir test dosyası setidir. Soruyu siz seçersiniz, + aracın seti kurar. Her hazır ayarın genelde ne bulduğunu, sette ne olduğunu ve kabul ettiği her + ayarı anlatan kendi sayfası vardır. +

+ +{{ template "presetsList" . }} + +
+

Hazır ayar bir tariften nasıl farklıdır?

+

+ Altta, hiç farklı değildir. Hazır ayar, aracın sizin için birkaç ayardan yazdığı bir tariftir. + tfg preset eject o tarifi yazdırır, böylece testlerinizin yanında tutup + düzenleyebilirsiniz ve kendi tarifiniz tek satırla bir hazır ayarın üzerine kurulabilir: + extends: preset: ve ardından kimliği. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Varsayılanlara güvenebilir miyim?

+

+ Dosyalar için evet. Yükleme formunun sınırı gibi yalnızca sisteminizin bildiği bir sayı için + varsayılan bizim geçici değerimizdir ve araç birini kullandığı her seferde bunu söyler. Her + hazır ayarın sayfası bu ayarları işaretler ve tfg preset show bir şey yazılmadan + önce söyler. +

+
diff --git a/web/content/tr/site.json b/web/content/tr/site.json new file mode 100644 index 00000000..1bc477e0 --- /dev/null +++ b/web/content/tr/site.json @@ -0,0 +1,328 @@ +{ + "code": "tr", + "locale": "tr_TR", + "name": "Türkçe", + "dir": "tr", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Ana sayfa", + "title": "QA için test dosyası oluşturucu - tam boyut, {{ .Facts.FormatCount }} gerçek biçim", + "description": "QA için ücretsiz, açık kaynaklı test dosyası oluşturucu. Tam boyutta gerçek PDF, DOCX, PNG ve ZIP dosyaları ve sisteminizin tepkisini söyleyen bir manifest." + }, + { + "key": "formats", + "slug": "bicimler", + "nav": "Biçimler", + "title": "{{ .Facts.FormatCount }} desteklenen dosya biçimi - PDF, DOCX, PNG, ZIP ve daha fazlası", + "description": "Üretilen tüm biçimler, her birinin mümkün olan en küçük dosyası ve kabul ettiği ayarlar. {{ .Facts.FormatCount }} biçimin hepsi kendi programında açılır." + }, + { + "key": "presets", + "slug": "hazir-ayarlar", + "nav": "Hazır ayarlar", + "title": "Test dosyası hazır ayarları - QA için hazır setler", + "description": "Hazır test dosyası setleri, her biri tek bir test sorusunu yanıtlar: yükleme sınırları, dosya adları, kodlamalar, tablo içe aktarma, boş dosyalar ve doğrulama." + }, + { + "key": "docs", + "slug": "dokumantasyon", + "nav": "Dokümantasyon", + "title": "Dokümantasyon - komutlar, tarifler, manifest, çıkış kodları", + "description": "Komut satırından veya bir YAML tarifinden test dosyası nasıl üretilir, manifestin içeriği ve araç CI içinde çalışırken her çıkış kodunun anlamı." + }, + { + "key": "use-cases", + "slug": "kullanim-senaryolari", + "nav": "Kullanım senaryoları", + "title": "Kullanım senaryoları - yükleme sınırları, CI fixture'ları, testler", + "description": "Yükleme boyut sınırını test etmek, CI için tekrarlanabilir fixture'lar kurmak, on bin dosya üretmek ve arşivleri gerçek içerikle doldurmak." + }, + { + "key": "exact-size", + "slug": "tam-boyutta-dosya-olusturma", + "nav": "Tam boyut", + "title": "Belirli boyutta dosya oluşturma - Windows, Linux, macOS", + "description": "fsutil, dd, truncate ve mkfile, her biri kendi sisteminde ölçüldü, ve bir test PDF veya PNG gerektirdiğinde bu yolla yapılan dosyanın neden onlar olmadığı." + }, + { + "key": "faq", + "slug": "sss", + "nav": "SSS", + "title": "SSS - test dosyası üretimi hakkında sorular", + "description": "dd ve fsutil'den farkı, dosyaların commit edilip edilemeyeceği, çalıştırmaların bayt bayt tekrar edip etmediği ve bir boyuta ulaşılamadığında ne olduğu." + }, + { + "key": "damage", + "slug": "bozuk-test-dosyalari", + "nav": "Bozuk dosyalar", + "title": "Bozuk test dosyaları - tam boyutta bozuk dosyalar", + "description": "Kasıtlı bozulmuş, tam boyutta bir dosya ve sisteminizin onu reddetmesi gerektiğini söyleyen bir bildirim. Yükleme doğrulaması ve ayrıştırıcıları sınamak için.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "ci-icinde-test-dosyalari", + "nav": "CI'da test dosyaları", + "title": "CI'da test dosyaları - GitHub Actions, GitLab CI ve PowerShell", + "description": "İkili dosya commit etmek yerine test dosyalarını hat içinde üretin: GitHub Actions iş akışı, GitLab işi, çıkış kodları ve PowerShell tuzağı.", + "parent": "use-cases" + } + ], + "words": { + "skip": "İçeriğe geç", + "navLabel": "Ana", + "langLabel": "Dil", + "breadcrumbHome": "Ana sayfa", + "imageAlt": "Testing Files Generator - tam boyutta gerçek test dosyaları ve sisteminizin her birine nasıl tepki vermesi gerektiğini söyleyen bir manifest", + "schemaDescription": "QA için ücretsiz ve açık kaynaklı bir test dosyası oluşturucu. {{ .Facts.FormatCount }} biçimde tam boyutta gerçek dosyalar üretir ve test edilen sistemin her birine nasıl tepki vermesi gerektiğini söyleyen bir manifest yazar.", + "ctaDownload": "İndir", + "ctaSource": "Kaynak kodu görüntüle", + "ctaNote": "Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.", + "colFormat": "Biçim", + "colName": "Ad", + "colExtension": "Uzantı", + "colSmallest": "En küçük dosya", + "colFidelity": "Bütünlük", + "colChecked": "Doğrulayan", + "colSetting": "Ayar", + "colAccepts": "Kabul eder", + "colSystem": "Sistem", + "colCli": "Komut satırı", + "colWindow": "Masaüstü penceresi", + "noBinary": "henüz ikili dosya yok", + "colCode": "Kod", + "colMeaning": "Anlamı", + "footerBlurb": "QA için tam boyutta test dosyaları ve sisteminizin her birine nasıl tepki vermesi gerektiğini söyleyen bir manifest.", + "footerProject": "Proje", + "footerSource": "GitHub'da kaynak kod", + "footerReleases": "İndirmeler", + "footerIssues": "Sorun bildir", + "footerSupport": "Projeyi destekle", + "footerPages": "Sayfalar", + "footerLicence": "Telif (C) 2026 DonislawDev. GNU Genel Kamu Lisansı sürüm 3 altında yayımlanmıştır. Ürettiğiniz dosyalar sizindir - lisans aracı kapsar, çıktısını değil.", + "footerPrivacy": "Bu site hiçbir yerden yazı tipi, betik veya izleyici yüklemez. Çerez bırakmaz.", + "notFoundTitle": "Bu sayfa burada yok", + "notFoundLead": "Takip ettiğiniz adres bu sitedeki hiçbir sayfayla eşleşmiyor.", + "notFoundBack": "Ana sayfaya git", + "read.format": "Setteki her dosyanın biçimi. Aracın kendi bayrağıdır ve hazır ayar yalnızca ona bir varsayılan verir.", + "readTakes.format": "biçimler sayfasındaki bir biçim kimliği", + "colDamage": "Hasar", + "colEffect": "Baytlara ne yapar", + "colSettings": "Ayarlar", + "noSettings": "yok" + }, + "endings": { + "0": "Her şey çalıştı.", + "1": "Araç içinde beklenmeyen bir hata.", + "2": "Yanlış komut veya bayrak.", + "3": "Tarif geçerli değil.", + "4": "Biçim istenen şeyi yapamıyor.", + "5": "Bir okuma veya yazma başarısız oldu.", + "6": "Yeterli disk alanı yok.", + "7": "verify bir uyuşmazlık buldu.", + "8": "Çalıştırma bitti ama her şey üretilmedi.", + "130": "Ctrl+C ile kesildi.", + "143": "Bir sinyalle durduruldu, CI zaman aşımı böyle görünür." + }, + "presets": { + "empty-and-minimal": { + "question": "Biçimin izin verdiği kadar küçük, geçerli bir dosya geçer mi?", + "title": "Boş ve asgari", + "pageTitle": "Her biçimde en küçük geçerli ve boş test dosyaları", + "description": "Aracın {{ .Facts.FormatCount }} biçiminin her birinde yazdığı en küçük geçerli dosya, biçim izin veriyorsa bir de boş dosya, her biri beklenen tepkiyle.", + "catches": [ + "kontrol baytları okumak yerine saydığı için çok küçük diye reddedilen geçerli bir dosya", + "bildirilmek yerine okuyucuyu çökerten boş bir dosya", + "küçük resme giderken sıfıra bölen bir piksel genişliğinde görüntü", + "sıfır baytı başarısız yükleme sayıp durmadan yeniden deneyen depolama" + ], + "details": { + "formats": "Setin hangi biçimlerden oluştuğu. Bu sürümdeki tüm biçimler için all bırakın veya sisteminizin kabul ettiklerini yazın." + } + }, + "filename-handling": { + "question": "Sistemim beklemediği bir dosya adını saklayıp gösterecek ve geri verecek mi?", + "title": "Dosya adı işleme", + "pageTitle": "Test için sorunlu dosya adları - Unicode ve uzunluk", + "description": "Yüklemeleri ve depolamayı bozan adlara sahip dosyalar: başka yazılar ve emoji, yön geçersiz kılma, görünmez karakterler, kabuk ve SQL sözdizimi, uzunluk sınırları.", + "catches": [ + "ekranda, bir günlükte veya bir listede başka bir ad gibi görünen bir ad", + "yükleme ile depolama arasında kesilen, kırpılan veya yeniden yazılan bir ad", + "depolama bayt sayarken karakterle sayılan bir uzunluk sınırı" + ], + "details": {} + }, + "size-boundaries": { + "question": "Bir boyut sınırı tam bildirildiği yerde uygulanıyor mu?", + "title": "Boyut sınırları", + "pageTitle": "Yükleme boyut sınırını test etme - tam sınırdaki dosyalar", + "description": "Sisteminizin bildirdiği sınırın bir bayt altında, tam üzerinde ve bir bayt üstünde dosyalar, iki yanda daha geniş adımlar, her biri kabul bilgisiyle işaretli.", + "catches": [ + "sınırda bir eksik veya fazla hataları", + "MB ile MiB'in karıştırılması, yani yüzde 4,8, geçmemesi gereken bir dosyayı geçirmeye yeter", + "tarayıcıda uygulanan ama sunucuda uygulanmayan bir sınır" + ], + "details": { + "limit": "Sisteminizin bildirdiği boyut sınırı. Geri kalan her şey buradan ölçülür.", + "spread": "Sınırın iki yanında ne kadar uzağa gidileceği, boyutlar listesi olarak." + } + }, + "tabular-import": { + "question": "Tablo içe aktarmam gerçek araçların dışa aktardıklarına dayanıyor mu?", + "title": "Tablo içe aktarma", + "pageTitle": "CSV ve Excel içe aktarma test dosyaları - ayırıcılar, başlıklar", + "description": "Başka ayırıcılı, CR LF satır sonlu, başlıksız ve başka tırnaklı CSV, çok geniş bir tablo, bir Excel çalışma kitabı ve birkaç düzende JSON.", + "catches": [ + "ayırıcı aranmak yerine varsayıldığı için tek sütun olarak okunan noktalı virgüllü dosya", + "her satırdan sonra boş bir satırla satırlara bölünen CRLF dosyası", + "ilk veri satırı sütun adı diye yutulan başlıksız bir tablo", + "gösterebildiği sütunları tutup geri kalanını tek söz etmeden atan bir içe aktarma", + "JSON kayıtlarını satır satır alıp ilk girintili belgede duran bir okuyucu" + ], + "details": { + "rows": "Elektronik tablonun kaç satır içerdiği. O kadar satırın paketlendiği tam boyutta yazılır, bu yüzden yukarıdaki bütçe bu değerle kayar.", + "columns": "Elektronik tablonun her satırında kaç sütun olduğu. Satır çarpı sütunun bir tavanı vardır ve aşılması bir şey yazılmadan önce reddedilir." + } + }, + "text-encoding": { + "question": "Okuyucum bir dosyanın hangi kodlamada olduğunu biliyor mu, yoksa tahmin mi ediyor?", + "title": "Metin kodlaması", + "pageTitle": "Metin kodlaması test dosyaları - UTF-8, UTF-16, BOM, CRLF", + "description": "Aynı metin UTF-8, UTF-16LE ve UTF-16BE olarak, bayt sırası işaretiyle ve işaretsiz, ayrıca CR LF ve LF satır sonlarıyla, okuyucunun metni nasıl çözdüğünü sınamak için.", + "catches": [ + "UTF-8 varsayıp bir UTF-16 dosyasını üç karakterde bir karakter olarak veya kutu sıraları olarak gösteren okuyucu", + "içerik olarak okunan bir bayt sırası işareti, böylece bir içe aktarmanın ilk alanı üç yabancı karakterle başlar", + "kodlamayı ilk baytlardan tahmin edip daha uzun bir dosyada farklı tahmin eden bir içe aktarıcı", + "her satırdan sonra boş bir satırla satırlara bölünen CRLF dosyası veya son alanda kalan bir satır başı karakteri" + ], + "details": { + "sample": "Setteki her dosyanın büyüklüğü. UTF-16 her karakter için iki bayt saklar, bu yüzden tek sayı reddedilir." + } + }, + "upload-validation": { + "question": "Yükleme formum alması gerekeni alıp geri kalanı reddediyor mu?", + "title": "Yükleme doğrulama", + "pageTitle": "Yükleme doğrulama test dosyaları - tür, boyut ve ad", + "description": "Yükleme formunu test etmek için dosyalar: izinli ve yasaklı türler, uzantıyla uyuşmayan içerik, boyut sınırı, düşmanca adlar ve toplu yükleme.", + "catches": [ + "tarayıcıda uygulanan ama sunucuda uygulanmayan bir sınır", + "resim veya düz metin sanılan bir SVG ya da HTML dosyası, yani bir betiği formdan geçirmenin yolu", + "uzantısına bakılıp hiç açılmayan bir dosya, böylece .jpg adlı bir PDF geçer", + "ne kadar büyük olduğuna bakmadan önce tüm gövdeyi belleğe okuyan bir form", + "photo.jpg kabul edilirken reddedilen PHOTO.JPG adlı bir yükleme veya tersi", + "boşluk, parantez veya ASCII dışı karakter içeren bir adın diske değişmeden yazılması" + ], + "details": { + "limit": "Yükleme formunuzun bildirdiği boyut sınırı. Bu set her iki yanda birer adım atar - her uzaklıktaki dosya için size-boundaries hazır ayarını çalıştırın.", + "allow": "Formunuzun hangi türleri kabul etmesi gerektiği. Her biri o türden gerçek bir dosya olur ve tüm setin pozitif kontrolünü oluşturur.", + "deny": "Formunuzun hangi uzantıları reddetmesi gerektiği. Bu sürümde biçimi olmayan bir uzantı yine de o adla, düz metin içeren bir dosya alır.", + "far-over": "Tek büyük dosyanın sınırın ne kadar ötesine geçtiği. Sınırın birkaç katını yazmak diske değmiyorsa kapatın.", + "bulk": "Toplu yüklemenin kaç dosya içerdiği. Sıfır, bu grubu setten tamamen çıkarır." + } + } + }, + "commands": { + "generate": "tariften veya bayraklardan dosya üret", + "validate": "bir tarifi denetle, hiçbir şey yazma", + "verify": "bir dizini bir manifeste göre denetle", + "cleanup": "bir manifestin listelediği dosyaları sil", + "recipe fmt": "bir tarifi oturmuş biçiminde yazdır", + "preset": "adlandırılmış bir test sorusundan dosya seti oluştur", + "formats": "bu sürümün desteklediği biçimleri listele", + "damage": "bu sürümün bir dosyayı kasıtlı bozma yollarını listele", + "tool": "elinizdeki dosyalar için küçük araçlar", + "version": "araç sürümünü yazdır", + "license": "lisansı ve üretilen dosyalar için anlamını yazdır" + }, + "outcomes": { + "accept": "Sisteminiz dosyayı kabul etmeli.", + "reject": "Sisteminiz dosyayı reddetmeli.", + "sanitize": "Sisteminiz dosyayı kabul edip temizlemeli, örneğin yeniden adlandırarak.", + "unspecified": "Sisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız." + }, + "damages": { + "zero-head": "Dosyanın ilk baytlarını uzunluğuna dokunmadan sıfırlarla ezer. Okuyucuların çoğu önce oraya bakar, bu yüzden hemen her şey bu hasarı fark eder." + }, + "terms": { + "oracleNone": "uygulanamaz", + "int": "herhangi bir tam sayı", + "choice": "sabit bir kümeden biri", + "bool": "doğru veya yanlış", + "size": "2mb gibi bir boyut", + "text": "metin", + "pixels": "piksel", + "paragraphs": "paragraf", + "rows": "satır", + "columns": "sütun", + "slides": "slayt", + "hertz": "hertz", + "megapixels": "megapiksel", + "million cells": "milyon hücre", + "entries per second": "saniyedeki girdi", + "files": "dosya", + "sizes separated by commas": "virgülle ayrılmış boyutlar", + "format ids separated by commas": "virgülle ayrılmış biçim kimlikleri", + "format ids separated by commas, or all": "virgülle ayrılmış biçim kimlikleri veya all", + "extensions separated by commas": "virgülle ayrılmış uzantılar", + "the id of a format, as tfg formats lists them": "tfg formats'ın listelediği gibi bir biçimin kimliği", + "the password, in plain text": "parola, düz metin olarak", + "any text": "herhangi bir metin", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "2024-02-29 veya 2024-02-29T13:45:00+02:00 gibi bir tarih, veya none" + }, + "faq": [ + { + "q": "dd, fsutil veya truncate'ten farkı nedir?", + "a": "Onlar size doğru boyutta, içi bomboş bir dosya verir. Bu şekilde yapılmış photo.png adlı 2 MB'lık bir dosya PNG değildir, bu yüzden onu gerçekten ayrıştıran her şey yanlış nedenle reddeder ve testiniz de yanlış nedenle geçer. Bu araç tam 2 MB'lık gerçek bir PNG üretir, resim görüntüleyicide açılır ve sisteminizin onu nasıl ele alması gerektiğine dair bir bildirimle gelir.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Ücretsiz mi, ve işte kullanabilir miyim?", + "a": "İkisi de evet. GPL-3.0 altında yayımlanır ve hiçbir şeye mal olmaz. Hesap, lisans anahtarı veya ücretli katman yoktur." + }, + { + "q": "Üretilen dosyaları kapalı kaynaklı bir üründe kullanabilir miyim?", + "a": "Evet. Lisans aracın kodunu kapsar, aracın ürettiğini değil. Üretilen dosyalar, tarifler ve manifestler türev eser değil çıktıdır, bu yüzden hiçbir yükümlülük olmadan commit edip dağıtabilirsiniz." + }, + { + "q": "Üretilen dosyalar gerçek kişisel veri içeriyor mu?", + "a": "Hayır. İçindeki her şey bir seed'den sentezlenir. Hiçbir veri kümesi okunmaz, hiçbir servise bağlanılmaz ve üçüncü taraf içeriği gömülmez. Üretilmiş bir e-posta adresini kullanılmamış değil kullanılamaz sayın, çünkü rastgele bir dize tesadüfen gerçek biriyle çakışabilir." + }, + { + "q": "Başka bir makinede tam olarak aynı dosyaları alır mıyım?", + "a": "Evet, aynı tarif ve aynı seed ile bayt bayt. Proje bunu her değişiklikte test eder ve bozmak büyük sürüm artışı gerektirir. Büyük ikili fixture'lar yerine küçük bir tarifi commit etmenizi sağlayan da budur." + }, + { + "q": "İnternet bağlantısı gerekiyor mu?", + "a": "Asla. Telemetri, güncelleme denetimi veya bulut istemcisi yoktur ve komut satırı ikilisinin içine hiç ağ yığını derlenmemiştir. Ağı olmayan bir makinede ve kapalı bir kurumsal ortamda çalışır." + }, + { + "q": "Bir biçimin ulaşamayacağı bir boyut istersem ne olur?", + "a": "Biçimi, olabilecek en küçük boyutu, bu alt sınırın nedenini ve bunun yerine ne yapılacağını söyleyen bir hata alırsınız ve hiçbir dosya yazılmaz. Araç bir boyutu asla sessizce yuvarlamaz. Her alt sınır biçimler sayfasında listelenir.", + "code": "tfg formats png" + }, + { + "q": "Kasıtlı olarak bozuk bir dosya üretebilir miyim?", + "a": "Evet. --damage zero-head ekleyin, dosya tam istediğiniz boyutta ve ilk baytları sıfırlarla ezilmiş olarak çıkar. Böylece bir okuyucu onu reddeder ve bildirim sisteminizin onu reddetmesi gerektiğini söyler. Ayrıntılar bozuk test dosyaları sayfasındadır.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Sırada hangi biçimler var?", + "a": "7z, mp3 ve mp4. Bugün {{ .Facts.FormatCount }} biçim uçtan uca çalışıyor." + }, + { + "q": "Hangi sistemlerde çalıştırabilirim?", + "a": "Komut satırı Windows ve Linux'ta hem Intel hem ARM üzerinde, ayrıca Apple Silicon Mac'lerde çalışır. Masaüstü penceresi Intel üzerinde Windows, Intel üzerinde Linux ve Apple Silicon Mac'ler için sunulur. Intel Mac'ler desteklenmez ve onlar için hiçbir şey derlenmez." + }, + { + "q": "Bir şey kurmam gerekiyor mu?", + "a": "Hayır. Sisteminiz için arşivi indirin, açın ve ikiliyi çalıştırın. Yükleyici, eklenecek bir çalışma zamanı veya çözülecek bir bağımlılık yoktur. Go'nuz varsa tek bir go install komutu da işe yarar.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Binlerce dosya üzerindeki çalıştırma Windows'ta neden daha yavaş?", + "a": "Çünkü Windows baktığı her yol için daha fazla bedel ister ve binlerce dosyayı dolaşan bir komut binlerce yola bakar. Her biri 1 kB'lık 3000 dosyalı bir makinede ölçüldü: verify Windows'ta yaklaşık 0,9 saniye, bir konteynerdeki Linux'ta yaklaşık 0,2 saniye sürer. Daha kısa bir çıktı yolu Windows rakamını küçültür, çünkü dosyaların üstündeki her klasör bakılanın parçasıdır." + } + ] +} diff --git a/web/content/tr/use-cases.html b/web/content/tr/use-cases.html new file mode 100644 index 00000000..8ca45544 --- /dev/null +++ b/web/content/tr/use-cases.html @@ -0,0 +1,131 @@ +

İnsanlar bunu ne için kullanıyor

+

+ İnsanlardan dosya kabul eden hemen her projede çıkan beş iş ve her birini yapan komut. Aşağıdaki her + örnek yazıldığı gibi çalışır. +

+ +
+

Yükleme sınırları

+

Bir dosya boyutu sınırının söylediği yerde uygulanıp uygulanmadığını test etmek

+

+ Bir sınır bir değil üç test durumudur: hemen altı, tam üstü ve hemen üzeri. Bunları elle yapmak bayt + sayıları hesaplamak ve bir kayma yapmadığınızı ummak demektir. Bunun yerine seti isteyin: +

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

+ 1048575, 1048576 ve 1048577 baytlık üç gerçek PDF ve ilk ikisinin kabul edilmesi, üçüncünün + size_limit nedeniyle reddedilmesi gerektiğini söyleyen bir manifest alırsınız. + Testiniz üç assertion'ı elle yazmanız yerine beklentiyi okur - sınır değiştiğinde bir sayıyı + değiştirip yeniden çalıştırırsınız. +

+

+ Satır içi tek bir sınır seti istediğinizde aynısı hazır ayar olmadan da çalışır: +

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

Sürekli entegrasyon

+

Fixture'ları kaybetmeden depodan uzak tutmak

+

+ Büyük ikili fixture'lar bir depoyu klonlamada yavaş, incelemede zahmetli yapar ve biri + değiştirildiğinde neyin değiştiğini kimse söyleyemez. Tarif, özdeş dosyaları yeniden kuran + birkaç yüz karakterlik YAML'dir - bayt bayt, her makinede - çünkü her dosya + çalıştırmanın seed'inden türetilir. +

+
- 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
+

+ Her sonun kendi çıkış kodu vardır, bu yüzden bir hat kötü bir tarifi dolu bir diskten ve bir + doğrulama uyuşmazlığından ayırt edebilir. Başarısız bir çalıştırma standart çıktıya hiçbir şey + yazdırmaz, bu da bir günlük ayrıştırıcısının hatayı veri sanmasını önler. +

+
+ +
+

Ölçek

+

Klasör büyükken ne olduğunu öğrenmek

+

+ İçe aktarma rutinleri, gece işleri ve dizin listeleri on bin dosyada ona göre farklı davranır. Bir + aralıktan çekilen boyutlar seti on bin özdeş dosya yerine gerçek trafiğe benzetir ve çekiliş + seed'den gelir, yani set yarın da aynıdır. +

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

+ Toplam gigabayt cinsinden ölçülüyorsa önem kazanan şeyi, bir çalıştırmanın bir şey yazmadan önce + neye mal olacağını denetleyin: +

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

+ Diskteki boş alandan büyük bir çalıştırma, diski doldurup yarıda başarısız olmak yerine ilk bayt + yazılmadan önce reddedilir. +

+
+ +
+

Arşivler

+

Bir açıcıyı gerçekten dosya içeren bir arşivle test etmek

+

+ Doğru uzantılı boş bir arşiv, onu açıp içindekini dolaşan kod hakkında hiçbir şey kanıtlamaz. + İçeriği bildirin, arşiv onu gerçekten içersin: +

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

+ İç içe geçme derinliği, girdi sayıları ve içindekilerin boyutu, bir içe aktarma rutininin görüş + sahibi olduğu şeylerdir ve bu görüşlerin ne olduğunu böyle öğrenirsiniz. +

+
+ +
+

Ayrıştırıcılar ve görüntüleyiciler

+

Kendi kodunuzun bir biçimi gerçek yazılım gibi okuduğunu denetlemek

+

+ Buradaki her biçim yayımlanmadan önce bağımsız bir okuyucuyla doğrulanır - bir PNG açılır ve + pikselleri karşılaştırılır, bir DOCX ayrı kitaplıklarca geri okunur, bir arşiv çıkarılır. Bu, + ayrıştırıcınızın reddettiği bir dosyanın üretici hakkında değil ayrıştırıcınız hakkında bir + bulgu olduğu anlamına gelir. +

+
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
+

+ Biçimler sayfası her birinin kabul ettiği ayarları ve her birinin + olabileceği en küçük dosyayı listeler. +

+
+ +
+

Rehberler

+

Bunlardan ikisi daha ayrıntılı

+ +
+ +
+

Kimler için

+

+ QA mühendisleri, test otomasyonu ve kodunun arkasında bir yükleme formu, içe aktarma rutini, + ayrıştırıcı veya depolama kotası olan herkes. Hiç ağı olmayan bir makinede çalışır, bu da + tarayıcı tabanlı bir üreticinin seçenek olmadığı kapalı bir kurumsal ortamda önem taşır. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/uk/ci.html b/web/content/uk/ci.html new file mode 100644 index 00000000..55b6b25d --- /dev/null +++ b/web/content/uk/ci.html @@ -0,0 +1,190 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Як генерувати тестові файли в конвеєрі CI

+

+ Двійкова фікстура в репозиторії лишається в його історії назавжди, її не можна перевірити в діфі, і + вона перестає бути можливою, коли файл великий. Генеруйте файли всередині конвеєра з рецепта. + Рецепт - це текст, байти щоразу виходять однакові, а останній крок доводить, що нічого не + зсунулося. +

+ +
+

Коротка відповідь

+

+ Установіть tfg, запустіть tfg generate fixtures.yaml --out ./fixtures + перед тестами і tfg verify ./fixtures/manifest.json після них. Обидва кроки самі + валять збірку, з кодом завершення, який каже чому. +

+
+ +
+

Чому не комітити

+

Чому фікстурі не місце в репозиторії

+ +

+ Комітити потрібно рецепт. Той самий рецепт із тим самим зерном записує ті самі байти на будь-якій + машині, тож файл, створений у конвеєрі, - це файл, який був у вас на ноутбуці. +

+
+ +
+

Рецепт

+

Рецепт, що лежить поруч із тестами

+

+ Цей записує двадцять п'ять рахунків, які мають бути прийняті, і два зображення понад ліміт, які + мають бути відхилені, а маніфест фіксує обидва очікування: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml перевіряє його, нічого не записуючи, і називає одразу всі + проблеми. +

+
+ +
+

GitHub Actions

+

Workflow, що встановлює інструмент і збирає фікстури

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Рядок із контрольною сумою звіряє архів із verify-SHA256SUMS.txt з того самого випуску. + Версію закріплено, тож новий випуск ніколи не змінить збірку, якої ви не торкалися. +

+
+ +
+

GitLab CI

+

Те саме як завдання GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Коли стає червоно

+

Що валить крок і чому

+

+ У кожного завершення свій код, тож крок падає сам, а журнал каже, який саме. Ті, що трапляються + конвеєру: +

+ +

+ Невдалий запуск нічого не друкує у стандартний вивід, тож розбирач журналів ніколи не сприйме + помилку за дані. Уся таблиця на сторінці документації. +

+
+ +
+

PowerShell

+

Скрипту PowerShell потрібен ще один рядок

+

+ PowerShell не виносить код завершення програми з файлу .ps1. Запустіть такий файл із + -File, і скрипт відповість 0, навіть коли інструмент усередині + відмовився працювати, тож збірка, яка мала б бути червоною, стає зеленою. Останній рядок - це + все виправлення: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Так поводиться PowerShell, а не цей інструмент. cmd, bash і + zsh нічого зайвого не потребують. +

+
+ +
+

Кілька завдань

+

Як ділитися фікстурами між завданнями

+

+ Зазвичай завантажувати їх не треба. Оскільки той самий рецепт записує ті самі байти, кожне завдання + може запустити власний tfg generate, що швидше за завантаження й скачування. Коли + завдання має отримати файли від іншого, запустіть після передачі tfg verify на + маніфесті, і він скаже, чи збігається отримане із записаним. +

+
+ +
+

Далі

+

Куди йти звідси

+ +
diff --git a/web/content/uk/damage.html b/web/content/uk/damage.html new file mode 100644 index 00000000..907a4b0c --- /dev/null +++ b/web/content/uk/damage.html @@ -0,0 +1,175 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Як зробити пошкоджений файл для тестів

+

+ Валідатор, якому показували лише здорові файли, насправді не перевірений. Ось як отримати файл, + навмисно зіпсований, що виходить точно такого розміру, який ви просите, і несе + маніфест із вказівкою, що ваша система має з ним зробити. +

+ +
+

Коротка відповідь

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out записує PNG рівно в + 2097152 байти, перші байти якого нулі, а маніфест поруч фіксує, що ваша система має його + відхилити. +

+
+ +
+

Звичайний шлях

+

Чому файл, зіпсований вручну, - поганий тест

+

+ Зазвичай беруть шістнадцятковий редактор, скрипт, що перевертає кілька випадкових байтів, або + вкорочують файл через head чи truncate. Один раз це працює, а потім + коштує дорого: +

+ +
+ +
+

Що ви отримуєте

+

Пошкоджений файл лишається потрібного розміру

+

+ Файл створюється як зазвичай і псується потім, дорогою на диск. Він зберігає заданий розмір, а та + сама команда знову записує ті самі байти. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Налаштування пишуться після двокрапки. Параметр можна повторювати, а пошкодження застосовуються в + тому порядку, в якому ви їх записали. Це працює з кожним із {{ .Facts.FormatCount }} форматів. +

+
+ +
+

Що він уміє

+

Які бувають пошкодження?

+

+ Це список, який друкує програма, прочитаний із неї під час збирання цієї сторінки. tfg + damage друкує той самий список, а tfg damage <id> каже, що приймає + одне з них. +

+ {{ template "damagesTable" . }} +

+ zero-head записує нулі поверх початку файлу. Більшість програм читання дивляться + спочатку туди, на сигнатуру й заголовок, які кажуть, що це за файл, тому помічає майже будь-яка. + У простого тексту та журналів сигнатури немає, і їх теж відхиляють, бо послідовність нульових + байтів не є текстом. Менше ніж чотири байти - і в деяких форматів виходить пошкодження, на яке + не скаржиться жодна програма читання, тому налаштування починається з чотирьох. +

+
+ +
+

Що каже маніфест

+

Маніфест, який каже, що має статися

+

+ Кожен пошкоджений файл отримує запис про те, що ваша система має його відхилити, а поруч записано + пошкодження: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Два запити відхиляються, перш ніж щось буде записано, бо кожен залишив би на диску файл, який + маніфест описує хибно: +

+ +
+ +
+

У рецепті

+

Здорові й зламані файли за один запуск

+

+ Покладіть обидва види в один рецепт, і маніфест несе очікування для кожного файлу, тож тесту не + потрібен список, який файл який: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

У тесті

+

Перетворюємо це на тест

+

+ Тест читає маніфест і перевіряє, що сталося те, що було заявлено. Список імен файлів йому не + потрібен: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Гарна відмова - це чиста відмова. Повідомлення, що каже, що було не так, - та відповідь, яка вам + потрібна. Помилка сервера, зависання або наполовину збережений файл - той дефект, заради якого + цей тест і існує. +

+
+ +
+

Далі

+

Куди йти звідси

+ +
diff --git a/web/content/uk/docs.html b/web/content/uk/docs.html new file mode 100644 index 00000000..f4ca7b7b --- /dev/null +++ b/web/content/uk/docs.html @@ -0,0 +1,280 @@ +

Документація

+

+ Усе, що робить інструмент, розкладено за питаннями, з якими люди справді приходять. + README у репозиторії - повний довідник, і він завжди відповідає + завантаженій вами збірці. +

+ +
+

Які є команди?

+

Кожна робить одну справу:

+ {{ template "commandList" . }} +
+ +
+

Як створити один файл точного розміру?

+

+ Укажіть формат, розмір і місце призначення. Розміри рахуються по 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. Вибір іде від seed
--boundary <size>три файли навколо ліміту: на байт менше, сам ліміт, на байт більше
--count <n>скільки файлів створити. За замовчуванням 1
--name <template>шаблон імені, наприклад invoice_{index:04}.txt
--out <dir>каталог, у який записувати
--seed <n>seed запуску. Той самий seed дає ті самі байти
--set <k>=<v>налаштування формату, можна повторювати
--damage <name>навмисно зіпсувати файли, можна повторювати, застосовується по порядку. Список виводить tfg damage
--expected <outcome>accept, reject, sanitize або unspecified
--dry-runпорахувати й показати, нічого не записуючи
--jsonзаписати маніфест у стандартний вивід
+
+
+ +
+

Як зробити навмисно зламаний файл?

+

+ Будь-який інший файл, що його записує цей інструмент, коректний за побудовою, і це відповідає на два + з трьох питань, які ставить перевірка завантаження. --damage відповідає на третє - + чи відкривається файл узагалі. Файл створюється як зазвичай, а потім псується, тому в нього + лишається запитаний розмір. +

+
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 із записаним поруч пошкодженням. + Дві речі відхиляються до запису чого-небудь, бо кожна залишила б на диску файл, неправильно + описаний маніфестом: +

+ +

+ Третє наперед дізнатися не можна. Якщо пошкодження виконується й не змінює жодного байта, такий файл + відкидається, а не записується - запуск триває, повідомляє, що це був за файл, і завершується + кодом часткового завершення. +

+

+ Крок за кроком, з тестом, який читає маніфест: як зробити + пошкоджений файл для тестів. +

+
+ +
+

Як виглядає рецепт?

+

+ Рецепт - це файл 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. Два - це помилка, і жодного - теж. Недійсний + рецепт записує жодного файлу і повідомляє про всі проблеми одразу, а не лише + про першу, щоразу називаючи налаштування, якого вона стосується. +

+
+ +
+

Як оголосити, що моя система має робити з файлом?

+

Коротка форма, коли досить результату, і довга, коли важлива причина:

+
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. +

+

+ Причина називає чинне правило, а не вердикт. Тому та сама причина може стояти під + будь-яким результатом - файл на байт менший за ліміт отримує accept, а правило, про + яке йдеться, усе одно size_limit. +

+
+ +
+

Що в маніфесті?

+

+ Він записується поряд із файлами наприкінці кожного запуску, зокрема й перерваного. Один запис на + файл: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 - якщо за пресетом, тож маніфест завжди можна простежити до того, що його + створило. +

+

+ Кожен запис також містить target_id - id цілі рецепта, що створила файл, а + summary.by_target рахує файли кожної цілі. Рецепт із кількома цілями можна тому + перевірити ціль за ціллю, не читаючи імена файлів. +

+
+ +
+

Що таке пресет?

+

+ Готовий набір файлів, що відповідає на поширене тестове питання, щоб вам не доводилося проєктувати + набір самостійно. Пресети - звичайні рецепти всередині, а eject виводить рецепт, + щоб ви могли його відредагувати. Кожен пресет має окрему сторінку про + те, що він зазвичай знаходить, що входить у набір і які налаштування приймає. +

+ {{ template "presetsList" . }} +
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 повідомляє, скільки коштував би набір, перш ніж ви його зберете, і прямо каже, + коли число - наша тимчасова підстановка, а не ваш ліміт. +

+
+ +
+

Що означають коди завершення?

+

+ Кожен кінець має власний код, машиночитний вивід іде в стандартний вивід, а невдалий запуск нічого + туди не друкує. Таблиця - заморожений контракт: зміна значення коду вимагає підвищення мажорної + версії. +

+ {{ template "exitCodesTable" . }} +
- 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, усе одно залишає маніфест і ніколи не залишає наполовину + записаного файлу, тож скасоване завдання може бути прибране наступним. +

+

+ Готові workflow для GitHub Actions і GitLab CI: як генерувати + тестові файли в конвеєрі CI. +

+
+ +
+

Чи є десктопне вікно?

+

+ Так, той самий рушій із вікном згори, для тестування, яке не автоматизується. Це не урізана версія: + тест порівнює два інтерфейси можливість за можливістю, і все, що вміє лише один із них, має бути + оголошене й обґрунтоване, а не тихо розходитися. +

+

+ Екрани: одна партія, пресети, кілька партій одночасно та про програму. Вікно показує, скільки + коштував би запуск, перш ніж щось записати, відображає перебіг роботи й може бути скасоване на + півдорозі без наполовину записаного файлу. Файл рецепта воно поки не відкриває - рецепти поки + справа командного рядка, а вікно збирає свої партії у формі. +

+
diff --git a/web/content/uk/exact-size.html b/web/content/uk/exact-size.html new file mode 100644 index 00000000..aaba5286 --- /dev/null +++ b/web/content/uk/exact-size.html @@ -0,0 +1,146 @@ +

Як створити файл точного розміру

+

+ У кожній системі для цього є команда, і всі три наведено нижче. Вони дають файл із точною кількістю + байтів, а для багатьох тестів цього досить. Кожну команду на цій сторінці було виконано до + публікації у тій системі, до якої вона належить. +

+ +
+

Коротка відповідь

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Розміри вказуються в байтах, а 10 + МБ, пораховані так, як рахує ваш файловий менеджер, - це 10485760. +

+
+ +
+

Windows

+

fsutil і варіант на PowerShell, якому не потрібно нічого додаткового

+

+ fsutil входить до Windows. Він приймає розмір у байтах, тому спершу + порахуйте число: 10 МБ - це 10485760, 100 МБ - 104857600, 1 ГБ - 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Виміряно у Windows 11: працює зі звичайного командного рядка без підвищених прав, і файл виходить + рівно в 10485760 байт. +

+

PowerShell може зробити те саме, не викликаючи іншу програму, і розуміє одиниці:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB у PowerShell означає 10485760 байт, той самий рахунок за основою 1024, що його + використовує Провідник, тому дві команди вище дають той самий розмір. +

+
+ +
+

Linux

+

dd, truncate і fallocate, і різниця, що ловить людей

+

dd знають усі. Він справді записує байти:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate спрацьовує миттєво, і в цьому підступ. Виміряно в Alpine Linux: файл + повідомляє 10485760 байт і займає нуль блоків - це розріджений + файл. Усе, що його читає, отримує десять мегабайт нулів, але диск місця так і не + віддав: +

+
truncate -s 10M test10mb.bin
+

+ Для перевірки ліміту завантаження це нормально, а для перевірки дискової квоти вводить в оману. + fallocate - те, до чого варто вдатися, коли місце має бути справжнім: +

+
fallocate -l 10M test10mb.bin
+

А коли вміст має бути нестисливим, щоб архіватор не міг знову його стиснути:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, що не є розрідженим, і дві команди, які ви вже знаєте

+

+ У macOS є mkfile. Виміряно в macOS 26.6.2: 10485760 байт і 20480 блоків, тобто місце + справді виділено, а не обіцяно: +

+
mkfile 10m test10mb.bin
+

dd і truncate теж є й поводяться як у Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Де це перестає працювати

+

Файл правильного розміру - не файл правильного виду

+

+ Усе сказане вище дає блок нулів. Цього досить, коли тестоване дивиться лише на розмір: ліміт + завантаження, квота, передача. Цього перестає вистачати, щойно щось відкриває + файл. +

+

+ Виміряно, і варто перевірити самому: зробіть файл на 2 МБ командою fsutil, назвіть його + photo.png і передайте бібліотеці роботи із зображеннями. Pillow відповість + cannot identify image file. Це не PNG. Він ним ніколи й не був, так казало лише + ім'я. +

+

+ Це важливіше, ніж здається, через те, в який бік тест тоді провалюється. Ваша точка + завантаження відхиляє файл, ваш тест зеленіє, і ви робите висновок, що ліміт розміру працює. + Вона відхилила його не через розмір. Вона відхилила його тому, що байти не були зображенням, і + правило, яке ви хотіли перевірити, так і не було досягнуте. +

+ +
+ +
+

Інший шлях

+

Справжній файл цього формату точно того розміру, який ви запросили

+

+ Саме це робить Testing Files Generator. Файл - справжній файл свого формату, він відкривається у + своїй програмі, і в ньому рівно стільки байтів, скільки ви запросили, з точністю до байта: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Запросіть розмір, якого формат не може досягти, і ви отримаєте помилку з назвою мінімуму та + причиною, а не файл неправильного розміру. Сторінка форматів + перелічує кожен формат з найменшим файлом, який він може створити. +

+

А ліміт - це три тестові випадки, а не один, тому інструмент збирає всі три:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Ви отримаєте 10485759, 10485760 і 10485761 байт та маніфест, що каже, які з них ваша система має + прийняти, а які відхилити. Сторінка сценаріїв розбирає це та ще + чотири завдання, для яких інструмент створений. +

+ {{ template "downloadCta" . }} +
+ +
+

Тож що використовувати?

+ +

+ Обидві є на цій сторінці, бо обидві бувають слушними. Помилка, якої слід уникати, - використати + першу там, де потрібна друга, і сприйняти зелений тест за доказ. +

+
diff --git a/web/content/uk/faq.html b/web/content/uk/faq.html new file mode 100644 index 00000000..4cfe81f6 --- /dev/null +++ b/web/content/uk/faq.html @@ -0,0 +1,19 @@ +

Часті запитання

+

+ Ліцензія, приватність, відтворюваність і те, що люди перевіряють, перш ніж додавати генератор до + конвеєра збірки. Якщо вашого питання тут немає, трекер задач + відкритий. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Усе ще вирішуєте?

+

+ Сторінка сценаріїв показує завдання, для яких інструмент створений, а + сторінка форматів перелічує кожен формат з найменшим файлом, який він + може створити. README у репозиторії - повний довідник. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/uk/formats.html b/web/content/uk/formats.html new file mode 100644 index 00000000..ea77ed4b --- /dev/null +++ b/web/content/uk/formats.html @@ -0,0 +1,79 @@ +

{{ .Facts.FormatCount }} форматів файлів, кожен створюється точного розміру

+

+ Кожен із них - справжній файл цього формату. Він відкривається у своїй програмі та + має рівно стільки байтів, скільки ви запросили. Жоден не є нулями-заповнювачами з приклеєним + розширенням. +

+ +{{ template "formatsTable" . }} + +
+

Що означають стовпці

+ +

+ Кожен формат до того ж повторюється до байта: той самий рецепт і той самий seed дають однакові файли + на будь-якій машині, і саме це робить безпечним коміт рецепта замість самих фікстур. +

+
+ +
+

Налаштування, які приймає кожен формат

+

+ Більшість форматів мають власні налаштування - розміри зображення, якість JPEG, кількість сторінок + PDF, рядки й стовпці в таблиці, скільки записів входить в архів. Задайте їх через --set + key=value у командному рядку або в розділі properties: рецепта. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Значення поза допустимим для налаштування відхиляється повідомленням із назвою налаштування, + допустимим діапазоном і тим, що використати натомість. Невідоме налаштування теж помилка, а не + мовчазне значення за замовчуванням - друкарська помилка, прийнята мовчки, дає файл із хибними + налаштуваннями та годину роздумів, чому тест проходить, хоча не мав би. +

+

+ Виконайте tfg formats <id>, щоб побачити, що саме приймає один формат у вашій + збірці. +

+
+ +
+

Архіви містять справжні файли

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} і {{ end }}{{ $c.ID }}{{ end }} + можна наповнити записами, а не лишати порожньою оболонкою. Створений архів справді містить + документи, які заявляє, тому все, що розпаковує його під час тесту, знаходить усередині справжні + файли. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/uk/index.html b/web/content/uk/index.html new file mode 100644 index 00000000..0c7bc7c7 --- /dev/null +++ b/web/content/uk/index.html @@ -0,0 +1,196 @@ +
+
+

Створюйте справжні тестові файли точного розміру

+

+ PDF, PNG, DOCX, ZIP - усього {{ .Facts.FormatCount }} форматів, і кожен із них - + справжній файл, що відкривається у своїй програмі, точно того розміру, який ви + запросили. Кожен запуск ще й записує, що ваш застосунок має робити з кожним файлом. + Командний рядок і десктопне вікно, безкоштовно та з відкритим кодом, усе працює на вашій машині. +

+ + {{ template "downloadCta" . }} +
+ +
+ Десктопне вікно Testing Files Generator, підготовлене до запису партії тестових файлів +
Десктопне вікно, підготовлене до запису партії файлів. За командним рядком працює той самий рушій.
+
+
+ + + +
+

Проблема

+

Зробити один тестовий файл легко. Зробити потрібну тисячу - ось виснажлива частина

+

Ви тестуєте програму, що приймає файли від людей. Рано чи пізно вам знадобляться:

+ +

+ Саме це він замінює. Він створений для QA-інженерів, автоматизації тестування та всіх, за чиїм кодом + стоїть форма завантаження, процедура імпорту, парсер чи квота сховища. +

+
+ +
+

Чим він відрізняється

+

Інші генератори зупиняються на байтах. Цей відповідає на те, про що насправді питає ваш тест

+

+ Тека з файлами все одно залишає вам вирішувати, що має доводити кожен із них. Кожен запуск тут + записує поряд із файлами manifest.json - простий перелік усього створеного та для + кожного запису заявлене очікування. +

+

Припустімо, ваша точка завантаження допускає 1 МБ. Запросіть три файли, що лежать на цій межі:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ФайлБайтівВаша система маєТому що
1mb_under_1b.pdf1048575прийнятивін у межах ліміту
1mb_at_limit.pdf1048576прийнятисам ліміт дозволений
1mb_over_1b.pdf1048577відхилитиsize_limit
+
+ +

Три файли, три різні відповіді, у машиночитному вигляді. Ваш тест читає маніфест замість того, щоб ви писали перевірки вручну:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Там, де відповідь залежить від вашої власної політики, маніфест так і каже

+

+ Він записує unspecified, а не вигадує очікування. Генератор, що вгадує, дає хибні збої, + а набір тестів, що кричить «вовки», зрештою вимикають. +

+
+
+ +
+

Пресети

+

Виберіть питання, отримайте весь набір

+

+ Пресет - це набір тестових файлів, продуманий навколо одного тестового питання, щоб вам не довелося + з'ясовувати, які файли що доводять. Кожен має сторінку про те, що він зазвичай знаходить, що + входить у набір і які налаштування приймає. +

+ {{ template "presetsList" . }} +

Усі пресети та як вони пов'язані з рецептами

+
+ +
+

Швидкий старт

+

Три команди, щоб побачити роботу

+
    +
  1. +

    Створіть файл

    +

    Один PNG, рівно два мегабайти:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Створіть багато файлів

    +

    + Десять тисяч файлів журналу, кожен від одного до восьми кілобайтів, з розмірами з seed, щоб завтра + вийшов той самий набір. Давайте кожному запуску власний каталог - маніфест + лишається єдиним записом про те, що записав запуск, тому інструмент відмовляється записувати + другий поверх нього: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Перевірте їх, потім видаліть

    +

    verify повідомляє, що нічого не зсунулося. cleanup видаляє рівно те, що було записано, і нічого більше:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Розміри рахуються по 1024, як у вашому файловому менеджері, тому 2mb означає 2097152 + байти. Підійде й просте число байтів. Документація охоплює рецепти, + маніфест і коди завершення. +

+
+ +
+

Що ви отримуєте

+

Створений для набору тестів, що працює без нагляду

+ +
+ +
+

Завантаження

+

Виберіть збірку для вашої системи

+

+ Розпакуйте архів і запустіть. tfg - це командний рядок, а tfg-gui - + десктопне вікно. Немає інсталятора й нічого, що треба додавати на вашу машину. +

+ {{ template "downloadsTable" . }} +
+

Що підписано, а що ні

+

+ Збірки для Windows і macOS підписані, тому запускаються без попередження про невідомого розробника. + Збірки для Linux не підписані, бо в десктопного Linux немає еквівалента, яким їх можна + підписати. Кожен архів указано в verify-SHA256SUMS.txt на сторінці релізу, тож ви + можете перевірити, що завантажили. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/uk/preset.html b/web/content/uk/preset.html new file mode 100644 index 00000000..add24d6c --- /dev/null +++ b/web/content/uk/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Пресет {{ .ID }} однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ +{{ if .Catches }} +
+

Що він зазвичай знаходить?

+ +
+{{ end }} + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show {{ .ID }}:

+
+ + + + + + + +
Файлів{{ .Budget.Files }}
Цілей у його рецепті{{ .Budget.Targets }}
Загальний розмір{{ .Bytes }} B
Формати{{ join .Budget.Formats ", " }}
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
ОчікуєтьсяЗначенняФайлів
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Що можна змінити?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Це значення за замовчуванням - наша тимчасова підстановка, а не значення вашої системи. Передайте своє.{{ end }}
+
+ {{- else }} +

Цей пресет не має налаштувань. Набір щоразу однаковий.

+ {{- end }} +
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/uk/presets.html b/web/content/uk/presets.html new file mode 100644 index 00000000..d34cc763 --- /dev/null +++ b/web/content/uk/presets.html @@ -0,0 +1,32 @@ +

Пресети тестових файлів, по набору на кожне тестове питання

+

+ Пресет - це цілий набір тестових файлів, продуманий навколо одного питання, з маніфестом про + очікувану реакцію вашої системи на кожен файл. Ви вибираєте питання, інструмент збирає набір. + Кожен пресет має власну сторінку про те, що він зазвичай знаходить, що входить у набір і які + налаштування приймає. +

+ +{{ template "presetsList" . }} + +
+

Чим пресет відрізняється від рецепта?

+

+ По суті нічим. Пресет - це рецепт, який інструмент пише для вас із кількох налаштувань. tfg + preset eject виводить цей рецепт, щоб ви могли зберігати його поряд із тестами й + редагувати, а ваш власний рецепт може спиратися на пресет одним рядком: extends: + preset: і його id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Чи можна довіряти значенням за замовчуванням?

+

+ Для файлів - так. Для числа, яке знає лише ваша система, як-от ліміту форми завантаження, значення + за замовчуванням - наша тимчасова підстановка, і інструмент каже про це щоразу, коли її + використовує. Сторінка кожного пресета позначає такі налаштування, а tfg preset + show повідомляє про це до запису чого-небудь. +

+
diff --git a/web/content/uk/site.json b/web/content/uk/site.json new file mode 100644 index 00000000..b3752144 --- /dev/null +++ b/web/content/uk/site.json @@ -0,0 +1,328 @@ +{ + "code": "uk", + "locale": "uk_UA", + "name": "Українська", + "dir": "uk", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Головна", + "title": "Генератор тестових файлів для QA - точний розмір, {{ .Facts.FormatCount }} форматів", + "description": "Безкоштовний генератор тестових файлів для QA з відкритим кодом. Справжні PDF, DOCX, PNG і ZIP точного розміру та маніфест з очікуваною реакцією вашої системи." + }, + { + "key": "formats", + "slug": "formats", + "nav": "Формати", + "title": "{{ .Facts.FormatCount }} форматів файлів - PDF, DOCX, PNG, ZIP та інші", + "description": "Усі формати, які створює генератор, найменший можливий файл кожного та допустимі налаштування. Усі {{ .Facts.FormatCount }} відкриваються у своїх програмах." + }, + { + "key": "presets", + "slug": "presets", + "nav": "Пресети", + "title": "Пресети тестових файлів - готові набори для QA", + "description": "Готові набори тестових файлів, кожен відповідає на одне питання: ліміти завантаження, імена файлів, кодування, імпорт таблиць, порожні файли та перевірка завантаження." + }, + { + "key": "docs", + "slug": "docs", + "nav": "Документація", + "title": "Документація - команди, рецепти, маніфест, коди завершення", + "description": "Як створювати тестові файли з командного рядка чи рецепта YAML, що містить маніфест і що означає кожен код завершення під час запуску в CI." + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "Сценарії", + "title": "Сценарії - ліміти завантаження, фікстури для CI, масові тести", + "description": "Перевірка ліміту розміру завантаження, відтворювані фікстури для CI, десять тисяч файлів за один запуск і архіви зі справжнім вмістом." + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "Точний розмір", + "title": "Як створити файл точного розміру - Windows, Linux, macOS", + "description": "fsutil, dd, truncate і mkfile, кожну команду виміряно у своїй системі, і чому такий файл не є PDF чи PNG, коли тесту потрібен справжній." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - питання про створення тестових файлів", + "description": "Чим це відрізняється від dd і fsutil, чи можна комітити файли, чи повторюються запуски байт у байт і що буде, якщо розмір недосяжний." + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "Пошкоджені файли", + "title": "Пошкоджені тестові файли - зламані файли точного розміру", + "description": "Навмисно зіпсований файл точного розміру з маніфестом, який каже, що ваша система має його відхилити. Для перевірки валідації завантаження та парсерів.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "Тестові файли в CI", + "title": "Тестові файли в CI - GitHub Actions, GitLab CI і PowerShell", + "description": "Генеруйте тестові файли в конвеєрі, а не комітьте бінарники: workflow GitHub Actions, завдання GitLab, коди завершення та пастка PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Перейти до вмісту", + "navLabel": "Основне", + "langLabel": "Мова", + "breadcrumbHome": "Головна", + "imageAlt": "Testing Files Generator - справжні тестові файли точного розміру та маніфест з очікуваною реакцією вашої системи на кожен із них", + "schemaDescription": "Безкоштовний генератор тестових файлів для QA з відкритим кодом. Створює справжні файли у {{ .Facts.FormatCount }} форматах точного розміру й записує маніфест з очікуваною реакцією тестованої системи на кожен із них.", + "ctaDownload": "Завантажити", + "ctaSource": "Вихідний код", + "ctaNote": "Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.", + "colFormat": "Формат", + "colName": "Назва", + "colExtension": "Розширення", + "colSmallest": "Найменший файл", + "colFidelity": "Повнота", + "colChecked": "Перевіряється за допомогою", + "colSetting": "Налаштування", + "colAccepts": "Допускає", + "colSystem": "Система", + "colCli": "Командний рядок", + "colWindow": "Десктопне вікно", + "noBinary": "поки без збірки", + "colCode": "Код", + "colMeaning": "Значення", + "footerBlurb": "Тестові файли для QA точного розміру та маніфест з очікуваною реакцією вашої системи на кожен із них.", + "footerProject": "Проєкт", + "footerSource": "Вихідний код на GitHub", + "footerReleases": "Завантаження", + "footerIssues": "Повідомити про проблему", + "footerSupport": "Підтримати проєкт", + "footerPages": "Сторінки", + "footerLicence": "Copyright (C) 2026 DonislawDev. Поширюється за ліцензією GNU General Public License версії 3. Файли, які ви створюєте, належать вам - ліцензія охоплює інструмент, а не його результат.", + "footerPrivacy": "Цей сайт не завантажує шрифти, скрипти чи трекери звідки б то не було. Він не встановлює куки.", + "notFoundTitle": "Такої сторінки немає", + "notFoundLead": "Адреса, за якою ви перейшли, не відповідає жодній сторінці цього сайту.", + "notFoundBack": "На головну", + "read.format": "Формат кожного файлу набору. Це прапорець самого інструмента, а пресет лише задає йому значення за замовчуванням.", + "readTakes.format": "id формату зі сторінки форматів", + "colDamage": "Пошкодження", + "colEffect": "Що воно робить із байтами", + "colSettings": "Налаштування", + "noSettings": "немає" + }, + "endings": { + "0": "Усе спрацювало.", + "1": "Непередбачена помилка всередині інструмента.", + "2": "Неправильна команда або прапорець.", + "3": "Рецепт недійсний.", + "4": "Формат не може зробити те, що просили.", + "5": "Не вдалося прочитати або записати.", + "6": "Недостатньо місця на диску.", + "7": "verify виявив розбіжність.", + "8": "Запуск завершено, але створено не все.", + "130": "Перервано за допомогою Ctrl+C.", + "143": "Зупинено сигналом, так виглядає тайм-аут у CI." + }, + "presets": { + "empty-and-minimal": { + "question": "Чи пройде коректний файл, настільки малий, наскільки дозволяє формат?", + "title": "Порожні та мінімальні", + "pageTitle": "Мінімальні коректні та порожні тестові файли в кожному форматі", + "description": "Найменший коректний файл, який інструмент записує в кожному з {{ .Facts.FormatCount }} форматів, і порожній файл там, де формат це допускає, з очікуваною реакцією для кожного.", + "catches": [ + "коректний файл, відхилений як надто малий, бо перевірка рахує байти, а не читає їх", + "порожній файл, який валить читальний код замість того, щоб бути поміченим", + "картинка завширшки один піксель, яка ділить на нуль дорогою до мініатюри", + "сховище, яке сприймає нуль байтів як невдале завантаження й безкінечно повторює спроби" + ], + "details": { + "formats": "З яких форматів складається набір. Залиште all для всіх форматів цієї збірки або перелічіть ті, які приймає ваша система." + } + }, + "filename-handling": { + "question": "Чи збереже, покаже та поверне моя система ім'я файлу, якого не очікувала?", + "title": "Обробка імен файлів", + "pageTitle": "Проблемні імена файлів для тестів - Unicode і довжина", + "description": "Файли з іменами, що ламають завантаження та зберігання: інші писемності й емодзі, зміна напряму письма, невидимі символи, синтаксис shell і SQL, ліміти довжини.", + "catches": [ + "ім'я, що на екрані, в журналі чи в списку виглядає як інше", + "ім'я, обрізане, скорочене або переписане між завантаженням і зберіганням", + "ліміт довжини, що рахується в символах там, де сховище рахує байти" + ], + "details": {} + }, + "size-boundaries": { + "question": "Чи застосовується ліміт розміру саме там, де його оголошено?", + "title": "Межі розміру", + "pageTitle": "Перевірка ліміту розміру завантаження - файли на самій межі", + "description": "Файли на байт менші, рівно за лімітом і на байт більші за ліміт вашої системи, плюс ширші кроки в обидва боки, з позначкою, чи треба приймати кожен.", + "catches": [ + "помилки на одиницю на межі ліміту", + "МБ, сплутані з МіБ, тобто 4,8 відсотка, чого досить, щоб пропустити файл, який не мав би пройти", + "ліміт, що застосовується в браузері, а не на сервері" + ], + "details": { + "limit": "Ліміт розміру, який оголошує ваша система. Усе інше відмірюється від нього.", + "spread": "Як далеко відходити від ліміту в обидва боки, списком розмірів." + } + }, + "tabular-import": { + "question": "Чи переживе мій імпорт таблиць те, що експортують справжні інструменти?", + "title": "Імпорт таблиць", + "pageTitle": "Тестові файли для імпорту CSV та Excel - роздільники й заголовки", + "description": "CSV з іншими роздільниками, кінцями рядків CR LF, без заголовка й з іншими лапками, дуже широка таблиця, книга Excel та JSON у кількох виглядах.", + "catches": [ + "файл із крапкою з комою, прочитаний як один стовпець, бо роздільник припустили, а не шукали", + "файл CRLF, розбитий на рядки з порожнім рядком після кожного", + "таблиця без заголовка, перший рядок даних якої з'їдається як імена стовпців", + "імпорт, що залишає стовпці, які може показати, і мовчки відкидає решту", + "читач, що бере записи JSON по одному рядку й зупиняється на першому документі з відступами" + ], + "details": { + "rows": "Скільки рядків у таблиці. Файл записується рівно того розміру, у який пакується стільки рядків, тому бюджет вище змінюється разом із цим значенням.", + "columns": "Скільки стовпців у кожному рядку таблиці. Добуток рядків на стовпці має стелю, і запит понад неї відхиляється до запису чого-небудь." + } + }, + "text-encoding": { + "question": "Чи знає мій читач, у якому кодуванні файл, чи вгадує?", + "title": "Кодування тексту", + "pageTitle": "Тестові файли кодування тексту - UTF-8, UTF-16, BOM, CRLF", + "description": "Той самий текст в UTF-8, UTF-16LE та UTF-16BE, з позначкою порядку байтів і без неї, та кінці рядків CR LF і LF, щоб перевірити, як читач декодує текст.", + "catches": [ + "читач, що припускає UTF-8 і показує файл UTF-16 з одним символом із трьох або рядами квадратиків", + "позначка порядку байтів, прочитана як вміст, через що перше поле імпорту починається з трьох зайвих символів", + "імпортер, що вгадує кодування за першими байтами й вгадує інакше для довшого файлу", + "файл CRLF, розбитий на рядки з порожнім рядком після кожного, або повернення каретки, що залишилося в останньому полі" + ], + "details": { + "sample": "Розмір кожного файлу набору. UTF-16 зберігає по два байти на символ, тому непарне число відхиляється." + } + }, + "upload-validation": { + "question": "Чи приймає моя форма завантаження те, що має, і відхиляє решту?", + "title": "Перевірка завантаження", + "pageTitle": "Тестові файли перевірки завантаження - тип, розмір та ім'я", + "description": "Файли для перевірки форми завантаження: дозволені й заборонені типи, вміст не за розширенням, ліміт розміру, ворожі імена та масове завантаження.", + "catches": [ + "ліміт, що застосовується в браузері, а не на сервері", + "SVG або HTML, прийнятий за картинку чи простий текст, що дає змогу провести скрипт крізь форму", + "файл, перевірений за розширенням і жодного разу не відкритий, тож PDF з ім'ям .jpg проходить", + "форма, що читає все тіло в пам'ять, перш ніж подивитися, наскільки воно велике", + "завантаження з ім'ям PHOTO.JPG відхилене там, де photo.jpg приймається, або навпаки", + "ім'я з пробілами, дужками чи символами поза ASCII, записане на диск без змін" + ], + "details": { + "limit": "Ліміт розміру, який оголошує ваша форма завантаження. Цей набір робить по одному кроку в обидва боки - для файлу на кожній відстані запустіть пресет size-boundaries.", + "allow": "Які типи має приймати ваша форма. Кожен стає справжнім файлом цього типу, і разом вони є позитивним контролем усього набору.", + "deny": "Які розширення має відхиляти ваша форма. Розширення, для якого в цій збірці немає формату, усе одно отримує файл із таким ім'ям і простим текстом усередині.", + "far-over": "Наскільки далеко за ліміт заходить єдиний великий файл. Вимкніть, якщо запис кількох лімітів не вартий місця на диску.", + "bulk": "Скільки файлів у масовому завантаженні. Нуль повністю прибирає цю групу з набору." + } + } + }, + "commands": { + "generate": "створити файли за рецептом або за прапорцями", + "validate": "перевірити рецепт, нічого не записуючи", + "verify": "звірити каталог із маніфестом", + "cleanup": "видалити файли, перелічені в маніфесті", + "recipe fmt": "вивести рецепт у усталеному вигляді", + "preset": "зібрати набір файлів за іменованим тестовим питанням", + "formats": "перелічити формати цієї збірки", + "damage": "перелічити способи, якими ця збірка може навмисно зіпсувати файл", + "tool": "невеликі інструменти для вже наявних файлів", + "version": "вивести версію інструмента", + "license": "вивести ліцензію та що вона означає для створених файлів" + }, + "outcomes": { + "accept": "Ваша система має прийняти файл.", + "reject": "Ваша система має відхилити файл.", + "sanitize": "Ваша система має прийняти файл і очистити його, наприклад перейменувавши.", + "unspecified": "Залежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі." + }, + "damages": { + "zero-head": "Перезаписує перші байти файлу нулями, не змінюючи його довжину. Більшість програм читання дивляться спочатку туди, тому це пошкодження помічає майже все." + }, + "terms": { + "oracleNone": "не застосовується", + "int": "будь-яке ціле число", + "choice": "одне зі значень фіксованого набору", + "bool": "істина або хибність", + "size": "розмір, наприклад 2mb", + "text": "текст", + "pixels": "пікселів", + "paragraphs": "абзаців", + "rows": "рядків", + "columns": "стовпців", + "slides": "слайдів", + "hertz": "герців", + "megapixels": "мегапікселів", + "million cells": "мільйонів комірок", + "entries per second": "записів на секунду", + "files": "файлів", + "sizes separated by commas": "розміри через кому", + "format ids separated by commas": "id форматів через кому", + "format ids separated by commas, or all": "id форматів через кому або all", + "extensions separated by commas": "розширення через кому", + "the id of a format, as tfg formats lists them": "id формату в тому вигляді, як його виводить tfg formats", + "the password, in plain text": "пароль відкритим текстом", + "any text": "будь-який текст", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "дата на кшталт 2024-02-29 або 2024-02-29T13:45:00+02:00, або none" + }, + "faq": [ + { + "q": "Чим це відрізняється від dd, fsutil чи truncate?", + "a": "Вони дають файл потрібного розміру, набитий порожнечею. Файл photo.png на 2 МБ, зроблений так, не є PNG, тому все, що справді його розбирає, відхиляє його з хибної причини, і ваш тест теж проходить із хибної причини. Цей інструмент створює справжній PNG рівно на 2 МБ, який відкривається в переглядачі зображень, і супроводжує його заявою про те, як ваша система має з ним вчинити.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Це безкоштовно, і чи можна використовувати на роботі?", + "a": "Так в обох випадках. Інструмент випущено під GPL-3.0, і він нічого не коштує. Немає ні облікового запису, ні ліцензійного ключа, ні платного тарифу." + }, + { + "q": "Чи можна використовувати створені файли в продукті із закритим кодом?", + "a": "Так. Ліцензія охоплює код інструмента, а не те, що він створює. Створені файли, рецепти й маніфести є результатом, а не похідними творами, тож їх можна комітити та постачати без жодних зобов'язань." + }, + { + "q": "Чи містять створені файли справжні персональні дані?", + "a": "Ні. Усе всередині синтезується з seed. Жоден набір даних не читається, до жодного сервісу не звертаються і жоден сторонній вміст не вбудовується. Вважайте створену адресу електронної пошти непридатною, а не невикористаною, бо будь-який випадковий рядок може випадково збігтися зі справжнім." + }, + { + "q": "Чи отримаю я точно такі самі файли на іншій машині?", + "a": "Так, байт у байт, за того самого рецепта й того самого seed. Проєкт перевіряє це при кожній зміні, а порушити це можна лише підвищенням мажорної версії. Саме тому ви можете комітити невеликий рецепт замість великих бінарних фікстур." + }, + { + "q": "Чи потрібне підключення до інтернету?", + "a": "Ніколи. Немає ні телеметрії, ні перевірки оновлень, ні хмарного клієнта, а в бінарний файл командного рядка взагалі не скомпільовано мережевий стек. Він працює на машині без мережі й у закритому корпоративному середовищі." + }, + { + "q": "Що буде, якщо запросити розмір, якого формат не може досягти?", + "a": "Ви отримаєте помилку з назвою формату, найменшим можливим розміром, причиною цього мінімуму та тим, що робити натомість, а файл записано не буде. Інструмент ніколи не округлює розмір мовчки. Кожен мінімум указано на сторінці форматів.", + "code": "tfg formats png" + }, + { + "q": "Чи можна створити навмисно зламаний файл?", + "a": "Так. Додайте --damage zero-head, і файл вийде точно заданого розміру, з першими байтами, перезаписаними нулями, тож програма читання його відхилить, а маніфест скаже, що ваша система має його відхилити. Подробиці на сторінці про пошкоджені тестові файли.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Які формати з'являться далі?", + "a": "7z, mp3 і mp4. Сьогодні повністю працюють {{ .Facts.FormatCount }} форматів." + }, + { + "q": "У яких системах це можна запускати?", + "a": "Командний рядок працює у Windows і Linux на Intel та ARM, а також на Mac з Apple Silicon. Десктопне вікно постачається для Windows на Intel, Linux на Intel і Mac з Apple Silicon. Mac на Intel не підтримуються, і для них нічого не збирається." + }, + { + "q": "Чи потрібно щось установлювати?", + "a": "Ні. Завантажте архів для своєї системи, розпакуйте й запустіть бінарний файл. Немає інсталятора, середовища виконання, яке треба додавати, і залежностей, які треба розв'язувати. Якщо у вас є Go, підійде й одна команда go install.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Чому запуск на тисячах файлів у Windows повільніший?", + "a": "Бо Windows бере більше за кожен шлях, який переглядає, а команда, що обходить тисячі файлів, переглядає тисячі шляхів. Виміряно на одній машині з 3000 файлів по 1 КБ: verify займає близько 0,9 секунди у Windows і близько 0,2 секунди в Linux у контейнері. Коротший шлях виводу зменшує цифру для Windows, бо кожна тека над файлами входить у те, що переглядається." + } + ] +} diff --git a/web/content/uk/use-cases.html b/web/content/uk/use-cases.html new file mode 100644 index 00000000..5799f125 --- /dev/null +++ b/web/content/uk/use-cases.html @@ -0,0 +1,131 @@ +

Для чого це використовують

+

+ П'ять завдань, що виникають майже в кожному проєкті, який приймає файли від людей, і команда, що + розв'язує кожне. Кожен приклад нижче запускається як написано. +

+ +
+

Ліміти завантаження

+

Перевірка того, що ліміт розміру файлу застосовується там, де заявлено

+

+ Ліміт - це три тестові випадки, а не один: трохи нижче, рівно за лімітом і трохи вище. Отримати їх + вручну означає рахувати числа байтів і сподіватися, що ви не помилилися на одиницю. Запросіть + натомість набір: +

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

+ Ви отримаєте три справжні PDF по 1048575, 1048576 і 1048577 байт та маніфест, що каже: перші два + слід прийняти, а третій відхилити за size_limit. Ваш тест читає очікування, замість + того щоб ви писали три перевірки вручну, а коли ліміт змінюється, ви змінюєте одне число й + запускаєте знову. +

+

+ Те саме працює й без пресета, коли потрібен один набір меж просто в команді: +

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

Безперервна інтеграція

+

Тримати фікстури поза репозиторієм, не втрачаючи їх

+

+ Великі бінарні фікстури сповільнюють клонування репозиторію й заважають рев'ю, а при заміні ніхто не + може сказати, що змінилося. Рецепт - це кілька сотень символів YAML, що відтворюють ті самі + файли - байт у байт, на будь-якій машині - бо кожен файл виводиться з 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
+

+ Кожен кінець має власний код завершення, тому конвеєр відрізняє поганий рецепт від повного диска й + від розбіжності під час перевірки. Невдалий запуск нічого не друкує в стандартний вивід, і + розбірник журналів не сприймає помилку за дані. +

+
+ +
+

Масштаб

+

З'ясувати, що відбувається, коли тека велика

+

+ Процедури імпорту, нічні завдання та списки каталогів поводяться інакше за десяти тисяч файлів, ніж + за десяти. Розміри, вибрані з діапазону, роблять набір схожим на справжній трафік, а не на + десять тисяч однакових файлів, і вибір іде від seed, тож завтра набір буде той самий. +

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

+ Перевірте, скільки коштував би запуск, перш ніж він щось запише, це важливо, коли підсумок + вимірюється гігабайтами: +

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

+ Запуск, більший за вільне місце на диску, відхиляється до запису першого байта, а не заповнює диск і + не падає на півдорозі. +

+
+ +
+

Архіви

+

Перевірка розпакувальника на архіві, що справді містить файли

+

+ Порожній архів із правильним розширенням нічого не доводить про код, який його відкриває й обходить + вміст. Оголосіть вміст, і архів справді його містить: +

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

+ Глибина вкладеності, кількість записів і розмір вмісту - це те, про що в процедури імпорту є власна + думка, і так ви дізнаєтеся, яка вона. +

+
+ +
+

Парсери та переглядачі

+

Перевірка того, що ваш власний код читає формат так само, як справжнє ПЗ

+

+ Кожен формат тут перевіряється незалежним читачем до випуску: PNG відкривається й порівнюються його + пікселі, DOCX перечитується окремими бібліотеками, архів розпаковується. Це означає, що файл, + який відхиляє ваш парсер, - знахідка про ваш парсер, а не про генератор. +

+
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
+

+ Сторінка форматів перелічує налаштування кожного формату та найменший + файл, яким він може бути. +

+
+ +
+

Посібники

+

Два з них докладніше

+ +
+ +
+

Для кого це

+

+ QA-інженери, автоматизація тестування та всі, за чиїм кодом стоїть форма завантаження, процедура + імпорту, парсер чи квота сховища. Працює на машині взагалі без мережі, що важливо в закритому + корпоративному середовищі, де генератор у браузері - не варіант. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/vi/ci.html b/web/content/vi/ci.html new file mode 100644 index 00000000..a12a45dc --- /dev/null +++ b/web/content/vi/ci.html @@ -0,0 +1,187 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cách tạo tệp kiểm thử trong pipeline CI

+

+ Một fixture nhị phân trong kho mã nằm lại mãi trong lịch sử của nó, không thể review trong diff và + trở nên bất khả thi khi tệp lớn. Hãy tạo tệp ngay trong pipeline từ một công thức. Công thức là + văn bản, các byte ra giống hệt mỗi lần, và một bước cuối chứng minh không có gì xê dịch. +

+ +
+

Câu trả lời ngắn

+

+ Cài tfg, chạy tfg generate fixtures.yaml --out ./fixtures trước các bài + kiểm thử và tfg verify ./fixtures/manifest.json sau đó. Cả hai bước tự làm bản dựng + thất bại, với một mã thoát nói lý do. +

+
+ +
+

Vì sao không commit

+

Vì sao fixture không nên nằm trong kho mã

+ +

+ Thứ cần commit là công thức. Cùng công thức và cùng seed ghi ra cùng các byte trên mọi máy, nên tệp + tạo trong pipeline chính là tệp bạn có trên laptop. +

+
+ +
+

Công thức

+

Một công thức nằm cạnh các bài kiểm thử

+

+ Công thức này ghi hai mươi lăm hóa đơn phải được chấp nhận và hai ảnh vượt giới hạn phải bị từ chối, + và manifest ghi cả hai kỳ vọng: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml kiểm tra nó mà không ghi gì, và nêu mọi vấn đề cùng một lúc. +

+
+ +
+

GitHub Actions

+

Một workflow cài công cụ và dựng các fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Dòng checksum so sánh tệp lưu trữ với verify-SHA256SUMS.txt của cùng bản phát hành. + Phiên bản được ghim cố định, nên một bản phát hành mới không bao giờ đổi một bản dựng bạn chưa + đụng tới. +

+
+ +
+

GitLab CI

+

Cùng việc đó dưới dạng job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Khi nó chuyển đỏ

+

Điều gì làm một bước thất bại, và vì sao

+

+ Mỗi kết cục có mã thoát riêng, nên bước tự thất bại và nhật ký nói là mã nào. Những mã một pipeline + gặp: +

+ +

+ Lần chạy thất bại không in gì ra đầu ra chuẩn, nên trình phân tích nhật ký không bao giờ nhầm một + lỗi là dữ liệu. Cả bảng nằm ở trang tài liệu. +

+
+ +
+

PowerShell

+

Script PowerShell cần thêm một dòng

+

+ PowerShell không mang mã thoát của một chương trình ra khỏi tệp .ps1. Chạy một script + với -File và script trả lời 0 ngay cả khi công cụ bên trong đã từ chối + công việc, nên một bản dựng lẽ ra phải đỏ lại thành xanh. Dòng cuối là toàn bộ cách sửa: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell hành xử như vậy, không phải điều gì của công cụ này. cmd, bash + và zsh không cần thêm gì. +

+
+ +
+

Nhiều job

+

Chia sẻ fixture giữa các job

+

+ Thường không cần tải chúng lên. Vì cùng công thức ghi cùng các byte, mỗi job có thể chạy tfg + generate của riêng nó, nhanh hơn một lần tải lên rồi tải xuống. Khi một job phải nhận tệp + từ job khác, hãy chạy tfg verify trên manifest sau khi chuyển, và nó cho biết thứ + đến nơi có đúng là thứ đã được ghi không. +

+
+ +
+

Tiếp theo

+

Đi đâu từ đây

+ +
diff --git a/web/content/vi/damage.html b/web/content/vi/damage.html new file mode 100644 index 00000000..562d1961 --- /dev/null +++ b/web/content/vi/damage.html @@ -0,0 +1,172 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

Cách tạo tệp bị hỏng để kiểm thử

+

+ Một trình kiểm tra chỉ từng được cho xem tệp lành thì chưa thực sự được kiểm thử. Đây là cách có + được một tệp cố ý làm hỏng, ra đúng kích thước bạn yêu cầu và mang theo manifest + nói hệ thống của bạn phải làm gì với nó. +

+ +
+

Câu trả lời ngắn

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out ghi một tệp PNG + đúng 2097152 byte với các byte đầu là số không, và manifest bên cạnh ghi rằng hệ thống của bạn + phải từ chối nó. +

+
+ +
+

Cách thường dùng

+

Vì sao tệp làm hỏng bằng tay là một bài kiểm thử tồi

+

+ Cách thường dùng là trình soạn thảo hex, một script đảo vài byte ngẫu nhiên, hoặc cắt ngắn tệp bằng + head hay truncate. Dùng được một lần, rồi nó làm bạn tốn công: +

+ +
+ +
+

Bạn nhận được gì

+

Tệp bị hỏng vẫn có kích thước bạn đã yêu cầu

+

+ Tệp được tạo bình thường rồi mới bị làm hỏng, trên đường ghi xuống đĩa. Nó giữ kích thước bạn yêu + cầu, và cùng một lệnh ghi lại đúng các byte đó. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Cài đặt viết sau dấu hai chấm. Tùy chọn có thể lặp lại, và các hỏng hóc được áp dụng theo thứ tự bạn + viết. Nó dùng được với từng định dạng trong {{ .Facts.FormatCount }} định dạng. +

+
+ +
+

Nó làm được gì

+

Có những kiểu hỏng nào?

+

+ Đây là danh sách chương trình in ra, được đọc từ chính nó khi trang này được dựng. tfg + damage in ra cùng danh sách đó, và tfg damage <id> cho biết một kiểu + nhận những gì. +

+ {{ template "damagesTable" . }} +

+ zero-head ghi số không đè lên phần đầu tệp. Hầu hết trình đọc nhìn vào đó trước, vào + chữ ký và phần đầu cho biết tệp là gì, nên gần như trình đọc nào cũng nhận ra. Văn bản thuần và + nhật ký không có chữ ký và cũng bị từ chối, vì một chuỗi byte không không phải là văn bản. Dưới + bốn byte, một số định dạng ra với hỏng hóc mà không trình đọc nào phàn nàn, đó là lý do cài đặt + bắt đầu từ bốn. +

+
+ +
+

Manifest nói gì

+

Một manifest nói điều phải xảy ra

+

+ Mỗi tệp bị hỏng nhận một mục nói rằng hệ thống của bạn phải từ chối nó, với hỏng hóc được ghi bên + cạnh: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Hai yêu cầu bị từ chối trước khi có gì được ghi, vì mỗi yêu cầu sẽ để lại trên đĩa một tệp mà + manifest mô tả sai: +

+ +
+ +
+

Trong một công thức

+

Tệp lành và tệp hỏng trong một lần chạy

+

+ Đặt cả hai vào một công thức, và manifest mang kỳ vọng của từng tệp, nên bài kiểm thử không cần danh + sách tệp nào là tệp nào: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Trong một bài kiểm thử

+

Biến nó thành một bài kiểm thử

+

+ Bài kiểm thử đọc manifest và kiểm tra điều đã xảy ra có đúng như điều đã khai báo. Nó không cần danh + sách tên tệp: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Một lần từ chối tốt là một lần từ chối gọn. Một thông báo nói điều gì sai là câu trả lời bạn muốn. + Lỗi máy chủ, treo máy hoặc một tệp lưu dở là khiếm khuyết mà bài kiểm thử này sinh ra để tìm. +

+
+ +
+

Tiếp theo

+

Đi đâu từ đây

+ +
diff --git a/web/content/vi/docs.html b/web/content/vi/docs.html new file mode 100644 index 00000000..847a13f6 --- /dev/null +++ b/web/content/vi/docs.html @@ -0,0 +1,274 @@ +

Tài liệu

+

+ Mọi thứ công cụ làm, sắp xếp theo những câu hỏi mà mọi người thật sự mang đến. + README trong kho mã là tài liệu tham chiếu đầy đủ và luôn khớp với + bản dựng bạn đã tải. +

+ +
+

Có những lệnh nào?

+

Mỗi lệnh làm đúng một việc:

+ {{ template "commandList" . }} +
+ +
+

Làm sao tạo một tệp đơn có kích thước chính xác?

+

+ Nêu định dạng, kích thước và nơi đặt. Kích thước đếm theo 1024, nên 2mb là 2097152 + byte. Số byte thuần cũng được, nên --size 10485761 yêu cầu đúng chừng đó. +

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

Các cờ hữu ích của generate:

+
+ + + + + + + + + + + + + + + + + +
CờTác dụng
--format <id>định dạng của các tệp, ví dụ txt
--size <size>kích thước chính xác của mỗi tệp, như 10mb hoặc số byte thuần
--size-range <a-b>kích thước rút cho từng tệp từ một khoảng, như 1kb-8kb. Lần rút lấy từ seed
--boundary <size>ba tệp quanh một giới hạn: thấp hơn một byte, đúng giới hạn, cao hơn một byte
--count <n>tạo bao nhiêu tệp. Mặc định 1
--name <template>mẫu tên, ví dụ invoice_{index:04}.txt
--out <dir>thư mục để ghi vào
--seed <n>seed của lần chạy. Cùng seed cho cùng các byte
--set <k>=<v>một thiết lập định dạng, lặp lại được
--damage <name>cố ý làm hỏng tệp, lặp lại được và áp dụng theo thứ tự. Chạy tfg damage để xem danh sách
--expected <outcome>accept, reject, sanitize hoặc unspecified
--dry-runđếm và hiển thị, hoàn toàn không ghi gì
--jsonghi manifest ra đầu ra chuẩn
+
+
+ +
+

Làm sao tạo một tệp cố ý bị hỏng?

+

+ Mọi tệp khác mà công cụ này ghi đều đúng theo cách xây dựng, điều đó trả lời hai trong ba câu hỏi mà + trình kiểm tra tải lên đặt ra. --damage trả lời câu thứ ba - tệp có mở được không. + Tệp được tạo bình thường rồi bị làm hỏng, nên nó vẫn có kích thước bạn đã yêu cầu. +

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

+ Các thiết lập đặt sau dấu hai chấm. Cờ lặp lại được, và thứ tự bạn viết là thứ tự chúng được áp + dụng. tfg damage liệt kê những gì bản dựng này làm được và mỗi kiểu nhận gì. +

+

Trong công thức, khóa là một danh sách, gồm tên hoặc thiết lập:

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

+ Tệp bị làm hỏng nhận expected: reject trong manifest, kèm kiểu hỏng được ghi bên cạnh. + Hai thứ bị từ chối trước khi ghi bất cứ gì, vì mỗi thứ sẽ đặt lên đĩa một tệp mà manifest mô tả + sai: +

+ +

+ Thứ ba không thể biết trước. Nếu một kiểu hỏng chạy mà không đổi byte nào, tệp đó bị bỏ thay vì được + ghi - lần chạy tiếp tục, nói đó là tệp nào và kết thúc bằng mã thoát một phần. +

+

+ Từng bước, với một bài kiểm thử đọc manifest: cách tạo tệp bị + hỏng để kiểm thử. +

+
+ +
+

Một công thức trông thế nào?

+

+ Công thức là một tệp YAML mô tả cả một lần chạy. Hãy commit nó bên cạnh các bài kiểm thử và fixture + thôi là tệp nhị phân trong kho mã - ai cũng có thể dựng lại chúng, từng byte, từ một tệp vài + trăm ký tự. +

+
# 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
+

+ Mỗi target cần đúng một trong size, size-range, boundary hoặc + contains. Hai cái là lỗi và không cái nào cũng là lỗi. Công thức không hợp lệ ghi + không tệp nào và báo mọi vấn đề cùng lúc thay vì chỉ cái đầu, mỗi cái nêu thiết + lập mà nó nói đến. +

+
+ +
+

Làm sao khai báo hệ thống của tôi cần làm gì với một tệp?

+

Dạng ngắn khi kết quả là đủ, dạng dài khi lý do quan trọng:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Các kết quả là accept, reject, sanitize và + unspecified. Các lý do là một danh sách đóng để báo cáo có thể nhóm theo chúng: + 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 và size_zero. +

+

+ Một lý do nêu quy tắc đang áp dụng, không phải phán quyết. Vì vậy cùng một lý do có + thể nằm dưới cả hai kết quả - tệp thấp hơn giới hạn một byte là accept, và quy tắc + liên quan vẫn là size_limit. +

+
+ +
+

Manifest chứa gì?

+

+ Nó được ghi bên cạnh các tệp ở cuối mỗi lần chạy, kể cả lần chạy bị ngắt. Một mục cho mỗi tệp: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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 được thêm khi lần chạy đến từ một công thức, và preset cùng + overrides khi nó đến từ một preset, nên manifest luôn truy ngược được về thứ đã tạo + ra nó. +

+

+ Mỗi mục còn mang target_id, id của target trong công thức đã tạo tệp, và + summary.by_target đếm số tệp mà mỗi target tạo ra. Một công thức có nhiều target + nhờ vậy kiểm tra được từng target mà không cần đọc tên tệp. +

+
+ +
+

Preset là gì?

+

+ Một bộ tệp dựng sẵn trả lời một câu hỏi kiểm thử thường gặp, để bạn không phải tự thiết kế bộ. + Preset thực chất là công thức bình thường, và eject in công thức ra để bạn chỉnh + sửa từ đó. Mỗi preset có trang riêng nói nó thường tìm thấy gì, trong + bộ có gì và mọi thiết lập nó nhận. +

+ {{ template "presetsList" . }} +
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 cho bạn biết bộ sẽ tốn bao nhiêu trước khi dựng, và nói thẳng khi một con số là + giá trị tạm của chúng tôi chứ không phải giới hạn của bạn. +

+
+ +
+

Các mã thoát có nghĩa gì?

+

+ Mỗi kết cục có mã riêng, đầu ra máy đọc được đi ra đầu ra chuẩn, và lần chạy thất bại không in gì ở + đó. Bảng này là một hợp đồng đóng băng - đổi nghĩa của một mã đòi hỏi tăng phiên bản chính. +

+ {{ template "exitCodesTable" . }} +
- 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
+

+ Lần chạy bị dừng bằng Ctrl+C vẫn để lại manifest và không bao giờ để lại tệp ghi dở, nên tác vụ bị + hủy vẫn có thể được dọn bởi tác vụ sau. +

+

+ Workflow có sẵn cho GitHub Actions và GitLab CI: cách tạo tệp + kiểm thử trong pipeline CI. +

+
+ +
+

Có cửa sổ desktop không?

+

+ Có, cùng một động cơ với một cửa sổ phủ lên, cho kiểu kiểm thử không viết kịch bản. Nó không phải + bản cắt giảm: một bài kiểm thử so sánh hai giao diện từng khả năng một, và bất cứ điều gì chỉ + một bên làm được đều phải được khai báo và biện minh thay vì lặng lẽ lệch nhau. +

+

+ Các màn hình là một lô, preset, nhiều lô cùng lúc và giới thiệu. Nó cho biết một lần chạy sẽ tốn bao + nhiêu trước khi ghi gì, báo tiến độ khi đang chạy và có thể hủy giữa chừng mà không để lại tệp + ghi dở. Nó chưa mở được tệp công thức - hiện công thức là việc của dòng lệnh, còn cửa sổ dựng + các lô trong biểu mẫu. +

+
diff --git a/web/content/vi/exact-size.html b/web/content/vi/exact-size.html new file mode 100644 index 00000000..4e4dcb1b --- /dev/null +++ b/web/content/vi/exact-size.html @@ -0,0 +1,144 @@ +

Cách tạo tệp có kích thước chính xác

+

+ Hệ thống nào cũng có một lệnh cho việc này, và cả ba nằm bên dưới. Chúng cho bạn một tệp có đúng số + byte cần thiết - và với nhiều bài kiểm thử, thế là đủ. Mọi lệnh trên trang này đã được + chạy trước khi đăng, trên hệ thống mà nó thuộc về. +

+ +
+

Câu trả lời ngắn

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Kích thước tính bằng byte, và 10 MB + đếm theo cách trình quản lý tệp của bạn đếm là 10485760. +

+
+ +
+

Windows

+

fsutil, và một bản PowerShell không cần thêm gì

+

+ fsutil có sẵn trong Windows. Nó nhận kích thước bằng byte, nên hãy + tính số trước - 10 MB là 10485760, 100 MB là 104857600, 1 GB là 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Đo trên Windows 11: nó chạy từ một dấu nhắc thường mà không cần quyền nâng cao, và tệp ra đúng + 10485760 byte. +

+

PowerShell làm được điều tương tự mà không gọi chương trình khác, và hiểu đơn vị:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB trong PowerShell nghĩa là 10485760 byte, cùng cách đếm cơ số 1024 mà Explorer + dùng, nên hai lệnh ở trên cho cùng một kích thước. +

+
+ +
+

Linux

+

dd, truncate và fallocate, và sự khác biệt làm người ta vấp

+

dd là lệnh ai cũng biết. Nó thật sự ghi các byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate chạy tức thì, và đó là cái bẫy. Đo trên Alpine Linux, tệp báo 10485760 byte và + chiếm không khối nào - nó là một tệp thưa. Bất cứ thứ gì đọc + nó nhận mười megabyte số không, nhưng đĩa chưa bao giờ nhường chỗ: +

+
truncate -s 10M test10mb.bin
+

+ Điều đó ổn để kiểm thử giới hạn tải lên và gây hiểu lầm khi kiểm thử hạn ngạch đĩa. + fallocate là lệnh nên dùng khi dung lượng phải là thật: +

+
fallocate -l 10M test10mb.bin
+

Và khi nội dung phải không nén được, để trình nén không thể ép nó nhỏ lại:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, không phải tệp thưa, và hai lệnh bạn đã biết

+

+ macOS có sẵn mkfile. Đo trên macOS 26.6.2: 10485760 byte và 20480 khối, nên dung lượng + thật sự được cấp phát chứ không chỉ hứa hẹn: +

+
mkfile 10m test10mb.bin
+

dd và truncate cũng có và hoạt động như trên Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Khi điều này ngừng hiệu quả

+

Tệp đúng kích thước không phải tệp đúng loại

+

+ Mọi thứ ở trên cho bạn một khối số không. Điều đó đủ khi thứ được kiểm thử chỉ nhìn kích thước - + giới hạn tải lên, hạn ngạch, một lần truyền. Nó thôi đủ ngay khi có thứ gì mở + tệp. +

+

+ Đã đo, và đáng để tự làm: tạo tệp 2 MB bằng fsutil, đặt tên photo.png rồi + đưa cho một thư viện ảnh. Pillow trả lời cannot identify image file. Nó không phải + PNG. Nó chưa bao giờ là - chỉ cái tên nói vậy. +

+

+ Điều đó quan trọng hơn vẻ ngoài, vì bài kiểm thử sau đó hỏng theo hướng nào. + Endpoint tải lên từ chối tệp, bài kiểm thử của bạn xanh và bạn kết luận giới hạn kích thước hoạt + động. Nó không từ chối vì kích thước. Nó từ chối vì các byte không phải ảnh, và quy tắc bạn định + kiểm thử chưa bao giờ được chạm tới. +

+ +
+ +
+

Con đường còn lại

+

Một tệp thật của định dạng đó, đúng kích thước bạn đã yêu cầu

+

+ Đây là việc Testing Files Generator làm. Tệp là tệp thật của định dạng - mở được bằng phần mềm của + nó - và có đúng số byte bạn đã yêu cầu, chính xác đến từng byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Yêu cầu kích thước mà định dạng không thể đạt và bạn nhận một lỗi nêu mức sàn cùng lý do, không bao + giờ là tệp sai kích thước. Trang định dạng liệt kê mỗi định dạng + cùng tệp nhỏ nhất nó có thể tạo. +

+

Và một giới hạn là ba trường hợp kiểm thử chứ không phải một, nên công cụ dựng cả ba:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Điều đó cho bạn 10485759, 10485760 và 10485761 byte, cùng manifest nói tệp nào hệ thống của bạn nên + chấp nhận và tệp nào nên từ chối. Trang trường hợp sử dụng + đi qua việc đó và bốn việc khác mà nó được làm ra để giải quyết. +

+ {{ template "downloadCta" . }} +
+ +
+

Vậy nên dùng cái nào?

+ +

+ Cả hai đều có trên trang này vì cả hai đúng trong một phần thời gian. Sai lầm cần tránh là dùng cái + đầu ở nơi cần cái sau và coi bài kiểm thử xanh là bằng chứng. +

+
diff --git a/web/content/vi/faq.html b/web/content/vi/faq.html new file mode 100644 index 00000000..cabcb701 --- /dev/null +++ b/web/content/vi/faq.html @@ -0,0 +1,20 @@ +

Câu hỏi thường gặp

+

+ Giấy phép, quyền riêng tư, khả năng tái lập và những điều mọi người kiểm tra trước khi đưa một trình + tạo vào pipeline build. Nếu câu hỏi của bạn chưa có ở đây, trình + theo dõi issue luôn mở. +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

Vẫn đang cân nhắc?

+

+ Trang trường hợp sử dụng cho thấy các việc nó được làm ra để + giải quyết, và trang định dạng liệt kê mỗi định dạng cùng tệp nhỏ + nhất nó có thể tạo. README trong kho mã là tài liệu tham chiếu + đầy đủ. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/vi/formats.html b/web/content/vi/formats.html new file mode 100644 index 00000000..b7c86ca6 --- /dev/null +++ b/web/content/vi/formats.html @@ -0,0 +1,76 @@ +

{{ .Facts.FormatCount }} định dạng tệp, mỗi định dạng được tạo ở kích thước chính xác

+

+ Mỗi cái là một tệp thật của định dạng đó. Nó mở được bằng phần mềm của nó và có + đúng số byte bạn đã yêu cầu. Không cái nào là số không độn với phần mở rộng dán vào. +

+ +{{ template "formatsTable" . }} + +
+

Ý nghĩa các cột

+ +

+ Mỗi định dạng cũng lặp lại đến từng byte: cùng công thức và cùng seed cho các tệp giống hệt trên mọi + máy, điều làm cho việc commit một công thức thay cho chính các fixture trở nên an toàn. +

+
+ +
+

Các thiết lập mỗi định dạng nhận

+

+ Hầu hết định dạng có thiết lập riêng - kích thước ảnh, chất lượng JPEG, số trang PDF, số dòng và cột + trong bảng tính, số mục nằm trong một tệp nén. Đặt chúng bằng --set key=value trên + dòng lệnh, hoặc dưới properties: trong công thức. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ Giá trị nằm ngoài thứ một thiết lập chấp nhận bị từ chối bằng thông báo nêu thiết lập, khoảng cho + phép và nên dùng gì thay thế. Thiết lập lạ cũng là lỗi, không bao giờ là mặc định im lặng - lỗi + gõ được chấp nhận trong im lặng cho ra tệp sai thiết lập và một giờ tự hỏi vì sao bài kiểm thử + qua khi lẽ ra không. +

+

+ Chạy tfg formats <id> để xem chính xác một định dạng nhận gì trong bản dựng bạn + có. +

+
+ +
+

Tệp nén chứa tệp thật

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} và {{ end }}{{ $c.ID }}{{ end }} có + thể được nhồi các mục thay vì để thành cái vỏ rỗng. Tệp nén được tạo thật sự chứa các tài liệu + nó tuyên bố chứa, nên bất cứ thứ gì giải nén nó trong lúc kiểm thử đều thấy tệp thật bên trong. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/vi/index.html b/web/content/vi/index.html new file mode 100644 index 00000000..0028e541 --- /dev/null +++ b/web/content/vi/index.html @@ -0,0 +1,195 @@ +
+
+

Tạo tệp kiểm thử thật đúng kích thước

+

+ PDF, PNG, DOCX, ZIP - tổng cộng {{ .Facts.FormatCount }} định dạng, và mỗi tệp là + tệp thật mở được bằng phần mềm của nó, ở đúng kích thước bạn yêu cầu. Mỗi lần + chạy còn ghi lại ứng dụng của bạn cần làm gì với từng tệp. Dòng lệnh và cửa sổ desktop, miễn + phí, mã nguồn mở, chạy hoàn toàn trên máy của bạn. +

+ + {{ template "downloadCta" . }} +
+ +
+ Cửa sổ desktop của Testing Files Generator, sẵn sàng ghi một lô tệp kiểm thử +
Cửa sổ desktop, sẵn sàng ghi một lô tệp. Cùng một động cơ chạy phía sau dòng lệnh.
+
+
+ + + +
+

Vấn đề

+

Làm một tệp kiểm thử thì dễ. Làm đúng một nghìn tệp mới là phần mệt mỏi

+

Bạn đang kiểm thử phần mềm nhận tệp từ con người. Sớm hay muộn bạn sẽ cần:

+ +

+ Đó là thứ nó thay thế. Nó được làm cho kỹ sư QA, tự động hóa kiểm thử và bất kỳ ai có mã đứng sau là + biểu mẫu tải lên, quy trình nhập, bộ phân tích cú pháp hoặc hạn ngạch lưu trữ. +

+
+ +
+

Điều làm nó khác biệt

+

Các trình tạo khác dừng ở các byte. Cái này trả lời điều bài kiểm thử của bạn thật sự hỏi

+

+ Một thư mục tệp vẫn để bạn tự quyết định mỗi tệp chứng minh điều gì. Mỗi lần chạy ở đây ghi một + manifest.json bên cạnh các tệp - danh sách đơn giản mọi thứ đã tạo, và với mỗi mục + là một kỳ vọng được khai báo. +

+

Giả sử endpoint tải lên của bạn cho phép 1 MB. Hãy yêu cầu ba tệp nằm trên ranh giới đó:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
TệpByteHệ thống của bạn nênVì
1mb_under_1b.pdf1048575chấp nhậnnó nằm trong giới hạn
1mb_at_limit.pdf1048576chấp nhậnchính giới hạn được cho phép
1mb_over_1b.pdf1048577từ chốisize_limit
+
+ +

Ba tệp, ba câu trả lời khác nhau, ở dạng máy đọc được. Bài kiểm thử của bạn đọc manifest thay vì bạn tự viết các câu khẳng định:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Khi câu trả lời phụ thuộc chính sách của riêng bạn, manifest sẽ nói rõ

+

+ Nó ghi unspecified thay vì bịa ra kỳ vọng. Một trình tạo đoán mò tạo ra thất bại giả, + và bộ kiểm thử cứ báo động giả sẽ bị tắt. +

+
+
+ +
+

Preset

+

Chọn câu hỏi, nhận cả bộ

+

+ Preset là một bộ tệp kiểm thử được thiết kế quanh một câu hỏi kiểm thử, để bạn không phải tự tìm ra + tệp nào chứng minh điều gì. Mỗi preset có một trang nói nó thường tìm thấy gì, trong bộ có gì và + mọi thiết lập nó nhận. +

+ {{ template "presetsList" . }} +

Mọi preset, và chúng liên quan thế nào đến công thức

+
+ +
+

Bắt đầu nhanh

+

Ba lệnh để thấy nó hoạt động

+
    +
  1. +

    Tạo một tệp

    +

    Một PNG, đúng hai megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Tạo nhiều tệp

    +

    + Mười nghìn tệp nhật ký, mỗi tệp từ một đến tám kilobyte, với kích thước rút từ seed để ngày mai ra + cùng một bộ. Cho mỗi lần chạy một thư mục riêng - manifest là bản ghi duy + nhất về những gì một lần chạy đã ghi, nên công cụ từ chối ghi cái thứ hai đè lên: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Kiểm tra chúng, rồi xóa

    +

    verify cho bạn biết không có gì đổi chỗ. cleanup xóa đúng những gì đã ghi và không gì khác:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Kích thước đếm theo 1024, như trình quản lý tệp của bạn, nên 2mb nghĩa là 2097152 byte. + Số byte thuần cũng được. Tài liệu bao gồm công thức, manifest và các + mã thoát. +

+
+ +
+

Bạn nhận được gì

+

Làm cho bộ kiểm thử chạy không cần người trông

+ +
+ +
+

Tải xuống

+

Chọn bản dựng cho hệ thống của bạn

+

+ Giải nén kho lưu trữ rồi chạy. tfg là dòng lệnh và tfg-gui là cửa sổ + desktop. Không có trình cài đặt và không có gì phải thêm vào máy của bạn. +

+ {{ template "downloadsTable" . }} +
+

Cái nào được ký, cái nào không

+

+ Bản tải cho Windows và macOS đã được ký, nên khởi động mà không có cảnh báo nhà phát triển không xác + định. Bản Linux thì không, vì Linux desktop không có gì tương đương để ký. Mỗi kho lưu trữ + được liệt kê trong verify-SHA256SUMS.txt trên trang phát hành, để bạn kiểm tra + thứ mình đã tải. +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/vi/preset.html b/web/content/vi/preset.html new file mode 100644 index 00000000..aebc4418 --- /dev/null +++ b/web/content/vi/preset.html @@ -0,0 +1,91 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ Preset {{ .ID }} dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ +{{ if .Catches }} +
+

Nó thường tìm thấy gì?

+ +
+{{ end }} + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show {{ .ID }} báo cáo:

+
+ + + + + + + +
Tệp{{ .Budget.Files }}
Target trong công thức của nó{{ .Budget.Targets }}
Tổng kích thước{{ .Bytes }} B
Định dạng{{ join .Budget.Formats ", " }}
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
Mong đợiÝ nghĩaTệp
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

Bạn có thể đổi gì?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
Thiết lậpNhậnMặc địnhTác dụng
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} Giá trị mặc định này là giá trị tạm của chúng tôi, không phải giá trị của hệ thống bạn. Hãy truyền giá trị của riêng bạn.{{ end }}
+
+ {{- else }} +

Preset này không có thiết lập. Bộ luôn giống nhau mỗi lần.

+ {{- end }} +
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/vi/presets.html b/web/content/vi/presets.html new file mode 100644 index 00000000..20d1127c --- /dev/null +++ b/web/content/vi/presets.html @@ -0,0 +1,31 @@ +

Preset tệp kiểm thử, một bộ cho mỗi câu hỏi kiểm thử

+

+ Preset là cả một bộ tệp kiểm thử được thiết kế quanh một câu hỏi, kèm manifest nêu cách hệ thống của + bạn cần phản ứng với từng tệp. Bạn chọn câu hỏi, công cụ dựng bộ. Mỗi preset có trang riêng nói nó + thường tìm thấy gì, trong bộ có gì và mọi thiết lập nó nhận. +

+ +{{ template "presetsList" . }} + +
+

Preset khác công thức thế nào?

+

+ Về bản chất thì không khác. Preset là công thức mà công cụ viết cho bạn từ vài thiết lập. tfg + preset eject in công thức đó ra để bạn giữ cạnh các bài kiểm thử và chỉnh sửa, và công + thức của riêng bạn có thể xây trên một preset bằng một dòng, extends: preset: theo + sau là id của nó. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Tôi có thể tin các giá trị mặc định không?

+

+ Với các tệp thì có. Với con số chỉ hệ thống của bạn biết, như giới hạn của một biểu mẫu tải lên, giá + trị mặc định là giá trị tạm của chúng tôi, và công cụ nói vậy mỗi lần dùng một giá trị như thế. + Trang của mỗi preset đánh dấu các thiết lập đó, và tfg preset show nói điều đó + trước khi ghi bất cứ gì. +

+
diff --git a/web/content/vi/site.json b/web/content/vi/site.json new file mode 100644 index 00000000..f6f73567 --- /dev/null +++ b/web/content/vi/site.json @@ -0,0 +1,328 @@ +{ + "code": "vi", + "locale": "vi_VN", + "name": "Tiếng Việt", + "dir": "vi", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "Trang chủ", + "title": "Trình tạo tệp kiểm thử cho QA - kích thước chính xác, {{ .Facts.FormatCount }} định dạng", + "description": "Trình tạo tệp kiểm thử miễn phí, mã nguồn mở cho QA. Tệp PDF, DOCX, PNG, ZIP thật đúng kích thước, kèm manifest nêu cách hệ thống của bạn cần phản ứng." + }, + { + "key": "formats", + "slug": "dinh-dang", + "nav": "Định dạng", + "title": "{{ .Facts.FormatCount }} định dạng tệp được hỗ trợ - PDF, DOCX, PNG, ZIP và hơn nữa", + "description": "Mọi định dạng tệp mà trình tạo này tạo ra, tệp nhỏ nhất có thể của mỗi định dạng và các thiết lập nó nhận. Cả {{ .Facts.FormatCount }} đều mở được bằng phần mềm của chúng." + }, + { + "key": "presets", + "slug": "preset", + "nav": "Preset", + "title": "Preset tệp kiểm thử - bộ tệp dựng sẵn cho câu hỏi QA", + "description": "Các bộ tệp kiểm thử dựng sẵn, mỗi bộ trả lời một câu hỏi kiểm thử: giới hạn tải lên, tên tệp, mã hóa, nhập bảng, tệp rỗng và kiểm tra hợp lệ." + }, + { + "key": "docs", + "slug": "tai-lieu", + "nav": "Tài liệu", + "title": "Tài liệu - lệnh, công thức, manifest, mã thoát", + "description": "Cách tạo tệp kiểm thử từ dòng lệnh hoặc công thức YAML, manifest chứa gì và mỗi mã thoát có nghĩa gì khi công cụ chạy trong CI." + }, + { + "key": "use-cases", + "slug": "truong-hop-su-dung", + "nav": "Trường hợp sử dụng", + "title": "Trường hợp sử dụng - giới hạn tải lên, fixture CI, kiểm thử", + "description": "Kiểm thử giới hạn kích thước tải lên, dựng fixture tái lập được cho CI, tạo mười nghìn tệp và nhồi nội dung thật vào tệp nén." + }, + { + "key": "exact-size", + "slug": "tao-tep-kich-thuoc-chinh-xac", + "nav": "Kích thước chính xác", + "title": "Cách tạo tệp có kích thước chính xác - Windows, Linux, macOS", + "description": "fsutil, dd, truncate và mkfile, mỗi lệnh được đo trên hệ thống của nó, và vì sao tệp tạo kiểu đó không phải PDF hay PNG khi bài kiểm thử cần." + }, + { + "key": "faq", + "slug": "faq", + "nav": "FAQ", + "title": "FAQ - câu hỏi về việc tạo tệp kiểm thử", + "description": "Khác gì dd và fsutil, tệp có commit an toàn không, các lần chạy có giống từng byte không và chuyện gì xảy ra khi không đạt được kích thước." + }, + { + "key": "damage", + "slug": "tep-kiem-thu-bi-hong", + "nav": "Tệp bị hỏng", + "title": "Tệp kiểm thử bị hỏng - tệp hỏng đúng kích thước", + "description": "Một tệp cố ý làm hỏng, đúng kích thước, với manifest nói hệ thống của bạn phải từ chối nó. Để kiểm thử xác thực tải lên và trình phân tích cú pháp.", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "tep-kiem-thu-trong-ci", + "nav": "Tệp kiểm thử trong CI", + "title": "Tệp kiểm thử trong CI - GitHub Actions, GitLab CI và PowerShell", + "description": "Tạo tệp kiểm thử trong pipeline thay vì commit tệp nhị phân: workflow GitHub Actions, job GitLab, mã thoát và cái bẫy của PowerShell.", + "parent": "use-cases" + } + ], + "words": { + "skip": "Chuyển đến nội dung", + "navLabel": "Chính", + "langLabel": "Ngôn ngữ", + "breadcrumbHome": "Trang chủ", + "imageAlt": "Testing Files Generator - tệp kiểm thử thật đúng kích thước, kèm manifest nêu cách hệ thống của bạn cần phản ứng với từng tệp", + "schemaDescription": "Trình tạo tệp kiểm thử miễn phí, mã nguồn mở cho QA. Nó tạo tệp thật ở {{ .Facts.FormatCount }} định dạng, đúng kích thước, và ghi manifest nêu cách hệ thống được kiểm thử cần phản ứng với từng tệp.", + "ctaDownload": "Tải xuống", + "ctaSource": "Xem mã nguồn", + "ctaNote": "Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.", + "colFormat": "Định dạng", + "colName": "Tên", + "colExtension": "Phần mở rộng", + "colSmallest": "Tệp nhỏ nhất", + "colFidelity": "Độ đầy đủ", + "colChecked": "Kiểm tra bằng", + "colSetting": "Thiết lập", + "colAccepts": "Chấp nhận", + "colSystem": "Hệ thống", + "colCli": "Dòng lệnh", + "colWindow": "Cửa sổ desktop", + "noBinary": "chưa có bản nhị phân", + "colCode": "Mã", + "colMeaning": "Ý nghĩa", + "footerBlurb": "Tệp kiểm thử cho QA, đúng kích thước, kèm manifest nêu cách hệ thống của bạn cần phản ứng với từng tệp.", + "footerProject": "Dự án", + "footerSource": "Mã nguồn trên GitHub", + "footerReleases": "Tải xuống", + "footerIssues": "Báo lỗi", + "footerSupport": "Ủng hộ dự án", + "footerPages": "Trang", + "footerLicence": "Copyright (C) 2026 DonislawDev. Phát hành theo Giấy phép Công cộng GNU, phiên bản 3. Tệp bạn tạo ra là của bạn - giấy phép áp dụng cho công cụ, không áp dụng cho kết quả của nó.", + "footerPrivacy": "Trang này không tải phông chữ, tập lệnh hay công cụ theo dõi từ bất kỳ đâu. Nó không đặt cookie.", + "notFoundTitle": "Trang này không có ở đây", + "notFoundLead": "Địa chỉ bạn vừa theo không khớp với trang nào trên trang web này.", + "notFoundBack": "Về trang chủ", + "read.format": "Định dạng của mọi tệp trong bộ. Đây là một cờ của chính công cụ, và preset chỉ cho nó một giá trị mặc định.", + "readTakes.format": "id định dạng từ trang định dạng", + "colDamage": "Hỏng hóc", + "colEffect": "Nó làm gì với các byte", + "colSettings": "Cài đặt", + "noSettings": "không có" + }, + "endings": { + "0": "Mọi thứ đều chạy tốt.", + "1": "Lỗi bất ngờ bên trong công cụ.", + "2": "Lệnh hoặc cờ sai.", + "3": "Công thức không hợp lệ.", + "4": "Định dạng không làm được điều được yêu cầu.", + "5": "Đọc hoặc ghi thất bại.", + "6": "Không đủ dung lượng đĩa.", + "7": "verify phát hiện sai lệch.", + "8": "Lần chạy đã xong nhưng không phải mọi thứ đều được tạo.", + "130": "Bị ngắt bằng Ctrl+C.", + "143": "Bị dừng bởi một tín hiệu, đó là hình dạng của việc CI hết thời gian." + }, + "presets": { + "empty-and-minimal": { + "question": "Một tệp hợp lệ và nhỏ nhất mà định dạng cho phép có qua được không?", + "title": "Rỗng và tối thiểu", + "pageTitle": "Tệp kiểm thử hợp lệ nhỏ nhất và tệp rỗng ở mọi định dạng", + "description": "Tệp hợp lệ nhỏ nhất mà công cụ ghi ở mỗi trong {{ .Facts.FormatCount }} định dạng, cộng tệp rỗng nơi định dạng cho phép, mỗi tệp kèm phản ứng cần có.", + "catches": [ + "tệp hợp lệ bị từ chối vì quá nhỏ, khi bước kiểm tra đếm byte thay vì đọc chúng", + "tệp rỗng làm trình đọc sập thay vì được báo cáo", + "ảnh rộng một pixel chia cho không trên đường tạo ảnh thu nhỏ", + "bộ lưu trữ đọc không byte như một lần tải lên thất bại và cứ thử lại mãi" + ], + "details": { + "formats": "Bộ được dựng từ những định dạng nào. Để all cho mọi định dạng của bản dựng này, hoặc nêu những định dạng hệ thống của bạn chấp nhận." + } + }, + "filename-handling": { + "question": "Hệ thống của tôi có lưu, hiển thị và trả lại một tên tệp mà nó không ngờ tới không?", + "title": "Xử lý tên tệp", + "pageTitle": "Tên tệp gây rắc rối để kiểm thử - Unicode và độ dài", + "description": "Tệp có tên làm hỏng việc tải lên và lưu trữ: chữ viết khác và emoji, đảo chiều văn bản, ký tự vô hình, cú pháp shell và SQL, giới hạn độ dài.", + "catches": [ + "một tên trông như tên khác trên màn hình, trong nhật ký hoặc trong danh sách", + "một tên bị cắt, xén hoặc viết lại giữa lúc tải lên và lưu trữ", + "giới hạn độ dài tính bằng ký tự trong khi bộ lưu trữ tính bằng byte" + ], + "details": {} + }, + "size-boundaries": { + "question": "Giới hạn kích thước có được áp dụng đúng nơi nó được khai báo không?", + "title": "Ranh giới kích thước", + "pageTitle": "Kiểm thử giới hạn kích thước tải lên - tệp đúng ranh giới", + "description": "Tệp thấp hơn một byte, đúng bằng và cao hơn một byte so với giới hạn hệ thống bạn khai báo, cùng các bước rộng hơn hai phía, mỗi tệp đánh dấu có nên được chấp nhận.", + "catches": [ + "lỗi lệch một ở giới hạn", + "nhầm MB với MiB, tức 4,8 phần trăm và đủ để lọt một tệp lẽ ra không được qua", + "giới hạn được áp dụng ở trình duyệt chứ không phải ở máy chủ" + ], + "details": { + "limit": "Giới hạn kích thước mà hệ thống của bạn khai báo. Mọi thứ khác được đo từ đó.", + "spread": "Vươn ra xa bao nhiêu về hai phía của giới hạn, dưới dạng danh sách kích thước." + } + }, + "tabular-import": { + "question": "Việc nhập bảng của tôi có chịu được những gì công cụ thật xuất ra không?", + "title": "Nhập bảng", + "pageTitle": "Tệp kiểm thử nhập CSV và Excel - dấu phân cách, tiêu đề", + "description": "CSV với dấu phân cách khác, kết thúc dòng CR LF, không tiêu đề và dấu trích dẫn khác, bảng rất rộng, sổ làm việc Excel và JSON ở vài bố cục.", + "catches": [ + "tệp dùng dấu chấm phẩy bị đọc thành một cột, vì dấu phân cách được giả định thay vì được dò tìm", + "tệp CRLF bị tách thành các dòng với một dòng trống sau mỗi dòng", + "bảng không có tiêu đề mà dòng dữ liệu đầu bị nuốt làm tên cột", + "lần nhập giữ các cột nó hiển thị được và lặng lẽ bỏ phần còn lại", + "trình đọc lấy bản ghi JSON từng dòng một và dừng ở tài liệu thụt lề đầu tiên" + ], + "details": { + "rows": "Bảng tính có bao nhiêu dòng. Tệp được ghi đúng bằng kích thước mà chừng đó dòng đóng gói thành, nên ngân sách ở trên dịch chuyển theo giá trị này.", + "columns": "Mỗi dòng của bảng tính có bao nhiêu cột. Số dòng nhân số cột có trần, và yêu cầu vượt trần sẽ bị từ chối trước khi ghi bất cứ thứ gì." + } + }, + "text-encoding": { + "question": "Trình đọc của tôi có biết tệp ở mã hóa nào, hay chỉ đoán?", + "title": "Mã hóa văn bản", + "pageTitle": "Tệp kiểm thử mã hóa văn bản - UTF-8, UTF-16, BOM, CRLF", + "description": "Cùng một văn bản ở UTF-8, UTF-16LE và UTF-16BE, có và không có dấu thứ tự byte, cùng kết thúc dòng CR LF và LF, để kiểm thử cách trình đọc giải mã.", + "catches": [ + "trình đọc giả định UTF-8 và hiện tệp UTF-16 thành cứ ba ký tự mới có một, hoặc thành hàng ô vuông", + "dấu thứ tự byte bị đọc như nội dung, nên trường đầu tiên của lần nhập bắt đầu bằng ba ký tự lạ", + "trình nhập đoán mã hóa từ các byte đầu và đoán khác đi với tệp dài hơn", + "tệp CRLF bị tách thành các dòng với một dòng trống sau mỗi dòng, hoặc ký tự xuống dòng còn sót trong trường cuối" + ], + "details": { + "sample": "Mỗi tệp trong bộ lớn bao nhiêu. UTF-16 lưu hai byte cho mỗi ký tự, nên số lẻ bị từ chối." + } + }, + "upload-validation": { + "question": "Biểu mẫu tải lên của tôi có nhận đúng thứ nó cần và từ chối phần còn lại không?", + "title": "Kiểm tra tải lên", + "pageTitle": "Tệp kiểm thử kiểm tra tải lên - loại, kích thước và tên", + "description": "Tệp để kiểm thử biểu mẫu tải lên: loại được phép và bị cấm, nội dung không khớp phần mở rộng, giới hạn kích thước, tên độc hại và tải lên hàng loạt.", + "catches": [ + "giới hạn được áp dụng ở trình duyệt chứ không phải ở máy chủ", + "tệp SVG hoặc HTML bị tưởng là ảnh hay văn bản thuần, một cách để lách tập lệnh qua biểu mẫu", + "tệp chỉ được kiểm bằng phần mở rộng mà không bao giờ mở, nên PDF đặt tên .jpg vẫn qua", + "biểu mẫu đọc cả phần thân vào bộ nhớ trước khi xem nó lớn đến đâu", + "lần tải lên tên PHOTO.JPG bị từ chối trong khi photo.jpg được nhận, hoặc ngược lại", + "tên có dấu cách, ngoặc hoặc ký tự ngoài ASCII được ghi xuống đĩa không thay đổi" + ], + "details": { + "limit": "Giới hạn kích thước mà biểu mẫu tải lên của bạn khai báo. Bộ này đi một bước về mỗi phía - muốn tệp ở mọi khoảng cách, hãy chạy preset size-boundaries.", + "allow": "Biểu mẫu của bạn nên chấp nhận những loại nào. Mỗi loại trở thành một tệp thật thuộc loại đó, và chúng là đối chứng dương của cả bộ.", + "deny": "Biểu mẫu của bạn nên từ chối những phần mở rộng nào. Phần mở rộng mà bản dựng này không có định dạng vẫn nhận một tệp mang tên đó, chứa văn bản thuần.", + "far-over": "Tệp lớn duy nhất vượt giới hạn bao xa. Tắt đi nếu ghi gấp nhiều lần giới hạn không đáng với dung lượng đĩa.", + "bulk": "Số tệp trong lần tải lên hàng loạt. Bằng không thì bỏ hẳn nhóm đó khỏi bộ." + } + } + }, + "commands": { + "generate": "tạo tệp, từ công thức hoặc từ các cờ", + "validate": "kiểm tra công thức và không ghi gì cả", + "verify": "kiểm tra một thư mục đối chiếu với manifest", + "cleanup": "xóa các tệp mà manifest liệt kê", + "recipe fmt": "in công thức ở dạng chuẩn hóa", + "preset": "dựng một bộ tệp từ một câu hỏi kiểm thử có tên", + "formats": "liệt kê các định dạng bản dựng này hỗ trợ", + "damage": "liệt kê các cách bản dựng này có thể cố ý làm hỏng một tệp", + "tool": "các tiện ích nhỏ cho tệp bạn đã có", + "version": "in phiên bản công cụ", + "license": "in giấy phép và ý nghĩa của nó với tệp được tạo" + }, + "outcomes": { + "accept": "Hệ thống của bạn nên nhận tệp.", + "reject": "Hệ thống của bạn nên từ chối tệp.", + "sanitize": "Hệ thống của bạn nên nhận tệp và làm sạch nó, ví dụ bằng cách đổi tên.", + "unspecified": "Tùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không." + }, + "damages": { + "zero-head": "Ghi đè các byte đầu của tệp bằng số không, giữ nguyên độ dài. Hầu hết trình đọc nhìn vào đó trước, nên gần như mọi thứ đều nhận ra hỏng hóc này." + }, + "terms": { + "oracleNone": "không áp dụng", + "int": "số nguyên bất kỳ", + "choice": "một trong một tập cố định", + "bool": "đúng hoặc sai", + "size": "kích thước như 2mb", + "text": "văn bản", + "pixels": "pixel", + "paragraphs": "đoạn văn", + "rows": "dòng", + "columns": "cột", + "slides": "trang chiếu", + "hertz": "hertz", + "megapixels": "megapixel", + "million cells": "triệu ô", + "entries per second": "mục mỗi giây", + "files": "tệp", + "sizes separated by commas": "các kích thước cách nhau bằng dấu phẩy", + "format ids separated by commas": "các id định dạng cách nhau bằng dấu phẩy", + "format ids separated by commas, or all": "các id định dạng cách nhau bằng dấu phẩy, hoặc all", + "extensions separated by commas": "các phần mở rộng cách nhau bằng dấu phẩy", + "the id of a format, as tfg formats lists them": "id của một định dạng, như tfg formats liệt kê", + "the password, in plain text": "mật khẩu, ở dạng văn bản thuần", + "any text": "văn bản bất kỳ", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "ngày như 2024-02-29 hoặc 2024-02-29T13:45:00+02:00, hoặc none" + }, + "faq": [ + { + "q": "Điều này khác gì dd, fsutil hay truncate?", + "a": "Chúng cho bạn một tệp đúng kích thước nhưng đầy sự trống rỗng. Tệp 2 MB tên photo.png tạo kiểu đó không phải PNG, nên bất cứ thứ gì thực sự phân tích nó sẽ từ chối vì lý do sai, và bài kiểm thử của bạn cũng qua vì lý do sai. Công cụ này tạo ra một PNG thật đúng 2 MB, mở được trong trình xem ảnh, và đi kèm lời khai về cách hệ thống của bạn cần xử lý nó.", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "Nó có miễn phí không, và tôi dùng ở chỗ làm được không?", + "a": "Có cho cả hai. Nó phát hành theo GPL-3.0 và không tốn gì. Không có tài khoản, khóa giấy phép hay gói trả phí." + }, + { + "q": "Tôi có dùng tệp được tạo trong sản phẩm mã nguồn đóng được không?", + "a": "Được. Giấy phép áp dụng cho mã của công cụ, không áp dụng cho thứ công cụ tạo ra. Tệp, công thức và manifest được tạo là đầu ra chứ không phải tác phẩm phái sinh, nên bạn có thể commit và phân phối mà không có nghĩa vụ nào." + }, + { + "q": "Tệp được tạo có chứa dữ liệu cá nhân thật không?", + "a": "Không. Mọi thứ bên trong đều được tổng hợp từ một seed. Không có tập dữ liệu nào được đọc, không dịch vụ nào được liên hệ và không nội dung bên thứ ba nào được nhúng. Hãy coi địa chỉ e-mail được tạo là không dùng được thay vì chưa dùng, vì chuỗi ngẫu nhiên nào cũng có thể ngẫu nhiên trùng với địa chỉ thật." + }, + { + "q": "Tôi có nhận đúng các tệp giống hệt trên máy khác không?", + "a": "Có, từng byte, với cùng công thức và cùng seed. Dự án kiểm thử điều đó ở mỗi thay đổi, và phá vỡ nó đòi hỏi tăng phiên bản chính. Đó là điều cho phép bạn commit một công thức nhỏ thay vì các fixture nhị phân lớn." + }, + { + "q": "Nó có cần kết nối internet không?", + "a": "Không bao giờ. Không có telemetry, không kiểm tra cập nhật và không có máy khách đám mây, và bản nhị phân dòng lệnh hoàn toàn không biên dịch sẵn ngăn xếp mạng. Nó chạy trên máy không có mạng và trong môi trường doanh nghiệp đóng." + }, + { + "q": "Chuyện gì xảy ra nếu tôi yêu cầu kích thước mà một định dạng không thể đạt tới?", + "a": "Bạn nhận một lỗi nêu định dạng, kích thước nhỏ nhất có thể, lý do của mức sàn đó và việc nên làm thay thế, và không có tệp nào được ghi. Công cụ không bao giờ làm tròn kích thước một cách lặng lẽ. Mỗi mức sàn đều được liệt kê trên trang định dạng.", + "code": "tfg formats png" + }, + { + "q": "Tôi có thể tạo một tệp cố ý bị hỏng không?", + "a": "Có. Thêm --damage zero-head và tệp ra đúng kích thước bạn yêu cầu, với các byte đầu bị ghi đè bằng số không, nên trình đọc từ chối nó, và manifest nói hệ thống của bạn phải từ chối nó. Chi tiết nằm ở trang về tệp kiểm thử bị hỏng.", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "Những định dạng nào sắp có?", + "a": "7z, mp3 và mp4. Hôm nay có {{ .Facts.FormatCount }} định dạng hoạt động trọn vẹn từ đầu đến cuối." + }, + { + "q": "Tôi chạy nó trên những hệ thống nào?", + "a": "Dòng lệnh chạy trên Windows và Linux cả Intel lẫn ARM, và trên Mac Apple Silicon. Cửa sổ desktop được cung cấp cho Windows trên Intel, Linux trên Intel và Mac Apple Silicon. Mac Intel không được hỗ trợ và không có gì được dựng cho chúng." + }, + { + "q": "Tôi có phải cài gì không?", + "a": "Không. Tải kho lưu trữ cho hệ thống của bạn, giải nén và chạy bản nhị phân. Không có trình cài đặt, không có runtime cần thêm và không có phụ thuộc cần giải quyết. Nếu bạn có Go, một lệnh go install duy nhất cũng được.", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "Vì sao chạy trên hàng nghìn tệp chậm hơn trên Windows?", + "a": "Vì Windows tính phí nhiều hơn cho mỗi đường dẫn nó xem, và một lệnh duyệt hàng nghìn tệp xem hàng nghìn đường dẫn. Đo trên một máy với 3000 tệp 1 kB, verify mất khoảng 0,9 giây trên Windows và khoảng 0,2 giây trên Linux trong container. Đường dẫn đầu ra ngắn hơn làm con số Windows nhỏ đi, vì mỗi thư mục phía trên các tệp đều nằm trong thứ được xem." + } + ] +} diff --git a/web/content/vi/use-cases.html b/web/content/vi/use-cases.html new file mode 100644 index 00000000..3c1cc6aa --- /dev/null +++ b/web/content/vi/use-cases.html @@ -0,0 +1,129 @@ +

Mọi người dùng nó để làm gì

+

+ Năm việc xuất hiện trong gần như mọi dự án nhận tệp từ con người, và lệnh làm từng việc. Mỗi ví dụ + bên dưới chạy đúng như được viết. +

+ +
+

Giới hạn tải lên

+

Kiểm thử xem giới hạn kích thước tệp có được áp dụng đúng nơi nó nói không

+

+ Một giới hạn là ba trường hợp kiểm thử chứ không phải một: ngay dưới, đúng bằng và ngay trên. Làm + tay thì phải tính số byte và hy vọng không lệch một. Hãy yêu cầu cả bộ: +

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

+ Bạn nhận ba PDF thật có 1048575, 1048576 và 1048577 byte, cùng manifest nói hai tệp đầu nên được + chấp nhận và tệp thứ ba bị từ chối vì size_limit. Bài kiểm thử của bạn đọc kỳ vọng + thay vì bạn viết tay ba câu khẳng định - và khi giới hạn đổi, bạn đổi một con số rồi chạy lại. +

+

+ Điều tương tự dùng được không cần preset khi bạn muốn một bộ ranh giới đơn ngay trong lệnh: +

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

Tích hợp liên tục

+

Giữ fixture ngoài kho mã mà không mất chúng

+

+ Fixture nhị phân lớn làm kho mã clone chậm và khó review, và không ai biết cái gì đã đổi khi thay + một tệp. Công thức là vài trăm ký tự YAML dựng lại các tệp giống hệt - từng byte, trên + mọi máy - vì mọi tệp đều suy ra từ seed của lần chạy. +

+
- 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
+

+ Mỗi kết cục có mã thoát riêng, nên pipeline phân biệt được công thức xấu, đĩa đầy và sai lệch khi + xác minh. Lần chạy thất bại không in gì ra đầu ra chuẩn, nhờ vậy trình phân tích nhật ký không + đọc lỗi thành dữ liệu. +

+
+ +
+

Quy mô

+

Tìm hiểu chuyện gì xảy ra khi thư mục lớn

+

+ Quy trình nhập, tác vụ ban đêm và danh sách thư mục hoạt động khác nhau ở mười nghìn tệp so với mười + tệp. Kích thước rút từ một khoảng làm bộ trông như lưu lượng thật thay vì mười nghìn tệp giống + hệt, và lần rút lấy từ seed, nên bộ ngày mai vẫn như cũ. +

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

+ Kiểm tra một lần chạy sẽ tốn bao nhiêu trước khi nó ghi gì, điều quan trọng khi tổng được đo bằng + gigabyte: +

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

+ Lần chạy lớn hơn dung lượng trống của đĩa bị từ chối trước khi byte đầu tiên được ghi, thay vì làm + đầy đĩa rồi hỏng giữa chừng. +

+
+ +
+

Tệp nén

+

Kiểm thử trình giải nén với tệp nén thật sự chứa tệp

+

+ Tệp nén rỗng có đuôi đúng chẳng chứng minh gì về mã mở nó và duyệt những gì bên trong. Hãy khai báo + nội dung và tệp nén thật sự chứa nó: +

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

+ Độ sâu lồng nhau, số mục và kích thước phần bên trong đều là những thứ mà quy trình nhập có ý kiến + riêng, và đây là cách bạn biết ý kiến đó là gì. +

+
+ +
+

Bộ phân tích và trình xem

+

Kiểm tra mã của chính bạn đọc một định dạng như phần mềm thật

+

+ Mỗi định dạng ở đây được kiểm tra bằng trình đọc độc lập trước khi phát hành - PNG được mở và so + sánh pixel, DOCX được các thư viện riêng đọc lại, tệp nén được giải nén. Nghĩa là tệp mà bộ phân + tích của bạn từ chối là một phát hiện về bộ phân tích của bạn, không phải về trình tạo. +

+
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
+

+ Trang định dạng liệt kê các thiết lập mỗi định dạng nhận và tệp nhỏ + nhất mà mỗi định dạng có thể có. +

+
+ +
+

Hướng dẫn

+

Hai trong số đó, chi tiết hơn

+ +
+ +
+

Dành cho ai

+

+ Kỹ sư QA, tự động hóa kiểm thử và bất kỳ ai có mã đứng sau là biểu mẫu tải lên, quy trình nhập, bộ + phân tích cú pháp hoặc hạn ngạch lưu trữ. Nó chạy trên máy hoàn toàn không có mạng, điều quan + trọng trong môi trường doanh nghiệp đóng nơi trình tạo chạy trên trình duyệt không phải một lựa + chọn. +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/zh-Hans/ci.html b/web/content/zh-Hans/ci.html new file mode 100644 index 00000000..7cb9c3dd --- /dev/null +++ b/web/content/zh-Hans/ci.html @@ -0,0 +1,170 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

如何在 CI 流水线中生成测试文件

+

+ 仓库里的二进制 fixture 会永远留在历史中,无法在 diff + 里审查,文件一大就根本行不通。请改为在流水线内部用配方生成这些文件。配方是文本,每次生成的字节都相同,最后一步还能证明什么都没有变动。 +

+ +
+

简短回答

+

+ 安装 tfg,在测试之前运行 tfg generate fixtures.yaml --out ./fixtures,在测试之后运行 + tfg verify ./fixtures/manifest.json。这两步都会自行让构建失败,并给出说明原因的退出码。 +

+
+ +
+

为什么不提交

+

为什么 fixture 不该放在仓库里

+ +

+ 该提交的是配方。相同的配方和种子在每台机器上写出相同的字节,所以在流水线里生成的文件,就是你在笔记本上用过的那个文件。 +

+
+ +
+

配方

+

放在测试旁边的配方

+

+ 这个配方写出二十五张应被接受的发票和两张超过限制、应被拒绝的图片,清单会记录这两种预期: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml 会检查它而不写入任何内容,并一次列出所有问题。 +

+
+ +
+

GitHub Actions

+

安装工具并构建 fixture 的工作流

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 校验和那一行把压缩包与同一发行版中的 verify-SHA256SUMS.txt 比对。版本是固定的,所以新发行版绝不会改变你没动过的构建。 +

+
+ +
+

GitLab CI

+

同样的事,写成 GitLab 作业

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

变红的时候

+

什么会让一个步骤失败,为什么

+

+ 每种结局都有自己的退出码,所以步骤会自行失败,日志会说明是哪一种。流水线会遇到的有: +

+ +

+ 失败的运行不会向标准输出打印任何内容,所以日志解析器永远不会把错误当成数据。完整的表格在文档页面上。 +

+
+ +
+

PowerShell

+

PowerShell 脚本还需要多写一行

+

+ PowerShell 不会把程序的退出码带出 .ps1 文件。用 -File 运行一个脚本,即使里面的工具拒绝了工作,脚本也会返回 + 0,于是本该变红的构建变成了绿色。最后一行就是全部的修复: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 这是 PowerShell 的行为,与本工具无关。cmd、bash 和 zsh 不需要额外处理。 +

+
+ +
+

多个作业

+

在作业之间共享 fixture

+

+ 通常不需要上传它们。因为相同的配方写出相同的字节,每个作业都可以运行自己的 tfg + generate,这比上传再下载更快。当一个作业必须接收另一个作业的文件时,在传输之后对清单运行 tfg verify,它会告诉你收到的是否就是写出的。 +

+
+ +
+

接下来

+

从这里去哪里

+ +
diff --git a/web/content/zh-Hans/damage.html b/web/content/zh-Hans/damage.html new file mode 100644 index 00000000..5d31022c --- /dev/null +++ b/web/content/zh-Hans/damage.html @@ -0,0 +1,150 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

如何制作用于测试的损坏文件

+

+ 一个只见过完好文件的校验器,并没有真正被测试过。下面介绍如何得到一个故意弄坏的文件:它的大小恰好就是你要求的大小,并附带一份清单,说明你的系统该如何处理它。 +

+ +
+

简短回答

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out 会写出一个恰好 2097152 字节的 + PNG,它的开头几个字节是零,旁边的清单则记录你的系统应该拒绝它。 +

+
+ +
+

常见做法

+

为什么手工弄坏的文件不是好测试

+

+ 常见做法是用十六进制编辑器、用脚本翻转几个随机字节,或用 head 或 truncate 把文件截短。它们能用一次,之后就要付出代价: +

+ +
+ +
+

你会得到什么

+

损坏的文件仍然是你要求的大小

+

+ 文件先正常生成,再在写入磁盘的途中被弄坏。它保持你要求的大小,同一条命令再次写出的字节也完全相同。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 设置写在冒号之后。该选项可以重复,损坏按你写下的顺序依次应用。它适用于全部 {{ .Facts.FormatCount }} 种格式。 +

+
+ +
+

它能做什么

+

有哪些损坏方式?

+

+ 这是程序打印出的列表,在构建本页时从程序中读取。tfg damage 打印的是同一份列表,tfg damage <id> + 则说明其中某一项接受什么设置。 +

+ {{ template "damagesTable" . }} +

+ zero-head + 把文件开头写成零。大多数读取器最先看的就是那里,也就是说明文件是什么的签名和文件头,所以几乎任何读取器都会发现。纯文本和日志没有签名,同样会被拒绝,因为一串零字节不是文本。低于四个字节时,有些格式产生的损坏没有任何读取器会抱怨,这就是该设置从四开始的原因。 +

+
+ +
+

清单怎么说

+

一份说明应发生什么的清单

+

+ 每个损坏的文件都会得到一条记录,说明你的系统应该拒绝它,损坏方式记在旁边: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 有两种请求会在写入任何内容之前被拒绝,因为各自都会在磁盘上留下一个清单描述有误的文件: +

+ +
+ +
+

在配方中

+

一次运行中的完好文件和损坏文件

+

+ 把两者放进同一个配方,清单就带有每个文件的预期,测试因此不需要一份说明哪个是哪个的列表: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

在测试中

+

把它变成测试

+

+ 测试读取清单,检查实际发生的是否就是所声明的。它不需要文件名列表: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 好的拒绝是干净的拒绝。一条说明错在哪里的消息,就是你想要的答案。服务器错误、卡死或只保存了一半的文件,正是这个测试要找出来的缺陷。 +

+
+ +
+

接下来

+

从这里去哪里

+ +
diff --git a/web/content/zh-Hans/docs.html b/web/content/zh-Hans/docs.html new file mode 100644 index 00000000..a18c2b4f --- /dev/null +++ b/web/content/zh-Hans/docs.html @@ -0,0 +1,244 @@ +

文档

+

+ 工具的全部功能,按人们实际会问的问题来组织。仓库中的 README 是完整参考,并且始终与你下载的版本一致。 +

+ +
+

有哪些命令?

+

每个命令只做一件事:

+ {{ template "commandList" . }} +
+ +
+

如何生成一个大小精确的文件?

+

+ 指定格式、大小和输出位置。大小按 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>围绕一个限制的三个文件:小一字节、恰好等于限制、大一字节
--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将清单写到标准输出
+
+
+ +
+

如何做一个故意损坏的文件?

+

+ 本工具写出的其他所有文件在构造上都是正确的,这回答了上传校验器会问的三个问题中的两个。--damage + 回答第三个,也就是文件到底能不能打开。文件先正常生成,再被破坏,因此仍然保持你请求的大小。 +

+
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,并在旁边记录所做的破坏。有两种情况会在写入任何内容之前被拒绝,因为各自都会在磁盘上留下清单描述有误的文件: +

+ +

+ 第三种无法提前得知。如果某个破坏运行后没有改动任何字节,该文件会被丢弃而不是写出,运行会继续,指出是哪个文件,并以部分完成的退出码结束。 +

+

+ 一步一步来,附带一个读取清单的测试:如何制作用于测试的损坏文件。 +

+
+ +
+

配方是什么样子?

+

+ 配方是一个描述整次运行的 YAML 文件。把它与测试放在一起提交,fixture 就不再是仓库里的二进制文件,任何人都可以用一个只有几百个字符的文件逐字节重建它们。 +

+
# 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
+

+ 每个 target 必须恰好有 size、size-range、boundary 或 + contains + 中的一个。两个是错误,一个都没有也是错误。无效的配方不会写入任何文件,并且会一次报告所有问题,而不是只报第一个,每个问题都会指明所涉及的设置。 +

+
+ +
+

如何声明我的系统应如何处理某个文件?

+

只需结果时用短写法,原因重要时用长写法:

+
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。 +

+

+ 原因指明的是起作用的规则,而不是裁决。所以同一个原因可以出现在两种结果之下:比限制小一字节的文件是 accept,而它所涉及的规则仍然是 + size_limit。 +

+
+ +
+

清单里有什么?

+

+ 每次运行结束时,包括被中断的运行,它都会写在文件旁边。每个文件一项: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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,因此清单总能追溯到产生它的来源。 +

+

+ 每一项还带有 target_id,即配方中生成该文件的 target 的 id,summary.by_target 则统计每个 target + 生成的文件数。因此有多个 target 的配方可以逐个 target 检查,无需阅读文件名。 +

+
+ +
+

什么是预设?

+

+ 预设是回答常见测试问题的现成文件集,你不必自己设计。预设底层就是普通配方,eject + 会把配方打印出来,供你从那里开始编辑。每个预设都有自己的页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+ {{ template "presetsList" . }} +
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 会在你构建之前告诉你这个集合的开销,并且在某个数字只是我们的占位值而不是你的限制时直接说明。 +

+
+ +
+

退出码是什么意思?

+

+ 每种结束方式都有自己的代码,机器可读的输出写到标准输出,失败的运行不会在那里打印任何内容。这张表是冻结的约定,改变某个代码的含义需要提升主版本号。 +

+ {{ template "exitCodesTable" . }} +
- 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 流水线中生成测试文件。 +

+
+ +
+

有桌面窗口吗?

+

+ 有,它就是在同一个引擎上加了一个窗口,用于不走脚本的测试。它不是缩水版:有测试逐项对比这两种界面,只有其中一方能做的事必须被声明并说明理由,而不是悄悄地渐行渐远。 +

+

+ 界面有单批生成、预设、同时多批和关于。它会在写入任何内容之前显示一次运行的开销,运行时报告进度,并且可以在中途取消而不会留下写了一半的文件。它目前还不能打开配方文件,配方暂时只属于命令行,窗口通过表单来构建批次。 +

+
diff --git a/web/content/zh-Hans/exact-size.html b/web/content/zh-Hans/exact-size.html new file mode 100644 index 00000000..0f2a3dd9 --- /dev/null +++ b/web/content/zh-Hans/exact-size.html @@ -0,0 +1,123 @@ +

如何创建大小精确的文件

+

+ 每个系统都有对应的命令,下面列出了全部三个。它们能给你一个字节数恰好正确的文件,对许多测试来说这就够了。本页的每条命令在发布前都在对应系统上运行过。 +

+ +
+

简短回答

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。大小以字节计,按文件管理器的算法,10 MB 就是 10485760 字节。 +

+
+ +
+

Windows

+

fsutil,以及无需额外工具的 PowerShell 写法

+

+ fsutil 随 Windows 提供。它接受以字节为单位的大小,所以先算出数字:10 MB 是 10485760,100 MB 是 + 104857600,1 GB 是 1073741824。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ 在 Windows 11 上实测:它可以在普通命令提示符下运行,不需要管理员权限,生成的文件恰好是 10485760 字节。 +

+

PowerShell 不需要调用其他程序也能做到同样的事,并且认识单位:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell 中的 10MB 表示 10485760 字节,与资源管理器使用的 1024 进制算法相同,所以上面两条命令得到的大小一样。 +

+
+ +
+

Linux

+

dd、truncate 和 fallocate,以及容易坑人的差别

+

dd 是人人皆知的那个。它真的会写入这些字节:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate 是瞬间完成的,而这正是陷阱所在。在 Alpine Linux 上实测,该文件报告 10485760 + 字节,却占用零个块,它是一个稀疏文件。任何读取它的程序会得到十兆字节的零,但磁盘从未真正让出空间: +

+
truncate -s 10M test10mb.bin
+

+ 用它测试上传限制没问题,但用来测试磁盘配额就会误导人。当空间必须真实占用时,应该使用 fallocate: +

+
fallocate -l 10M test10mb.bin
+

而当内容必须不可压缩,让归档程序无法再把它压小时:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile(不是稀疏文件),以及你已经熟悉的另外两个

+

+ macOS 自带 mkfile。在 macOS 26.6.2 上实测:10485760 字节和 20480 个块,所以空间是真正分配的,而不只是承诺: +

+
mkfile 10m test10mb.bin
+

dd 和 truncate 也都有,行为与 Linux 上相同:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

这种办法在哪里失效

+

大小正确的文件不等于类型正确的文件

+

+ 以上所有方法给你的都是一块零。如果被测对象只看大小,比如上传限制、配额或传输,这就够了。一旦有任何东西打开这个文件,就不够了。 +

+

+ 实测过,而且值得你自己试一试:用 fsutil 做一个 2 MB 的文件,把它命名为 photo.png,再交给图像库处理。Pillow 会回答 + cannot identify image file。它不是 PNG,从来就不是,只是名字这么说。 +

+

+ 这比听起来更重要,因为测试随后会以哪种方式失败。你的上传接口拒绝了这个文件,测试变绿,于是你断定大小限制有效。其实它并不是因为大小而拒绝的,而是因为这些字节不是图片,你本想测试的规则根本没有被触及。 +

+ +
+ +
+

另一种办法

+

该格式的真实文件,大小恰好是你要求的

+

+ 这就是 Testing Files Generator 所做的事。文件是该格式的真实文件,能在对应软件中打开,字节数恰好等于你的要求,精确到字节: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 请求格式无法达到的大小,你会得到一个说明下限及其原因的错误,绝不会得到大小错误的文件。格式页面列出了每种格式及其能生成的最小文件。 +

+

而一个限制对应的是三个测试用例,而不是一个,所以工具会把三个都构建出来:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 这会给你 10485759、10485760 和 10485761 + 字节的文件,以及一份清单,说明你的系统应该接受哪些、拒绝哪些。使用场景页面会讲解这一点,以及它为之而生的另外四项任务。 +

+ {{ template "downloadCta" . }} +
+ +
+

那么该用哪个?

+ +

+ 两种办法都在本页,因为它们各自在一部分情况下是对的。要避免的错误,是在需要后者的地方用了前者,还把变绿的测试当成证明。 +

+
diff --git a/web/content/zh-Hans/faq.html b/web/content/zh-Hans/faq.html new file mode 100644 index 00000000..c90f0107 --- /dev/null +++ b/web/content/zh-Hans/faq.html @@ -0,0 +1,16 @@ +

常见问题

+

+ 许可证、隐私、可复现性,以及人们在把生成器放进构建流水线之前会确认的事项。如果这里没有你的问题,问题跟踪器是开放的。 +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

还在犹豫?

+

+ 使用场景页面展示了它为之而生的任务,格式页面列出了每种格式及其能生成的最小文件。仓库中的 + README 是完整参考。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/zh-Hans/formats.html b/web/content/zh-Hans/formats.html new file mode 100644 index 00000000..5c6a566d --- /dev/null +++ b/web/content/zh-Hans/formats.html @@ -0,0 +1,65 @@ +

{{ .Facts.FormatCount }} 种文件格式,每一种都按精确大小生成

+

+ 它们每一个都是该格式的真实文件。它能在对应软件中打开,字节数恰好等于你的要求。没有一个是粘上扩展名的填充零。 +

+ +{{ template "formatsTable" . }} + +
+

各列的含义

+ +

+ 每种格式也都能精确到字节地重复:相同的配方和种子在任何机器上都生成相同的文件,这正是提交配方来代替 fixture 本身是安全的原因。 +

+
+ +
+

每种格式接受的设置

+

+ 大多数格式有自己的设置,比如图片尺寸、JPEG 质量、PDF 页数、电子表格的行数和列数、压缩包里放多少条目。在命令行用 --set key=value 设置,或在配方的 + properties: 下设置。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ 超出设置所接受范围的值会被拒绝,并给出指明该设置、允许范围以及应改用什么的消息。未知的设置同样是错误,绝不会静默使用默认值,因为悄悄接受的拼写错误会生成设置有误的文件,让你花一小时纳闷为什么该失败的测试却通过了。 +

+

+ 运行 tfg formats <id> 即可查看某个格式在你当前版本中接受哪些设置。 +

+
+ +
+

压缩包里装的是真实文件

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} 和 {{ end }}{{ $c.ID }}{{ end }} + 可以填入条目,而不是只留一个空壳。生成的压缩包确实包含它声称包含的文档,所以测试期间解压它的任何程序都会在里面找到真实文件。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/zh-Hans/index.html b/web/content/zh-Hans/index.html new file mode 100644 index 00000000..9c73cb4a --- /dev/null +++ b/web/content/zh-Hans/index.html @@ -0,0 +1,183 @@ +
+
+

生成大小精确的真实测试文件

+

+ PDF、PNG、DOCX、ZIP,共 {{ .Facts.FormatCount }} + 种格式,每一种都是能在对应软件中打开的真实文件,大小恰好等于你的要求。每次运行还会写下你的应用应该如何处理每个文件。命令行加桌面窗口,免费开源,完全在你的机器上运行。 +

+ + {{ template "downloadCta" . }} +
+ +
+ Testing Files Generator 的桌面窗口,已准备好写出一批测试文件 +
桌面窗口,已准备好写出一批文件。命令行背后运行的是同一个引擎。
+
+
+ + + +
+

问题所在

+

做一个测试文件很容易,做出对的一千个才是麻烦所在

+

你在测试接收用户文件的软件。迟早你会需要:

+ +

+ 这正是它要取代的。它为 QA 工程师、测试自动化,以及代码背后有上传表单、导入程序、解析器或存储配额的所有人而做。 +

+
+ +
+

它的与众不同之处

+

其他生成器止步于字节。这个工具回答你的测试真正要问的问题

+

+ 一个满是文件的文件夹仍然要你自己判断每个文件应该证明什么。这里每次运行都会在文件旁写出一个 + manifest.json,它是所生成内容的简单清单,并为每一项给出声明的预期。 +

+

假设你的上传接口允许 1 MB。请求恰好位于这条线上的三个文件:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
文件字节你的系统应该原因
1mb_under_1b.pdf1048575接受在限制之内
1mb_at_limit.pdf1048576接受限制本身是允许的
1mb_over_1b.pdf1048577拒绝size_limit
+
+ +

三个文件,三种不同的答案,以机器可读的形式给出。你的测试读取清单,而不是由你手写断言:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

当答案取决于你自己的策略时,清单会如实说明

+

+ 它记录的是 unspecified,而不是凭空编造预期。会猜测的生成器会制造误报,而总是误报的测试套件最终会被关掉。 +

+
+
+ +
+

预设

+

选好问题,拿到整套文件

+

+ 预设是围绕一个测试问题设计的测试文件集,你不必自己琢磨哪些文件能证明什么。每个预设都有一个页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+ {{ template "presetsList" . }} +

全部预设,以及它们与配方的关系

+
+ +
+

快速开始

+

三条命令,看它如何工作

+
    +
  1. +

    生成一个文件

    +

    一个 PNG,恰好两兆字节:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    生成大量文件

    +

    + 一万个日志文件,每个在 1 到 8 KB + 之间,大小由种子抽取,因此明天会得到同样的文件集。给每次运行一个独立的目录,清单是一次运行所写内容的唯一记录,所以工具拒绝在其上再写第二份: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    先检查,再删除

    +

    verify 告诉你没有任何变动。cleanup 只删除写出的内容,不动其他任何东西:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 大小按 1024 进制计算,与你的文件管理器一致,所以 2mb 表示 2097152 + 字节。直接写字节数也可以。文档涵盖配方、清单和退出码。 +

+
+ +
+

你将得到什么

+

为无人值守的测试套件而生

+ +
+ +
+

下载

+

选择适合你系统的版本

+

+ 解压压缩包后运行即可。tfg 是命令行,tfg-gui 是桌面窗口。没有安装程序,也无需向你的机器添加任何东西。 +

+ {{ template "downloadsTable" . }} +
+

哪些已签名,哪些没有

+

+ Windows 和 macOS 的下载包已签名,因此启动时不会出现未知开发者的警告。Linux 的没有签名,因为桌面 Linux 没有可用的对应签名机制。每个压缩包都列在发布页面的 + verify-SHA256SUMS.txt 中,你可以据此核对所下载的内容。 +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/zh-Hans/preset.html b/web/content/zh-Hans/preset.html new file mode 100644 index 00000000..ac3d7c53 --- /dev/null +++ b/web/content/zh-Hans/preset.html @@ -0,0 +1,90 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }} 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ +{{ if .Catches }} +
+

它通常能发现什么?

+ +
+{{ end }} + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show {{ .ID }} 所报告的:

+
+ + + + + + + +
文件数{{ .Budget.Files }}
其配方中的 target 数{{ .Budget.Targets }}
总大小{{ .Bytes }} B
格式{{ join .Budget.Formats ", " }}
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
预期含义文件数
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

你可以更改什么?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
设置接受默认值作用
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} 这个默认值是我们的占位值,不是你的系统的值。请传入你自己的值。{{ end }}
+
+ {{- else }} +

这个预设没有任何设置。每次得到的集合都相同。

+ {{- end }} +
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/zh-Hans/presets.html b/web/content/zh-Hans/presets.html new file mode 100644 index 00000000..5e24837c --- /dev/null +++ b/web/content/zh-Hans/presets.html @@ -0,0 +1,25 @@ +

测试文件预设,每个测试问题一套文件

+

+ 预设是围绕一个问题设计的整套测试文件,并附带说明你的系统应如何响应每个文件的清单。你选择问题,工具构建文件集。每个预设都有自己的页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+ +{{ template "presetsList" . }} + +
+

预设与配方有何不同?

+

+ 在底层没有不同。预设就是工具根据几项设置替你写出的配方。tfg preset eject + 会把这个配方打印出来,方便你与测试放在一起并加以编辑,你自己的配方也可以用一行基于某个预设,即 extends: preset: 后面跟上它的 id。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

我可以信任默认值吗?

+

+ 对文件来说可以。对于只有你的系统才知道的数字,比如上传表单的限制,默认值是我们的占位值,工具每次使用时都会这样说明。每个预设的页面都会标出这些设置,tfg preset + show 会在写入任何内容之前告知你。 +

+
diff --git a/web/content/zh-Hans/site.json b/web/content/zh-Hans/site.json new file mode 100644 index 00000000..dcf0983e --- /dev/null +++ b/web/content/zh-Hans/site.json @@ -0,0 +1,328 @@ +{ + "code": "zh-Hans", + "locale": "zh_CN", + "name": "简体中文", + "dir": "zh-hans", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "首页", + "title": "测试文件生成器 - 精确大小,{{ .Facts.FormatCount }} 种真实格式", + "description": "免费开源的 QA 测试文件生成器。生成精确大小的真实 PDF、DOCX、PNG、ZIP 文件,并附带说明系统应如何响应的清单。" + }, + { + "key": "formats", + "slug": "formats", + "nav": "格式", + "title": "{{ .Facts.FormatCount }} 种支持的文件格式 - PDF、DOCX、PNG、ZIP 等", + "description": "生成器支持的全部文件格式、每种格式可能的最小文件,以及各自接受的设置。全部 {{ .Facts.FormatCount }} 种都能在对应软件中打开。" + }, + { + "key": "presets", + "slug": "presets", + "nav": "预设", + "title": "测试文件预设 - 面向 QA 问题的现成文件集", + "description": "现成的测试文件集,每套回答一个测试问题:上传限制、文件名、编码、表格导入、空文件和上传校验。" + }, + { + "key": "docs", + "slug": "docs", + "nav": "文档", + "title": "文档 - 命令、配方、清单、退出码", + "description": "如何通过命令行或 YAML 配方生成测试文件,清单包含什么,以及在 CI 中运行时每个退出码的含义。" + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "使用场景", + "title": "使用场景 - 上传限制、CI fixture、批量测试", + "description": "测试上传大小限制,为 CI 构建可复现的 fixture,生成一万个文件,并用真实内容填充压缩包。" + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "精确大小", + "title": "如何创建指定大小的文件 - Windows、Linux、macOS", + "description": "fsutil、dd、truncate 和 mkfile,每个都在对应系统上实测,以及当测试需要 PDF 或 PNG 时,这样生成的文件为何不行。" + }, + { + "key": "faq", + "slug": "faq", + "nav": "常见问题", + "title": "常见问题 - 关于生成测试文件", + "description": "与 dd 和 fsutil 有何不同,文件能否放心提交,每次运行是否逐字节一致,以及大小无法达到时会怎样。" + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "损坏文件", + "title": "损坏的测试文件 - 大小精确的损坏文件", + "description": "一个故意弄坏、大小精确的文件,附带说明你的系统应拒绝它的清单。用于测试上传校验和解析器。", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "CI 中的测试文件", + "title": "CI 中的测试文件 - GitHub Actions、GitLab CI 和 PowerShell", + "description": "在流水线中生成测试文件,而不是提交二进制文件:GitHub Actions 工作流、GitLab 作业、让构建失败的退出码,以及 PowerShell 的陷阱。", + "parent": "use-cases" + } + ], + "words": { + "skip": "跳到正文", + "navLabel": "主导航", + "langLabel": "语言", + "breadcrumbHome": "首页", + "imageAlt": "Testing Files Generator - 精确大小的真实测试文件,并附带说明系统应如何响应每个文件的清单", + "schemaDescription": "面向 QA 的免费开源测试文件生成器。它生成 {{ .Facts.FormatCount }} 种格式、大小精确的真实文件,并写出说明被测系统应如何响应每个文件的清单。", + "ctaDownload": "下载", + "ctaSource": "查看源代码", + "ctaNote": "免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。", + "colFormat": "格式", + "colName": "名称", + "colExtension": "扩展名", + "colSmallest": "最小文件", + "colFidelity": "完整度", + "colChecked": "验证方式", + "colSetting": "设置", + "colAccepts": "接受", + "colSystem": "系统", + "colCli": "命令行", + "colWindow": "桌面窗口", + "noBinary": "暂无二进制文件", + "colCode": "代码", + "colMeaning": "含义", + "footerBlurb": "面向 QA 的精确大小测试文件,并附带说明系统应如何响应每个文件的清单。", + "footerProject": "项目", + "footerSource": "GitHub 上的源代码", + "footerReleases": "下载", + "footerIssues": "报告问题", + "footerSupport": "支持本项目", + "footerPages": "页面", + "footerLicence": "Copyright (C) 2026 DonislawDev。以 GNU 通用公共许可证第 3 版发布。你生成的文件归你所有,许可证涵盖的是工具本身,而不是它的输出。", + "footerPrivacy": "本站不会从任何地方加载字体、脚本或跟踪器,也不设置 Cookie。", + "notFoundTitle": "找不到这个页面", + "notFoundLead": "你访问的地址与本站任何页面都不匹配。", + "notFoundBack": "返回首页", + "read.format": "集合中每个文件的格式。它是工具本身的参数,预设只是给它一个默认值。", + "readTakes.format": "格式页面中的格式 id", + "colDamage": "损坏方式", + "colEffect": "对字节做了什么", + "colSettings": "设置", + "noSettings": "无" + }, + "endings": { + "0": "一切正常。", + "1": "工具内部出现意外错误。", + "2": "命令或参数有误。", + "3": "配方无效。", + "4": "该格式无法完成所请求的操作。", + "5": "读取或写入失败。", + "6": "磁盘空间不足。", + "7": "verify 发现了不一致。", + "8": "运行已结束,但并非所有文件都已生成。", + "130": "被 Ctrl+C 中断。", + "143": "被信号终止,CI 超时就是这个样子。" + }, + "presets": { + "empty-and-minimal": { + "question": "一个合法且达到格式允许的最小大小的文件能通过吗?", + "title": "空文件与最小文件", + "pageTitle": "各格式最小的合法文件与空文件", + "description": "本工具在 {{ .Facts.FormatCount }} 种格式中各自写出的最小合法文件,以及格式允许时的空文件,每个都附带应有的响应。", + "catches": [ + "合法文件因过小被拒绝,因为检查按字节数判断而不是去读取内容", + "空文件让读取器崩溃,而不是被如实报告", + "只有一像素宽的图片在生成缩略图的途中发生除零错误", + "存储把零字节当成上传失败,并不断重试" + ], + "details": { + "formats": "集合由哪些格式构成。填 all 表示此版本的所有格式,也可以只列出你的系统接受的格式。" + } + }, + "filename-handling": { + "question": "我的系统能否正确保存、显示并返回它没料到的文件名?", + "title": "文件名处理", + "pageTitle": "用于测试的问题文件名 - Unicode 与长度", + "description": "文件名会破坏上传和存储:其他文字与 emoji、从右到左覆盖、不可见字符、shell 与 SQL 语法、长度限制。", + "catches": [ + "在屏幕、日志或列表中看起来像另一个名字的文件名", + "在上传与存储之间被截断、裁剪或改写的文件名", + "按字符计数的长度限制,而存储是按字节计数的" + ], + "details": {} + }, + "size-boundaries": { + "question": "大小限制是否恰好在声明的位置生效?", + "title": "大小边界", + "pageTitle": "测试上传大小限制 - 恰好在边界上的文件", + "description": "比系统声明的大小限制小一字节、恰好等于以及大一字节的文件,外加两侧更宽的梯度,每个都标明是否应被接受。", + "catches": [ + "限制处的差一错误", + "把 MB 与 MiB 混淆,相差 4.8%,足以放过本不该通过的文件", + "限制只在浏览器中生效,而不在服务器上" + ], + "details": { + "limit": "你的系统声明的大小限制。其他一切都以它为基准测量。", + "spread": "在限制两侧各延伸多远,以大小列表表示。" + } + }, + "tabular-import": { + "question": "我的表格导入能应付真实工具导出的内容吗?", + "title": "表格导入", + "pageTitle": "CSV 与 Excel 导入测试文件 - 分隔符、表头", + "description": "使用其他分隔符、CR LF 换行、无表头和其他引号的 CSV,一张极宽的表格,一个 Excel 工作簿,以及多种布局的 JSON。", + "catches": [ + "用分号分隔的文件被读成单列,因为分隔符是假定的而不是探测出来的", + "CRLF 文件被拆成行,每行后面多出一个空行", + "没有表头的表格,第一行数据被当成列名吞掉", + "导入只保留能显示的列,其余的悄悄丢弃", + "读取器逐行读取 JSON 记录,遇到第一个带缩进的文档就停下" + ], + "details": { + "rows": "表格有多少行。文件会写成这么多行恰好打包出的大小,所以上面的预算会随这个值变化。", + "columns": "表格每行有多少列。行数乘列数有上限,超出时会在写入任何内容之前被拒绝。" + } + }, + "text-encoding": { + "question": "我的读取器知道文件是什么编码,还是在猜?", + "title": "文本编码", + "pageTitle": "文本编码测试文件 - UTF-8、UTF-16、BOM、CRLF", + "description": "同一段文本分别用 UTF-8、UTF-16LE 和 UTF-16BE 编码,带或不带字节顺序标记,并使用 CR LF 与 LF 换行,用来测试读取器如何解码文本。", + "catches": [ + "读取器假定为 UTF-8,把 UTF-16 文件显示成每三个字符一个,或一排排方框", + "字节顺序标记被当成内容读取,导致导入的第一个字段以三个多余字符开头", + "导入器根据开头几个字节猜测编码,遇到更长的文件却猜成了别的", + "CRLF 文件被拆成行,每行后面多出一个空行,或回车符残留在最后一个字段里" + ], + "details": { + "sample": "集合中每个文件的大小。UTF-16 每个字符占两个字节,所以奇数会被拒绝。" + } + }, + "upload-validation": { + "question": "我的上传表单是否接受该接受的,并拒绝其余的?", + "title": "上传校验", + "pageTitle": "上传校验测试文件 - 类型、大小与文件名", + "description": "用于测试上传表单的文件:允许与拒绝的类型、内容与扩展名不符、大小限制两侧、恶意文件名,以及批量上传。", + "catches": [ + "限制只在浏览器中生效,而不在服务器上", + "SVG 或 HTML 文件被当成图片或纯文本,这是让脚本绕过表单的一种办法", + "只按扩展名检查而从不打开文件,于是名为 .jpg 的 PDF 蒙混过关", + "表单在查看大小之前就把整个请求体读进内存", + "名为 PHOTO.JPG 的上传被拒绝,而 photo.jpg 被接受,或者相反", + "含空格、括号或非 ASCII 字符的文件名被原样写入磁盘" + ], + "details": { + "limit": "你的上传表单声明的大小限制。这个集合在限制两侧各取一步,若要覆盖任意距离的文件,请运行 size-boundaries 预设。", + "allow": "你的表单应该接受哪些类型。每种类型都会变成该类型的真实文件,它们构成整个集合的阳性对照。", + "deny": "你的表单应该拒绝哪些扩展名。此版本没有对应格式的扩展名,仍会得到一个同名文件,内容为纯文本。", + "far-over": "那个超大文件超出限制多少。如果写入限制数倍大小的文件不值得占用磁盘,可以关闭。", + "bulk": "批量上传包含多少个文件。设为零则完全不包含这一组。" + } + } + }, + "commands": { + "generate": "根据配方或参数生成文件", + "validate": "检查配方,不写入任何内容", + "verify": "对照清单检查目录", + "cleanup": "删除清单中列出的文件", + "recipe fmt": "以规范形式打印配方", + "preset": "根据具名测试问题构建一组文件", + "formats": "列出此版本支持的格式", + "damage": "列出此版本可以故意破坏文件的方式", + "tool": "处理现有文件的小工具", + "version": "打印工具版本", + "license": "打印许可证及其对生成文件的含义" + }, + "outcomes": { + "accept": "你的系统应该接受这个文件。", + "reject": "你的系统应该拒绝这个文件。", + "sanitize": "你的系统应该接受这个文件并加以清理,例如重命名。", + "unspecified": "取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。" + }, + "damages": { + "zero-head": "用零覆盖文件开头的若干字节,长度保持不变。大多数读取器最先看的就是那里,所以几乎任何东西都会发现这种损坏。" + }, + "terms": { + "oracleNone": "不适用", + "int": "任意整数", + "choice": "固定集合中的一个", + "bool": "真或假", + "size": "形如 2mb 的大小", + "text": "文本", + "pixels": "像素", + "paragraphs": "段落", + "rows": "行", + "columns": "列", + "slides": "幻灯片", + "hertz": "赫兹", + "megapixels": "百万像素", + "million cells": "百万个单元格", + "entries per second": "条目每秒", + "files": "个文件", + "sizes separated by commas": "以逗号分隔的大小", + "format ids separated by commas": "以逗号分隔的格式 id", + "format ids separated by commas, or all": "以逗号分隔的格式 id,或 all", + "extensions separated by commas": "以逗号分隔的扩展名", + "the id of a format, as tfg formats lists them": "格式的 id,与 tfg formats 列出的一致", + "the password, in plain text": "明文密码", + "any text": "任意文本", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none" + }, + "faq": [ + { + "q": "这与 dd、fsutil 或 truncate 有何不同?", + "a": "它们给你的是大小正确但内容空空如也的文件。用这种方式做出的名为 photo.png 的 2 MB 文件并不是 PNG,所以任何真正解析它的程序都会因为错误的原因拒绝它,而你的测试也会因为错误的原因通过。本工具生成的是大小恰好 2 MB 的真实 PNG,可以在图片查看器中打开,并附带一份说明,告诉你的系统该如何处理它。", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "它免费吗,我能在工作中使用吗?", + "a": "两者都可以。它以 GPL-3.0 发布,不收取任何费用。没有账号,没有许可证密钥,也没有付费版本。" + }, + { + "q": "我能在闭源产品中使用生成的文件吗?", + "a": "可以。许可证涵盖的是工具的代码,而不是工具生成的内容。生成的文件、配方和清单属于输出而非衍生作品,所以你可以提交它们并随产品分发,不负任何义务。" + }, + { + "q": "生成的文件包含真实的个人数据吗?", + "a": "不包含。里面的一切都由种子合成。不读取任何数据集,不联系任何服务,也不嵌入任何第三方内容。请把生成的电子邮件地址视为不可用,而不是未被使用,因为任何随机字符串都有可能碰巧与真实地址相同。" + }, + { + "q": "在另一台机器上能得到完全相同的文件吗?", + "a": "能,只要配方和种子相同,就能逐字节一致。项目在每次改动时都会测试这一点,要打破它必须提升主版本号。这正是你可以提交一个小配方,而不是大型二进制 fixture 的原因。" + }, + { + "q": "它需要联网吗?", + "a": "从不需要。没有遥测,没有更新检查,也没有云客户端,命令行二进制文件里甚至没有编译进网络栈。它可以在没有网络的机器上运行,也能在封闭的企业环境中使用。" + }, + { + "q": "如果我请求格式无法达到的大小会怎样?", + "a": "你会收到一个错误,说明格式、可能的最小大小、该下限的原因以及应改用什么,并且不会写入任何文件。工具从不会悄悄取整。每个下限都列在格式页面上。", + "code": "tfg formats png" + }, + { + "q": "我能生成故意损坏的文件吗?", + "a": "可以。加上 --damage zero-head,文件就会以恰好所要求的大小输出,开头几个字节被零覆盖,读取器会拒绝它,清单也会说明你的系统应该拒绝它。详情见关于损坏测试文件的页面。", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "接下来会支持哪些格式?", + "a": "7z、mp3 和 mp4。目前有 {{ .Facts.FormatCount }} 种格式可以端到端使用。" + }, + { + "q": "我可以在哪些系统上运行?", + "a": "命令行可在 Windows 和 Linux 上运行,支持 Intel 和 ARM,也支持 Apple 芯片的 Mac。桌面窗口提供 Windows(Intel)、Linux(Intel)和 Apple 芯片 Mac 版本。不支持 Intel Mac,也不会为其构建。" + }, + { + "q": "我需要安装什么吗?", + "a": "不需要。下载适合你系统的压缩包,解压后运行二进制文件即可。没有安装程序,没有需要添加的运行时,也没有需要解决的依赖。如果你装有 Go,一条 go install 命令同样可用。", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "为什么在 Windows 上处理数千个文件更慢?", + "a": "因为 Windows 对查看的每个路径收取更多开销,而遍历数千个文件的命令要查看数千个路径。在一台有 3000 个 1 kB 文件的机器上实测,verify 在 Windows 上约需 0.9 秒,在容器中的 Linux 上约需 0.2 秒。输出路径更短会让 Windows 的数字变小,因为文件上方的每一级文件夹都属于被查看的内容。" + } + ] +} diff --git a/web/content/zh-Hans/use-cases.html b/web/content/zh-Hans/use-cases.html new file mode 100644 index 00000000..549cfa05 --- /dev/null +++ b/web/content/zh-Hans/use-cases.html @@ -0,0 +1,109 @@ +

人们用它来做什么

+

+ 几乎每个接收用户文件的项目都会遇到的五项任务,以及完成每一项的命令。下面的每个示例都能按原样运行。 +

+ +
+

上传限制

+

测试文件大小限制是否在声称的位置生效

+

+ 一个限制对应三个测试用例,而不是一个:刚好低于、恰好等于和刚好高于。手工做这些意味着计算字节数,并祈祷自己没有算错一位。不如直接请求整套文件: +

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

+ 你会得到三个真实的 PDF,大小分别是 1048575、1048576 和 1048577 字节,以及一份清单,说明前两个应被接受,第三个应因 size_limit + 被拒绝。你的测试读取预期,而不是由你手写三个断言,限制改变时,你只需改一个数字再重新运行。 +

+

+ 如果你只想要一组内联的边界文件,不用预设也可以做到: +

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

持续集成

+

让 fixture 留在仓库之外又不丢失

+

+ 大型二进制 fixture 会拖慢仓库克隆,也让评审变得别扭,而且替换其中一个时没有人能看出改了什么。配方只是几百个字符的 + YAML,就能重建出完全相同的文件,在任何机器上逐字节一致,因为每个文件都由运行的种子派生。 +

+
- 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
+

+ 每种结束方式都有自己的退出码,所以流水线可以区分配方错误、磁盘已满和校验不一致。失败的运行不会在标准输出上打印任何内容,这样日志解析器就不会把错误当成数据。 +

+
+ +
+

规模

+

弄清文件夹很大时会发生什么

+

+ 导入程序、夜间任务和目录列表在一万个文件时的表现与十个文件时不同。从范围中抽取的大小让文件集看起来像真实流量,而不是一万个完全相同的文件,并且抽取来自种子,所以明天文件集依然相同。 +

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

+ 在运行写入任何内容之前先查看它的开销,当总量以 GB 计时这一点很重要: +

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

+ 比磁盘可用空间更大的运行会在写入第一个字节之前就被拒绝,而不是把磁盘写满再半途失败。 +

+
+ +
+

压缩包

+

用真正装有文件的压缩包测试解压程序

+

+ 只有正确扩展名的空压缩包,无法证明任何关于打开它并遍历内容的代码的事情。声明内容,压缩包就真的包含它们: +

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

+ 嵌套深度、条目数量和内部内容的大小,导入程序都有自己的看法,而这正是你弄清这些看法的办法。 +

+
+ +
+

解析器与查看器

+

检查你自己的代码读取格式的方式是否与真实软件一致

+

+ 这里的每种格式在发布前都用独立读取器验证过:PNG 被打开并比对像素,DOCX 由另外的库读回,压缩包被解压。这意味着你的解析器拒绝的文件,是关于你的解析器的发现,而不是关于生成器的。 +

+
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
+

+ 格式页面列出了每种格式接受的设置,以及每种格式能达到的最小文件。 +

+
+ +
+

指南

+

其中两项的详细说明

+ +
+ +
+

适合谁

+

+ QA 工程师、测试自动化,以及代码背后有上传表单、导入程序、解析器或存储配额的所有人。它可以在完全没有网络的机器上运行,这在基于浏览器的生成器行不通的封闭企业环境中尤为重要。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/zh-Hant/ci.html b/web/content/zh-Hant/ci.html new file mode 100644 index 00000000..cc09fb8f --- /dev/null +++ b/web/content/zh-Hant/ci.html @@ -0,0 +1,170 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

如何在 CI 流程中產生測試檔案

+

+ 儲存庫裡的二進位 fixture 會永遠留在歷史中,無法在 diff + 裡審查,檔案一大就根本行不通。請改為在流程內部用配方產生這些檔案。配方是文字,每次產生的位元組都相同,最後一步還能證明什麼都沒有變動。 +

+ +
+

簡短回答

+

+ 安裝 tfg,在測試之前執行 tfg generate fixtures.yaml --out ./fixtures,在測試之後執行 + tfg verify ./fixtures/manifest.json。這兩步都會自行讓建置失敗,並給出說明原因的結束碼。 +

+
+ +
+

為什麼不提交

+

為什麼 fixture 不該放在儲存庫裡

+ +

+ 該提交的是配方。相同的配方和種子在每台機器上寫出相同的位元組,所以在流程裡產生的檔案,就是你在筆電上用過的那個檔案。 +

+
+ +
+

配方

+

放在測試旁邊的配方

+

+ 這個配方寫出二十五張應被接受的發票和兩張超過限制、應被拒絕的圖片,清單會記錄這兩種預期: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml 會檢查它而不寫入任何內容,並一次列出所有問題。 +

+
+ +
+

GitHub Actions

+

安裝工具並建置 fixture 的工作流程

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "{{ .Facts.Version }}"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base={{ .Facts.Releases }}/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 檢查碼那一行把壓縮檔與同一發行版中的 verify-SHA256SUMS.txt 比對。版本是固定的,所以新發行版絕不會改變你沒動過的建置。 +

+
+ +
+

GitLab CI

+

同樣的事,寫成 GitLab 作業

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "{{ .Facts.Version }}"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base={{ .Facts.Releases }}/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

變紅的時候

+

什麼會讓一個步驟失敗,為什麼

+

+ 每種結局都有自己的結束碼,所以步驟會自行失敗,日誌會說明是哪一種。流程會遇到的有: +

+ +

+ 失敗的執行不會向標準輸出印出任何內容,所以日誌剖析器永遠不會把錯誤當成資料。完整的表格在文件頁面上。 +

+
+ +
+

PowerShell

+

PowerShell 指令碼還需要多寫一行

+

+ PowerShell 不會把程式的結束碼帶出 .ps1 檔案。用 -File 執行一個指令碼,即使裡面的工具拒絕了工作,指令碼也會回傳 + 0,於是本該變紅的建置變成了綠色。最後一行就是全部的修正: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 這是 PowerShell 的行為,與本工具無關。cmd、bash 和 zsh 不需要額外處理。 +

+
+ +
+

多個作業

+

在作業之間共用 fixture

+

+ 通常不需要上傳它們。因為相同的配方寫出相同的位元組,每個作業都可以執行自己的 tfg + generate,這比上傳再下載更快。當一個作業必須接收另一個作業的檔案時,在傳輸之後對清單執行 tfg verify,它會告訴你收到的是否就是寫出的。 +

+
+ +
+

接下來

+

從這裡去哪裡

+ +
diff --git a/web/content/zh-Hant/damage.html b/web/content/zh-Hant/damage.html new file mode 100644 index 00000000..5a71331f --- /dev/null +++ b/web/content/zh-Hant/damage.html @@ -0,0 +1,150 @@ +{{ with .Up }}

{{ .Label }}

{{ end }} +

如何製作用於測試的損毀檔案

+

+ 一個只見過完好檔案的驗證器,並沒有真正被測試過。以下說明如何取得一個刻意弄壞的檔案:它的大小恰好就是你要求的大小,並附帶一份清單,說明你的系統該如何處理它。 +

+ +
+

簡短回答

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out 會寫出一個恰好 2097152 + 位元組的 PNG,它開頭的幾個位元組是零,旁邊的清單則記錄你的系統應該拒絕它。 +

+
+ +
+

常見做法

+

為什麼手工弄壞的檔案不是好測試

+

+ 常見做法是用十六進位編輯器、用指令碼翻轉幾個隨機位元組,或用 head 或 truncate 把檔案截短。這些做法能用一次,之後就要付出代價: +

+ +
+ +
+

你會得到什麼

+

損毀的檔案仍然是你要求的大小

+

+ 檔案先正常產生,再在寫入磁碟的途中被弄壞。它保持你要求的大小,同一個指令再次寫出的位元組也完全相同。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 設定寫在冒號之後。該選項可以重複,損毀依你寫下的順序逐一套用。它適用於全部 {{ .Facts.FormatCount }} 種格式。 +

+
+ +
+

它能做什麼

+

有哪些損毀方式?

+

+ 這是程式印出的清單,在建置本頁時從程式中讀取。tfg damage 印出的是同一份清單,tfg damage <id> + 則說明其中某一項接受什麼設定。 +

+ {{ template "damagesTable" . }} +

+ zero-head + 把檔案開頭寫成零。大多數讀取器最先看的就是那裡,也就是說明檔案是什麼的簽章和檔頭,所以幾乎任何讀取器都會發現。純文字和日誌沒有簽章,同樣會被拒絕,因為一串零位元組不是文字。低於四個位元組時,有些格式產生的損毀沒有任何讀取器會抱怨,這就是該設定從四開始的原因。 +

+
+ +
+

清單怎麼說

+

一份說明應發生什麼的清單

+

+ 每個損毀的檔案都會得到一筆記錄,說明你的系統應該拒絕它,損毀方式記在旁邊: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 有兩種請求會在寫入任何內容之前被拒絕,因為各自都會在磁碟上留下一個清單描述有誤的檔案: +

+ +
+ +
+

在配方中

+

一次執行中的完好檔案和損毀檔案

+

+ 把兩者放進同一個配方,清單就帶有每個檔案的預期,測試因此不需要一份說明哪個是哪個的列表: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

在測試中

+

把它變成測試

+

+ 測試讀取清單,檢查實際發生的是否就是所宣告的。它不需要檔名列表: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 好的拒絕是乾淨的拒絕。一則說明錯在哪裡的訊息,就是你想要的答案。伺服器錯誤、卡死或只儲存了一半的檔案,正是這個測試要找出來的缺陷。 +

+
+ +
+

接下來

+

從這裡去哪裡

+ +
diff --git a/web/content/zh-Hant/docs.html b/web/content/zh-Hant/docs.html new file mode 100644 index 00000000..e6831827 --- /dev/null +++ b/web/content/zh-Hant/docs.html @@ -0,0 +1,244 @@ +

文件

+

+ 工具的全部功能,依人們實際會問的問題來組織。儲存庫中的 README 是完整參考,並且始終與你下載的版本一致。 +

+ +
+

有哪些指令?

+

每個指令只做一件事:

+ {{ template "commandList" . }} +
+ +
+

如何產生一個大小精確的檔案?

+

+ 指定格式、大小與輸出位置。大小以 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>圍繞一個限制的三個檔案:小一位元組、恰好等於限制、大一位元組
--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將清單寫到標準輸出
+
+
+ +
+

如何做出刻意損壞的檔案?

+

+ 本工具寫出的其他所有檔案在構造上都是正確的,這回答了上傳驗證器會問的三個問題中的兩個。--damage + 回答第三個,也就是檔案到底能不能開啟。檔案先正常產生,再被破壞,因此仍然維持你要求的大小。 +

+
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,並在旁邊記錄所做的破壞。有兩種情況會在寫入任何內容之前被拒絕,因為各自都會在磁碟上留下清單描述有誤的檔案: +

+ +

+ 第三種無法事先得知。如果某個破壞執行後沒有改動任何位元組,該檔案會被捨棄而不是寫出,執行會繼續,指出是哪個檔案,並以部分完成的結束碼收尾。 +

+

+ 一步一步來,附帶一個讀取清單的測試:如何製作用於測試的損毀檔案。 +

+
+ +
+

配方長什麼樣子?

+

+ 配方是一個描述整次執行的 YAML 檔案。把它與測試放在一起提交,fixture 就不再是儲存庫裡的二進位檔,任何人都可以用一個只有幾百個字元的檔案逐位元組重建它們。 +

+
# 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
+

+ 每個 target 必須恰好有 size、size-range、boundary 或 + contains + 其中一個。兩個是錯誤,一個都沒有也是錯誤。無效的配方不會寫入任何檔案,並且會一次回報所有問題,而不是只報第一個,每個問題都會指明所涉及的設定。 +

+
+ +
+

如何宣告我的系統應如何處理某個檔案?

+

只需結果時用簡短寫法,原因重要時用完整寫法:

+
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。 +

+

+ 原因指明的是起作用的規則,而不是裁決。所以同一個原因可以出現在兩種結果之下:比限制小一位元組的檔案是 accept,而它所涉及的規則仍然是 + size_limit。 +

+
+ +
+

清單裡有什麼?

+

+ 每次執行結束時,包括被中斷的執行,它都會寫在檔案旁邊。每個檔案一項: +

+
{
+  "manifest_version": "1.0",
+  "tool": { "name": "testing-files-generator", "version": "{{ .Facts.Version }}" },
+  "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,因此清單總能追溯到產生它的來源。 +

+

+ 每一項還帶有 target_id,也就是配方中產生該檔案的 target 的 id,summary.by_target 則統計每個 target + 產生的檔案數。因此有多個 target 的配方可以逐個 target 檢查,無需閱讀檔名。 +

+
+ +
+

什麼是預設集?

+

+ 預設集是回答常見測試問題的現成檔案組,你不必自己設計。預設集底層就是普通配方,eject + 會把配方列印出來,供你從那裡開始編輯。每個預設集都有自己的頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+ {{ template "presetsList" . }} +
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 會在你建置之前告訴你這個組合的開銷,並且在某個數字只是我們的預留值而不是你的限制時直接說明。 +

+
+ +
+

結束碼是什麼意思?

+

+ 每種結束方式都有自己的代碼,機器可讀的輸出寫到標準輸出,失敗的執行不會在那裡列印任何內容。這張表是凍結的約定,改變某個代碼的意義需要提升主版本號。 +

+ {{ template "exitCodesTable" . }} +
- 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 流程中產生測試檔案。 +

+
+ +
+

有桌面視窗嗎?

+

+ 有,它就是在同一個引擎上加了一個視窗,用於不走腳本的測試。它不是縮水版:有測試逐項比對這兩種介面,只有其中一方能做的事必須被宣告並說明理由,而不是悄悄地漸行漸遠。 +

+

+ 畫面有單批產生、預設集、同時多批與關於。它會在寫入任何內容之前顯示一次執行的開銷,執行時回報進度,並且可以在中途取消而不會留下寫了一半的檔案。它目前還不能開啟配方檔,配方暫時只屬於命令列,視窗透過表單來建立批次。 +

+
diff --git a/web/content/zh-Hant/exact-size.html b/web/content/zh-Hant/exact-size.html new file mode 100644 index 00000000..c657995a --- /dev/null +++ b/web/content/zh-Hant/exact-size.html @@ -0,0 +1,123 @@ +

如何建立大小精確的檔案

+

+ 每個系統都有對應的指令,下面列出了全部三個。它們能給你一個位元組數恰好正確的檔案,對許多測試來說這就夠了。本頁的每個指令在發布前都在對應系統上執行過。 +

+ +
+

簡短回答

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。大小以位元組計,依檔案管理員的算法,10 MB 就是 10485760 位元組。 +

+
+ +
+

Windows

+

fsutil,以及無需額外工具的 PowerShell 寫法

+

+ fsutil 隨 Windows 提供。它接受以位元組為單位的大小,所以先算出數字:10 MB 是 10485760,100 MB 是 + 104857600,1 GB 是 1073741824。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ 在 Windows 11 上實測:它可以在一般的命令提示字元下執行,不需要系統管理員權限,產生的檔案恰好是 10485760 位元組。 +

+

PowerShell 不需要呼叫其他程式也能做到同樣的事,並且認得單位:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell 中的 10MB 代表 10485760 位元組,與檔案總管使用的 1024 進位算法相同,所以上面兩個指令得到的大小一樣。 +

+
+ +
+

Linux

+

dd、truncate 與 fallocate,以及容易坑人的差別

+

dd 是人人皆知的那個。它真的會寫入這些位元組:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate 是瞬間完成的,而這正是陷阱所在。在 Alpine Linux 上實測,該檔案回報 10485760 + 位元組,卻占用零個區塊,它是一個稀疏檔案。任何讀取它的程式會得到十 MB 的零,但磁碟從未真正讓出空間: +

+
truncate -s 10M test10mb.bin
+

+ 用它測試上傳限制沒問題,但用來測試磁碟配額就會誤導人。當空間必須真實占用時,應該使用 fallocate: +

+
fallocate -l 10M test10mb.bin
+

而當內容必須無法壓縮,讓封存程式無法再把它壓小時:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile(不是稀疏檔案),以及你已經熟悉的另外兩個

+

+ macOS 內建 mkfile。在 macOS 26.6.2 上實測:10485760 位元組與 20480 個區塊,所以空間是真正配置的,而不只是承諾: +

+
mkfile 10m test10mb.bin
+

dd 與 truncate 也都有,行為與 Linux 上相同:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

這種辦法在哪裡失效

+

大小正確的檔案不等於類型正確的檔案

+

+ 以上所有方法給你的都是一塊零。如果受測對象只看大小,比如上傳限制、配額或傳輸,這就夠了。一旦有任何東西開啟這個檔案,就不夠了。 +

+

+ 實測過,而且值得你自己試一試:用 fsutil 做一個 2 MB 的檔案,把它命名為 photo.png,再交給影像函式庫處理。Pillow 會回答 + cannot identify image file。它不是 PNG,從來就不是,只是名字這麼說。 +

+

+ 這比聽起來更重要,因為測試隨後會以哪種方式失敗。你的上傳端點拒絕了這個檔案,測試變綠,於是你斷定大小限制有效。其實它並不是因為大小而拒絕的,而是因為這些位元組不是圖片,你本想測試的規則根本沒有被觸及。 +

+ +
+ +
+

另一種辦法

+

該格式的真實檔案,大小恰好是你要求的

+

+ 這就是 Testing Files Generator 所做的事。檔案是該格式的真實檔案,能在對應軟體中開啟,位元組數恰好等於你的要求,精確到位元組: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 要求格式無法達到的大小,你會得到一個說明下限及其原因的錯誤,絕不會得到大小錯誤的檔案。格式頁面列出了每種格式及其能產生的最小檔案。 +

+

而一個限制對應的是三個測試案例,而不是一個,所以工具會把三個都建置出來:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 這會給你 10485759、10485760 與 10485761 + 位元組的檔案,以及一份清單,說明你的系統應該接受哪些、拒絕哪些。使用情境頁面會講解這一點,以及它為之而生的另外四項任務。 +

+ {{ template "downloadCta" . }} +
+ +
+

那麼該用哪個?

+ +

+ 兩種辦法都在本頁,因為它們各自在一部分情況下是對的。要避免的錯誤,是在需要後者的地方用了前者,還把變綠的測試當成證明。 +

+
diff --git a/web/content/zh-Hant/faq.html b/web/content/zh-Hant/faq.html new file mode 100644 index 00000000..a04fc587 --- /dev/null +++ b/web/content/zh-Hant/faq.html @@ -0,0 +1,16 @@ +

常見問題

+

+ 授權、隱私、可重現性,以及人們在把產生器放進建置流程之前會確認的事項。如果這裡沒有你的問題,問題追蹤器是開放的。 +

+ +{{ template "faqList" . }} +{{ template "faqSchema" . }} + +
+

還在猶豫?

+

+ 使用情境頁面展示了它為之而生的任務,格式頁面列出了每種格式及其能產生的最小檔案。儲存庫中的 + README 是完整參考。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/content/zh-Hant/formats.html b/web/content/zh-Hant/formats.html new file mode 100644 index 00000000..8c14b5bb --- /dev/null +++ b/web/content/zh-Hant/formats.html @@ -0,0 +1,65 @@ +

{{ .Facts.FormatCount }} 種檔案格式,每一種都以精確大小產生

+

+ 它們每一個都是該格式的真實檔案。它能在對應軟體中開啟,位元組數恰好等於你的要求。沒有一個是黏上副檔名的填充零。 +

+ +{{ template "formatsTable" . }} + +
+

各欄的意義

+ +

+ 每種格式也都能精確到位元組地重複:相同的配方與種子在任何電腦上都產生相同的檔案,這正是提交配方來取代 fixture 本身是安全的原因。 +

+
+ +
+

每種格式接受的設定

+

+ 大多數格式有自己的設定,例如圖片尺寸、JPEG 品質、PDF 頁數、試算表的列數與欄數、壓縮檔裡放多少項目。在命令列用 --set key=value 設定,或在配方的 + properties: 下設定。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+ {{ template "propertiesTable" . }} +

+ 超出設定所接受範圍的值會被拒絕,並附上指明該設定、允許範圍以及應改用什麼的訊息。未知的設定同樣是錯誤,絕不會靜默使用預設值,因為悄悄被接受的拼字錯誤會產生設定有誤的檔案,讓你花一小時納悶為什麼該失敗的測試卻通過了。 +

+

+ 執行 tfg formats <id> 即可查看某個格式在你目前版本中接受哪些設定。 +

+
+ +
+

壓縮檔裡裝的是真實檔案

+

+ {{ range $i, $c := .Facts.Containers }}{{ if $i }} 與 {{ end }}{{ $c.ID }}{{ end }} + 可以填入項目,而不是只留一個空殼。產生的壓縮檔確實包含它宣稱包含的文件,所以測試期間解壓縮它的任何程式都會在裡面找到真實檔案。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ diff --git a/web/content/zh-Hant/index.html b/web/content/zh-Hant/index.html new file mode 100644 index 00000000..32f339f7 --- /dev/null +++ b/web/content/zh-Hant/index.html @@ -0,0 +1,183 @@ +
+
+

產生大小精確的真實測試檔案

+

+ PDF、PNG、DOCX、ZIP,共 {{ .Facts.FormatCount }} + 種格式,每一種都是能在對應軟體中開啟的真實檔案,大小恰好等於你的要求。每次執行還會寫下你的應用程式應該如何處理每個檔案。命令列加桌面視窗,免費開源,完全在你的電腦上執行。 +

+ + {{ template "downloadCta" . }} +
+ +
+ Testing Files Generator 的桌面視窗,已準備好寫出一批測試檔案 +
桌面視窗,已準備好寫出一批檔案。命令列背後執行的是同一個引擎。
+
+
+ + + +
+

問題所在

+

做一個測試檔案很容易,做出對的一千個才是麻煩所在

+

你在測試接收使用者檔案的軟體。遲早你會需要:

+ +

+ 這正是它要取代的。它為 QA 工程師、測試自動化,以及程式碼背後有上傳表單、匯入程式、剖析器或儲存配額的所有人而做。 +

+
+ +
+

它的與眾不同之處

+

其他產生器止步於位元組。這個工具回答你的測試真正要問的問題

+

+ 一個滿是檔案的資料夾仍然要你自己判斷每個檔案應該證明什麼。這裡每次執行都會在檔案旁寫出一個 + manifest.json,它是所產生內容的簡單清單,並為每一項給出宣告的預期。 +

+

假設你的上傳端點允許 1 MB。請求恰好位於這條線上的三個檔案:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
檔案位元組你的系統應該原因
1mb_under_1b.pdf1048575接受在限制之內
1mb_at_limit.pdf1048576接受限制本身是允許的
1mb_over_1b.pdf1048577拒絕size_limit
+
+ +

三個檔案,三種不同的答案,以機器可讀的形式給出。你的測試讀取清單,而不是由你手寫斷言:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

當答案取決於你自己的政策時,清單會如實說明

+

+ 它記錄的是 unspecified,而不是憑空捏造預期。會猜測的產生器會製造誤報,而總是誤報的測試套件最終會被關掉。 +

+
+
+ +
+

預設集

+

選好問題,拿到整組檔案

+

+ 預設集是圍繞一個測試問題設計的測試檔案組,你不必自己琢磨哪些檔案能證明什麼。每個預設集都有一個頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+ {{ template "presetsList" . }} +

全部預設集,以及它們與配方的關係

+
+ +
+

快速開始

+

三個指令,看它如何運作

+
    +
  1. +

    產生一個檔案

    +

    一個 PNG,恰好兩 MB:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    產生大量檔案

    +

    + 一萬個記錄檔,每個介於 1 到 8 KB + 之間,大小由種子抽取,因此明天會得到同樣的檔案組。給每次執行一個獨立的目錄,清單是一次執行所寫內容的唯一記錄,所以工具拒絕在其上再寫第二份: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    先檢查,再刪除

    +

    verify 告訴你沒有任何變動。cleanup 只刪除寫出的內容,不動其他任何東西:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 大小以 1024 進位計算,與你的檔案管理員一致,所以 2mb 代表 2097152 + 位元組。直接寫位元組數也可以。文件涵蓋配方、清單與結束碼。 +

+
+ +
+

你將得到什麼

+

為無人看管的測試套件而生

+ +
+ +
+

下載

+

選擇適合你系統的版本

+

+ 解壓縮後執行即可。tfg 是命令列,tfg-gui 是桌面視窗。沒有安裝程式,也無需向你的電腦新增任何東西。 +

+ {{ template "downloadsTable" . }} +
+

哪些已簽署,哪些沒有

+

+ Windows 與 macOS 的下載檔已簽署,因此啟動時不會出現未知開發者的警告。Linux 的沒有簽署,因為桌面 Linux 沒有可用的對應簽署機制。每個壓縮檔都列在發布頁面的 + verify-SHA256SUMS.txt 中,你可以據此核對所下載的內容。 +

+
+ {{ template "downloadCta" . }} +
+ diff --git a/web/content/zh-Hant/preset.html b/web/content/zh-Hant/preset.html new file mode 100644 index 00000000..a34ab7d0 --- /dev/null +++ b/web/content/zh-Hant/preset.html @@ -0,0 +1,90 @@ +{{ with .Preset }} +

{{ $.Up.Label }}

+

{{ .Title }}

+

{{ .Question }}

+

+ {{ .ID }} 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ +{{ if .Catches }} +
+

它通常能發現什麼?

+ +
+{{ end }} + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show {{ .ID }} 所回報的:

+
+ + + + + + + +
檔案數{{ .Budget.Files }}
其配方中的 target 數{{ .Budget.Targets }}
總大小{{ .Bytes }} B
格式{{ join .Budget.Formats ", " }}
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + {{- range .Outcomes }} + + {{- end }} + +
預期意義檔案數
{{ .Name }}{{ .Meaning }}{{ .Count }}
+
+
+ +
+

你可以變更什麼?

+ {{- if .Settings }} +
+ + + + + + {{- range .Settings }} + + + + + + + {{- end }} + +
設定接受預設值作用
--{{ .Flag }}{{ .Takes }}{{ .Default }}{{ .Detail }}{{ if .Placeholder }} 這個預設值是我們的預留值,不是你的系統的值。請傳入你自己的值。{{ end }}
+
+ {{- else }} +

這個預設集沒有任何設定。每次得到的組合都相同。

+ {{- end }} +
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show {{ .ID }}
+tfg generate --preset {{ .ID }}{{ range .Placeholders }} --{{ .Flag }} {{ .Default }}{{ end }} --out ./{{ .ID }}
+tfg preset eject {{ .ID }} > {{ .ID }}.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:{{ .ID }}
+{{- with .Placeholders }}
+with:
+{{- range . }}
+  {{ .Flag }}: {{ .Default }}
+{{- end }}
+{{- end }}
+
+{{ end }} diff --git a/web/content/zh-Hant/presets.html b/web/content/zh-Hant/presets.html new file mode 100644 index 00000000..296384be --- /dev/null +++ b/web/content/zh-Hant/presets.html @@ -0,0 +1,25 @@ +

測試檔案預設集,每個測試問題一組檔案

+

+ 預設集是圍繞一個問題設計的整組測試檔案,並附上說明你的系統應如何回應每個檔案的清單。你選擇問題,工具建置檔案組。每個預設集都有自己的頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+ +{{ template "presetsList" . }} + +
+

預設集與配方有何不同?

+

+ 在底層沒有不同。預設集就是工具根據幾項設定替你寫出的配方。tfg preset eject + 會把這個配方列印出來,方便你與測試放在一起並加以編輯,你自己的配方也可以用一行以某個預設集為基礎,也就是 extends: preset: 後面接上它的 id。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

我可以信任預設值嗎?

+

+ 對檔案來說可以。對於只有你的系統才知道的數字,比如上傳表單的限制,預設值是我們的預留值,工具每次使用時都會這樣說明。每個預設集的頁面都會標出這些設定,tfg preset + show 會在寫入任何內容之前告知你。 +

+
diff --git a/web/content/zh-Hant/site.json b/web/content/zh-Hant/site.json new file mode 100644 index 00000000..9b9bd721 --- /dev/null +++ b/web/content/zh-Hant/site.json @@ -0,0 +1,328 @@ +{ + "code": "zh-Hant", + "locale": "zh_TW", + "name": "繁體中文", + "dir": "zh-hant", + "pages": [ + { + "key": "index", + "slug": "", + "nav": "首頁", + "title": "測試檔案產生器 - 精確大小,{{ .Facts.FormatCount }} 種真實格式", + "description": "免費開源的 QA 測試檔案產生器。產生精確大小的真實 PDF、DOCX、PNG、ZIP 檔案,並附上說明系統應如何回應的清單。" + }, + { + "key": "formats", + "slug": "formats", + "nav": "格式", + "title": "{{ .Facts.FormatCount }} 種支援的檔案格式 - PDF、DOCX、PNG、ZIP 等", + "description": "產生器支援的所有檔案格式、每種格式可能的最小檔案,以及各自接受的設定。全部 {{ .Facts.FormatCount }} 種都能在對應軟體中開啟。" + }, + { + "key": "presets", + "slug": "presets", + "nav": "預設集", + "title": "測試檔案預設集 - 針對 QA 問題的現成檔案組", + "description": "現成的測試檔案組,每組回答一個測試問題:上傳限制、檔名、編碼、表格匯入、空檔案與上傳驗證。" + }, + { + "key": "docs", + "slug": "docs", + "nav": "文件", + "title": "文件 - 指令、配方、清單、結束碼", + "description": "如何透過命令列或 YAML 配方產生測試檔案、清單包含什麼,以及在 CI 中執行時每個結束碼的意義。" + }, + { + "key": "use-cases", + "slug": "use-cases", + "nav": "使用情境", + "title": "使用情境 - 上傳限制、CI fixture、大量測試", + "description": "測試上傳大小限制、為 CI 建立可重現的 fixture、產生一萬個檔案,並用真實內容填滿壓縮檔。" + }, + { + "key": "exact-size", + "slug": "create-file-exact-size", + "nav": "精確大小", + "title": "如何建立指定大小的檔案 - Windows、Linux、macOS", + "description": "fsutil、dd、truncate 與 mkfile,各自在對應系統上實測,以及當測試需要 PDF 或 PNG 時,這樣產生的檔案為何不行。" + }, + { + "key": "faq", + "slug": "faq", + "nav": "常見問題", + "title": "常見問題 - 關於產生測試檔案", + "description": "與 dd、fsutil 有何不同、檔案能否放心提交、每次執行是否逐位元組相同,以及大小無法達成時會怎樣。" + }, + { + "key": "damage", + "slug": "corrupt-test-files", + "nav": "損毀檔案", + "title": "損毀的測試檔案 - 大小精確的損毀檔案", + "description": "一個刻意弄壞、大小精確的檔案,附帶說明你的系統應拒絕它的清單。用於測試上傳驗證和剖析器。", + "parent": "use-cases" + }, + { + "key": "ci", + "slug": "test-files-in-ci", + "nav": "CI 中的測試檔案", + "title": "CI 中的測試檔案 - GitHub Actions、GitLab CI 和 PowerShell", + "description": "在流程中產生測試檔案,而不是提交二進位檔案:GitHub Actions 工作流程、GitLab 作業、讓建置失敗的結束碼,以及 PowerShell 的陷阱。", + "parent": "use-cases" + } + ], + "words": { + "skip": "跳到內容", + "navLabel": "主選單", + "langLabel": "語言", + "breadcrumbHome": "首頁", + "imageAlt": "Testing Files Generator - 精確大小的真實測試檔案,並附上說明系統應如何回應每個檔案的清單", + "schemaDescription": "專為 QA 設計的免費開源測試檔案產生器。它產生 {{ .Facts.FormatCount }} 種格式、大小精確的真實檔案,並寫出說明受測系統應如何回應每個檔案的清單。", + "ctaDownload": "下載", + "ctaSource": "檢視原始碼", + "ctaNote": "免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。", + "colFormat": "格式", + "colName": "名稱", + "colExtension": "副檔名", + "colSmallest": "最小檔案", + "colFidelity": "完整度", + "colChecked": "驗證方式", + "colSetting": "設定", + "colAccepts": "接受", + "colSystem": "系統", + "colCli": "命令列", + "colWindow": "桌面視窗", + "noBinary": "尚無執行檔", + "colCode": "代碼", + "colMeaning": "意義", + "footerBlurb": "專為 QA 設計的精確大小測試檔案,並附上說明系統應如何回應每個檔案的清單。", + "footerProject": "專案", + "footerSource": "GitHub 上的原始碼", + "footerReleases": "下載", + "footerIssues": "回報問題", + "footerSupport": "支持本專案", + "footerPages": "頁面", + "footerLicence": "Copyright (C) 2026 DonislawDev。依 GNU 通用公共授權條款第 3 版發布。你產生的檔案歸你所有,授權涵蓋的是工具本身,而不是它的輸出。", + "footerPrivacy": "本站不會從任何地方載入字型、指令碼或追蹤器,也不會設定 Cookie。", + "notFoundTitle": "找不到這個頁面", + "notFoundLead": "你造訪的網址與本站任何頁面都不相符。", + "notFoundBack": "回到首頁", + "read.format": "組合中每個檔案的格式。它是工具本身的參數,預設集只是給它一個預設值。", + "readTakes.format": "格式頁面中的格式 id", + "colDamage": "損毀方式", + "colEffect": "對位元組做了什麼", + "colSettings": "設定", + "noSettings": "無" + }, + "endings": { + "0": "一切正常。", + "1": "工具內部發生非預期的錯誤。", + "2": "指令或參數有誤。", + "3": "配方無效。", + "4": "該格式無法完成所要求的操作。", + "5": "讀取或寫入失敗。", + "6": "磁碟空間不足。", + "7": "verify 發現不一致。", + "8": "執行已結束,但並非所有檔案都已產生。", + "130": "被 Ctrl+C 中斷。", + "143": "被訊號終止,CI 逾時就是這個樣子。" + }, + "presets": { + "empty-and-minimal": { + "question": "一個合法且達到格式允許最小大小的檔案能通過嗎?", + "title": "空檔案與最小檔案", + "pageTitle": "各格式最小的合法檔案與空檔案", + "description": "本工具在 {{ .Facts.FormatCount }} 種格式中各自寫出的最小合法檔案,以及格式允許時的空檔案,每個都附上應有的回應。", + "catches": [ + "合法檔案因過小而被拒絕,因為檢查是以位元組數判斷,而不是去讀取內容", + "空檔案讓讀取器當機,而不是被如實回報", + "只有一個像素寬的圖片在產生縮圖的途中發生除以零的錯誤", + "儲存空間把零位元組當成上傳失敗,並不斷重試" + ], + "details": { + "formats": "組合由哪些格式構成。填 all 代表此版本的所有格式,也可以只列出你的系統接受的格式。" + } + }, + "filename-handling": { + "question": "我的系統能否正確儲存、顯示並傳回它沒料到的檔名?", + "title": "檔名處理", + "pageTitle": "用於測試的問題檔名 - Unicode 與長度", + "description": "檔名會破壞上傳與儲存:其他文字與 emoji、由右至左覆寫、不可見字元、shell 與 SQL 語法、長度限制。", + "catches": [ + "在畫面、記錄或清單中看起來像另一個名稱的檔名", + "在上傳與儲存之間被截斷、修剪或改寫的檔名", + "以字元計算的長度限制,而儲存空間是以位元組計算的" + ], + "details": {} + }, + "size-boundaries": { + "question": "大小限制是否恰好在宣告的位置生效?", + "title": "大小邊界", + "pageTitle": "測試上傳大小限制 - 恰好落在邊界上的檔案", + "description": "比系統宣告的大小限制小一位元組、恰好等於以及大一位元組的檔案,另加兩側更寬的間距,每個都標明是否應被接受。", + "catches": [ + "限制處的差一錯誤", + "把 MB 與 MiB 搞混,相差 4.8%,足以放過本不該通過的檔案", + "限制只在瀏覽器中生效,而不在伺服器上" + ], + "details": { + "limit": "你的系統宣告的大小限制。其他一切都以它為基準測量。", + "spread": "在限制兩側各延伸多遠,以大小清單表示。" + } + }, + "tabular-import": { + "question": "我的表格匯入能應付真實工具匯出的內容嗎?", + "title": "表格匯入", + "pageTitle": "CSV 與 Excel 匯入測試檔案 - 分隔符號、標題列", + "description": "使用其他分隔符號、CR LF 換行、無標題列和其他引號的 CSV,一張極寬的表格、一個 Excel 活頁簿,以及多種版面的 JSON。", + "catches": [ + "以分號分隔的檔案被讀成單一欄位,因為分隔符號是假設的,而不是偵測出來的", + "CRLF 檔案被拆成多列,每列後面多出一個空列", + "沒有標題列的表格,第一列資料被當成欄位名稱吞掉", + "匯入只保留能顯示的欄位,其餘的默默丟棄", + "讀取器逐行讀取 JSON 記錄,遇到第一個有縮排的文件就停下來" + ], + "details": { + "rows": "試算表有多少列。檔案會寫成這麼多列恰好打包出的大小,所以上面的預算會隨這個值變動。", + "columns": "試算表每列有多少欄。列數乘以欄數有上限,超出時會在寫入任何內容之前被拒絕。" + } + }, + "text-encoding": { + "question": "我的讀取器知道檔案是什麼編碼,還是在猜?", + "title": "文字編碼", + "pageTitle": "文字編碼測試檔案 - UTF-8、UTF-16、BOM、CRLF", + "description": "同一段文字分別以 UTF-8、UTF-16LE 與 UTF-16BE 編碼,含或不含位元組順序標記,並使用 CR LF 與 LF 換行,用來測試讀取器如何解碼文字。", + "catches": [ + "讀取器假設為 UTF-8,把 UTF-16 檔案顯示成每三個字元一個,或一排排方框", + "位元組順序標記被當成內容讀取,導致匯入的第一個欄位以三個多餘字元開頭", + "匯入器依據開頭幾個位元組猜測編碼,遇到較長的檔案卻猜成別的", + "CRLF 檔案被拆成多列,每列後面多出一個空列,或歸位字元殘留在最後一個欄位裡" + ], + "details": { + "sample": "組合中每個檔案的大小。UTF-16 每個字元佔兩個位元組,所以奇數會被拒絕。" + } + }, + "upload-validation": { + "question": "我的上傳表單是否接受該接受的,並拒絕其餘的?", + "title": "上傳驗證", + "pageTitle": "上傳驗證測試檔案 - 類型、大小與檔名", + "description": "用來測試上傳表單的檔案:允許與拒絕的類型、內容與副檔名不符、大小限制兩側、惡意檔名,以及大量上傳。", + "catches": [ + "限制只在瀏覽器中生效,而不在伺服器上", + "SVG 或 HTML 檔案被當成圖片或純文字,這是讓指令碼繞過表單的一種辦法", + "只依副檔名檢查而從不開啟檔案,於是名為 .jpg 的 PDF 蒙混過關", + "表單在查看大小之前就把整個請求本文讀進記憶體", + "名為 PHOTO.JPG 的上傳被拒絕,而 photo.jpg 被接受,或者相反", + "含空格、括號或非 ASCII 字元的檔名被原封不動寫入磁碟" + ], + "details": { + "limit": "你的上傳表單宣告的大小限制。這個組合在限制兩側各取一步,若要涵蓋任意距離的檔案,請執行 size-boundaries 預設集。", + "allow": "你的表單應該接受哪些類型。每種類型都會變成該類型的真實檔案,它們構成整個組合的陽性對照。", + "deny": "你的表單應該拒絕哪些副檔名。此版本沒有對應格式的副檔名,仍會得到一個同名檔案,內容為純文字。", + "far-over": "那個超大檔案超出限制多少。如果寫入限制數倍大小的檔案不值得占用磁碟,可以關閉。", + "bulk": "大量上傳包含多少個檔案。設為零則完全不包含這一組。" + } + } + }, + "commands": { + "generate": "依配方或參數產生檔案", + "validate": "檢查配方,不寫入任何內容", + "verify": "對照清單檢查目錄", + "cleanup": "刪除清單中列出的檔案", + "recipe fmt": "以標準形式列印配方", + "preset": "依具名的測試問題建立一組檔案", + "formats": "列出此版本支援的格式", + "damage": "列出此版本可以刻意破壞檔案的方式", + "tool": "處理現有檔案的小工具", + "version": "列印工具版本", + "license": "列印授權條款及其對產生檔案的意義" + }, + "outcomes": { + "accept": "你的系統應該接受這個檔案。", + "reject": "你的系統應該拒絕這個檔案。", + "sanitize": "你的系統應該接受這個檔案並加以清理,例如重新命名。", + "unspecified": "取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。" + }, + "damages": { + "zero-head": "用零覆蓋檔案開頭的若干位元組,長度保持不變。大多數讀取器最先看的就是那裡,所以幾乎任何東西都會發現這種損毀。" + }, + "terms": { + "oracleNone": "不適用", + "int": "任意整數", + "choice": "固定集合中的其中一個", + "bool": "真或假", + "size": "形如 2mb 的大小", + "text": "文字", + "pixels": "像素", + "paragraphs": "段落", + "rows": "列", + "columns": "欄", + "slides": "投影片", + "hertz": "赫茲", + "megapixels": "百萬像素", + "million cells": "百萬個儲存格", + "entries per second": "每秒項目數", + "files": "個檔案", + "sizes separated by commas": "以逗號分隔的大小", + "format ids separated by commas": "以逗號分隔的格式 id", + "format ids separated by commas, or all": "以逗號分隔的格式 id,或 all", + "extensions separated by commas": "以逗號分隔的副檔名", + "the id of a format, as tfg formats lists them": "格式的 id,與 tfg formats 列出的相同", + "the password, in plain text": "明文密碼", + "any text": "任意文字", + "a date such as 2024-02-29 or 2024-02-29T13:45:00+02:00, or none": "形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none" + }, + "faq": [ + { + "q": "這與 dd、fsutil 或 truncate 有何不同?", + "a": "它們給你的是大小正確但內容空空如也的檔案。用這種方式做出的名為 photo.png 的 2 MB 檔案並不是 PNG,所以任何真正剖析它的程式都會因為錯誤的原因拒絕它,而你的測試也會因為錯誤的原因通過。本工具產生的是大小恰好 2 MB 的真實 PNG,可以在圖片檢視器中開啟,並附上一份說明,告訴你的系統該如何處理它。", + "code": "tfg generate --format png --size 2mb --out ./fixtures" + }, + { + "q": "它免費嗎?我能在工作中使用嗎?", + "a": "兩者都可以。它以 GPL-3.0 發布,不收取任何費用。沒有帳號,沒有授權金鑰,也沒有付費方案。" + }, + { + "q": "我能在閉源產品中使用產生的檔案嗎?", + "a": "可以。授權涵蓋的是工具的程式碼,而不是工具產生的內容。產生的檔案、配方與清單屬於輸出而非衍生作品,所以你可以提交它們並隨產品散布,不負任何義務。" + }, + { + "q": "產生的檔案包含真實的個人資料嗎?", + "a": "不包含。裡面的一切都由種子合成。不讀取任何資料集,不聯繫任何服務,也不嵌入任何第三方內容。請把產生的電子郵件地址視為無法使用,而不是尚未使用,因為任何隨機字串都有可能碰巧與真實地址相同。" + }, + { + "q": "在另一台電腦上能得到完全相同的檔案嗎?", + "a": "能,只要配方與種子相同,就能逐位元組一致。專案在每次變更時都會測試這一點,要打破它必須提升主版本號。這正是你可以提交一個小配方,而不是大型二進位 fixture 的原因。" + }, + { + "q": "它需要連上網際網路嗎?", + "a": "從不需要。沒有遙測,沒有更新檢查,也沒有雲端用戶端,命令列執行檔裡甚至沒有編譯進網路堆疊。它可以在沒有網路的電腦上執行,也能在封閉的企業環境中使用。" + }, + { + "q": "如果我要求格式無法達到的大小會怎樣?", + "a": "你會收到一個錯誤,說明格式、可能的最小大小、該下限的原因以及應改用什麼,而且不會寫入任何檔案。工具絕不會默默四捨五入。每個下限都列在格式頁面上。", + "code": "tfg formats png" + }, + { + "q": "我能產生刻意損壞的檔案嗎?", + "a": "可以。加上 --damage zero-head,檔案就會以恰好所要求的大小輸出,開頭幾個位元組被零覆蓋,讀取器會拒絕它,清單也會說明你的系統應該拒絕它。詳情見關於損毀測試檔案的頁面。", + "code": "tfg generate --format png --size 2mb --damage zero-head --out ./out" + }, + { + "q": "接下來會支援哪些格式?", + "a": "7z、mp3 與 mp4。目前有 {{ .Facts.FormatCount }} 種格式可以端到端使用。" + }, + { + "q": "我可以在哪些系統上執行?", + "a": "命令列可在 Windows 與 Linux 上執行,支援 Intel 與 ARM,也支援 Apple 晶片的 Mac。桌面視窗提供 Windows(Intel)、Linux(Intel)與 Apple 晶片 Mac 版本。不支援 Intel Mac,也不會為其建置。" + }, + { + "q": "我需要安裝什麼嗎?", + "a": "不需要。下載適合你系統的壓縮檔,解壓縮後執行執行檔即可。沒有安裝程式,沒有需要新增的執行階段,也沒有需要解決的相依套件。如果你裝有 Go,一個 go install 指令同樣可用。", + "code": "go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest" + }, + { + "q": "為什麼在 Windows 上處理數千個檔案比較慢?", + "a": "因為 Windows 對查看的每個路徑收取較多開銷,而走訪數千個檔案的指令要查看數千個路徑。在一台有 3000 個 1 kB 檔案的電腦上實測,verify 在 Windows 上約需 0.9 秒,在容器中的 Linux 上約需 0.2 秒。輸出路徑較短會讓 Windows 的數字變小,因為檔案上方的每一層資料夾都屬於被查看的內容。" + } + ] +} diff --git a/web/content/zh-Hant/use-cases.html b/web/content/zh-Hant/use-cases.html new file mode 100644 index 00000000..56de27e8 --- /dev/null +++ b/web/content/zh-Hant/use-cases.html @@ -0,0 +1,110 @@ +

人們用它來做什麼

+

+ 幾乎每個接收使用者檔案的專案都會遇到的五項任務,以及完成每一項的指令。下面的每個範例都能照原樣執行。 +

+ +
+

上傳限制

+

測試檔案大小限制是否在宣稱的位置生效

+

+ 一個限制對應三個測試案例,而不是一個:剛好低於、恰好等於和剛好高於。手工做這些意味著計算位元組數,並祈禱自己沒有算錯一位。不如直接要求整組檔案: +

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

+ 你會得到三個真實的 PDF,大小分別是 1048575、1048576 與 1048577 位元組,以及一份清單,說明前兩個應被接受,第三個應因 size_limit + 被拒絕。你的測試讀取預期,而不是由你手寫三個斷言,限制改變時,你只需改一個數字再重新執行。 +

+

+ 如果你只想要一組內嵌的邊界檔案,不用預設集也可以做到: +

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

持續整合

+

讓 fixture 留在儲存庫之外又不遺失

+

+ 大型二進位 fixture 會拖慢儲存庫複製,也讓審查變得彆扭,而且替換其中一個時沒有人能看出改了什麼。配方只是幾百個字元的 + YAML,就能重建出完全相同的檔案,在任何電腦上逐位元組一致,因為每個檔案都由執行的種子衍生。 +

+
- 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
+

+ 每種結束方式都有自己的結束碼,所以流程可以區分配方錯誤、磁碟已滿和驗證不一致。失敗的執行不會在標準輸出上列印任何內容,這樣記錄剖析器就不會把錯誤當成資料。 +

+
+ +
+

規模

+

弄清資料夾很大時會發生什麼

+

+ 匯入程式、夜間工作與目錄列表在一萬個檔案時的表現與十個檔案時不同。從範圍中抽取的大小讓檔案組看起來像真實流量,而不是一萬個完全相同的檔案,並且抽取來自種子,所以明天檔案組依然相同。 +

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

+ 在執行寫入任何內容之前先查看它的開銷,當總量以 GB 計時這一點很重要: +

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

+ 比磁碟可用空間更大的執行會在寫入第一個位元組之前就被拒絕,而不是把磁碟寫滿再半途失敗。 +

+
+ +
+

壓縮檔

+

用真正裝有檔案的壓縮檔測試解壓縮程式

+

+ 只有正確副檔名的空壓縮檔,無法證明任何關於開啟它並走訪內容的程式碼的事情。宣告內容,壓縮檔就真的包含它們: +

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

+ 巢狀深度、項目數量和內部內容的大小,匯入程式都有自己的看法,而這正是你弄清這些看法的辦法。 +

+
+ +
+

剖析器與檢視器

+

檢查你自己的程式碼讀取格式的方式是否與真實軟體一致

+

+ 這裡的每種格式在發布前都用獨立讀取器驗證過:PNG 被開啟並比對像素,DOCX 由另外的函式庫讀回,壓縮檔被解壓縮。這意味著你的剖析器拒絕的檔案,是關於你的剖析器的發現,而不是關於產生器的。 +

+
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
+

+ 格式頁面列出了每種格式接受的設定,以及每種格式能達到的最小檔案。 +

+
+ +
+

指南

+

其中兩項的詳細說明

+ +
+ +
+

適合誰

+

+ QA 工程師、測試自動化,以及程式碼背後有上傳表單、匯入程式、剖析器或儲存配額的所有人。它可以在完全沒有網路的電腦上執行,這在以瀏覽器為基礎的產生器行不通的封閉企業環境中尤為重要。 +

+ {{ template "downloadCta" . }} +
diff --git a/web/public/404.html b/web/public/404.html index 4f092c3c..db69e6a4 100644 --- a/web/public/404.html +++ b/web/public/404.html @@ -3,12 +3,13 @@ + That page is not here - + @@ -45,8 +46,6 @@ Exact size FAQ -
-
diff --git a/web/public/ar/corrupt-test-files/index.html b/web/public/ar/corrupt-test-files/index.html new file mode 100644 index 00000000..046b1e14 --- /dev/null +++ b/web/public/ar/corrupt-test-files/index.html @@ -0,0 +1,371 @@ + + + + + + +ملفات اختبار تالفة - ملفات معطوبة بحجم دقيق + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

حالات الاستخدام

+

كيف تصنع ملفًا تالفًا للاختبار

+

+ المدقق الذي لم يُعرض عليه إلا ملفات سليمة لم يُختبر حقًّا. إليك طريقة الحصول على ملف أُتلف عمدًا، + ويخرج بالحجم الذي تطلبه تمامًا، ويحمل بيانًا يقول ما الذي ينبغي أن يفعله نظامك + به. +

+ +
+

الجواب المختصر

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out يكتب ملف PNG حجمه + 2097152 بايتًا بالضبط، وبايتاته الأولى أصفار، ويسجّل البيان المجاور له أن نظامك ينبغي أن يرفضه. +

+
+ +
+

الطريقة المعتادة

+

لماذا يُعدّ الملف المتلف يدويًا اختبارًا رديئًا

+

+ الطرق المعتادة هي محرر سداسي عشري، أو سكربت يقلب بضع بايتات عشوائية، أو قصّ الملف بـ + head أو truncate. تنجح مرة واحدة، ثم تكلّفك: +

+
    +
  • + يختلف في كل مرة. البايت العشوائي يقع في مكان جديد عند كل تشغيل، فقد لا يعود فشل يوم + الثلاثاء يوم الأربعاء. +
  • +
  • + يغيّر الحجم. الملف المقصوص أصغر من الحد الذي كان ينبغي أن يبقى تحته، فيجيب فحص + الحجم قبل فحص المحتوى، ويمرّ الاختبار لسبب خاطئ. +
  • +
  • + كثيرًا ما يمرّ دون أن يلاحظه أحد. النص العادي يبقى مقروءًا مع تغيير بايت في الوسط، + وقارئ الصور المتسامح يرسمه ببساطة، فيُقبل الملف الذي كان يُفترض أن يكون تالفًا. +
  • +
  • + لا يقول شيئًا عمّا ينبغي أن يحدث. الملف مجرد بايتات، ومن يقرأ الاختبار لاحقًا عليه + أن يخمّن هل كان المقصود القبول أم الرفض. +
  • +
+
+ +
+

ما تحصل عليه

+

الملف التالف يبقى بالحجم الذي طلبته

+

+ يُولَّد الملف كالمعتاد ثم يُتلَف في طريقه إلى القرص. يحتفظ بالحجم الذي طلبته، ويكتب الأمر نفسه + البايتات نفسها مرة أخرى. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ تُكتب الإعدادات بعد النقطتين. يمكن تكرار الخيار، وتُطبَّق أنواع التلف بالترتيب الذي تكتبه. ويعمل مع + كل واحدة من 26 صيغة. +

+
+ +
+

ما الذي يستطيعه

+

ما أنواع التلف المتاحة؟

+

+ هذه هي القائمة التي يطبعها البرنامج، وتُقرأ منه عند بناء هذه الصفحة. يطبع tfg damage + القائمة نفسها، ويبيّن tfg damage <id> ما يقبله واحد منها. +

+
+ + + + + + + + + + + + + + + + + +
التلفما يفعله بالبايتاتأصغر ملفالإعدادات
zero-headيكتب أصفارًا فوق أول بايتات الملف دون المساس بطوله. معظم القارئات تنظر إلى هناك أولًا، فيلاحظ هذا التلف كل شيء تقريبًا.8bytes
+
+

+ يكتب zero-head أصفارًا فوق بداية الملف. معظم القارئات تنظر إلى هناك أولًا، إلى التوقيع + والترويسة اللذين يقولان ما هو الملف، فتلاحظ ذلك أي قارئة تقريبًا. والنص العادي والسجلات لا توقيع + لها وتُرفض أيضًا، لأن سلسلة من البايتات الصفرية ليست نصًّا. وتحت أربعة بايتات تخرج بعض الصيغ + بتلف لا تشتكي منه أي قارئة، ولهذا يبدأ الإعداد من أربعة. +

+
+ +
+

ما يقوله البيان

+

بيان يقول ما ينبغي أن يحدث

+

+ كل ملف تالف يحصل على مدخل يقول إن نظامك ينبغي أن يرفضه، ويُسجَّل التلف بجانبه: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ يُرفض طلبان قبل أن يُكتب أي شيء، لأن كلًّا منهما سيترك على القرص ملفًا يصفه البيان وصفًا خاطئًا: +

+
    +
  • ملف أصغر مما يحتاجه التلف، وكان سيخرج دون تغيير
  • +
  • + expected: accept بجانب تلف، لأن لا شيء يمكنه تحقيق ذلك. اكتب sanitize إن + كان نظامك مقصودًا به إصلاح الملف، أو unspecified إن كان هذا هو السؤال الذي تطرحه +
  • +
+
+ +
+

في وصفة

+

ملفات سليمة وتالفة في تشغيل واحد

+

+ ضع الاثنين في وصفة واحدة، فيحمل البيان المتوقَّع لكل ملف، ولا يحتاج الاختبار إلى قائمة تقول أيها + أيّ: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

في اختبار

+

تحويله إلى اختبار

+

+ يقرأ الاختبار البيان ويتحقق من أن ما حدث هو ما أُعلن. لا يحتاج إلى قائمة بأسماء الملفات: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ الرفض الجيد هو الرفض النظيف. رسالة تقول ما الخطأ هي الجواب الذي تريده. أما خطأ الخادم أو التعليق أو + ملف حُفظ نصفه فهو العيب الذي وُجد هذا الاختبار لاكتشافه. +

+
+ +
+

التالي

+

إلى أين من هنا

+ +
+ +
+ + + + diff --git a/web/public/ar/create-file-exact-size/index.html b/web/public/ar/create-file-exact-size/index.html new file mode 100644 index 00000000..5cdadd32 --- /dev/null +++ b/web/public/ar/create-file-exact-size/index.html @@ -0,0 +1,327 @@ + + + + + + +كيف تنشئ ملفًا بحجم محدد - ويندوز ولينكس وماك + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

كيف تنشئ ملفًا بحجم دقيق

+

+ لكل نظام أمر لذلك، والثلاثة كلها أدناه. تعطيك ملفًا بعدد البايتات الصحيح تمامًا، وفي كثير من + الاختبارات هذا كل ما تحتاجه. كل أمر في هذه الصفحة جُرِّب قبل النشر على النظام + الذي ينتمي إليه. +

+ +
+

الجواب المختصر

+

+ ويندوز: fsutil file createnew name 10485760. لينكس: dd if=/dev/zero of=name bs=1M + count=10. ماك: mkfile 10m name. الأحجام بالبايت، و10 MB محسوبة كما يحسبها + مدير الملفات لديك تساوي 10485760. +

+
+ +
+

ويندوز

+

fsutil، ونسخة PowerShell لا تحتاج إلى شيء إضافي

+

+ يأتي fsutil مع ويندوز. يأخذ الحجم بالبايت، فاحسب الرقم أولًا: 10 MB + تساوي 10485760، و100 MB تساوي 104857600، و1 GB تساوي 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ قيس على ويندوز 11: يعمل من موجّه عادي دون حاجة إلى موجّه مرتفع الصلاحيات، ويخرج الملف بحجم 10485760 + بايتًا بالضبط. +

+

يستطيع PowerShell فعل الشيء نفسه دون استدعاء برنامج آخر، ويفهم الوحدات:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ تعني 10MB في PowerShell ما قدره 10485760 بايتًا، وهو العدّ نفسه بأساس 1024 الذي يستخدمه + مستكشف الملفات، فيُنتج الأمران أعلاه الحجم نفسه. +

+
+ +
+

لينكس

+

dd وtruncate وfallocate، والفرق الذي يوقع الناس

+

dd هو الأمر الذي يعرفه الجميع. يكتب البايتات فعلًا:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate فوري، وهنا الفخ. قيس على Alpine Linux، فأبلغ الملف عن 10485760 بايتًا وشغل + صفر كتل، فهو ملف متناثر. كل ما يقرؤه يحصل على عشرة ميغابايت من + الأصفار، لكن القرص لم يتنازل عن المساحة قط: +

+
truncate -s 10M test10mb.bin
+

+ هذا مناسب لاختبار حد الرفع، ومضلل لاختبار حصة القرص. أما fallocate فهو ما تلجأ إليه حين + يجب أن تكون المساحة حقيقية: +

+
fallocate -l 10M test10mb.bin
+

وحين يجب أن يكون المحتوى غير قابل للضغط، حتى لا يستطيع أداة الأرشفة تصغيره من جديد:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

ماك

+

mkfile، وهو غير متناثر، والأمران اللذان تعرفهما بالفعل

+

+ يأتي ماك مع mkfile. قيس على macOS 26.6.2: 10485760 بايتًا و20480 كتلة، فالمساحة مخصصة + فعلًا لا موعودة فقط: +

+
mkfile 10m test10mb.bin
+

dd وtruncate موجودان أيضًا ويتصرفان كما في لينكس:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

أين يتوقف هذا عن الصلاحية

+

ملف بالحجم الصحيح ليس ملفًا من النوع الصحيح

+

+ كل ما سبق يعطيك كتلة من الأصفار. وهذا يكفي حين لا ينظر الشيء المختبَر إلا إلى الحجم، كحد الرفع أو + الحصة أو النقل. ويتوقف عن الكفاية لحظة أن يفتح أي شيء الملف. +

+

+ قيس، وهو يستحق أن تجرّبه بنفسك: أنشئ ملفًا بحجم 2 MB بـ fsutil، وسمّه + photo.png، وسلّمه إلى مكتبة صور. تجيب Pillow بـ cannot identify image + file. إنه ليس PNG. ولم يكن كذلك قط، فالاسم وحده قال ذلك. +

+

+ هذا أهم مما يبدو، بسبب الاتجاه الذي يفشل فيه الاختبار بعد ذلك. ترفض نقطة الرفع عندك + الملف، فيصبح اختبارك أخضر، وتستنتج أن حد الحجم يعمل. لم ترفضه بسبب الحجم. رفضته لأن البايتات لم + تكن صورة، ولم تُبلَغ القاعدة التي أردت اختبارها قط. +

+
    +
  • محلل يرفضه قبل النظر في أي قاعدة للحجم
  • +
  • تفشل خطوة الصورة المصغرة، والخطأ الذي تقرؤه عن الصورة المصغرة
  • +
  • يرفضه برنامج مكافحة فيروسات أو فحص محتوى لسبب ثالث
  • +
  • عارض لا يظهر شيئًا، ولا أحد يستطيع الجزم إن كان هذا هو الخطأ
  • +
+
+ +
+

الطريق الآخر

+

ملف حقيقي من تلك الصيغة، بالحجم الذي طلبته تمامًا

+

+ هذا ما يفعله Testing Files Generator. الملف ملف أصيل من صيغته، يُفتح في البرنامج الذي يملكه، وعدد + بايتاته هو ما طلبته بالضبط، حتى البايت: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ اطلب حجمًا لا تستطيع الصيغة بلوغه فتحصل على خطأ يذكر الحد الأدنى وسببه، لا ملفًا بحجم خاطئ أبدًا. + تسرد صفحة الصيغ كل صيغة مع أصغر ملف تستطيع إنتاجه. +

+

والحد حالات اختبار ثلاث لا حالة واحدة، لذا تبني الأداة الثلاث كلها:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ وهذا يعطيك 10485759 و10485760 و10485761 بايتًا، وبيانًا يقول أيها يجب أن يقبله نظامك وأيها يجب أن + يرفضه. تستعرض صفحة حالات الاستخدام هذا وأربع مهام أخرى بُنيت الأداة + لها. +

+ +

مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.

+
+ +
+

فأيهما تستخدم؟

+
    +
  • +

    استخدم أمر النظام

    +

    + حين لا يفتح أي شيء الملف. اختبار حد حجم على نقطة تفحص الحجم أولًا، أو نقل، أو حصة، أو قرص ممتلئ. سطر + واحد، وهو مثبّت أصلًا. +

    +
  • +
  • +

    استخدم مولّدًا حقيقيًا

    +

    + حين يحلّل شيء ما الملف أو يعرضه أو يستورده أو يفكّه، وحين تحتاج غدًا إلى بيانات الاختبار نفسها على + جهاز آخر، بايتًا ببايت. +

    +
  • +
+

+ الاثنان في هذه الصفحة لأن كلًّا منهما صواب في بعض الأحيان. الخطأ الذي ينبغي تجنبه هو استخدام الأول + حيث يلزم الثاني وقراءة الاختبار الأخضر كدليل. +

+
+ +
+ + + + diff --git a/web/public/ar/docs/index.html b/web/public/ar/docs/index.html new file mode 100644 index 00000000..68ce9b70 --- /dev/null +++ b/web/public/ar/docs/index.html @@ -0,0 +1,547 @@ + + + + + + +التوثيق - الأوامر والوصفات والبيان ورموز الخروج + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

التوثيق

+

+ كل ما تفعله الأداة، مرتبًا على هيئة الأسئلة التي يأتي بها الناس فعلًا. ملف + README في المستودع هو المرجع الكامل ويطابق دائمًا الإصدار الذي + نزّلته. +

+ +
+

ما الأوامر المتاحة؟

+

كل أمر يؤدي مهمة واحدة:

+
tfg generate    توليد ملفات، من وصفة أو من خيارات
+tfg validate    فحص وصفة دون كتابة شيء
+tfg verify      فحص مجلد مقابل بيان
+tfg cleanup     حذف الملفات التي يسردها بيان
+tfg recipe fmt  طباعة وصفة بشكلها المستقر
+tfg preset      بناء مجموعة ملفات من سؤال اختبار مُسمّى
+tfg formats     سرد الصيغ التي يدعمها هذا الإصدار
+tfg damage      سرد الطرق التي يستطيع بها هذا الإصدار إتلاف ملف عمدًا
+tfg tool        أدوات صغيرة للملفات التي لديك بالفعل
+tfg version     طباعة إصدار الأداة
+tfg license     طباعة الرخصة ومعناها للملفات المولَّدة
+
+ +
+

كيف أولّد ملفًا واحدًا بحجم دقيق؟

+

+ حدد الصيغة والحجم ووجهة الملف. تُعدّ الأحجام بالمضاعفات 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>ثلاثة ملفات حول حد: أقل بايتًا واحدًا، والحد نفسه، وأكثر بايتًا واحدًا
--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اكتب البيان إلى المخرج القياسي
+
+
+ +
+

كيف أصنع ملفًا تالفًا عمدًا؟

+

+ كل ملف آخر تكتبه هذه الأداة صحيح بحكم بنائه، وهذا يجيب عن اثنين من ثلاثة أسئلة يطرحها مدقق الرفع. + أما --damage فيجيب عن الثالث: هل يُفتح الملف أصلًا. يُنتَج الملف بشكل طبيعي ثم + يُتلف، فيبقى بالحجم الذي طلبته. +

+
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 في البيان، مع تسجيل الإتلاف بجانبه. يُرفض أمران + قبل كتابة أي شيء، لأن كلًّا منهما كان سيضع على القرص ملفًا يصفه البيان وصفًا خاطئًا: +

+
    +
  • ملف أصغر مما يحتاجه الإتلاف، لأنه كان سيخرج دون تغيير
  • +
  • + expected: accept بجانب إتلاف، لأن لا شيء يمكن أن يحققه. اكتب sanitize إن + كان المقصود أن يصلح النظام قيد الاختبار الملف، أو unspecified إن كان هذا هو + السؤال الذي تطرحه +
  • +
+

+ أما الثالث فلا يمكن معرفته مسبقًا. إذا نُفّذ إتلاف ولم يحرّك أي بايت، يُسقَط ذلك الملف بدل كتابته، + ويستمر التشغيل ويذكر أي ملف كان، وينتهي برمز الخروج الجزئي. +

+

+ خطوة بخطوة، مع اختبار يقرأ البيان: كيف تصنع ملفًا تالفًا + للاختبار. +

+
+ +
+

كيف تبدو الوصفة؟

+

+ الوصفة ملف 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. اثنان خطأ، وعدم وجود أي منها خطأ كذلك. الوصفة غير الصالحة لا + تكتب أي ملف وتبلّغ عن كل المشكلات دفعة واحدة لا عن أولها فقط، وتسمّي كل مشكلة الإعداد + الذي تخصه. +

+
+ +
+

كيف أصرّح بما يجب أن يفعله نظامي بملف ما؟

+

الصيغة القصيرة حين تكفي النتيجة، والطويلة حين يهم السبب:

+
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. +

+

+ يسمّي السبب القاعدة المعنية لا الحكم. ولهذا يمكن أن يقع السبب نفسه تحت أي من + النتيجتين: ملف أقل من الحد بايتًا واحدًا نتيجته accept، والقاعدة المعنية تبقى + size_limit. +

+
+ +
+

ماذا يوجد في البيان؟

+

+ يُكتب بجانب الملفات في نهاية كل تشغيل، بما في ذلك التشغيل الذي أُوقف. عنصر واحد لكل ملف: +

+
{
+  "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 حين يأتي من إعداد مسبق، فيمكن دائمًا تتبّع البيان إلى ما أنتجه. +

+

+ يحمل كل عنصر أيضًا target_id، وهو معرّف الهدف في الوصفة الذي أنتج الملف، ويحصي + summary.by_target الملفات التي انتهى إليها كل هدف. وهكذا يمكن فحص وصفة متعددة + الأهداف هدفًا هدفًا دون قراءة أسماء الملفات. +

+
+ +
+

ما الإعداد المسبق؟

+

+ مجموعة ملفات جاهزة تجيب عن سؤال اختبار شائع، فلا تحتاج إلى تصميم المجموعة بنفسك. الإعدادات المسبقة + وصفات عادية في جوهرها، ويطبع eject الوصفة لتعدّلها من هناك. لكل إعداد مسبق + صفحة خاصة تذكر ما يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+
    +
  • +

    الفارغ والأدنى

    +

    هل يمر ملف صالح بأصغر حجم تسمح به الصيغة؟

    +

    empty-and-minimal

    +
  • +
  • +

    التعامل مع أسماء الملفات

    +

    هل سيخزّن نظامي ويعرض ويعيد اسم ملف لم يتوقعه؟

    +

    filename-handling

    +
  • +
  • +

    حدود الحجم

    +

    هل يُطبَّق حد الحجم تمامًا حيث أُعلن عنه؟

    +

    size-boundaries

    +
  • +
  • +

    استيراد الجداول

    +

    هل يصمد استيراد الجداول عندي أمام ما تصدّره الأدوات الحقيقية؟

    +

    tabular-import

    +
  • +
  • +

    ترميز النص

    +

    هل يعرف قارئي ترميز الملف، أم يخمّن؟

    +

    text-encoding

    +
  • +
  • +

    التحقق من الرفع

    +

    هل يقبل نموذج الرفع عندي ما يجب قبوله ويرفض الباقي؟

    +

    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 بكلفة المجموعة قبل أن تبنيها، ويقول صراحةً حين يكون رقم ما قيمة مؤقتة منا لا + حدًّا منك. +

+
+ +
+

ما معنى رموز الخروج؟

+

+ لكل نهاية رمزها الخاص، وتذهب المخرجات المقروءة آليًا إلى المخرج القياسي، ولا يطبع التشغيل الفاشل + شيئًا هناك. الجدول عقد مجمّد، وتغيير معنى رمز يتطلب رفع الإصدار الرئيسي. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
الرمزالمعنى
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. +

+
+ +
+

هل توجد نافذة سطح مكتب؟

+

+ نعم، المحرك نفسه بنافذة فوقه، للاختبار الذي لا يُكتب له سكربت. وهي ليست نسخة مبتورة: يقارن اختبار + الواجهتين ميزةً ميزة، وكل ما تستطيع إحداهما فعله دون الأخرى يجب أن يُعلَن ويُبرَّر بدل أن + يتباعدا بصمت. +

+

+ الشاشات هي دفعة واحدة، والإعدادات المسبقة، وعدة دفعات معًا، وحول. تُظهر كلفة التشغيل قبل كتابة أي + شيء، وتبلّغ عن التقدم أثناء العمل، ويمكن إلغاؤها في منتصف الطريق دون ترك ملف مكتوب نصفه. لا تفتح + ملف وصفة بعد، فالوصفات شأن سطر الأوامر حاليًا، وتبني النافذة دفعاتها في النموذج. +

+
+ +
+ + + + diff --git a/web/public/ar/faq/index.html b/web/public/ar/faq/index.html new file mode 100644 index 00000000..a24cd4ae --- /dev/null +++ b/web/public/ar/faq/index.html @@ -0,0 +1,348 @@ + + + + + + +الأسئلة الشائعة - عن توليد ملفات الاختبار + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

الأسئلة الشائعة

+

+ الترخيص والخصوصية وقابلية إعادة الإنتاج وما يتحقق منه الناس قبل إدخال مولّد في خط بناء. إذا لم يكن + سؤالك هنا، فإن متتبع المشكلات مفتوح. +

+ +
+
+

بماذا يختلف عن dd أو fsutil أو truncate؟

+
+

تلك الأوامر تعطيك ملفًا بالحجم الصحيح مملوءًا بلا شيء. ملف بحجم 2 MB باسم photo.png صُنع بهذه الطريقة ليس PNG، فكل ما يحلله فعلًا يرفضه لسبب خاطئ، ويمر اختبارك أيضًا لسبب خاطئ. هذه الأداة تنتج ملف PNG حقيقيًا بحجم 2 MB تمامًا يُفتح في عارض الصور، ويصل مع بيان عن كيفية معاملة نظامك له.

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

هل هو مجاني، وهل يمكنني استخدامه في العمل؟

+
+

نعم في الحالتين. صدر بموجب GPL-3.0 ولا يكلّف شيئًا. لا يوجد حساب ولا مفتاح ترخيص ولا مستوى مدفوع.

+
+
+
+

هل يمكنني استخدام الملفات المولَّدة في منتج مغلق المصدر؟

+
+

نعم. الرخصة تشمل شيفرة الأداة لا ما تنتجه. الملفات والوصفات والبيانات المولَّدة مخرجات لا أعمال مشتقة، فيمكنك إيداعها وتوزيعها دون أي التزام.

+
+
+
+

هل تحتوي الملفات المولَّدة على بيانات شخصية حقيقية؟

+
+

لا. كل ما بداخلها يُركَّب من بذرة. لا تُقرأ أي مجموعة بيانات، ولا يُتصل بأي خدمة، ولا يُضمَّن أي محتوى من طرف ثالث. عامل عنوان البريد الإلكتروني المولَّد على أنه غير صالح للاستخدام لا على أنه غير مستخدم، لأن أي سلسلة عشوائية قد تتطابق مصادفة مع سلسلة حقيقية.

+
+
+
+

هل سأحصل على الملفات نفسها تمامًا على جهاز آخر؟

+
+

نعم، بايتًا ببايت، مع الوصفة نفسها والبذرة نفسها. يختبر المشروع ذلك مع كل تغيير، وكسره يتطلب رفع الإصدار الرئيسي. وهذا ما يتيح لك إيداع وصفة صغيرة بدل بيانات اختبار ثنائية كبيرة.

+
+
+
+

هل يحتاج إلى اتصال بالإنترنت؟

+
+

أبدًا. لا توجد قياسات عن بُعد ولا فحص للتحديثات ولا عميل سحابي، والملف التنفيذي لسطر الأوامر لا تُترجَم فيه حزمة شبكة أصلًا. يعمل على جهاز بلا شبكة وداخل بيئة مؤسسية مغلقة.

+
+
+
+

ماذا يحدث إذا طلبت حجمًا لا تستطيع الصيغة بلوغه؟

+
+

تحصل على خطأ يذكر الصيغة وأصغر حجم ممكن وسبب هذا الحد الأدنى وما يجب فعله بدلًا من ذلك، ولا يُكتب أي ملف. الأداة لا تقرّب الحجم بصمت أبدًا. وكل حد أدنى مذكور في صفحة الصيغ.

+
tfg formats png
+
+
+
+

هل يمكنني توليد ملف تالف عمدًا؟

+
+

نعم. أضف --damage zero-head فيخرج الملف بالحجم الذي طلبته تمامًا، وأول بايتاته مكتوب فوقها أصفار، فترفضه القارئة، ويقول البيان إن نظامك ينبغي أن يرفضه. التفاصيل في صفحة ملفات الاختبار التالفة.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

ما الصيغ القادمة؟

+
+

7z وmp3 وmp4. تعمل اليوم 26 صيغة من البداية إلى النهاية.

+
+
+
+

على أي أنظمة يمكنني تشغيله؟

+
+

يعمل سطر الأوامر على ويندوز ولينكس على معالجات Intel وARM، وعلى أجهزة ماك بمعالجات Apple Silicon. تُقدَّم نافذة سطح المكتب لويندوز على Intel، ولينكس على Intel، وأجهزة ماك بمعالجات Apple Silicon. أجهزة ماك بمعالجات Intel غير مدعومة ولا يُبنى لها شيء.

+
+
+
+

هل أحتاج إلى تثبيت شيء؟

+
+

لا. نزّل الأرشيف الخاص بنظامك وفك ضغطه وشغّل الملف التنفيذي. لا يوجد مثبّت ولا بيئة تشغيل تُضاف ولا اعتماديات تُحل. وإذا كان لديك Go فيكفي أمر go install واحد أيضًا.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

لماذا يكون التشغيل على آلاف الملفات أبطأ على ويندوز؟

+
+

لأن ويندوز يتقاضى أكثر عن كل مسار ينظر فيه، والأمر الذي يمر على آلاف الملفات ينظر في آلاف المسارات. قيس على جهاز واحد فيه 3000 ملف بحجم 1 kB، فاستغرق verify نحو 0.9 ثانية على ويندوز ونحو 0.2 ثانية على لينكس داخل حاوية. ويصغّر مسار الإخراج الأقصر رقم ويندوز، لأن كل مجلد فوق الملفات جزء مما يُنظر فيه.

+
+
+
+ + +
+

ما زلت تقرر؟

+

+ تعرض صفحة حالات الاستخدام المهام التي بُنيت الأداة لها، وتسرد + صفحة الصيغ كل صيغة مع أصغر ملف تستطيع إنتاجه. وملف + README في المستودع هو المرجع الكامل. +

+ +

مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.

+
+ +
+ + + + diff --git a/web/public/ar/formats/index.html b/web/public/ar/formats/index.html new file mode 100644 index 00000000..2d518603 --- /dev/null +++ b/web/public/ar/formats/index.html @@ -0,0 +1,906 @@ + + + + + + +26 صيغة ملف مدعومة - PDF وDOCX وPNG وZIP وغيرها + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 صيغة ملف، كلٌّ منها يُولَّد بحجم دقيق

+

+ كلٌّ منها ملف حقيقي من تلك الصيغة. يُفتح في البرنامج الذي يملكه، وعدد بايتاته هو ما + طلبته بالضبط. ولا واحد منها أصفار حشوية أُلصق بها امتداد. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
الصيغةالاسمالامتدادأصغر ملفالاكتماليُتحقق منه بواسطة
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullغير منطبق
mdMarkdown.md0fullغير منطبق
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullغير منطبق
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

معنى الأعمدة

+
    +
  • +

    أصغر ملف

    +

    + أقل عدد من البايتات تقبله هذه الأداة لتلك الصيغة، شاملًا الوسم الذي تكتبه داخل الملف. اطلب أقل فتحصل + على خطأ يذكر الحد الأدنى وسببه، لا ملفًا بحجم خاطئ أبدًا. +

    +
  • +
  • +

    الاكتمال

    +

    + مدى اكتمال الملف. تعني full أن قارئًا يحلل الصيغة فعلًا يقبله، لا أن الامتداد يطابق + فحسب. +

    +
  • +
  • +

    يُتحقق منه بواسطة

    +

    + القارئ المستقل الذي يفتح كل ملف مولَّد قبل إصدار الصيغة، وهو تنفيذ منفصل، لا شيفرتنا نحن تصحّح + واجباتها بنفسها. +

    +
  • +
+

+ وتتكرر كل صيغة حتى البايت أيضًا: الوصفة نفسها والبذرة نفسها تنتجان ملفات متطابقة على أي جهاز، وهذا + ما يجعل إيداع وصفة بدل بيانات الاختبار نفسها أمرًا آمنًا. +

+
+ +
+

الإعدادات التي تقبلها كل صيغة

+

+ لمعظم الصيغ إعدادات خاصة بها: أبعاد الصورة، وجودة JPEG، وعدد صفحات PDF، والصفوف والأعمدة في جدول + بيانات، وعدد العناصر داخل الأرشيف. اضبطها بـ --set key=value في سطر الأوامر أو تحت + properties: في وصفة. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
الصيغةالإعدادالقيم المقبولة
avifwidth1 - 16384 بكسل
height1 - 16384 بكسل
quality1 - 100
bmpwidth1 - 20000 بكسل
height1 - 20000 بكسل
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerصحيح أو خاطئ
quote_styleall, minimal, none
columns2 - 32768 أعمدة
docxparagraphs1 - 50000 فقرات
gifwidth1 - 20000 بكسل
height1 - 20000 بكسل
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 بكسل
height1 - 256 بكسل
embedbmp, png
jpgwidth1 - 20000 بكسل
height1 - 20000 بكسل
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 بكسل
height1 - 16384 بكسل
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 إدخال في الثانية
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomصحيح أو خاطئ
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleأي نص
authorأي نص
subjectأي نص
keywordsأي نص
creatorأي نص
producerأي نص
createdتاريخ مثل 2024-02-29 أو 2024-02-29T13:45:00+02:00، أو none
modifiedتاريخ مثل 2024-02-29 أو 2024-02-29T13:45:00+02:00، أو none
pngwidth1 - 20000 بكسل
height1 - 20000 بكسل
pptxslides1 - 500 شرائح
svgwidth1 - 20000 بكسل
height1 - 20000 بكسل
targzentries0 - 10000
entry_formatمعرّف صيغة، كما يسردها tfg formats
entry_sizeحجم مثل 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesصحيح أو خاطئ
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 بكسل
height1 - 20000 بكسل
txtencodingutf-16be, utf-16le, utf-8
bomصحيح أو خاطئ
wavsample_rate8000 - 192000 هرتز
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 بكسل
height1 - 16383 بكسل
xlsxrows1 - 200000 صفوف
columns1 - 32768 أعمدة
xmlencodingutf-16be, utf-16le, utf-8
bomصحيح أو خاطئ
zipentries0 - 10000
entry_formatمعرّف صيغة، كما يسردها tfg formats
entry_sizeحجم مثل 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesصحيح أو خاطئ
passwordكلمة المرور، كنص عادي
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ القيمة الواقعة خارج ما يقبله الإعداد تُرفض برسالة تسمّي الإعداد والنطاق المسموح وما يُستخدم بدلًا + منه. والإعداد المجهول خطأ أيضًا، وليس قيمة افتراضية صامتة أبدًا، فخطأ مطبعي يُقبل بصمت يعطي + ملفًا بإعدادات خاطئة وساعة من التساؤل عن سبب نجاح اختبار كان ينبغي ألا ينجح. +

+

+ شغّل tfg formats <id> لترى بالضبط ما تقبله صيغة واحدة في الإصدار الذي لديك. +

+
+ +
+

الأرشيفات تحتوي ملفات حقيقية

+

+ targz وzip يمكن + ملؤها بعناصر بدل تركها قشرة فارغة. الأرشيف المولَّد يحتوي فعلًا على المستندات التي يدّعي + احتواءها، فكل ما يفكّه أثناء اختبار يجد بداخله ملفات حقيقية. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/ar/index.html b/web/public/ar/index.html new file mode 100644 index 00000000..86a754ac --- /dev/null +++ b/web/public/ar/index.html @@ -0,0 +1,450 @@ + + + + + + +مولّد ملفات الاختبار لضمان الجودة - حجم دقيق، 26 صيغة حقيقية + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

ولّد ملفات اختبار حقيقية بحجم دقيق

+

+ PDF وPNG وDOCX وZIP، 26 صيغة في المجمل، وكلٌّ منها ملف حقيقي + يُفتح في البرنامج الذي يملكه، وبـالحجم الذي طلبته تمامًا. كما يدوّن كل تشغيل ما + يجب أن يفعله تطبيقك بكل ملف. سطر أوامر ونافذة سطح مكتب، مجاني ومفتوح المصدر، ويعمل بالكامل على + جهازك. +

+ + +

مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.

+
+ +
+ نافذة سطح المكتب لـ Testing Files Generator، مجهّزة لكتابة دفعة من ملفات الاختبار +
نافذة سطح المكتب، مجهّزة لكتابة دفعة من الملفات. المحرك نفسه يعمل خلف سطر الأوامر.
+
+
+ + + +
+

المشكلة

+

صنع ملف اختبار واحد سهل. صنع الألف الصحيحة هو الجزء المرهق

+

أنت تختبر برنامجًا يقبل ملفات من الناس. عاجلًا أم آجلًا ستحتاج إلى:

+
    +
  • ملف PDF بحجم 10 MB تمامًا، لتعرف إن كان حد الرفع حقيقيًا
  • +
  • الملفات الثلاثة على جانبي هذا الحد، لاصطياد أخطاء الفرق بواحد
  • +
  • 10,000 ملف سجل، لترى ماذا تفعل المهمة الليلية حين يكون المجلد كبيرًا
  • +
  • ملف ZIP يحتوي فعلًا على 200 مستند، لا قشرة فارغة بالامتداد الصحيح
  • +
  • ملف بحجم 4 GB دون الاحتفاظ بملف 4 GB في مستودعك
  • +
  • بيانات الاختبار نفسها على حاسوبك المحمول وعلى خادم البناء، بايتًا ببايت
  • +
+

+ هذا ما يحل محله هذا المولّد. صُمم لمهندسي ضمان الجودة وأتمتة الاختبار، ولكل من خلف شيفرته نموذج رفع + أو روتين استيراد أو محلل أو حصة تخزين. +

+
+ +
+

ما الذي يميّزه

+

المولّدات الأخرى تتوقف عند البايتات. هذا المولّد يجيب عما يسأله اختبارك فعلًا

+

+ مجلد من الملفات يتركك تقرر بنفسك ما يُفترض أن يثبته كل ملف. يكتب كل تشغيل هنا ملف + manifest.json بجانب الملفات، وهو قائمة بسيطة بكل ما أُنتج، ولكل عنصر توقّع + معلن. +

+

لنفترض أن نقطة الرفع عندك تسمح بـ 1 MB. اطلب الملفات الثلاثة الواقعة على هذا الخط:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
الملفالبايتاتما يجب أن يفعله نظامكالسبب
1mb_under_1b.pdf1048575قبولداخل الحد
1mb_at_limit.pdf1048576قبولالحد نفسه مسموح
1mb_over_1b.pdf1048577رفضsize_limit
+
+ +

ثلاثة ملفات، وثلاث إجابات مختلفة، بصيغة تقرؤها الآلة. يقرأ اختبارك البيان بدل أن تكتب التأكيدات يدويًا:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

حين تعتمد الإجابة على سياستك أنت، يقول البيان ذلك

+

+ يسجّل unspecified بدل اختلاق توقّع. المولّد الذي يخمّن يصنع إخفاقات زائفة، ومجموعة + الاختبارات التي تطلق إنذارات كاذبة يُوقف العمل بها. +

+
+
+ +
+

الإعدادات المسبقة

+

اختر السؤال، واحصل على المجموعة كاملة

+

+ الإعداد المسبق مجموعة ملفات اختبار مصممة حول سؤال اختبار واحد، فلا تحتاج إلى معرفة أي الملفات يثبت + ماذا. لكل منها صفحة تذكر ما يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+
    +
  • +

    الفارغ والأدنى

    +

    هل يمر ملف صالح بأصغر حجم تسمح به الصيغة؟

    +

    empty-and-minimal

    +
  • +
  • +

    التعامل مع أسماء الملفات

    +

    هل سيخزّن نظامي ويعرض ويعيد اسم ملف لم يتوقعه؟

    +

    filename-handling

    +
  • +
  • +

    حدود الحجم

    +

    هل يُطبَّق حد الحجم تمامًا حيث أُعلن عنه؟

    +

    size-boundaries

    +
  • +
  • +

    استيراد الجداول

    +

    هل يصمد استيراد الجداول عندي أمام ما تصدّره الأدوات الحقيقية؟

    +

    tabular-import

    +
  • +
  • +

    ترميز النص

    +

    هل يعرف قارئي ترميز الملف، أم يخمّن؟

    +

    text-encoding

    +
  • +
  • +

    التحقق من الرفع

    +

    هل يقبل نموذج الرفع عندي ما يجب قبوله ويرفض الباقي؟

    +

    upload-validation

    +
  • +
+

كل الإعدادات المسبقة، وعلاقتها بالوصفات

+
+ +
+

بداية سريعة

+

ثلاثة أوامر لترى الأداة تعمل

+
    +
  1. +

    أنشئ ملفًا

    +

    ملف PNG واحد، بحجم ميغابايتين تمامًا:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    أنشئ ملفات كثيرة

    +

    + عشرة آلاف ملف سجل، حجم كل منها بين واحد وثمانية كيلوبايت، تُسحب الأحجام من البذرة ليعطي الغد + المجموعة نفسها. امنح كل تشغيل مجلده الخاص، فالبيان هو السجل الوحيد لما كتبه + التشغيل، لذا ترفض الأداة كتابة بيان ثانٍ فوقه: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    افحصها، ثم احذفها

    +

    يخبرك verify بأن شيئًا لم يتحرك. ويحذف cleanup ما كُتب بالضبط ولا شيء غيره:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ تُعدّ الأحجام بالمضاعفات 1024 كما يفعل مدير الملفات لديك، فـ2mb تعني 2097152 بايتًا. + وعدد البايتات المجرد يصلح أيضًا. يغطي التوثيق الوصفات والبيان ورموز + الخروج. +

+
+ +
+

ما تحصل عليه

+

مبني لمجموعة اختبارات تعمل دون إشراف

+
    +
  • +

    حجم دقيق، حتى البايت

    +

    اطلب 10485761 بايتًا واحصل على هذا العدد بالضبط. الحجم الذي لا تستطيع الصيغة بلوغه خطأ مع سبب، وليس ملفًا بحجم خاطئ أبدًا.

    +
  • +
  • +

    26 صيغة حقيقية

    +

    ليست أصفارًا حشوية بامتداد. يُفتح ملف PNG المولَّد في عارض الصور، ويُفتح DOCX في Word، ويُفك ضغط ZIP. وتُفحص كل صيغة بقرّاء مستقلين قبل إصدارها.

    +
  • +
  • +

    بيان هو مرجع للاختبار

    +

    المسار والحجم وSHA-256 والصيغة والبذرة وإصدار الأداة، وما يجب أن يفعله نظامك بالملف.

    +
  • +
  • +

    قابل لإعادة الإنتاج

    +

    الوصفة نفسها والبذرة نفسها تعطيان البايتات نفسها على أي جهاز. أودع وصفة YAML صغيرة بدل بيانات اختبار ثنائية كبيرة.

    +
  • +
  • +

    واجهتان ومحرك واحد

    +

    سطر أوامر مبني للتكامل المستمر، ونافذة سطح مكتب للاختبار الاستكشافي. ليست أيٌّ منهما نسخة مبتورة من الأخرى، ويقارنهما اختبار ميزةً ميزة.

    +
  • +
  • +

    دون اتصال بالكامل

    +

    لا حساب ولا سحابة ولا قياسات عن بُعد ولا فحص للتحديثات. والملف التنفيذي لسطر الأوامر لا تُترجَم فيه حزمة شبكة أصلًا.

    +
  • +
+
+ +
+

التنزيل

+

اختر الإصدار المناسب لنظامك

+

+ فك ضغط الأرشيف وشغّل الملف. tfg هو سطر الأوامر وtfg-gui هو نافذة سطح + المكتب. لا يوجد مثبّت ولا شيء يُضاف إلى جهازك. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
النظامسطر الأوامرنافذة سطح المكتب
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

ما الموقَّع وما غير الموقَّع

+

+ تنزيلات ويندوز وماك موقّعة، لذا تبدأ دون تحذير من مطوّر غير معروف. أما تنزيلات لينكس فغير موقّعة، + لأن لينكس المكتبي لا يملك ما يوقَّع به. وكل أرشيف مدرج في verify-SHA256SUMS.txt + على صفحة الإصدارات، لتتحقق مما نزّلته. +

+
+ +

مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.

+
+ + +
+ + + + diff --git a/web/public/ar/presets/empty-and-minimal/index.html b/web/public/ar/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..aa549d37 --- /dev/null +++ b/web/public/ar/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +أصغر ملفات اختبار صالحة وفارغة في كل صيغة + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

الفارغ والأدنى

+

هل يمر ملف صالح بأصغر حجم تسمح به الصيغة؟

+

+ يبني الإعداد المسبق empty-and-minimal بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • ملف صالح يُرفض لأنه صغير جدًا، لأن الفحص يعدّ البايتات بدل قراءتها
  • +
  • ملف فارغ يُسقط القارئ بدل أن يُبلَّغ عنه
  • +
  • صورة بعرض بكسل واحد تقسم على صفر في طريقها إلى الصورة المصغرة
  • +
  • تخزين يقرأ صفر بايت على أنه رفع فاشل ويواصل إعادة المحاولة
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show empty-and-minimal:

+
+ + + + + + + +
الملفات28
الأهداف في وصفته28
الحجم الإجمالي32 667 B
الصيغavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.26
unspecifiedيعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته.2
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--formatsمعرّفات صيغ مفصولة بفواصل، أو allallالصيغ التي تتكون منها المجموعة. اتركها على all لكل صيغ هذا الإصدار، أو سمِّ الصيغ التي يقبلها نظامك.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/ar/presets/filename-handling/index.html b/web/public/ar/presets/filename-handling/index.html new file mode 100644 index 00000000..fdd7447f --- /dev/null +++ b/web/public/ar/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +أسماء ملفات إشكالية للاختبار - يونيكود والطول + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

التعامل مع أسماء الملفات

+

هل سيخزّن نظامي ويعرض ويعيد اسم ملف لم يتوقعه؟

+

+ يبني الإعداد المسبق filename-handling بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • اسم يبدو كاسم آخر على الشاشة أو في السجل أو في قائمة
  • +
  • اسم يُقطع أو يُقص أو يُعاد كتابته بين الرفع والتخزين
  • +
  • حد للطول يُحسب بالأحرف بينما يحسب التخزين بالبايتات
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show filename-handling:

+
+ + + + + + + +
الملفات50
الأهداف في وصفته50
الحجم الإجمالي51 200 B
الصيغtxt
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.4
unspecifiedيعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته.46
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--formatمعرّف صيغة من صفحة الصيغtxtصيغة كل ملف في المجموعة. إنه خيار في الأداة نفسها، والإعداد المسبق يمنحه قيمة افتراضية فقط.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/ar/presets/index.html b/web/public/ar/presets/index.html new file mode 100644 index 00000000..5fdc385c --- /dev/null +++ b/web/public/ar/presets/index.html @@ -0,0 +1,242 @@ + + + + + + +إعدادات مسبقة لملفات الاختبار - مجموعات جاهزة لأسئلة ضمان الجودة + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

إعدادات مسبقة لملفات الاختبار، مجموعة لكل سؤال اختبار

+

+ الإعداد المسبق مجموعة كاملة من ملفات الاختبار مصممة حول سؤال واحد، مع بيان يحدد كيف يجب أن يتفاعل + نظامك مع كل ملف. أنت تختار السؤال، والأداة تبني المجموعة. لكل إعداد مسبق صفحته الخاصة التي تذكر ما + يكتشفه عادةً، وما في المجموعة، وكل إعداد يقبله. +

+ + + +
+

بماذا يختلف الإعداد المسبق عن الوصفة؟

+

+ في جوهره، لا يختلف. الإعداد المسبق وصفة تكتبها الأداة لك من بضعة إعدادات. يطبع tfg preset + eject تلك الوصفة لتحتفظ بها بجانب اختباراتك وتعدّلها، ويمكن لوصفة خاصة بك أن تبني على + إعداد مسبق بسطر واحد: extends: preset: يليه معرّفه. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

هل يمكنني الوثوق بالقيم الافتراضية؟

+

+ بالنسبة إلى الملفات، نعم. أما الرقم الذي لا يعرفه إلا نظامك، مثل حد نموذج الرفع، فالقيمة الافتراضية + قيمة مؤقتة منا، وتقول الأداة ذلك في كل مرة تستخدم فيها واحدة. وتعلّم صفحة كل إعداد مسبق تلك + الإعدادات، ويقول tfg preset show ذلك قبل كتابة أي شيء. +

+
+ +
+ + + + diff --git a/web/public/ar/presets/size-boundaries/index.html b/web/public/ar/presets/size-boundaries/index.html new file mode 100644 index 00000000..4ea46c73 --- /dev/null +++ b/web/public/ar/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +اختبار حد حجم الرفع - ملفات عند الحد تمامًا + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

حدود الحجم

+

هل يُطبَّق حد الحجم تمامًا حيث أُعلن عنه؟

+

+ يبني الإعداد المسبق size-boundaries بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • أخطاء الفرق بواحد عند الحد
  • +
  • خلط MB مع MiB، أي 4.8 بالمئة، وهذا كافٍ لتمرير ملف لا ينبغي أن يمر
  • +
  • حد يُطبَّق في المتصفح لا على الخادم
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show size-boundaries:

+
+ + + + + + + +
الملفات7
الأهداف في وصفته7
الحجم الإجمالي73 400 320 B
الصيغpdf
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.4
rejectينبغي أن يرفض نظامك الملف.3
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--limitحجم مثل 2mb10mbحد الحجم الذي يعلنه نظامك. كل شيء آخر يُقاس منه. هذه القيمة الافتراضية مؤقتة منا، وليست قيمة نظامك. مرّر قيمتك أنت.
--spreadأحجام مفصولة بفواصل1B,1kb,1mbإلى أي مدى يمتد على جانبي الحد، كقائمة أحجام.
--formatمعرّف صيغة من صفحة الصيغpdfصيغة كل ملف في المجموعة. إنه خيار في الأداة نفسها، والإعداد المسبق يمنحه قيمة افتراضية فقط.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

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

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ar/presets/tabular-import/index.html b/web/public/ar/presets/tabular-import/index.html new file mode 100644 index 00000000..759931c0 --- /dev/null +++ b/web/public/ar/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +ملفات اختبار استيراد CSV وExcel - الفواصل والعناوين + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

استيراد الجداول

+

هل يصمد استيراد الجداول عندي أمام ما تصدّره الأدوات الحقيقية؟

+

+ يبني الإعداد المسبق tabular-import بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • ملف بفاصلة منقوطة يُقرأ كعمود واحد، لأن الفاصل افتُرض بدل أن يُبحث عنه
  • +
  • ملف CRLF يُقسَّم إلى صفوف مع صف فارغ بعد كل صف
  • +
  • جدول بلا ترويسة يُبتلع صف بياناته الأول كأسماء أعمدة
  • +
  • استيراد يحتفظ بالأعمدة التي يستطيع عرضها ويُسقط الباقي دون كلمة
  • +
  • قارئ يأخذ سجلات JSON سطرًا سطرًا ويتوقف عند أول مستند بمسافة بادئة
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show tabular-import:

+
+ + + + + + + +
الملفات13
الأهداف في وصفته13
الحجم الإجمالي3 080 060 B
الصيغcsv, json, xlsx
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.8
unspecifiedيعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته.5
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--rows1 - 200000 صفوف1000عدد الصفوف في الجدول. يُكتب الملف بالحجم الذي تُعبَّأ إليه هذه الصفوف تمامًا، لذا تتحرك الميزانية أعلاه مع هذه القيمة.
--columns1 - 32768 أعمدة10عدد الأعمدة في كل صف من الجدول. لحاصل ضرب الصفوف في الأعمدة سقف، وأي طلب يتجاوزه يُرفض قبل أن يُكتب أي شيء.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/ar/presets/text-encoding/index.html b/web/public/ar/presets/text-encoding/index.html new file mode 100644 index 00000000..19d0b622 --- /dev/null +++ b/web/public/ar/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +ملفات اختبار ترميز النص - UTF-8 وUTF-16 وBOM وCRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

ترميز النص

+

هل يعرف قارئي ترميز الملف، أم يخمّن؟

+

+ يبني الإعداد المسبق text-encoding بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • قارئ يفترض UTF-8 فيعرض ملف UTF-16 بحرف واحد من كل ثلاثة أو كصفوف من المربعات
  • +
  • علامة ترتيب بايتات تُقرأ كمحتوى، فيبدأ أول حقل في الاستيراد بثلاثة أحرف غريبة
  • +
  • مستورد يخمّن الترميز من البايتات الأولى ويخمّن بشكل مختلف مع ملف أطول
  • +
  • ملف CRLF يُقسَّم إلى صفوف مع صف فارغ بعد كل صف، أو حرف إرجاع الحامل يبقى داخل الحقل الأخير
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show text-encoding:

+
+ + + + + + + +
الملفات20
الأهداف في وصفته20
الحجم الإجمالي81 920 B
الصيغcsv, log, md, txt, xml
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.10
unspecifiedيعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته.10
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--sampleحجم مثل 2mb4kbحجم كل ملف في المجموعة. يخزّن UTF-16 بايتين لكل حرف، لذا يُرفض العدد الفردي.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/ar/presets/upload-validation/index.html b/web/public/ar/presets/upload-validation/index.html new file mode 100644 index 00000000..25ba5a15 --- /dev/null +++ b/web/public/ar/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +ملفات اختبار التحقق من الرفع - النوع والحجم والاسم + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

الإعدادات المسبقة

+

التحقق من الرفع

+

هل يقبل نموذج الرفع عندي ما يجب قبوله ويرفض الباقي؟

+

+ يبني الإعداد المسبق upload-validation بأمر واحد مجموعة كاملة من ملفات الاختبار الحقيقية لهذا + السؤال، وبجانبها manifest.json يحدد كيف يجب أن يتفاعل نظامك مع كل ملف. كل ما يلي + مقروء من البرنامج، عند القيم الافتراضية لهذا الإصدار. +

+ + +
+

ماذا يكتشف عادةً؟

+
    +
  • حد يُطبَّق في المتصفح لا على الخادم
  • +
  • ملف SVG أو HTML يُؤخذ على أنه صورة أو نص عادي، وهي طريقة لتمرير سكربت عبر نموذج
  • +
  • ملف يُفحص بامتداده ولا يُفتح أبدًا، فيمر ملف PDF اسمه .jpg
  • +
  • نموذج يقرأ الجسم كله في الذاكرة قبل أن ينظر كم حجمه
  • +
  • رفع باسم PHOTO.JPG يُرفض بينما يُقبل photo.jpg، أو العكس
  • +
  • اسم فيه مسافات أو أقواس أو أحرف خارج ASCII يُكتب على القرص دون تغيير
  • +
+
+ + +
+

ماذا في المجموعة؟

+

عند القيم الافتراضية، كما يبلّغ tfg preset show upload-validation:

+
+ + + + + + + +
الملفات71
الأهداف في وصفته22
الحجم الإجمالي120 639 488 B
الصيغhtml, jpg, pdf, png, svg, txt
+
+

وما يتوقعه بيان تلك المجموعة من نظامك:

+
+ + + + + + + + + +
المتوقعالمعنىالملفات
acceptينبغي أن يقبل نظامك الملف.56
rejectينبغي أن يرفض نظامك الملف.10
unspecifiedيعتمد على قواعد نظامك. أنت من يقرر، ثم تتحقق من أن ما يحدث هو ما قصدته.5
+
+
+ +
+

ما الذي يمكنك تغييره؟

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
الإعداديقبلالافتراضيما يفعله
--limitحجم مثل 2mb10mbحد الحجم الذي يعلنه نموذج الرفع عندك. تأخذ هذه المجموعة خطوة واحدة على كل جانب منه، ولملف عند كل مسافة شغّل الإعداد المسبق size-boundaries. هذه القيمة الافتراضية مؤقتة منا، وليست قيمة نظامك. مرّر قيمتك أنت.
--allowمعرّفات صيغ مفصولة بفواصلjpg,png,pdfالأنواع التي يجب أن يقبلها نموذجك. يصير كل نوع ملفًا حقيقيًا من ذلك النوع، وتشكّل الشاهد الإيجابي للمجموعة كلها.
--denyامتدادات مفصولة بفواصلsvg,html,exe,shالامتدادات التي يجب أن يرفضها نموذجك. الامتداد الذي لا صيغة له في هذا الإصدار يحصل مع ذلك على ملف بهذا الاسم يحتوي نصًا عاديًا.
--far-over10x, 2x, off2xإلى أي مدى يتجاوز الملف الكبير الوحيد الحد. أوقفه حيث لا يستحق كتابة أضعاف الحد مساحة القرص.
--bulk0 - 10000 ملفات50عدد الملفات في الرفع الجماعي. الصفر يُخرج هذه المجموعة من المجموعة كليًا.
+
+
+ +
+

كيف تشغّله؟

+

اطّلع على كلفة المجموعة، أو ابنِها، أو خذ وصفتها لتعدّلها:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

أو ابنِ عليه في وصفة خاصة بك، بجانب اختباراتك:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ar/test-files-in-ci/index.html b/web/public/ar/test-files-in-ci/index.html new file mode 100644 index 00000000..da26cef6 --- /dev/null +++ b/web/public/ar/test-files-in-ci/index.html @@ -0,0 +1,371 @@ + + + + + + +ملفات الاختبار في CI - GitHub Actions وGitLab CI وPowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

حالات الاستخدام

+

كيف تولّد ملفات الاختبار في خط CI

+

+ الملف الثنائي الثابت في المستودع يبقى في سجله إلى الأبد، ولا يمكن مراجعته في diff، ويصبح مستحيلًا + حين يكبر الملف. ولِّد الملفات بدلًا من ذلك داخل الخط من وصفة. الوصفة نص، والبايتات تخرج متطابقة في + كل مرة، وخطوة أخيرة تثبت أن شيئًا لم يتحرك. +

+ +
+

الجواب المختصر

+

+ ثبّت tfg، وشغّل tfg generate fixtures.yaml --out ./fixtures قبل + الاختبارات، وtfg verify ./fixtures/manifest.json بعدها. كلتا الخطوتين تُفشلان + البناء من تلقاء نفسيهما، برمز خروج يقول السبب. +

+
+ +
+

لماذا لا نودعها

+

لماذا لا ينبغي أن يعيش الملف الثابت في المستودع

+
    +
  • + يبقى في السجل. حذف ملف ثنائي لاحقًا لا يصغّر النسخة المستنسخة، لأن كل إصدار منه ما + زال هناك. +
  • +
  • + الـ diff لا يُظهر ما تغيّر. يرى المراجع أن ملف PDF مختلف ولا شيء غير ذلك. أما + الوصفة فتتغيّر بسطر واحد. +
  • +
  • + الملفات الكبيرة لا تتسع. يرفض GitHub دفعة تحتوي ملفًا أكبر من 100 ميغابايت، فلا يجد + اختبار حد رفع 500 ميغابايت ما يودعه. +
  • +
+

+ الذي يُودَع هو الوصفة. الوصفة نفسها مع البذرة نفسها تكتب البايتات نفسها على أي جهاز، فالملف المولَّد + في الخط هو الملف الذي كان عندك على حاسوبك المحمول. +

+
+ +
+

الوصفة

+

وصفة تعيش بجانب الاختبارات

+

+ تكتب هذه خمسًا وعشرين فاتورة ينبغي قبولها وصورتين فوق الحد ينبغي رفضهما، ويسجّل البيان التوقعين + معًا: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml يفحصها دون أن يكتب شيئًا، ويسمّي كل المشكلات دفعة واحدة. +

+
+ +
+

GitHub Actions

+

سير عمل يثبّت الأداة ويبني الملفات الثابتة

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ سطر المجموع الاختباري يقارن الأرشيف بالملف verify-SHA256SUMS.txt من الإصدار نفسه. + الإصدار مثبَّت، فلا يغيّر إصدار جديد أبدًا بناءً لم تلمسه. +

+
+ +
+

GitLab CI

+

الشيء نفسه كمهمة في GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

حين يصبح أحمر

+

ما الذي يُفشل خطوة، ولماذا

+

+ لكل نهاية رمز خروج خاص بها، فتفشل الخطوة من تلقاء نفسها ويقول السجل أيّها كان. هذه هي التي يصادفها + الخط: +

+
    +
  • 3 - الوصفة غير صالحة. لم يُكتب شيء، ويُسمّى كل خلل
  • +
  • 4 - الصيغة لا تستطيع ما طُلب منها، مثل حجم أقل من أصغر حجم لها
  • +
  • 6 - لا توجد مساحة كافية على القرص
  • +
  • 7 - وجد tfg verify ملفًا لا يطابق بيانه
  • +
  • 8 - انتهى التشغيل لكن لم يُنتَج كل شيء
  • +
+

+ التشغيل الفاشل لا يطبع شيئًا على الخرج القياسي، فلا يحسب محلل السجلات خطأً بيانات أبدًا. الجدول + الكامل في صفحة التوثيق. +

+
+ +
+

PowerShell

+

سكربت PowerShell يحتاج سطرًا إضافيًا

+

+ لا ينقل PowerShell رمز خروج برنامج إلى خارج ملف .ps1. شغّل واحدًا بـ -File + فيجيب السكربت 0 حتى حين رفضت الأداة داخله العمل، فيتحول بناء كان ينبغي أن يكون أحمر + إلى أخضر. السطر الأخير هو الإصلاح كله: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ هكذا يتصرف PowerShell، وليس في الأمر شيء يخص هذه الأداة. أما cmd وbash + وzsh فلا تحتاج إلى شيء إضافي. +

+
+ +
+

عدة مهام

+

مشاركة الملفات الثابتة بين المهام

+

+ لا حاجة عادةً إلى رفعها. لأن الوصفة نفسها تكتب البايتات نفسها، تستطيع كل مهمة تشغيل tfg + generate الخاص بها، وهذا أسرع من الرفع ثم التنزيل. وحين تحتاج مهمة إلى استلام ملفات من + أخرى، شغّل tfg verify على البيان بعد النقل، فيخبرك هل ما وصل هو ما كُتب. +

+
+ +
+

التالي

+

إلى أين من هنا

+ +
+ +
+ + + + diff --git a/web/public/ar/use-cases/index.html b/web/public/ar/use-cases/index.html new file mode 100644 index 00000000..f51c8c44 --- /dev/null +++ b/web/public/ar/use-cases/index.html @@ -0,0 +1,310 @@ + + + + + + +حالات الاستخدام - حدود الرفع وبيانات CI والاختبار الكمي + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

فيمَ يستخدمه الناس

+

+ خمس مهام تظهر في كل مشروع تقريبًا يقبل ملفات من الناس، والأمر الذي ينفذ كلًّا منها. كل مثال أدناه + يعمل كما هو مكتوب. +

+ +
+

حدود الرفع

+

اختبار ما إذا كان حد حجم الملف يُطبَّق حيث يقول إنه يُطبَّق

+

+ الحد ثلاث حالات اختبار لا حالة واحدة: أقل منه بقليل، وعنده تمامًا، وأعلى منه بقليل. الحصول عليها + يدويًا يعني حساب أعداد البايتات والأمل في ألا تخطئ بواحد. اطلب المجموعة بدلًا من ذلك: +

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

+ تحصل على ثلاثة ملفات PDF حقيقية بحجم 1048575 و1048576 و1048577 بايتًا، وبيان يقول إن الأولين يجب + قبولهما والثالث يُرفض بسبب size_limit. يقرأ اختبارك التوقّع بدل أن تكتب ثلاثة + تأكيدات يدويًا، وحين يتغير الحد تغيّر رقمًا واحدًا وتعيد التشغيل. +

+

+ ويعمل الأمر نفسه دون إعداد مسبق حين تريد مجموعة حدود واحدة داخل الأمر: +

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

التكامل المستمر

+

إبقاء بيانات الاختبار خارج المستودع دون فقدانها

+

+ بيانات الاختبار الثنائية الكبيرة تُبطئ استنساخ المستودع وتُصعّب مراجعته، ولا أحد يعرف ما الذي تغيّر + حين تُستبدل واحدة. الوصفة بضع مئات من أحرف YAML تعيد بناء الملفات المطابقة، بايتًا ببايت + وعلى أي جهاز، لأن كل ملف مشتق من بذرة التشغيل. +

+
- 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
+

+ لكل نهاية رمز خروج خاص بها، فيستطيع خط البناء التمييز بين وصفة سيئة وقرص ممتلئ وعدم تطابق في التحقق. + والتشغيل الفاشل لا يطبع شيئًا على المخرج القياسي، فلا يقرأ محلل السجلات خطأً على أنه بيانات. +

+
+ +
+

الحجم الكبير

+

معرفة ما يحدث حين يكون المجلد كبيرًا

+

+ تتصرف روتينات الاستيراد والمهام الليلية وقوائم المجلدات بشكل مختلف عند عشرة آلاف ملف عنه عند عشرة. + الأحجام المسحوبة من نطاق تجعل المجموعة تبدو كحركة حقيقية لا كعشرة آلاف ملف متطابق، ويأتي السحب + من البذرة، فتكون المجموعة نفسها غدًا. +

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

+ تحقق من كلفة التشغيل قبل أن يكتب أي شيء، وهذا مهم حين يُقاس المجموع بالغيغابايت: +

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

+ التشغيل الأكبر من المساحة الحرة على القرص يُرفض قبل كتابة أول بايت، بدل أن يملأ القرص ويفشل في منتصف + الطريق. +

+
+ +
+

الأرشيفات

+

اختبار أداة فك الضغط بأرشيف يحتوي ملفات حقيقية فعلًا

+

+ أرشيف فارغ بالامتداد الصحيح لا يثبت شيئًا عن شيفرة تفتحه وتجتاز ما بداخله. صرّح بالمحتوى فيحتويه + الأرشيف فعلًا: +

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

+ عمق التداخل وعدد العناصر وحجم ما بالداخل كلها أمور لروتين الاستيراد رأي فيها، وهكذا تعرف ما هي تلك + الآراء. +

+
+ +
+

المحللات والعارضات

+

التحقق من أن شيفرتك تقرأ الصيغة كما يفعل البرنامج الحقيقي

+

+ كل صيغة هنا تُفحص بقارئ مستقل قبل إصدارها: يُفتح PNG وتُقارَن بكسلاته، ويُقرأ DOCX من جديد بمكتبات + منفصلة، ويُفك أرشيف. وهذا يعني أن ملفًا يرفضه محللك هو نتيجة عن محللك، لا عن المولّد. +

+
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
+

+ تسرد صفحة الصيغ الإعدادات التي تقبلها كل صيغة وأصغر ملف يمكن أن تكونه. +

+
+ +
+

أدلة

+

اثنان منها بتفصيل أكبر

+ +
+ +
+

لمن هذا

+

+ لمهندسي ضمان الجودة وأتمتة الاختبار، ولكل من خلف شيفرته نموذج رفع أو روتين استيراد أو محلل أو حصة + تخزين. يعمل على جهاز بلا شبكة إطلاقًا، وهذا مهم في بيئة مؤسسية مغلقة لا يكون فيها المولّد القائم + على المتصفح خيارًا. +

+ +

مجاني ومفتوح المصدر، GPL-3.0. لا حاجة إلى التسجيل. تنزيلات ويندوز وماك موقّعة وتعمل دون تحذير.

+
+ +
+ + + + diff --git a/web/public/assets/site.css b/web/public/assets/site.css index c60dcaac..6b90b60e 100644 --- a/web/public/assets/site.css +++ b/web/public/assets/site.css @@ -82,18 +82,18 @@ body { .skip { position: absolute; - left: -9999px; + inset-inline-start: -9999px; top: 0; background: var(--accent); color: var(--on-bright); padding: 10px 16px; - border-radius: 0 0 var(--radius) 0; + border-end-end-radius: var(--radius); font-weight: 600; z-index: 100; } .skip:focus { - left: 0; + inset-inline-start: 0; } /* ------------------------------------------------------------------ topbar */ @@ -110,7 +110,7 @@ body { .topbar-inner { display: flex; align-items: center; - gap: 24px; + gap: 16px; min-height: 62px; flex-wrap: wrap; } @@ -132,15 +132,16 @@ body { .mainnav { display: flex; - gap: 4px; + gap: 2px; flex-wrap: wrap; - margin-right: auto; + flex: 1 1 0; + min-width: 0; } .mainnav a { color: var(--text-dim); text-decoration: none; - padding: 6px 10px; + padding: 6px 7px; border-radius: 8px; font-size: 15px; } @@ -155,25 +156,85 @@ body { background: var(--surface-2); } -.langswitch { - display: flex; - gap: 6px; +.langmenu { + position: relative; + margin-inline-start: auto; } -.langswitch a { +.langmenu > summary { + display: inline-flex; + align-items: center; + gap: 8px; + cursor: pointer; + list-style: none; font-size: 14px; - color: var(--muted); - text-decoration: none; + color: var(--text-dim); border: 1px solid var(--border); - padding: 4px 10px; + padding: 5px 12px; border-radius: 999px; + user-select: none; +} + +.langmenu > summary::-webkit-details-marker { + display: none; +} + +.langmenu > summary::after { + content: ""; + width: 6px; + height: 6px; + margin-top: -3px; + border-inline-end: 1.5px solid currentColor; + border-bottom: 1.5px solid currentColor; + transform: rotate(45deg); +} + +.langmenu[open] > summary::after { + margin-top: 3px; + transform: rotate(225deg); } -.langswitch a:hover { +.langmenu > summary:hover, +.langmenu[open] > summary { color: var(--text); border-color: var(--accent-dim); } +.langlist { + position: absolute; + inset-inline-end: 0; + top: calc(100% + 8px); + z-index: 50; + list-style: none; + margin: 0; + padding: 8px; + width: min(520px, calc(100vw - 40px)); + max-height: 70vh; + overflow-y: auto; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 2px; + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45); +} + +.langlist a { + display: block; + padding: 7px 10px; + border-radius: 8px; + font-size: 15px; + line-height: 1.4; + color: var(--text-dim); + text-decoration: none; +} + +.langlist a:hover { + color: var(--text); + background: var(--surface-2); +} + /* ------------------------------------------------------------- typography */ main { @@ -456,14 +517,14 @@ ul.plain li { .ticks li { position: relative; - padding-left: 26px; + padding-inline-start: 26px; margin-bottom: 10px; } .ticks li::before { content: ""; position: absolute; - left: 4px; + inset-inline-start: 4px; top: 0.62em; width: 8px; height: 8px; @@ -489,7 +550,7 @@ table.data { table.data th, table.data td { - text-align: left; + text-align: start; padding: 10px 14px; border-bottom: 1px solid var(--border-soft); vertical-align: top; @@ -516,7 +577,7 @@ table.data tbody tr:hover td { } table.data .num { - text-align: right; + text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; } @@ -553,6 +614,14 @@ pre code { white-space: pre; } +/* The short answer of a page is a sentence with a whole command in it, and a + * command can be longer than a phone is wide. A span that cannot break pushes + * the page sideways, so inside a note it may break where it has to. */ +.note code { + white-space: normal; + overflow-wrap: anywhere; +} + /* --------------------------------------------------------------------- faq */ .faq { @@ -610,7 +679,8 @@ pre code { } .qa-body { - padding: 0 20px 18px 46px; + padding: 0 20px 18px; + padding-inline-start: 46px; } .qa-body p:last-child { @@ -620,15 +690,16 @@ pre code { /* ------------------------------------------------------------------ callout */ .note { - border-left: 3px solid var(--accent); + border-inline-start: 3px solid var(--accent); background: var(--surface); - border-radius: 0 var(--radius) var(--radius) 0; + border-start-end-radius: var(--radius); + border-end-end-radius: var(--radius); padding: 16px 20px; margin: 24px 0; } .note.warn { - border-left-color: var(--warning); + border-inline-start-color: var(--warning); } .note p:last-child { @@ -652,14 +723,14 @@ pre code { .steps > li { counter-increment: step; position: relative; - padding-left: 46px; + padding-inline-start: 46px; margin-bottom: 30px; } .steps > li::before { content: counter(step); position: absolute; - left: 0; + inset-inline-start: 0; top: 0; width: 30px; height: 30px; @@ -737,6 +808,12 @@ pre code { padding-top: 40px; } + /* Sticky is a luxury of a header one row high. With the longer labels of + * some languages it takes a third of a phone, so it scrolls away here. */ + .topbar { + position: static; + } + .topbar-inner { gap: 12px; padding-top: 10px; @@ -745,8 +822,8 @@ pre code { .mainnav { order: 3; + flex-basis: 100%; width: 100%; - margin-right: 0; } .footer-inner { @@ -755,6 +832,91 @@ pre code { } .qa-body { - padding-left: 20px; + padding-inline-start: 20px; + } + + .langlist { + grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +/* --------------------------------------------------------------- languages */ + +/* The site loads no font in any language it is served in, so what a page is + * drawn in is whatever the visitor's system carries. + * The stacks below only put the right one first. A language tag on the page + * already tells a browser which regional form of a Han character to draw, but + * an unlucky default can still pick a face with no glyphs for the script, and + * naming the system faces is cheaper than finding out from a bug report. + * Every name is a face the operating system ships - nothing here is fetched. */ + +:root:lang(zh-Hans) { + --sans: system-ui, -apple-system, "PingFang SC", "Hiragino Sans GB", + "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif; +} + +:root:lang(zh-Hant) { + --sans: system-ui, -apple-system, "PingFang TC", "Microsoft JhengHei", + "Noto Sans CJK TC", "Noto Sans TC", sans-serif; +} + +:root:lang(ja) { + --sans: system-ui, -apple-system, "Hiragino Sans", "Hiragino Kaku Gothic ProN", + "Yu Gothic", Meiryo, "Noto Sans CJK JP", "Noto Sans JP", sans-serif; +} + +/* Japanese has no spaces to break a line at, so a browser that can read the + * phrases breaks between them rather than in the middle of one, and the strict + * rules keep small kana and the long vowel mark off the start of a line. A + * browser that does not know the first property ignores it and breaks as it + * always did. */ +:root:lang(ja) { + word-break: auto-phrase; + line-break: strict; +} + +:root:lang(ko) { + --sans: system-ui, -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", + "Noto Sans CJK KR", "Noto Sans KR", sans-serif; +} + +:root:lang(hi) { + --sans: system-ui, -apple-system, "Kohinoor Devanagari", "Nirmala UI", + "Noto Sans Devanagari", sans-serif; +} + +:root:lang(th) { + --sans: system-ui, -apple-system, "Thonburi", "Leelawadee UI", + "Noto Sans Thai", sans-serif; +} + +:root:lang(ar) { + --sans: system-ui, -apple-system, "Segoe UI", "Geeza Pro", Tahoma, + "Noto Sans Arabic", sans-serif; +} + +/* Thai and Devanagari carry marks above and below the line, and the body + * line height that suits Latin text crowds them. */ +:root:lang(th) body, +:root:lang(hi) body { + line-height: 1.85; +} + +/* Tracking is a Latin habit. Arabic letters join, so any space between them + * breaks a word apart, and in Devanagari and Thai it pulls the marks away + * from the letters they belong to. The headings and the small capitals above + * are tracked, so it is switched off for the whole page. */ +:root:lang(ar) *, +:root:lang(hi) *, +:root:lang(th) * { + letter-spacing: normal; +} + +/* Code is always left to right, in a page that reads right to left as well. + * Isolated, so the dashes and brackets of a flag stay where they were typed + * instead of being reordered by the sentence around them. */ +pre, +code { + direction: ltr; + unicode-bidi: isolate; +} diff --git a/web/public/corrupt-test-files/index.html b/web/public/corrupt-test-files/index.html new file mode 100644 index 00000000..757cb802 --- /dev/null +++ b/web/public/corrupt-test-files/index.html @@ -0,0 +1,379 @@ + + + + + + +Corrupt Test Files - Damaged Files of an Exact Size + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Use cases

+

How to make a corrupt file for testing

+

+ A validator that has only ever been shown healthy files has not really been tested. Here is how to + get a file that is broken on purpose, comes out at exactly the size you ask for, + and carries a manifest saying what your system should do with it. +

+ +
+

The short answer

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out writes a PNG of + exactly 2097152 bytes whose first bytes are zeros, and the manifest beside it records that your + system should reject it. +

+
+ +
+

The usual way

+

Why a file corrupted by hand makes a poor test

+

+ The usual ways are a hex editor, a script that flips a few random bytes, or cutting a file short + with head or truncate. They work once, and then they cost you: +

+
    +
  • + It is different every time. A random byte lands somewhere new on each run, so a + failure on Tuesday may not come back on Wednesday. +
  • +
  • + It changes the size. A file cut short is smaller than the limit it was meant to + sit under, so the size check answers before the content check and the test passes for the wrong + reason. +
  • +
  • + It often goes unnoticed. Plain text still reads with a byte changed in the + middle, and a forgiving image reader just draws it, so the file you meant to be broken is + accepted. +
  • +
  • + It says nothing about what should happen. The file is only bytes, and whoever + reads the test next has to guess whether acceptance or rejection was intended. +
  • +
+
+ +
+

What you get

+

A damaged file is still the size you asked for

+

+ The file is generated normally and broken afterwards, on its way to the disk. It keeps the size + you asked for, and the same command writes the same bytes again. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Settings go after a colon. The flag can be repeated, and the damages are applied in the order you + write them. It works with every one of the 26 formats. +

+
+ +
+

What it can do

+

Which damages are there?

+

+ This is the list the program prints, read from it when this page is built. tfg damage + prints the same, and tfg damage <id> says what one of them takes. +

+
+ + + + + + + + + + + + + + + + + +
DamageWhat it does to the bytesSmallest fileSettings
zero-headOverwrites the first bytes of the file with zeros, leaving its length alone. Most readers look there first, so this is the damage almost anything notices.8bytes
+
+

+ zero-head writes zeros over the start of the file. Most readers look there first, at + the signature and the header that say what the file is, so almost any reader notices. Plain text + and logs have no signature and are turned away as well, because a run of zero bytes is not text. + Below four bytes some formats come out with damage that no reader complains about, which is why + the setting starts at four. +

+
+ +
+

What the manifest says

+

A manifest that says what should happen

+

+ Every damaged file gets an entry saying your system should reject it, with the damage recorded + beside it: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Two requests are refused before anything is written, because each would leave a file on disk that + the manifest describes wrongly: +

+
    +
  • a file smaller than the damage needs, which would come out unchanged
  • +
  • + expected: accept beside a damage, because nothing could meet it. Write + sanitize if your system is meant to repair the file, or unspecified if + that is the question you are asking +
  • +
+
+ +
+

In a recipe

+

Healthy and broken files in one run

+

+ Put both in one recipe, and the manifest carries the expectation of every file, so the test does + not need a list of which is which: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In a test

+

Turning it into a test

+

+ The test reads the manifest and checks that what happened is what was declared. It needs no list + of file names: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ A good refusal is a clean one. A message that says what was wrong is the answer you want. A server + error, a hang or a half stored file is the defect this test exists to find. +

+
+ +
+

Next

+

Where to go from here

+ +
+ +
+ + + + diff --git a/web/public/create-file-exact-size/index.html b/web/public/create-file-exact-size/index.html index 73f5db87..516f6c0b 100644 --- a/web/public/create-file-exact-size/index.html +++ b/web/public/create-file-exact-size/index.html @@ -3,15 +3,36 @@ + Create a File of a Specific Size - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/cs/dokumentace/index.html b/web/public/cs/dokumentace/index.html new file mode 100644 index 00000000..ae45e541 --- /dev/null +++ b/web/public/cs/dokumentace/index.html @@ -0,0 +1,554 @@ + + + + + + +Dokumentace - příkazy, recepty, manifest, návratové kódy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Dokumentace

+

+ Vše, co nástroj dělá, uspořádané podle otázek, se kterými lidé skutečně přicházejí. + README v repozitáři je úplná reference a vždy odpovídá verzi, + kterou jste stáhli. +

+ +
+

Jaké příkazy existují?

+

Každý dělá jednu věc:

+
tfg generate    vytvořit soubory z receptu nebo z přepínačů
+tfg validate    zkontrolovat recept a nic nezapisovat
+tfg verify      zkontrolovat adresář proti manifestu
+tfg cleanup     odstranit soubory, které manifest uvádí
+tfg recipe fmt  vypsat recept v ustáleném tvaru
+tfg preset      sestavit sadu souborů z pojmenované testovací otázky
+tfg formats     vypsat formáty, které tato verze podporuje
+tfg damage      vypsat způsoby, jak tato verze umí soubor schválně poškodit
+tfg tool        drobné pomůcky pro soubory, které už máte
+tfg version     vypsat verzi nástroje
+tfg license     vypsat licenci a co znamená pro generované soubory
+
+ +
+

Jak vygeneruji jeden soubor přesné velikosti?

+

+ Uveďte formát, velikost a kam soubor půjde. Velikosti se počítají po 1024, takže 2mb je + 2097152 bajtů. Funguje i prostý počet bajtů, takže --size 10485761 žádá přesně + tolik. +

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

Užitečné přepínače příkazu generate:

+
+ + + + + + + + + + + + + + + + + +
PřepínačCo dělá
--format <id>formát souborů, například txt
--size <size>přesná velikost každého souboru, například 10mb nebo prostý počet bajtů
--size-range <a-b>velikost losovaná pro každý soubor z rozsahu, například 1kb-8kb. Losování vychází ze seedu
--boundary <size>tři soubory kolem limitu: o bajt pod, limit, o bajt nad
--count <n>kolik souborů vytvořit. Výchozí 1
--name <template>šablona názvu, například invoice_{index:04}.txt
--out <dir>adresář, do kterého se zapisuje
--seed <n>seed běhu. Stejný seed dává stejné bajty
--set <k>=<v>nastavení formátu, lze opakovat
--damage <name>záměrně soubory poškodit, lze opakovat a uplatňuje se v pořadí. Seznam získáte příkazem tfg damage
--expected <outcome>accept, reject, sanitize nebo unspecified
--dry-runspočítat a ukázat, nic nezapisovat
--jsonzapsat manifest na standardní výstup
+
+
+ +
+

Jak vytvořím soubor, který je záměrně rozbitý?

+

+ Každý jiný soubor, který tento nástroj zapíše, je správný z konstrukce, což odpovídá na dvě ze tří + otázek, které klade validátor nahrávání. --damage odpovídá na třetí - zda se soubor + vůbec otevře. Soubor se vytvoří normálně a pak se rozbije, takže má stále velikost, o kterou + jste požádali. +

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

+ Nastavení se zadávají za dvojtečku. Přepínač se opakuje a pořadí, v jakém je napíšete, je pořadí, v + jakém se uplatní. tfg damage vypíše, co tato verze umí a co která varianta přijímá. +

+

V receptu je klíč seznam, a to názvů nebo nastavení:

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

+ Poškozený soubor dostane v manifestu expected: reject a vedle toho zaznamenané + poškození. Dvě věci jsou odmítnuty dříve, než se cokoli zapíše, protože každá by jinak dala na + disk soubor, který manifest popisuje špatně: +

+
    +
  • soubor menší, než poškození potřebuje, protože by vyšel beze změny
  • +
  • + expected: accept vedle poškození, protože nic by to nemohlo splnit. Napište + sanitize, pokud má testovaný systém soubor opravit, nebo + unspecified, pokud je to právě ta otázka, kterou kladete +
  • +
+

+ Třetí se předem zjistit nedá. Pokud se poškození provede a nepohne žádným bajtem, soubor se zahodí + místo zapsání - běh pokračuje, řekne, o který soubor šlo, a skončí s částečným návratovým kódem. +

+

+ Krok za krokem, s testem, který čte manifest: jak + vytvořit poškozený soubor pro testy. +

+
+ +
+

Jak vypadá recept?

+

+ Recept je soubor YAML popisující celý běh. Commitujte ho vedle testů a fixtures přestanou být + binárkami ve vašem repozitáři - kdokoli je může bajt po bajtu znovu sestavit ze souboru o + několika stovkách znaků. +

+
# 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
+

+ Každý target potřebuje přesně jeden z klíčů size, size-range, + boundary nebo contains. Dva jsou chyba a žádný také. Neplatný recept + nezapíše žádné soubory a nahlásí všechny problémy najednou, ne jen první, každý + s názvem nastavení, kterého se týká. +

+
+ +
+

Jak deklaruji, co má můj systém se souborem udělat?

+

Krátká forma, když stačí výsledek, dlouhá forma, když záleží na důvodu:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Výsledky jsou accept, reject, sanitize a + unspecified. Důvody tvoří uzavřený seznam, aby podle nich mohl report seskupovat: + 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 a size_zero. +

+

+ Důvod pojmenovává pravidlo, o které jde, ne verdikt. Proto může stejný důvod stát + pod oběma výsledky - soubor o bajt pod limitem je accept a pravidlo, o které jde, + je stále size_limit. +

+
+ +
+

Co obsahuje manifest?

+

+ Zapisuje se vedle souborů na konci každého běhu, včetně přerušeného. Jedna položka na soubor: +

+
{
+  "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 se přidá, když běh pochází z receptu, a preset s + overrides, když pochází z předvolby, takže manifest lze vždy dohledat k tomu, co ho + vytvořilo. +

+

+ Každá položka nese také target_id, id targetu v receptu, který soubor vytvořil, a + summary.by_target počítá soubory, ke kterým každý target dospěl. Recept s více + targety lze tak kontrolovat target po targetu, aniž by se četly názvy souborů. +

+
+ +
+

Co je předvolba?

+

+ Hotová sada souborů, která odpovídá na běžnou testovací otázku, abyste sadu nemuseli navrhovat sami. + Předvolby jsou pod povrchem obyčejné recepty a eject recept vypíše, takže ho můžete + odtud upravit. Každá předvolba má vlastní stránku s tím, co obvykle + najde, co je v sadě a jaké nastavení přijímá. +

+
    +
  • +

    Prázdné a minimální

    +

    Projde platný soubor tak malý, jak formát dovolí?

    +

    empty-and-minimal

    +
  • +
  • +

    Zacházení s názvy souborů

    +

    Uloží, zobrazí a vrátí můj systém název souboru, který nečekal?

    +

    filename-handling

    +
  • +
  • +

    Hranice velikosti

    +

    Je limit velikosti vynucován přesně tam, kde je deklarován?

    +

    size-boundaries

    +
  • +
  • +

    Import tabulek

    +

    Přežije můj import tabulek to, co exportují skutečné nástroje?

    +

    tabular-import

    +
  • +
  • +

    Kódování textu

    +

    Ví moje čtečka, v jakém kódování soubor je, nebo hádá?

    +

    text-encoding

    +
  • +
  • +

    Validace nahrávání

    +

    Přijme můj formulář pro nahrávání to, co má, a zbytek odmítne?

    +

    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 vám řekne, kolik by sada stála, než ji sestavíte, a otevřeně řekne, když je číslo + naším zástupným údajem, a ne vaším limitem. +

+
+ +
+

Co znamenají návratové kódy?

+

+ Každý konec má svůj kód, strojově čitelný výstup jde na standardní výstup a neúspěšný běh tam + nevypíše nic. Tabulka je zmrazená smlouva - změna významu kódu vyžaduje novou hlavní verzi. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KódVýznam
0Vše fungovalo.
1Neočekávaná chyba uvnitř nástroje.
2Špatný příkaz nebo přepínač.
3Recept není platný.
4Formát neumí to, co bylo požadováno.
5Čtení nebo zápis selhal.
6Nedostatek místa na disku.
7verify našel nesrovnalost.
8Běh skončil, ale nebylo vytvořeno všechno.
130Přerušeno pomocí Ctrl+C.
143Zastaveno signálem, tak vypadá vypršení času v 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
+

+ Běh zastavený pomocí Ctrl+C po sobě stále zanechá manifest a nikdy nenechá napůl zapsaný soubor, + takže zrušenou úlohu může následující stále uklidit. +

+

+ Hotová workflow pro GitHub Actions a GitLab CI: jak generovat + testovací soubory v CI pipeline. +

+
+ +
+

Existuje desktopové okno?

+

+ Ano, stejný motor s oknem navrch, pro testování, které se neskriptuje. Není to osekaná verze: test + porovnává obě rozhraní schopnost po schopnosti a cokoli, co umí jen jedno z nich, musí být + deklarováno a zdůvodněno, ne tiše se rozcházet. +

+

+ Obrazovky jsou jedna dávka, předvolby, více dávek najednou a O aplikaci. Ukáže, kolik by běh stál, + než cokoli zapíše, hlásí průběh a lze ho zrušit uprostřed, aniž by zanechal napůl zapsaný + soubor. Soubor receptu zatím neotevře - recepty jsou zatím záležitostí příkazového řádku a okno + sestavuje své dávky ve formuláři. +

+
+ +
+ + + + diff --git a/web/public/cs/faq/index.html b/web/public/cs/faq/index.html new file mode 100644 index 00000000..eebc787f --- /dev/null +++ b/web/public/cs/faq/index.html @@ -0,0 +1,349 @@ + + + + + + +FAQ - otázky ke generování testovacích souborů + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Často kladené otázky

+

+ Licence, soukromí, opakovatelnost a věci, které lidé ověřují, než generátor zařadí do build + pipeline. Pokud tu vaše otázka není, sledování issues je + otevřené. +

+ +
+
+

Čím se to liší od dd, fsutil nebo truncate?

+
+

Ty vám dají soubor správné velikosti plný ničeho. Soubor o 2 MB pojmenovaný photo.png vytvořený takto není PNG, takže ho cokoli, co ho skutečně zpracovává, odmítne z nesprávného důvodu a váš test pak projde také z nesprávného důvodu. Tohle vytvoří skutečné PNG o přesně 2 MB, které se otevře v prohlížeči obrázků, a přichází s prohlášením, jak s ním má váš systém naložit.

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

Je to zdarma a mohu to používat v práci?

+
+

Ano k obojímu. Je vydáno pod GPL-3.0 a nestojí nic. Není tu účet, licenční klíč ani placená úroveň.

+
+
+
+

Mohu generované soubory použít v produktu s uzavřeným zdrojovým kódem?

+
+

Ano. Licence se vztahuje na kód nástroje, ne na to, co nástroj vytváří. Generované soubory, recepty a manifesty jsou výstup, nikoli odvozená díla, takže je můžete commitovat a dodávat bez jakékoli povinnosti.

+
+
+
+

Obsahují generované soubory skutečné osobní údaje?

+
+

Ne. Vše uvnitř je syntetizováno ze seedu. Nečte se žádný datový soubor, nekontaktuje se žádná služba a nevkládá se obsah třetích stran. Vygenerovanou e-mailovou adresu považujte za nepoužitelnou, ne za nepoužitou, protože libovolný náhodný řetězec se může shodou okolností shodovat se skutečným.

+
+
+
+

Dostanu na jiném počítači přesně stejné soubory?

+
+

Ano, bajt po bajtu, při stejném receptu a stejném seedu. Projekt to testuje při každé změně a porušit to vyžaduje novou hlavní verzi. Díky tomu můžete commitovat malý recept místo velkých binárních fixtures.

+
+
+
+

Potřebuje připojení k internetu?

+
+

Nikdy. Není tu telemetrie, kontrola aktualizací ani cloudový klient a do binárky příkazového řádku není zkompilován žádný síťový zásobník. Funguje na počítači bez sítě i v uzavřeném firemním prostředí.

+
+
+
+

Co se stane, když požádám o velikost, které formát nedosáhne?

+
+

Dostanete chybu, která pojmenuje formát, nejmenší možnou velikost, důvod tohoto minima a co dělat místo toho, a nezapíše se žádný soubor. Nástroj nikdy velikost mlčky nezaokrouhlí. Každé minimum je uvedeno na stránce formátů.

+
tfg formats png
+
+
+
+

Mohu vygenerovat soubor, který je záměrně rozbitý?

+
+

Ano. Přidejte --damage zero-head a soubor vyjde v přesně požadované velikosti, s prvními bajty přepsanými nulami, takže ho čtečka odmítne, a manifest říká, že ho má váš systém odmítnout. Podrobnosti jsou na stránce o poškozených testovacích souborech.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Které formáty přijdou dál?

+
+

7z, mp3 a mp4. Dnes funguje od začátku do konce 26 formátů.

+
+
+
+

Na kterých systémech to mohu spustit?

+
+

Příkazový řádek běží na Windows a Linuxu na Intelu i ARM a na Macích s Apple Silicon. Desktopové okno se dodává pro Windows na Intelu, Linux na Intelu a Macy s Apple Silicon. Intel Macy nejsou podporovány a nic se pro ně nesestavuje.

+
+
+
+

Musím něco instalovat?

+
+

Ne. Stáhněte archiv pro svůj systém, rozbalte ho a spusťte binárku. Není tu instalátor, běhové prostředí k doplnění ani závislost k vyřešení. Pokud máte Go, funguje i jediný příkaz go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Proč je běh nad tisíci soubory na Windows pomalejší?

+
+

Protože Windows si účtuje víc za každou cestu, na kterou se podívá, a příkaz, který prochází tisíce souborů, se dívá na tisíce cest. Změřeno na jednom počítači s 3000 soubory po 1 kB: verify trvá na Windows asi 0,9 sekundy a na Linuxu v kontejneru asi 0,2 sekundy. Kratší výstupní cesta číslo na Windows zmenší, protože každá složka nad soubory je součástí toho, na co se dívá.

+
+
+
+ + +
+

Ještě se rozhodujete?

+

+ Stránka případů použití ukazuje úlohy, pro které je určen, a + stránka formátů uvádí každý formát s nejmenším souborem, který umí + vytvořit. README v repozitáři je úplná reference. +

+ +

Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.

+
+ +
+ + + + diff --git a/web/public/cs/formaty/index.html b/web/public/cs/formaty/index.html new file mode 100644 index 00000000..44817ecf --- /dev/null +++ b/web/public/cs/formaty/index.html @@ -0,0 +1,909 @@ + + + + + + +26 podporovaných formátů souborů - PDF, DOCX, PNG, ZIP a další + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formátů souborů, každý generovaný v přesné velikosti

+

+ Každý z nich je skutečný soubor toho formátu. Otevře se v programu, kam patří, a má + přesně tolik bajtů, kolik jste požádali. Žádný není vycpávka z nul s přilepenou příponou. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormátNázevPříponaNejmenší souborÚplnostOvěřeno pomocí
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullnelze použít
mdMarkdown.md0fullnelze použít
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullnelze použít
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Co znamenají sloupce

+
    +
  • +

    Nejmenší soubor

    +

    + Nejméně bajtů, které tento nástroj pro daný formát přijme, včetně štítku, který zapisuje do souboru. + Požádejte o méně a dostanete chybu, která pojmenuje minimum a jeho důvod, nikdy soubor + špatné velikosti. +

    +
  • +
  • +

    Úplnost

    +

    + Jak úplný soubor je. full znamená, že ho přijme čtečka, která formát skutečně + zpracovává, ne jen že přípona souhlasí. +

    +
  • +
  • +

    Ověřeno pomocí

    +

    + Nezávislá čtečka, která otevře každý vygenerovaný soubor, než se formát vydá - samostatná + implementace, ne náš vlastní kód, který opravuje své vlastní úkoly. +

    +
  • +
+

+ Každý formát se také opakuje na bajt: stejný recept a stejný seed vytvoří na jakémkoli počítači + identické soubory, a to dělá z receptu bezpečnou věc k commitování místo samotných fixtures. +

+
+ +
+

Nastavení, která každý formát přijímá

+

+ Většina formátů má vlastní nastavení - rozměry obrázku, kvalitu JPEG, počet stránek PDF, řádky a + sloupce v tabulce, kolik položek jde do archivu. Nastavte je pomocí --set key=value + v příkazovém řádku nebo pod properties: v receptu. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormátNastaveníPřijímá
avifwidth1 - 16384 pixelů
height1 - 16384 pixelů
quality1 - 100
bmpwidth1 - 20000 pixelů
height1 - 20000 pixelů
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerpravda nebo nepravda
quote_styleall, minimal, none
columns2 - 32768 sloupců
docxparagraphs1 - 50000 odstavců
gifwidth1 - 20000 pixelů
height1 - 20000 pixelů
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixelů
height1 - 256 pixelů
embedbmp, png
jpgwidth1 - 20000 pixelů
height1 - 20000 pixelů
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixelů
height1 - 16384 pixelů
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 položek za sekundu
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bompravda nebo nepravda
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlelibovolný text
authorlibovolný text
subjectlibovolný text
keywordslibovolný text
creatorlibovolný text
producerlibovolný text
createddatum, například 2024-02-29 nebo 2024-02-29T13:45:00+02:00, nebo none
modifieddatum, například 2024-02-29 nebo 2024-02-29T13:45:00+02:00, nebo none
pngwidth1 - 20000 pixelů
height1 - 20000 pixelů
pptxslides1 - 500 snímků
svgwidth1 - 20000 pixelů
height1 - 20000 pixelů
targzentries0 - 10000
entry_formatid formátu tak, jak je vypisuje tfg formats
entry_sizevelikost, například 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriespravda nebo nepravda
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixelů
height1 - 20000 pixelů
txtencodingutf-16be, utf-16le, utf-8
bompravda nebo nepravda
wavsample_rate8000 - 192000 hertzů
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixelů
height1 - 16383 pixelů
xlsxrows1 - 200000 řádků
columns1 - 32768 sloupců
xmlencodingutf-16be, utf-16le, utf-8
bompravda nebo nepravda
zipentries0 - 10000
entry_formatid formátu tak, jak je vypisuje tfg formats
entry_sizevelikost, například 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriespravda nebo nepravda
passwordheslo ve formě prostého textu
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Hodnota mimo to, co nastavení přijímá, je odmítnuta zprávou, která pojmenuje nastavení, povolený + rozsah a co použít místo toho. Neznámé nastavení je také chyba, nikdy tichá výchozí hodnota - + tiše přijatý překlep dá soubor se špatným nastavením a hodinu přemýšlení, proč test prochází, + když neměl. +

+

+ Spusťte tfg formats <id> a uvidíte přesně, co jeden formát v dané verzi přijímá. +

+
+ +
+

Archivy obsahují skutečné soubory

+

+ targz a zip lze + naplnit položkami, místo aby zůstaly prázdnou skořápkou. Vygenerovaný archiv skutečně obsahuje + dokumenty, které tvrdí, že obsahuje, takže cokoli ho během testu rozbalí, uvnitř najde skutečné + soubory. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/cs/index.html b/web/public/cs/index.html new file mode 100644 index 00000000..b7d4b1de --- /dev/null +++ b/web/public/cs/index.html @@ -0,0 +1,452 @@ + + + + + + +Generátor testovacích souborů - přesná velikost, 26 formátů + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Generujte skutečné testovací soubory v přesné velikosti

+

+ PDF, PNG, DOCX, ZIP - celkem 26 formátů a každý je skutečný + soubor, který se otevře v programu, kam patří, v přesně té velikosti, o kterou jste + požádali. Každý běh také zapisuje, co má vaše aplikace s každým souborem udělat. + Příkazový řádek a desktopové okno, zdarma a open source, celé na vašem počítači. +

+ + +

Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.

+
+ +
+ Desktopové okno Testing Files Generator připravené zapsat dávku testovacích souborů +
Desktopové okno připravené zapsat dávku souborů. Za příkazovým řádkem běží stejný motor.
+
+
+ + + +
+

Problém

+

Vytvořit jeden testovací soubor je snadné. Vytvořit těch správných tisíc je ta únavná část

+

Testujete software, který přijímá soubory od lidí. Dříve nebo později budete potřebovat:

+
    +
  • PDF o přesně 10 MB, abyste zjistili, zda je limit nahrávání skutečný
  • +
  • tři soubory po obou stranách tohoto limitu, abyste zachytili chyby o jedna
  • +
  • 10 000 souborů logu, abyste viděli, co udělá noční úloha, když je složka velká
  • +
  • ZIP, který skutečně obsahuje 200 dokumentů, ne prázdnou skořápku se správnou příponou
  • +
  • soubor o 4 GB, aniž byste ve svém repozitáři drželi soubor o 4 GB
  • +
  • stejné fixtures na notebooku i na build serveru, bajt po bajtu
  • +
+

+ To je to, co toto nahrazuje. Je určeno pro QA inženýry, automatizaci testů a každého, za jehož kódem + stojí formulář pro nahrávání, importní rutina, parser nebo kvóta úložiště. +

+
+ +
+

Čím se liší

+

Jiné generátory končí u bajtů. Tento odpovídá na to, na co se váš test skutečně ptá

+

+ Složka souborů vás stále nechává rozhodovat, co má který dokazovat. Každý běh tady zapíše vedle + souborů manifest.json - prostý seznam všeho vytvořeného a u každé položky + deklarované očekávání. +

+

Řekněme, že váš endpoint pro nahrávání povoluje 1 MB. Požádejte o tři soubory, které leží na té hranici:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
SouborBajtyVáš systém máProtože
1mb_under_1b.pdf1048575přijmoutje uvnitř limitu
1mb_at_limit.pdf1048576přijmoutsamotný limit je povolen
1mb_over_1b.pdf1048577odmítnoutsize_limit
+
+ +

Tři soubory, tři různé odpovědi, ve strojově čitelné podobě. Váš test čte manifest místo toho, abyste vy ručně psali aserce:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Kde odpověď závisí na vaší vlastní politice, manifest to říká

+

+ Zapíše unspecified, místo aby vymýšlel očekávání. Generátor, který hádá, vytváří + falešná selhání a sada testů, která křičí vlk, bude vypnuta. +

+
+
+ +
+

Předvolby

+

Vyberte otázku, získejte celou sadu

+

+ Předvolba je sada testovacích souborů navržená kolem jedné testovací otázky, abyste nemuseli + vymýšlet, které soubory co dokazují. Každá má stránku, která říká, co obvykle najde, co je v + sadě a jaké nastavení přijímá. +

+
    +
  • +

    Prázdné a minimální

    +

    Projde platný soubor tak malý, jak formát dovolí?

    +

    empty-and-minimal

    +
  • +
  • +

    Zacházení s názvy souborů

    +

    Uloží, zobrazí a vrátí můj systém název souboru, který nečekal?

    +

    filename-handling

    +
  • +
  • +

    Hranice velikosti

    +

    Je limit velikosti vynucován přesně tam, kde je deklarován?

    +

    size-boundaries

    +
  • +
  • +

    Import tabulek

    +

    Přežije můj import tabulek to, co exportují skutečné nástroje?

    +

    tabular-import

    +
  • +
  • +

    Kódování textu

    +

    Ví moje čtečka, v jakém kódování soubor je, nebo hádá?

    +

    text-encoding

    +
  • +
  • +

    Validace nahrávání

    +

    Přijme můj formulář pro nahrávání to, co má, a zbytek odmítne?

    +

    upload-validation

    +
  • +
+

Všechny předvolby a jak souvisejí s recepty

+
+ +
+

Rychlý start

+

Tři příkazy, abyste to viděli fungovat

+
    +
  1. +

    Vytvořte soubor

    +

    Jedno PNG, přesně dva megabajty:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Vytvořte hodně souborů

    +

    + Deset tisíc souborů logu, každý mezi jedním a osmi kilobajty, s velikostmi losovanými ze seedu, aby + zítra vyšla stejná sada. Dejte každému běhu vlastní adresář - manifest je + jediný záznam o tom, co běh zapsal, takže nástroj odmítne zapsat druhý přes něj: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Ověřte je a pak je odstraňte

    +

    verify vám řekne, že se nic nepohnulo. cleanup odstraní přesně to, co bylo zapsáno, a nic jiného:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Velikosti se počítají po 1024, jak to dělá váš správce souborů, takže 2mb znamená + 2097152 bajtů. Funguje i prostý počet bajtů. Dokumentace pokrývá + recepty, manifest a návratové kódy. +

+
+ +
+

Co získáte

+

Vytvořeno pro sadu testů, která běží bez dozoru

+
    +
  • +

    Přesná velikost, na bajt

    +

    Požádejte o 10485761 bajtů a dostanete přesně tolik. Velikost, které formát nedosáhne, je chyba s důvodem, nikdy soubor špatné velikosti.

    +
  • +
  • +

    26 skutečných formátů

    +

    Ne vycpávkové nuly s příponou. Vygenerované PNG se otevře v prohlížeči obrázků, DOCX ve Wordu, ZIP se rozbalí. Každý formát je před vydáním ověřen nezávislými čtečkami.

    +
  • +
  • +

    Manifest, který je testovací orákulum

    +

    Cesta, velikost, SHA-256, formát, seed, verze nástroje - a co má váš systém se souborem udělat.

    +
  • +
  • +

    Opakovatelné

    +

    Stejný recept a stejný seed, stejné bajty, na jakémkoli počítači. Commitujte malý recept YAML místo velkých binárních fixtures.

    +
  • +
  • +

    Dvě rozhraní, jeden motor

    +

    Příkazový řádek vytvořený pro CI a desktopové okno pro průzkumné testování. Ani jedno není osekanou verzí druhého a test je porovnává schopnost po schopnosti.

    +
  • +
  • +

    Zcela offline

    +

    Žádný účet, žádný cloud, žádná telemetrie, žádná kontrola aktualizací. V binárce příkazového řádku není zkompilován vůbec žádný síťový zásobník.

    +
  • +
+
+ +
+

Stažení

+

Vyberte verzi pro svůj systém

+

+ Rozbalte archiv a spusťte ho. tfg je příkazový řádek a tfg-gui je + desktopové okno. Není tu instalátor a nic, co by se do vašeho počítače přidávalo. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SystémPříkazový řádekDesktopové okno
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Co je podepsáno a co ne

+

+ Soubory ke stažení pro Windows a macOS jsou podepsané, takže se spustí bez varování o neznámém + vývojáři. Ty pro Linux ne, protože desktopový Linux nemá ekvivalent, kterým by je šlo + podepsat. Každý archiv je uveden v verify-SHA256SUMS.txt na stránce vydání, takže + můžete ověřit, co jste stáhli. +

+
+ +

Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.

+
+ + +
+ + + + diff --git a/web/public/cs/poskozene-testovaci-soubory/index.html b/web/public/cs/poskozene-testovaci-soubory/index.html new file mode 100644 index 00000000..8cddf9d7 --- /dev/null +++ b/web/public/cs/poskozene-testovaci-soubory/index.html @@ -0,0 +1,377 @@ + + + + + + +Poškozené testovací soubory - rozbité soubory přesné velikosti + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Případy použití

+

Jak vytvořit poškozený soubor pro testy

+

+ Validátor, kterému se ukazovaly jen zdravé soubory, nebyl opravdu otestován. Tady je postup, jak + získat soubor záměrně rozbitý, který vyjde přesně v požadované velikosti a nese + manifest říkající, co s ním má váš systém udělat. +

+ +
+

Stručná odpověď

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out zapíše PNG o přesně + 2097152 bajtech, jehož první bajty jsou nuly, a manifest vedle něj zaznamená, že ho má váš + systém odmítnout. +

+
+ +
+

Obvyklý způsob

+

Proč je ručně poškozený soubor špatný test

+

+ Obvykle se sáhne po hexadecimálním editoru, skriptu, který převrátí pár náhodných bajtů, nebo po + zkrácení souboru pomocí head či truncate. Jednou to funguje a pak to + stojí: +

+
    +
  • + Pokaždé je to jiné. Náhodný bajt padne při každém spuštění jinam, takže chyba z + úterý se ve středu nemusí vrátit. +
  • +
  • + Mění to velikost. Zkrácený soubor je menší než limit, pod kterým měl zůstat, takže + kontrola velikosti odpoví dřív než kontrola obsahu a test projde z nesprávného důvodu. +
  • +
  • + Často si toho nikdo nevšimne. Prostý text se dá číst i se změněným bajtem uprostřed + a shovívavá čtečka obrázků ho prostě vykreslí, takže soubor, který měl být rozbitý, se přijme. +
  • +
  • + Neříká, co se má stát. Soubor jsou jen bajty a ten, kdo test čte později, musí + hádat, zda se mělo přijmout, nebo odmítnout. +
  • +
+
+ +
+

Co dostanete

+

Poškozený soubor má stále velikost, kterou jste chtěli

+

+ Soubor se vygeneruje normálně a poškodí se až potom, cestou na disk. Zachová velikost, kterou jste + chtěli, a stejný příkaz zapíše znovu stejné bajty. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Nastavení se píše za dvojtečku. Přepínač lze opakovat a poškození se použijí v pořadí, v jakém je + zapíšete. Funguje s každým z 26 formátů. +

+
+ +
+

Co umí

+

Jaká poškození existují?

+

+ Toto je seznam, který program vypisuje, načtený z něj při sestavení této stránky. tfg + damage vypíše totéž a tfg damage <id> řekne, co které z nich přijímá. +

+
+ + + + + + + + + + + + + + + + + +
PoškozeníCo dělá s bajtyNejmenší souborNastavení
zero-headPřepíše prvních několik bajtů souboru nulami a jeho délku nechá být. Většina čteček se dívá nejdřív tam, takže si tohoto poškození všimne téměř cokoli.8bytes
+
+

+ zero-head zapíše nuly přes začátek souboru. Většina čteček se dívá nejdřív tam, na + signaturu a hlavičku, které říkají, co soubor je, takže si toho všimne téměř každá. Prostý text + a logy signaturu nemají a odmítnou se také, protože řada nulových bajtů není text. Pod čtyřmi + bajty některé formáty vyjdou s poškozením, na které si žádná čtečka nestěžuje, proto nastavení + začíná na čtyřech. +

+
+ +
+

Co říká manifest

+

Manifest, který říká, co se má stát

+

+ Každý poškozený soubor dostane záznam, že ho má váš systém odmítnout, s poškozením zapsaným vedle: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dva požadavky se odmítnou dřív, než se cokoli zapíše, protože každý by na disku nechal soubor, který + manifest popisuje špatně: +

+
    +
  • soubor menší, než poškození potřebuje, který by vyšel nezměněný
  • +
  • + expected: accept vedle poškození, protože by to nic nemohlo splnit. Napište + sanitize, pokud má váš systém soubor opravit, nebo unspecified, + pokud je právě to vaše otázka +
  • +
+
+ +
+

V receptu

+

Zdravé a rozbité soubory v jednom běhu

+

+ Dejte obojí do jednoho receptu a manifest ponese očekávání každého souboru, takže test nepotřebuje + seznam, který je který: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

V testu

+

Z toho udělat test

+

+ Test přečte manifest a ověří, že to, co se stalo, je to, co bylo uvedeno. Nepotřebuje seznam názvů + souborů: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Dobré odmítnutí je čisté. Zpráva, která říká, co bylo špatně, je odpověď, kterou chcete. Chyba + serveru, zaseknutí nebo napůl uložený soubor je vada, kterou má tento test najít. +

+
+ +
+

Dál

+

Kam jít odtud

+ +
+ +
+ + + + diff --git a/web/public/cs/predvolby/empty-and-minimal/index.html b/web/public/cs/predvolby/empty-and-minimal/index.html new file mode 100644 index 00000000..3c01b61b --- /dev/null +++ b/web/public/cs/predvolby/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Nejmenší platné a prázdné testovací soubory v každém formátu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Prázdné a minimální

+

Projde platný soubor tak malý, jak formát dovolí?

+

+ Předvolba empty-and-minimal sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • platný soubor odmítnutý jako příliš malý, protože kontrola počítá bajty místo toho, aby je četla
  • +
  • prázdný soubor, který shodí čtečku, místo aby byl nahlášen
  • +
  • obrázek široký jeden pixel, který cestou k náhledu dělí nulou
  • +
  • úložiště, které čte nula bajtů jako selhané nahrání a stále to opakuje
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show empty-and-minimal:

+
+ + + + + + + +
Soubory28
Targety v receptu28
Celková velikost32 667 B
Formátyavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.26
unspecifiedZáleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli.2
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--formatsid formátů oddělená čárkami, nebo allallZ jakých formátů se sada skládá. Ponechte all pro všechny formáty této verze, nebo uveďte ty, které váš systém přijímá.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/cs/predvolby/filename-handling/index.html b/web/public/cs/predvolby/filename-handling/index.html new file mode 100644 index 00000000..8b39ae39 --- /dev/null +++ b/web/public/cs/predvolby/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Problematické názvy souborů pro testování - Unicode a délka + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Zacházení s názvy souborů

+

Uloží, zobrazí a vrátí můj systém název souboru, který nečekal?

+

+ Předvolba filename-handling sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • název, který na obrazovce, v logu nebo v seznamu vypadá jako jiný
  • +
  • název oříznutý, zkrácený nebo přepsaný mezi nahráním a uložením
  • +
  • limit délky počítaný ve znacích tam, kde úložiště počítá bajty
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show filename-handling:

+
+ + + + + + + +
Soubory50
Targety v receptu50
Celková velikost51 200 B
Formátytxt
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.4
unspecifiedZáleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli.46
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--formatid formátu ze stránky formátůtxtFormát každého souboru v sadě. Je to přepínač samotného nástroje a předvolba mu jen dává výchozí hodnotu.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/cs/predvolby/index.html b/web/public/cs/predvolby/index.html new file mode 100644 index 00000000..e1a6af79 --- /dev/null +++ b/web/public/cs/predvolby/index.html @@ -0,0 +1,244 @@ + + + + + + +Předvolby testovacích souborů - hotové sady pro QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Předvolby testovacích souborů, jedna sada pro každou testovací otázku

+

+ Předvolba je celá sada testovacích souborů navržená kolem jedné otázky, s manifestem, který říká, + jak má váš systém na každý soubor reagovat. Vy vyberete otázku, nástroj sestaví sadu. Každá + předvolba má vlastní stránku s tím, co obvykle najde, co je v sadě a jaké nastavení přijímá. +

+ + + +
+

Čím se předvolba liší od receptu?

+

+ Pod povrchem ničím. Předvolba je recept, který za vás nástroj napíše z několika nastavení. tfg + preset eject tento recept vypíše, abyste si ho mohli ponechat vedle testů a upravovat, a + váš vlastní recept může na předvolbě stavět jedním řádkem, extends: preset: + následovaným jejím id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Mohu výchozím hodnotám věřit?

+

+ U souborů ano. U čísla, které zná jen váš systém, například limitu formuláře pro nahrávání, je + výchozí hodnota naším zástupným údajem a nástroj to řekne pokaždé, když nějaký použije. Stránka + každé předvolby tato nastavení označuje a tfg preset show to řekne dřív, než se + cokoli zapíše. +

+
+ +
+ + + + diff --git a/web/public/cs/predvolby/size-boundaries/index.html b/web/public/cs/predvolby/size-boundaries/index.html new file mode 100644 index 00000000..3982b49a --- /dev/null +++ b/web/public/cs/predvolby/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Test limitu velikosti nahrávání - soubory přesně na hranici + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Hranice velikosti

+

Je limit velikosti vynucován přesně tam, kde je deklarován?

+

+ Předvolba size-boundaries sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • chyby o jedna na hranici limitu
  • +
  • MB zaměněné za MiB, což je 4,8 procenta a stačí to k propuštění souboru, který projít neměl
  • +
  • limit vynucovaný v prohlížeči a ne na serveru
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show size-boundaries:

+
+ + + + + + + +
Soubory7
Targety v receptu7
Celková velikost73 400 320 B
Formátypdf
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.4
rejectVáš systém má soubor odmítnout.3
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--limitvelikost, například 2mb10mbLimit velikosti, který váš systém deklaruje. Vše ostatní se měří od něj. Tato výchozí hodnota je náš zástupný údaj, ne hodnota vašeho systému. Zadejte vlastní.
--spreadvelikosti oddělené čárkami1B,1kb,1mbJak daleko na obě strany od limitu zajít, jako seznam velikostí.
--formatid formátu ze stránky formátůpdfFormát každého souboru v sadě. Je to přepínač samotného nástroje a předvolba mu jen dává výchozí hodnotu.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

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

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/cs/predvolby/tabular-import/index.html b/web/public/cs/predvolby/tabular-import/index.html new file mode 100644 index 00000000..9d19e9bd --- /dev/null +++ b/web/public/cs/predvolby/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Testovací soubory pro import CSV a Excelu - oddělovače + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Import tabulek

+

Přežije můj import tabulek to, co exportují skutečné nástroje?

+

+ Předvolba tabular-import sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • soubor se středníky přečtený jako jediný sloupec, protože oddělovač se předpokládal, místo aby se hledal
  • +
  • soubor CRLF rozdělený na řádky s prázdným řádkem za každým
  • +
  • tabulka bez hlavičky, jejíž první datový řádek se spolkne jako názvy sloupců
  • +
  • import, který ponechá sloupce, které umí zobrazit, a zbytek beze slova zahodí
  • +
  • čtečka, která bere záznamy JSON po jednom řádku a zastaví se u prvního odsazeného dokumentu
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show tabular-import:

+
+ + + + + + + +
Soubory13
Targety v receptu13
Celková velikost3 080 060 B
Formátycsv, json, xlsx
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.8
unspecifiedZáleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli.5
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--rows1 - 200000 řádků1000Kolik řádků tabulka obsahuje. Zapisuje se přesně v takové velikosti, jakou tolik řádků zabere, takže rozpočet výše se s touto hodnotou posouvá.
--columns1 - 32768 sloupců10Kolik sloupců má každý řádek tabulky. Řádky krát sloupce mají strop a požadavek nad ním je odmítnut dříve, než se cokoli zapíše.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/cs/predvolby/text-encoding/index.html b/web/public/cs/predvolby/text-encoding/index.html new file mode 100644 index 00000000..e6075b50 --- /dev/null +++ b/web/public/cs/predvolby/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Testovací soubory kódování textu - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Kódování textu

+

Ví moje čtečka, v jakém kódování soubor je, nebo hádá?

+

+ Předvolba text-encoding sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • čtečka, která předpokládá UTF-8 a zobrazí soubor UTF-16 jako každý třetí znak nebo jako řady čtverečků
  • +
  • označení pořadí bajtů přečtené jako obsah, takže první pole importu začíná třemi cizími znaky
  • +
  • importér, který hádá kódování z prvních bajtů a u delšího souboru hádá jinak
  • +
  • soubor CRLF rozdělený na řádky s prázdným řádkem za každým, nebo návrat vozíku zůstávající v posledním poli
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show text-encoding:

+
+ + + + + + + +
Soubory20
Targety v receptu20
Celková velikost81 920 B
Formátycsv, log, md, txt, xml
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.10
unspecifiedZáleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli.10
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--samplevelikost, například 2mb4kbJak velký je každý soubor sady. UTF-16 ukládá dva bajty na znak, takže lichý počet je odmítnut.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/cs/predvolby/upload-validation/index.html b/web/public/cs/predvolby/upload-validation/index.html new file mode 100644 index 00000000..9de6ff55 --- /dev/null +++ b/web/public/cs/predvolby/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Testovací soubory validace nahrávání - typ, velikost a název + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Předvolby

+

Validace nahrávání

+

Přijme můj formulář pro nahrávání to, co má, a zbytek odmítne?

+

+ Předvolba upload-validation sestaví jediným příkazem celou sadu skutečných testovacích souborů + pro tuto otázku a vedle nich manifest.json, který říká, jak má váš systém na každý + soubor reagovat. Vše níže se čte z programu při výchozích hodnotách této verze. +

+ + +
+

Co obvykle najde?

+
    +
  • limit vynucovaný v prohlížeči a ne na serveru
  • +
  • SVG nebo HTML považované za obrázek či prostý text, což je způsob, jak protlačit skript formulářem
  • +
  • soubor kontrolovaný podle přípony a nikdy neotevřený, takže PDF s názvem .jpg projde
  • +
  • formulář, který načte celé tělo do paměti, než se podívá, jak je velké
  • +
  • nahrání s názvem PHOTO.JPG odmítnuté tam, kde se photo.jpg přijme, nebo naopak
  • +
  • název s mezerami, závorkami nebo znaky mimo ASCII zapsaný na disk beze změny
  • +
+
+ + +
+

Co je v sadě?

+

Při výchozích hodnotách, jak je hlásí tfg preset show upload-validation:

+
+ + + + + + + +
Soubory71
Targety v receptu22
Celková velikost120 639 488 B
Formátyhtml, jpg, pdf, png, svg, txt
+
+

A co od vašeho systému očekává manifest té sady:

+
+ + + + + + + + + +
OčekávánoVýznamSoubory
acceptVáš systém má soubor přijmout.56
rejectVáš systém má soubor odmítnout.10
unspecifiedZáleží na pravidlech vašeho systému. Rozhodnete vy, a pak ověříte, že to, co se stane, je to, co jste chtěli.5
+
+
+ +
+

Co můžete změnit?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NastaveníPřijímáVýchozíCo dělá
--limitvelikost, například 2mb10mbLimit velikosti, který váš formulář pro nahrávání deklaruje. Tato sada udělá jeden krok na každou stranu - pro soubor v každé vzdálenosti spusťte předvolbu size-boundaries. Tato výchozí hodnota je náš zástupný údaj, ne hodnota vašeho systému. Zadejte vlastní.
--allowid formátů oddělená čárkamijpg,png,pdfKteré typy má váš formulář přijímat. Každý se stane skutečným souborem toho typu a tvoří pozitivní kontrolu celé sady.
--denypřípony oddělené čárkamisvg,html,exe,shKteré přípony má váš formulář odmítat. Přípona, pro kterou tato verze nemá formát, přesto dostane soubor s tímto názvem, obsahující prostý text.
--far-over10x, 2x, off2xJak daleko za limit sahá jediný velký soubor. Vypněte, kde zapsání několikanásobku limitu nestojí za místo na disku.
--bulk0 - 10000 souborů50Kolik souborů obsahuje hromadné nahrání. Nula tuto skupinu ze sady úplně vynechá.
+
+
+ +
+

Jak ji spustit?

+

Podívejte se, kolik by sada stála, sestavte ji, nebo si vezměte její recept k úpravě:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Nebo na ní stavte ve vlastním receptu vedle svých testů:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/cs/pripady-pouziti/index.html b/web/public/cs/pripady-pouziti/index.html new file mode 100644 index 00000000..cf8be805 --- /dev/null +++ b/web/public/cs/pripady-pouziti/index.html @@ -0,0 +1,315 @@ + + + + + + +Případy použití - limity nahrávání, fixtures pro CI, testy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

K čemu to lidé používají

+

+ Pět úloh, které se objevují téměř v každém projektu přijímajícím soubory od lidí, a příkaz, který + každou provede. Každý příklad níže běží tak, jak je napsán. +

+ +
+

Limity nahrávání

+

Test, zda je limit velikosti souboru vynucován tam, kde se tvrdí

+

+ Limit jsou tři testovací případy, ne jeden: těsně pod, přesně na něm a těsně nad. Získat je ručně + znamená počítat počty bajtů a doufat, že jste se nespletli o jedna. Požádejte raději o sadu: +

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

+ Dostanete tři skutečná PDF o 1048575, 1048576 a 1048577 bajtech a manifest, který říká, že první dvě + mají být přijata a třetí odmítnuto pro size_limit. Váš test čte očekávání místo + toho, abyste ručně psali tři aserce - a když se limit změní, změníte jedno číslo a spustíte + znovu. +

+

+ Totéž funguje bez předvolby, když chcete jedinou sadu hranic přímo v příkazu: +

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

Průběžná integrace

+

Držet fixtures mimo repozitář, aniž byste o ně přišli

+

+ Velké binární fixtures zpomalují klonování repozitáře a znepříjemňují revizi a nikdo nepozná, co se + změnilo, když se jeden vymění. Recept je pár set znaků YAML, které znovu sestaví totožné soubory + - bajt po bajtu, na jakémkoli počítači - protože každý soubor je odvozen ze + seedu běhu. +

+
- 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
+

+ Každý konec má svůj vlastní návratový kód, takže pipeline rozliší špatný recept od plného disku a od + nesrovnalosti při ověření. Neúspěšný běh nevypíše na standardní výstup nic, takže parser logu + nečte chybu jako data. +

+
+ +
+

Rozsah

+

Zjistit, co se stane, když je složka velká

+

+ Importní rutiny, noční úlohy a výpisy adresářů se chovají při deseti tisících souborů jinak než při + deseti. Velikosti losované z rozsahu dělají ze sady něco, co vypadá jako skutečný provoz, a ne + deset tisíc stejných souborů, a losování vychází ze seedu, takže sada je zítra stejná. +

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

+ Zkontrolujte, kolik by běh stál, než cokoli zapíše, což záleží, když se součet měří v gigabajtech: +

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

+ Běh větší než volné místo na disku je odmítnut dřív, než se zapíše první bajt, místo aby zaplnil + disk a selhal v půlce. +

+
+ +
+

Archivy

+

Test rozbalovače s archivem, který skutečně obsahuje soubory

+

+ Prázdný archiv se správnou příponou nic nedokazuje o kódu, který ho otevírá a prochází, co je + uvnitř. Deklarujte obsah a archiv ho skutečně obsahuje: +

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

+ Hloubka vnoření, počet položek a velikost toho, co je uvnitř, jsou věci, o kterých má importní + rutina názor, a takto zjistíte, jaké ty názory jsou. +

+
+ +
+

Parsery a prohlížeče

+

Ověření, že váš vlastní kód čte formát tak, jak to dělá skutečný software

+

+ Každý formát zde je před vydáním ověřen nezávislou čtečkou - PNG se otevře a porovnají se jeho + pixely, DOCX čtou zpět samostatné knihovny, archiv se rozbalí. To znamená, že soubor, který váš + parser odmítne, je zjištění o vašem parseru, ne o generátoru. +

+
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
+

+ Stránka formátů uvádí nastavení, která každý formát přijímá, a nejmenší + soubor, jakým každý může být. +

+
+ +
+

Návody

+

Dva z nich podrobněji

+
    +
  • + Poškozené testovací soubory - soubor záměrně rozbitý, + přesné velikosti, s tím, co se s ním má stát, zapsaným v manifestu. +
  • +
  • + Testovací soubory v CI - workflow pro GitHub Actions, job + v GitLabu a návratové kódy, které shodí build. +
  • +
+
+ +
+

Pro koho to je

+

+ QA inženýry, automatizaci testů a každého, za jehož kódem stojí formulář pro nahrávání, importní + rutina, parser nebo kvóta úložiště. Běží na počítači bez jakékoli sítě, na čem záleží v + uzavřeném firemním prostředí, kde generátor v prohlížeči není možnost. +

+ +

Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.

+
+ +
+ + + + diff --git a/web/public/cs/testovaci-soubory-v-ci/index.html b/web/public/cs/testovaci-soubory-v-ci/index.html new file mode 100644 index 00000000..73b55b15 --- /dev/null +++ b/web/public/cs/testovaci-soubory-v-ci/index.html @@ -0,0 +1,375 @@ + + + + + + +Testovací soubory v CI - GitHub Actions, GitLab CI a PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Případy použití

+

Jak generovat testovací soubory v CI pipeline

+

+ Binární fixture v repozitáři zůstává navždy v jeho historii, nedá se posoudit v diffu a při velkém + souboru přestává být možný. Generujte soubory raději v pipeline z receptu. Recept je text, bajty + vycházejí pokaždé stejné a poslední krok dokáže, že se nic nepohnulo. +

+ +
+

Stručná odpověď

+

+ Nainstalujte tfg, před testy spusťte tfg generate fixtures.yaml --out + ./fixtures a po nich tfg verify ./fixtures/manifest.json. Oba kroky shodí + build samy, s návratovým kódem, který říká proč. +

+
+ +
+

Proč je necommitovat

+

Proč fixture nepatří do repozitáře

+
    +
  • + Zůstává v historii. Pozdější smazání binárního souboru klon nezmenší, protože každá + jeho verze je tam pořád. +
  • +
  • + Diff neukáže, co se změnilo. Recenzent vidí, že PDF je jiné, a nic víc. Recept se + změní o jeden řádek. +
  • +
  • + Velké soubory se nevejdou. GitHub odmítne push, který obsahuje soubor větší než 100 + MB, takže test limitu nahrávání 500 MB nemá co commitovat. +
  • +
+

+ Commitovat je třeba recept. Stejný recept a stejný seed zapíší na každém počítači stejné bajty, + takže soubor vygenerovaný v pipeline je soubor, který jste měli na notebooku. +

+
+ +
+

Recept

+

Recept, který leží vedle testů

+

+ Tento zapíše pětadvacet faktur, které se mají přijmout, a dva obrázky nad limitem, které se mají + odmítnout, a manifest zaznamená obě očekávání: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml ho zkontroluje, aniž cokoli zapíše, a pojmenuje všechny + problémy najednou. +

+
+ +
+

GitHub Actions

+

Workflow, které nainstaluje nástroj a postaví fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Řádek s kontrolním součtem porovná archiv se souborem verify-SHA256SUMS.txt ze stejného + vydání. Verze je pevně daná, takže nové vydání nikdy nezmění build, na který jste nesáhli. +

+
+ +
+

GitLab CI

+

Totéž jako job v GitLabu

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Když se to zbarví načerveno

+

Co shodí krok, a proč

+

+ Každý konec má vlastní návratový kód, takže krok selže sám a log řekne který. Ty, které pipeline + potká: +

+
    +
  • 3 - recept není platný. Nic se nezapsalo a každý problém je pojmenován
  • +
  • 4 - formát neumí, co se chtělo, například velikost pod svým minimem
  • +
  • 6 - na disku není dost místa
  • +
  • 7 - tfg verify našel soubor, který nesedí s manifestem
  • +
  • 8 - běh skončil, ale ne všechno se vytvořilo
  • +
+

+ Neúspěšný běh nevypíše nic na standardní výstup, takže parser logů nikdy nevezme chybu za data. Celá + tabulka je na stránce dokumentace. +

+
+ +
+

PowerShell

+

Skript PowerShellu potřebuje ještě jeden řádek

+

+ PowerShell nevynese návratový kód programu ze souboru .ps1. Spusťte ho s + -File a skript odpoví 0, i když nástroj uvnitř práci odmítl, takže + build, který měl být červený, zezelená. Poslední řádek je celá oprava: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Tak se PowerShell chová, nejde o vlastnost tohoto nástroje. cmd, bash a + zsh nepotřebují nic navíc. +

+
+ +
+

Více jobů

+

Sdílení fixtures mezi joby

+

+ Nahrávat je obvykle není třeba. Protože stejný recept zapisuje stejné bajty, může každý job spustit + vlastní tfg generate, což je rychlejší než nahrání a stažení. Když má job přijmout + soubory od jiného, spusťte po přenosu tfg verify nad manifestem a řekne vám, zda + to, co dorazilo, je to, co bylo zapsáno. +

+
+ +
+

Dál

+

Kam jít odtud

+ +
+ +
+ + + + diff --git a/web/public/cs/vytvoreni-souboru-presne-velikosti/index.html b/web/public/cs/vytvoreni-souboru-presne-velikosti/index.html new file mode 100644 index 00000000..8c1712db --- /dev/null +++ b/web/public/cs/vytvoreni-souboru-presne-velikosti/index.html @@ -0,0 +1,329 @@ + + + + + + +Vytvoření souboru přesné velikosti - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Jak vytvořit soubor přesné velikosti

+

+ Každý systém na to má příkaz a všechny tři jsou níže. Dají vám soubor s přesně správným počtem bajtů + - a pro mnoho testů je to vše, co potřebujete. Každý příkaz na této stránce byl před + zveřejněním spuštěn na systému, kam patří. +

+ +
+

Krátká odpověď

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Velikosti jsou v bajtech a 10 MB + počítané tak, jak je počítá váš správce souborů, je 10485760. +

+
+ +
+

Windows

+

fsutil a verze v PowerShellu, která nepotřebuje nic navíc

+

+ fsutil je součástí Windows. Bere velikost v bajtech, takže si číslo + nejdřív spočítejte - 10 MB je 10485760, 100 MB je 104857600, 1 GB je 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Změřeno na Windows 11: funguje z běžného příkazového řádku a nepotřebuje zvýšená oprávnění a soubor + vyjde přesně na 10485760 bajtů. +

+

PowerShell umí totéž bez volání jiného programu a rozumí jednotkám:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB v PowerShellu znamená 10485760 bajtů, tedy stejné počítání po 1024 jako + Průzkumník, takže oba příkazy výše vytvoří stejnou velikost. +

+
+ +
+

Linux

+

dd, truncate a fallocate a rozdíl, který lidi chytí

+

dd zná každý. Bajty skutečně zapisuje:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate je okamžitý, a to je ten háček. Změřeno na Alpine Linuxu: soubor hlásí + 10485760 bajtů a zabírá nula bloků - je to řídký soubor. + Cokoli, co ho čte, dostane deset megabajtů nul, ale disk místo nikdy neuvolnil: +

+
truncate -s 10M test10mb.bin
+

+ To stačí k testu limitu nahrávání a klame to při testu diskové kvóty. fallocate je ten + správný, když musí být místo skutečné: +

+
fallocate -l 10M test10mb.bin
+

A když musí být obsah nestlačitelný, aby ho archivátor nemohl znovu zmenšit:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, který není řídký, a dva, které už znáte

+

+ macOS dodává mkfile. Změřeno na macOS 26.6.2: 10485760 bajtů a 20480 bloků, takže místo + je skutečně přiděleno, ne jen slíbeno: +

+
mkfile 10m test10mb.bin
+

dd a truncate tam jsou také a chovají se jako na Linuxu:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Kde to přestává stačit

+

Soubor správné velikosti není soubor správného druhu

+

+ Vše výše vám dá blok nul. To stačí, když testovaná věc hledí jen na velikost - limit nahrávání, + kvótu, přenos. Přestane to stačit ve chvíli, kdy soubor cokoli otevře. +

+

+ Změřeno a stojí za to to zkusit samostatně: vytvořte pomocí fsutil soubor o 2 MB, + pojmenujte ho photo.png a předejte ho knihovně pro obrázky. Pillow odpoví + cannot identify image file. Není to PNG. Nikdy nebylo - tvrdil to jen název. +

+

+ To je důležitější, než to zní, kvůli tomu, jakým směrem test pak selže. Váš + endpoint pro nahrávání soubor odmítne, váš test zezelená a vy usoudíte, že limit velikosti + funguje. Neodmítl ho kvůli velikosti. Odmítl ho proto, že bajty nebyly obrázek, a pravidlo, + které jste chtěli otestovat, nebylo nikdy dosaženo. +

+
    +
  • parser ho odmítne dřív, než se podívá na jakékoli pravidlo velikosti
  • +
  • selže krok náhledu a chyba, kterou čtete, je o náhledu
  • +
  • antivirus nebo kontrola obsahu ho odmítne z třetího důvodu
  • +
  • prohlížeč nezobrazí nic a nikdo nepozná, zda je to ta chyba
  • +
+
+ +
+

Druhá cesta

+

Skutečný soubor toho formátu, v přesně té velikosti, o kterou jste požádali

+

+ To je to, co dělá Testing Files Generator. Soubor je pravý soubor svého formátu - otevře se v + programu, kam patří - a má přesný počet bajtů, o který jste požádali, na bajt: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Požádejte o velikost, které formát nedosáhne, a dostanete chybu, která pojmenuje minimum a jeho + důvod, nikdy soubor špatné velikosti. Stránka formátů uvádí každý + formát s nejmenším souborem, který umí vytvořit. +

+

A limit jsou tři testovací případy, ne jeden, takže nástroj sestaví všechny tři:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ To vám dá 10485759, 10485760 a 10485761 bajtů a manifest, který říká, které má váš systém přijmout a + které odmítnout. Stránka případů použití to probírá spolu se + čtyřmi dalšími úlohami, pro které je určen. +

+ +

Zdarma a open source, GPL-3.0. Žádná registrace. Stažené soubory pro Windows a macOS jsou podepsané a spustí se bez varování.

+
+ +
+

Tak který použít?

+
    +
  • +

    Použijte příkaz systému

    +

    + Když soubor nic neotevírá. Test limitu velikosti na endpointu, který kontroluje velikost jako první, + přenos, kvóta, plný disk. Je to jeden řádek a už je nainstalovaný. +

    +
  • +
  • +

    Použijte skutečný generátor

    +

    + Když soubor cokoli zpracovává, vykresluje, importuje nebo rozbaluje - a když zítra na jiném počítači + potřebujete stejné fixtures, bajt po bajtu. +

    +
  • +
+

+ Oba jsou na této stránce, protože oba mají část času pravdu. Chybou, které je třeba se vyhnout, je + použít první tam, kde je třeba druhý, a číst zelený test jako důkaz. +

+
+ +
+ + + + diff --git a/web/public/de/anwendungsfaelle/index.html b/web/public/de/anwendungsfaelle/index.html new file mode 100644 index 00000000..0fdb702a --- /dev/null +++ b/web/public/de/anwendungsfaelle/index.html @@ -0,0 +1,321 @@ + + + + + + +Anwendungsfälle - Upload-Limits, CI-Fixtures, Massentests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Wofür Leute es einsetzen

+

+ Fünf Aufgaben, die in fast jedem Projekt vorkommen, das Dateien von Menschen annimmt, und der + Befehl, der jede erledigt. Jedes Beispiel unten läuft so, wie es geschrieben steht. +

+ +
+

Upload-Limits

+

Testen, ob ein Dateigrößenlimit dort durchgesetzt wird, wo es angegeben ist

+

+ Ein Limit sind drei Testfälle, nicht einer: knapp darunter, genau darauf und knapp darüber. Die von + Hand zu bekommen heißt, Byte-Zahlen auszurechnen und zu hoffen, dass man sich nicht um eins + verzählt hat. Fordere stattdessen das Set an: +

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

+ Du bekommst drei echte PDFs mit 1048575, 1048576 und 1048577 Bytes und ein Manifest, das sagt, dass + die ersten beiden akzeptiert und die dritte wegen size_limit abgelehnt werden soll. + Dein Test liest die Erwartung, statt dass du drei Assertions von Hand schreibst - und wenn sich + das Limit ändert, änderst du eine Zahl und startest neu. +

+

+ Dasselbe geht ohne Preset, wenn du ein einzelnes Grenzen-Set inline willst: +

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

Continuous Integration

+

Fixtures aus dem Repository heraushalten, ohne sie zu verlieren

+

+ Große binäre Fixtures machen ein Repository langsam beim Klonen und mühsam beim Review, und niemand + sieht, was sich geändert hat, wenn eine ersetzt wird. Ein Rezept sind ein paar hundert Zeichen + YAML, die die identischen Dateien neu erzeugen - Byte für Byte, auf jedem + Rechner - weil jede Datei aus dem Seed des Laufs abgeleitet wird. +

+
- 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
+

+ Jedes Ende hat einen eigenen Exit-Code, sodass eine Pipeline ein schlechtes Rezept von einem vollen + Datenträger und von einer Abweichung bei der Prüfung unterscheiden kann. Ein fehlgeschlagener + Lauf gibt nichts auf der Standardausgabe aus, wodurch ein Log-Parser einen Fehler nicht als + Daten liest. +

+
+ +
+

Skalierung

+

Herausfinden, was passiert, wenn der Ordner groß ist

+

+ Importroutinen, nächtliche Jobs und Verzeichnislisten verhalten sich bei zehntausend Dateien anders + als bei zehn. Aus einem Bereich gezogene Größen lassen das Set wie echten Datenverkehr aussehen + statt wie zehntausend identische Dateien, und die Ziehung kommt aus dem Seed, das Set ist also + morgen dasselbe. +

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

+ Prüfe, was ein Lauf kosten würde, bevor er etwas schreibt, was zählt, wenn die Summe in Gigabyte + gemessen wird: +

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

+ Ein Lauf, der größer ist als der freie Platz auf dem Datenträger, wird vor dem ersten geschriebenen + Byte abgelehnt, statt den Datenträger zu füllen und auf halbem Weg zu scheitern. +

+
+ +
+

Archive

+

Einen Entpacker mit einem Archiv testen, das wirklich Dateien enthält

+

+ Ein leeres Archiv mit der richtigen Endung beweist nichts über Code, der es öffnet und durchläuft, + was darin ist. Deklariere den Inhalt, und das Archiv enthält ihn wirklich: +

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

+ Verschachtelungstiefe, Eintragszahlen und die Größe dessen, was darin liegt, sind alles Dinge, zu + denen eine Importroutine Meinungen hat, und so findest du heraus, welche das sind. +

+
+ +
+

Parser und Viewer

+

Prüfen, dass dein eigener Code ein Format so liest wie echte Software

+

+ Jedes Format hier wird vor der Auslieferung mit einem unabhängigen Leser geprüft - ein PNG wird + geöffnet und seine Pixel verglichen, ein DOCX von separaten Bibliotheken zurückgelesen, ein + Archiv entpackt. Das heißt, eine Datei, die dein Parser abweist, ist ein Befund über deinen + Parser, nicht über den 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
+

+ Die Formate-Seite listet die Einstellungen jedes Formats und die kleinste + Datei auf, die es sein kann. +

+
+ +
+

Anleitungen

+

Zwei davon im Detail

+
    +
  • + Beschädigte Testdateien - eine absichtlich kaputte Datei + in exakter Größe, mit dem Manifest als Angabe, was mit ihr geschehen soll. +
  • +
  • + Testdateien in CI - ein GitHub-Actions-Workflow, ein GitLab-Job + und die Exit-Codes, die einen Build scheitern lassen. +
  • +
+
+ +
+

Für wen das gedacht ist

+

+ QA-Engineers, Testautomatisierung und alle, deren Code ein Upload-Formular, eine Importroutine, + einen Parser oder ein Speicherkontingent hinter sich hat. Es läuft auf einem Rechner ganz ohne + Netz, was in einer abgeschotteten Unternehmensumgebung zählt, wo ein browserbasierter Generator + keine Option ist. +

+ +

Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.

+
+ +
+ + + + diff --git a/web/public/de/beschaedigte-testdateien/index.html b/web/public/de/beschaedigte-testdateien/index.html new file mode 100644 index 00000000..6e0fa149 --- /dev/null +++ b/web/public/de/beschaedigte-testdateien/index.html @@ -0,0 +1,385 @@ + + + + + + +Beschädigte Testdateien - kaputte Dateien in exakter Größe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Anwendungsfälle

+

So erzeugen Sie eine beschädigte Datei zum Testen

+

+ Ein Validator, dem man nur gesunde Dateien gezeigt hat, ist nicht wirklich getestet. So bekommen Sie + eine Datei, die absichtlich kaputt ist, genau die Größe hat, die Sie verlangen, + und ein Manifest mitbringt, das sagt, was Ihr System damit tun soll. +

+ +
+

Die kurze Antwort

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out schreibt ein PNG + von genau 2097152 Byte, dessen erste Bytes Nullen sind, und das Manifest daneben hält fest, dass + Ihr System es ablehnen soll. +

+
+ +
+

Der übliche Weg

+

Warum eine von Hand beschädigte Datei ein schlechter Test ist

+

+ Üblich sind ein Hex-Editor, ein Skript, das ein paar zufällige Bytes kippt, oder eine Datei, die mit + head oder truncate gekürzt wird. Das funktioniert einmal, und dann + kostet es Sie: +

+
    +
  • + Es ist jedes Mal anders. Ein zufälliges Byte landet bei jedem Lauf woanders, ein + Fehler vom Dienstag kommt am Mittwoch womöglich nicht wieder. +
  • +
  • + Es verändert die Größe. Eine gekürzte Datei ist kleiner als das Limit, unter dem + sie liegen sollte, also antwortet die Größenprüfung vor der Inhaltsprüfung, und der Test + besteht aus dem falschen Grund. +
  • +
  • + Es fällt oft nicht auf. Reiner Text lässt sich mit einem geänderten Byte in der + Mitte weiterlesen, und ein nachsichtiger Bildleser zeichnet es einfach, sodass die Datei, die + kaputt sein sollte, angenommen wird. +
  • +
  • + Es sagt nichts darüber, was geschehen soll. Die Datei besteht nur aus Bytes, und + wer den Test später liest, muss raten, ob Annahme oder Ablehnung gemeint war. +
  • +
+
+ +
+

Was Sie bekommen

+

Eine beschädigte Datei hat trotzdem die verlangte Größe

+

+ Die Datei wird normal erzeugt und erst danach auf dem Weg zur Festplatte beschädigt. Sie behält die + verlangte Größe, und derselbe Befehl schreibt wieder dieselben Bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Einstellungen stehen nach einem Doppelpunkt. Die Option lässt sich wiederholen, und die + Beschädigungen werden in der Reihenfolge angewendet, in der Sie sie schreiben. Es funktioniert + mit allen 26 Formaten. +

+
+ +
+

Was möglich ist

+

Welche Beschädigungen gibt es?

+

+ Das ist die Liste, die das Programm ausgibt, beim Erstellen dieser Seite aus ihm gelesen. tfg + damage gibt dieselbe aus, und tfg damage <id> sagt, was eine davon + annimmt. +

+
+ + + + + + + + + + + + + + + + + +
BeschädigungWas sie mit den Bytes machtKleinste DateiEinstellungen
zero-headÜberschreibt die ersten Bytes der Datei mit Nullen und lässt ihre Länge unverändert. Die meisten Leser schauen zuerst dorthin, deshalb bemerkt fast alles diese Beschädigung.8bytes
+
+

+ zero-head schreibt Nullen über den Anfang der Datei. Die meisten Leser schauen zuerst + dorthin, auf die Signatur und den Header, die sagen, was die Datei ist, deshalb bemerkt es fast + jeder Leser. Reiner Text und Logs haben keine Signatur und werden ebenfalls abgewiesen, weil + eine Folge von Nullbytes kein Text ist. Unter vier Bytes entstehen bei manchen Formaten Schäden, + über die sich kein Leser beschwert, deshalb beginnt die Einstellung bei vier. +

+
+ +
+

Was das Manifest sagt

+

Ein Manifest, das sagt, was geschehen soll

+

+ Jede beschädigte Datei bekommt einen Eintrag, der besagt, dass Ihr System sie ablehnen soll, mit der + Beschädigung daneben: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Zwei Anfragen werden abgelehnt, bevor etwas geschrieben wird, denn jede würde eine Datei + hinterlassen, die das Manifest falsch beschreibt: +

+
    +
  • eine Datei, die kleiner ist, als die Beschädigung braucht, und unverändert herauskäme
  • +
  • + expected: accept neben einer Beschädigung, weil nichts es erfüllen könnte. Schreiben + Sie sanitize, wenn Ihr System die Datei reparieren soll, oder + unspecified, wenn genau das Ihre Frage ist +
  • +
+
+ +
+

In einem Rezept

+

Gesunde und kaputte Dateien in einem Lauf

+

+ Legen Sie beides in ein Rezept, dann trägt das Manifest die Erwartung jeder Datei, und der Test + braucht keine Liste, welche welche ist: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In einem Test

+

Daraus einen Test machen

+

+ Der Test liest das Manifest und prüft, ob das, was geschah, dem Erklärten entspricht. Er braucht + keine Liste von Dateinamen: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Eine gute Ablehnung ist eine saubere. Eine Meldung, die sagt, was falsch war, ist die gewünschte + Antwort. Ein Serverfehler, ein Hänger oder eine halb gespeicherte Datei ist der Fehler, den + dieser Test finden soll. +

+
+ +
+

Weiter

+

Wohin es von hier geht

+ +
+ +
+ + + + diff --git a/web/public/de/datei-bestimmter-groesse-erstellen/index.html b/web/public/de/datei-bestimmter-groesse-erstellen/index.html new file mode 100644 index 00000000..2c3fdd50 --- /dev/null +++ b/web/public/de/datei-bestimmter-groesse-erstellen/index.html @@ -0,0 +1,340 @@ + + + + + + +Datei mit bestimmter Größe erstellen - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

So erstellst du eine Datei in exakter Größe

+

+ Jedes System hat dafür einen Befehl, alle drei stehen unten. Sie liefern dir eine Datei mit genau + der richtigen Byte-Zahl - und für viele Tests ist das alles, was du brauchst. Jeder Befehl + auf dieser Seite wurde vor der Veröffentlichung ausgeführt, auf dem System, zu dem er + gehört. +

+ +
+

Die kurze Antwort

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Größen werden in Bytes angegeben, + und 10 MB, so gezählt wie dein Dateimanager zählt, sind 10485760 davon. +

+
+ +
+

Windows

+

fsutil und eine PowerShell-Variante, die nichts Zusätzliches braucht

+

+ fsutil gehört zu Windows. Es nimmt die Größe in Bytes, rechne die Zahl + also vorher aus - 10 MB sind 10485760, 100 MB sind 104857600, 1 GB ist 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Gemessen unter Windows 11: Es funktioniert in einer normalen Eingabeaufforderung und braucht keine + erhöhten Rechte, und die Datei hat genau 10485760 Bytes. +

+

PowerShell kann dasselbe, ohne ein anderes Programm aufzurufen, und versteht Einheiten:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB bedeutet in PowerShell 10485760 Bytes, dieselbe Zählung auf 1024er-Basis, die der + Explorer verwendet, die beiden Befehle oben erzeugen also dieselbe Größe. +

+
+ +
+

Linux

+

dd, truncate und fallocate und der Unterschied, der Leute erwischt

+

dd kennt jeder. Es schreibt die Bytes wirklich:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate ist sofort fertig, und genau das ist der Haken. Gemessen unter Alpine Linux + meldet die Datei 10485760 Bytes und belegt null Blöcke - sie ist eine + Sparse-Datei. Wer sie liest, bekommt zehn Megabyte Nullen, aber der Datenträger + hat den Platz nie hergegeben: +

+
truncate -s 10M test10mb.bin
+

+ Das ist für den Test eines Upload-Limits in Ordnung und für den Test einer Datenträgerquote + irreführend. fallocate ist das Mittel der Wahl, wenn der Platz wirklich belegt sein + muss: +

+
fallocate -l 10M test10mb.bin
+

Und wenn der Inhalt inkompressibel sein muss, damit ein Archivierer ihn nicht wieder zusammendrücken kann:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, das nicht sparse ist, und die beiden, die du schon kennst

+

+ macOS liefert mkfile mit. Gemessen unter macOS 26.6.2: 10485760 Bytes und 20480 Blöcke, + der Platz ist also wirklich belegt statt nur versprochen: +

+
mkfile 10m test10mb.bin
+

dd und truncate gibt es ebenfalls, und sie verhalten sich wie unter Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Wo das nicht mehr reicht

+

Eine Datei in der richtigen Größe ist keine Datei der richtigen Art

+

+ Alles oben Genannte liefert dir einen Block aus Nullen. Das reicht, wenn das Getestete nur auf die + Größe schaut - ein Upload-Limit, eine Quote, eine Übertragung. Es reicht nicht mehr, sobald + irgendetwas die Datei öffnet. +

+

+ Gemessen, und es lohnt sich, das selbst zu probieren: Erzeuge mit fsutil eine + 2-MB-Datei, nenne sie photo.png und gib sie einer Bildbibliothek. Pillow antwortet + cannot identify image file. Es ist kein PNG. Es war nie eines - nur der Name + behauptete es. +

+

+ Das ist wichtiger, als es klingt, wegen der Richtung, in der der Test dann + fehlschlägt. Dein Upload-Endpunkt weist die Datei ab, dein Test wird grün, und du + schließt, dass das Größenlimit funktioniert. Er hat sie nicht wegen der Größe abgewiesen. Er hat + sie abgewiesen, weil die Bytes kein Bild waren, und die Regel, die du testen wolltest, wurde nie + erreicht. +

+
    +
  • ein Parser weist sie ab, bevor eine Größenregel angesehen wird
  • +
  • ein Vorschauschritt schlägt fehl, und der Fehler, den du liest, betrifft die Vorschau
  • +
  • ein Virenscanner oder eine Inhaltsprüfung lehnt sie aus einem dritten Grund ab
  • +
  • ein Viewer zeigt nichts an, und niemand kann sagen, ob das der Fehler ist
  • +
+
+ +
+

Der andere Weg

+

Eine echte Datei dieses Formats, in genau der Größe, die du verlangt hast

+

+ Das ist es, was Testing Files Generator tut. Die Datei ist eine echte ihres Formats - sie öffnet + sich in der Software, zu der sie gehört - und hat die exakte Byte-Zahl, die du verlangt hast, + auf das Byte genau: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Verlange eine Größe, die ein Format nicht erreichen kann, und du bekommst einen Fehler, der die + Untergrenze und ihren Grund nennt, nie eine Datei in der falschen Größe. Die + Formate-Seite listet jedes Format mit der kleinsten Datei auf, die es + erzeugen kann. +

+

Und ein Limit sind drei Testfälle statt einem, deshalb baut das Tool alle drei:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Das ergibt 10485759, 10485760 und 10485761 Bytes und ein Manifest, das sagt, welche davon dein + System akzeptieren und welche es ablehnen soll. Die + Anwendungsfälle-Seite geht das und vier weitere Aufgaben + durch, für die es gebaut ist. +

+ +

Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.

+
+ +
+

Was solltest du also verwenden?

+
    +
  • +

    Den Systembefehl verwenden

    +

    + Wenn nichts die Datei öffnet. Ein Größenlimit an einem Endpunkt testen, der zuerst die Größe prüft, + eine Übertragung, eine Quote, ein voller Datenträger. Es ist eine Zeile, und es ist schon + installiert. +

    +
  • +
  • +

    Einen echten Generator verwenden

    +

    + Wenn irgendetwas die Datei parst, rendert, importiert oder entpackt - und wenn du morgen auf einem + anderen Rechner dieselben Fixtures brauchst, Byte für Byte. +

    +
  • +
+

+ Beides steht auf dieser Seite, weil beides manchmal richtig ist. Der Fehler, den es zu vermeiden + gilt, ist, das Erste zu verwenden, wo das Zweite nötig ist, und den grünen Test als Beweis zu + lesen. +

+
+ +
+ + + + diff --git a/web/public/de/dokumentation/index.html b/web/public/de/dokumentation/index.html new file mode 100644 index 00000000..852020c1 --- /dev/null +++ b/web/public/de/dokumentation/index.html @@ -0,0 +1,563 @@ + + + + + + +Dokumentation - Befehle, Rezepte, Manifest, Exit-Codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Dokumentation

+

+ Alles, was das Tool kann, geordnet nach den Fragen, mit denen die Leute tatsächlich kommen. Die + README im Repository ist die vollständige Referenz und passt immer + zu dem Build, den du heruntergeladen hast. +

+ +
+

Welche Befehle gibt es?

+

Jeder tut genau eine Sache:

+
tfg generate    Dateien erzeugen, aus einem Rezept oder über Flags
+tfg validate    ein Rezept prüfen und nichts schreiben
+tfg verify      ein Verzeichnis gegen ein Manifest prüfen
+tfg cleanup     die Dateien entfernen, die ein Manifest auflistet
+tfg recipe fmt  ein Rezept in seiner festen Form ausgeben
+tfg preset      ein Set von Dateien aus einer benannten Testfrage erzeugen
+tfg formats     die Formate dieses Builds auflisten
+tfg damage      die Arten auflisten, wie dieser Build eine Datei absichtlich beschädigen kann
+tfg tool        kleine Helfer für Dateien, die du schon hast
+tfg version     die Version des Tools ausgeben
+tfg license     die Lizenz ausgeben und was sie für erzeugte Dateien bedeutet
+
+ +
+

Wie erzeuge ich eine einzelne Datei in exakter Größe?

+

+ Nenne das Format, die Größe und das Ziel. Größen zählen in 1024ern, 2mb sind also + 2097152 Bytes. Eine einfache Byte-Zahl funktioniert auch, --size 10485761 verlangt + also genau so viele. +

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

Die nützlichen Flags von generate:

+
+ + + + + + + + + + + + + + + + + +
FlagWas es tut
--format <id>Format der Dateien, zum Beispiel txt
--size <size>exakte Größe jeder Datei, etwa 10mb oder eine einfache Byte-Zahl
--size-range <a-b>eine Größe, die pro Datei aus einem Bereich gezogen wird, etwa 1kb-8kb. Die Ziehung kommt aus dem Seed
--boundary <size>drei Dateien rund um ein Limit: ein Byte darunter, das Limit, ein Byte darüber
--count <n>wie viele Dateien erzeugt werden. Standard 1
--name <template>Namensvorlage, zum Beispiel invoice_{index:04}.txt
--out <dir>Verzeichnis, in das geschrieben wird
--seed <n>Seed des Laufs. Derselbe Seed ergibt dieselben Bytes
--set <k>=<v>eine Formateinstellung, wiederholbar
--damage <name>Dateien absichtlich beschädigen, wiederholbar und der Reihe nach angewendet. Mit tfg damage bekommst du die Liste
--expected <outcome>accept, reject, sanitize oder unspecified
--dry-runzählen und anzeigen, überhaupt nichts schreiben
--jsondas Manifest auf die Standardausgabe schreiben
+
+
+ +
+

Wie erzeuge ich eine absichtlich kaputte Datei?

+

+ Jede andere Datei, die dieses Tool schreibt, ist per Konstruktion korrekt, was zwei der drei Fragen + beantwortet, die ein Upload-Validator stellt. --damage beantwortet die dritte - + lässt sich die Datei überhaupt öffnen. Die Datei wird normal erzeugt und dann beschädigt, sie + hat also weiterhin die verlangte Größe. +

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

+ Einstellungen stehen hinter einem Doppelpunkt. Das Flag lässt sich wiederholen, und die Reihenfolge, + in der du sie schreibst, ist die Reihenfolge, in der sie angewendet werden. tfg + damage listet auf, was dieser Build kann und was jede Variante annimmt. +

+

In einem Rezept ist der Schlüssel eine Liste, aus Namen oder aus Einstellungen:

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

+ Eine beschädigte Datei bekommt im Manifest expected: reject, mit der daneben + festgehaltenen Beschädigung. Zwei Dinge werden abgelehnt, bevor etwas geschrieben wird, weil + sonst jeweils eine Datei auf die Platte käme, die das Manifest falsch beschreibt: +

+
    +
  • eine Datei, die kleiner ist, als die Beschädigung braucht, weil sie unverändert herauskäme
  • +
  • + expected: accept neben einer Beschädigung, weil es keine Datei geben kann, die das + erfüllt. Schreibe sanitize, wenn das getestete System die Datei reparieren soll, + oder unspecified, wenn genau das die Frage ist, die du stellst +
  • +
+

+ Eine dritte lässt sich nicht im Voraus wissen. Wenn eine Beschädigung läuft und kein Byte verändert, + wird diese Datei verworfen statt geschrieben - der Lauf macht weiter, sagt, um welche Datei es + ging, und endet mit dem Exit-Code für teilweise erfolgreiche Läufe. +

+

+ Schritt für Schritt, mit einem Test, der das Manifest liest: + So erzeugen Sie eine beschädigte Datei zum Testen. +

+
+ +
+

Wie sieht ein Rezept aus?

+

+ Ein Rezept ist eine YAML-Datei, die einen ganzen Lauf beschreibt. Checke sie neben deinen Tests ein, + und die Fixtures sind keine Binärdateien mehr in deinem Repository - jeder kann sie Byte für + Byte aus einer Datei von wenigen hundert Zeichen neu erzeugen. +

+
# 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
+

+ Jedes Target braucht genau eines von size, size-range, + boundary oder contains. Zwei davon sind ein Fehler, und keines + ebenfalls. Ein ungültiges Rezept schreibt überhaupt keine Dateien und meldet + alle Probleme auf einmal statt nur das erste, jedes mit der Einstellung, um die es geht. +

+
+ +
+

Wie lege ich fest, was mein System mit einer Datei tun soll?

+

Kurzform, wenn das Ergebnis reicht, Langform, wenn der Grund zählt:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Die Ergebnisse sind accept, reject, sanitize und + unspecified. Die Gründe sind eine geschlossene Liste, damit ein Report danach + gruppieren kann: 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 und + size_zero. +

+

+ Ein Grund benennt die Regel, um die es geht, nicht das Urteil. Deshalb kann + derselbe Grund unter beiden Ergebnissen stehen - eine Datei ein Byte unter einem Limit ist + accept, und die Regel, um die es geht, ist trotzdem size_limit. +

+
+ +
+

Was steht im Manifest?

+

+ Es wird am Ende jedes Laufs neben die Dateien geschrieben, auch bei einem unterbrochenen Lauf. Ein + Eintrag pro Datei: +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Ein recipe_hash kommt hinzu, wenn der Lauf aus einem Rezept stammt, und + preset mit overrides, wenn er aus einem Preset stammt, sodass sich ein + Manifest immer auf das zurückführen lässt, was es erzeugt hat. +

+

+ Jeder Eintrag trägt außerdem target_id, die ID des Targets im Rezept, das die Datei + erzeugt hat, und summary.by_target zählt, auf wie viele Dateien jedes Target kam. + Ein Rezept mit mehreren Targets lässt sich so Target für Target prüfen, ohne Dateinamen zu + lesen. +

+
+ +
+

Was ist ein Preset?

+

+ Ein fertiges Set aus Dateien, das eine gängige Testfrage beantwortet, damit du das Set nicht selbst + entwerfen musst. Presets sind darunter ganz normale Rezepte, und eject gibt das + Rezept aus, damit du es von dort aus bearbeiten kannst. Jedes Preset hat + eine eigene Seite mit dem, was es meist findet, was im Set steckt und + welche Einstellungen es kennt. +

+
    +
  • +

    Leer und minimal

    +

    Kommt eine gültige Datei durch, die so klein ist, wie das Format es erlaubt?

    +

    empty-and-minimal

    +
  • +
  • +

    Umgang mit Dateinamen

    +

    Speichert, zeigt und liefert mein System einen Dateinamen korrekt, mit dem es nicht gerechnet hat?

    +

    filename-handling

    +
  • +
  • +

    Größengrenzen

    +

    Wird ein Größenlimit genau dort durchgesetzt, wo es angegeben ist?

    +

    size-boundaries

    +
  • +
  • +

    Tabellenimport

    +

    Übersteht mein Tabellenimport das, was echte Tools exportieren?

    +

    tabular-import

    +
  • +
  • +

    Textkodierung

    +

    Weiß mein Leser, in welcher Kodierung eine Datei vorliegt, oder rät er?

    +

    text-encoding

    +
  • +
  • +

    Upload-Validierung

    +

    Nimmt mein Upload-Formular an, was es soll, und weist den Rest ab?

    +

    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 sagt dir, was das Set kosten würde, bevor du es baust, und sagt + unmissverständlich, wenn eine Zahl ein Platzhalter von uns statt ein Limit von dir ist. +

+
+ +
+

Was bedeuten die Exit-Codes?

+

+ Jedes Ende hat einen eigenen Code, maschinenlesbare Ausgabe geht auf die Standardausgabe, und ein + fehlgeschlagener Lauf gibt dort nichts aus. Die Tabelle ist ein eingefrorener Vertrag - die + Bedeutung eines Codes zu ändern erfordert einen Major-Versionssprung. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeBedeutung
0Alles hat funktioniert.
1Ein unerwarteter Fehler im Tool.
2Falscher Befehl oder falsches Flag.
3Das Rezept ist ungültig.
4Das Format kann nicht, was verlangt wurde.
5Lesen oder Schreiben ist fehlgeschlagen.
6Nicht genug Speicherplatz.
7verify hat eine Abweichung gefunden.
8Der Lauf ist beendet, aber nicht alles wurde erzeugt.
130Mit Strg+C abgebrochen.
143Durch ein Signal beendet, so sieht ein CI-Timeout aus.
+
+
- 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
+

+ Ein mit Strg+C gestoppter Lauf hinterlässt trotzdem ein Manifest und nie eine halb geschriebene + Datei, sodass ein abgebrochener Job vom nächsten noch aufgeräumt werden kann. +

+

+ Fertige Workflows für GitHub Actions und GitLab CI: So erzeugen Sie + Testdateien in einer CI-Pipeline. +

+
+ +
+

Gibt es ein Desktop-Fenster?

+

+ Ja, dieselbe Engine mit einem Fenster davor, für das Testen, das nicht skriptbar ist. Es ist keine + abgespeckte Version: Ein Test vergleicht die beiden Oberflächen Fähigkeit für Fähigkeit, und + alles, was nur eine von beiden kann, muss deklariert und begründet werden, statt unbemerkt + auseinanderzudriften. +

+

+ Die Bildschirme sind ein Stapel, Presets, mehrere Stapel gleichzeitig und Info. Es zeigt, was ein + Lauf kosten würde, bevor etwas geschrieben wird, meldet den Fortschritt während des Laufs und + lässt sich mittendrin abbrechen, ohne eine halb geschriebene Datei zu hinterlassen. Eine + Rezeptdatei öffnet es noch nicht - Rezepte gibt es vorerst nur auf der Kommandozeile, und das + Fenster baut seine Stapel im Formular. +

+
+ +
+ + + + diff --git a/web/public/de/faq/index.html b/web/public/de/faq/index.html new file mode 100644 index 00000000..b9ddd718 --- /dev/null +++ b/web/public/de/faq/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - Fragen zum Erzeugen von Testdateien + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Häufig gestellte Fragen

+

+ Lizenz, Datenschutz, Reproduzierbarkeit und das, was Leute prüfen, bevor sie einen Generator in eine + Build-Pipeline einbauen. Wenn deine Frage hier fehlt, ist der + Issue-Tracker offen. +

+ +
+
+

Worin unterscheidet sich das von dd, fsutil oder truncate?

+
+

Diese Befehle liefern dir eine Datei in der richtigen Größe, gefüllt mit nichts. Eine 2 MB große Datei namens photo.png, die so entstanden ist, ist kein PNG. Alles, was sie wirklich parst, weist sie aus dem falschen Grund ab, und dein Test besteht dann ebenfalls aus dem falschen Grund. Dieses Tool erzeugt ein echtes PNG von genau 2 MB, das sich in einem Bildbetrachter öffnet und mit einer Aussage darüber geliefert wird, wie dein System damit umgehen soll.

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

Ist es kostenlos, und darf ich es bei der Arbeit einsetzen?

+
+

Ja, beides. Es steht unter der GPL-3.0 und kostet nichts. Es gibt kein Konto, keinen Lizenzschlüssel und keine kostenpflichtige Stufe.

+
+
+
+

Darf ich die erzeugten Dateien in einem Closed-Source-Produkt verwenden?

+
+

Ja. Die Lizenz gilt für den Code des Tools, nicht für das, was das Tool erzeugt. Erzeugte Dateien, Rezepte und Manifeste sind Ausgabe und keine abgeleiteten Werke, du kannst sie also einchecken und ohne jede Verpflichtung weitergeben.

+
+
+
+

Enthalten die erzeugten Dateien echte personenbezogene Daten?

+
+

Nein. Alles darin wird aus einem Seed synthetisch erzeugt. Es wird kein Datensatz gelesen, kein Dienst kontaktiert und kein Inhalt Dritter eingebettet. Behandle eine erzeugte E-Mail-Adresse als unbrauchbar statt als unbenutzt, denn jede Zufallszeichenfolge kann zufällig mit einer echten übereinstimmen.

+
+
+
+

Bekomme ich auf einem anderen Rechner genau dieselben Dateien?

+
+

Ja, Byte für Byte, bei gleichem Rezept und gleichem Seed. Das Projekt testet das bei jeder Änderung, und es zu brechen erfordert einen Major-Versionssprung. Genau deshalb kannst du ein kleines Rezept einchecken statt großer binärer Fixtures.

+
+
+
+

Braucht es eine Internetverbindung?

+
+

Nie. Es gibt keine Telemetrie, keine Update-Prüfung und keinen Cloud-Client, und die Kommandozeilen-Binärdatei hat gar keinen Netzwerkstack einkompiliert. Sie läuft auf einem Rechner ohne Netz und in einer abgeschotteten Unternehmensumgebung.

+
+
+
+

Was passiert, wenn ich eine Größe verlange, die ein Format nicht erreichen kann?

+
+

Du bekommst einen Fehler, der das Format nennt, die kleinstmögliche Größe, den Grund für diese Untergrenze und was du stattdessen tun kannst, und es wird keine Datei geschrieben. Das Tool rundet eine Größe nie stillschweigend. Jede Untergrenze steht auf der Formate-Seite.

+
tfg formats png
+
+
+
+

Kann ich eine absichtlich kaputte Datei erzeugen?

+
+

Ja. Fügen Sie --damage zero-head hinzu, und die Datei kommt in genau der verlangten Größe heraus, mit Nullen über den ersten Bytes, sodass ein Leser sie abweist, und das Manifest sagt, dass Ihr System sie ablehnen soll. Die Einzelheiten stehen auf der Seite über beschädigte Testdateien.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Welche Formate kommen als Nächstes?

+
+

7z, mp3 und mp4. 26 Formate funktionieren heute durchgängig.

+
+
+
+

Auf welchen Systemen läuft es?

+
+

Die Kommandozeile läuft unter Windows und Linux auf Intel und ARM sowie auf Macs mit Apple Silicon. Das Desktop-Fenster gibt es für Windows auf Intel, Linux auf Intel und Macs mit Apple Silicon. Intel-Macs werden nicht unterstützt, und für sie wird nichts gebaut.

+
+
+
+

Muss ich etwas installieren?

+
+

Nein. Lade das Archiv für dein System herunter, entpacke es und starte die Binärdatei. Es gibt keinen Installer, keine Laufzeitumgebung zum Nachrüsten und keine Abhängigkeit, die aufgelöst werden müsste. Wenn du Go hast, funktioniert auch ein einziger go-install-Befehl.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Warum ist ein Lauf über Tausende Dateien unter Windows langsamer?

+
+

Weil Windows für jeden Pfad, den es ansieht, mehr verlangt, und ein Befehl über Tausende Dateien sieht sich Tausende Pfade an. Gemessen auf einem Rechner mit 3000 Dateien zu je 1 kB braucht verify unter Windows etwa 0,9 Sekunden und unter Linux in einem Container etwa 0,2 Sekunden. Ein kürzerer Ausgabepfad verkleinert den Windows-Wert, denn jeder Ordner über den Dateien gehört zu dem, was angesehen wird.

+
+
+
+ + +
+

Noch unentschlossen?

+

+ Die Anwendungsfälle-Seite zeigt die Aufgaben, für die es gebaut + ist, und die Formate-Seite listet jedes Format mit der kleinsten + Datei auf, die es erzeugen kann. Die README im Repository ist + die vollständige Referenz. +

+ +

Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.

+
+ +
+ + + + diff --git a/web/public/de/formate/index.html b/web/public/de/formate/index.html new file mode 100644 index 00000000..5d37b72a --- /dev/null +++ b/web/public/de/formate/index.html @@ -0,0 +1,913 @@ + + + + + + +26 unterstützte Dateiformate - PDF, DOCX, PNG, ZIP und mehr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 Dateiformate, jedes in exakter Größe erzeugt

+

+ Jedes davon ist eine echte Datei dieses Formats. Sie öffnet sich in der Software, + zu der sie gehört, und hat genau die Byte-Zahl, die du verlangt hast. Keines davon besteht aus + aufgefüllten Nullen mit einer angeklebten Endung. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatNameEndungKleinste DateiVollständigkeitGeprüft mit
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullnicht zutreffend
mdMarkdown.md0fullnicht zutreffend
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullnicht zutreffend
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Was die Spalten bedeuten

+
    +
  • +

    Kleinste Datei

    +

    + Die wenigsten Bytes, die dieses Tool für das Format akzeptiert, einschließlich des Labels, das es in + die Datei schreibt. Verlangst du weniger, bekommst du einen Fehler, der die Untergrenze und + ihren Grund nennt, nie eine Datei in der falschen Größe. +

    +
  • +
  • +

    Vollständigkeit

    +

    + Wie vollständig die Datei ist. full heißt, dass ein Leser, der das Format wirklich + parst, sie akzeptiert, nicht nur, dass die Endung passt. +

    +
  • +
  • +

    Geprüft mit

    +

    + Der unabhängige Leser, der jede erzeugte Datei öffnet, bevor das Format ausgeliefert wird - eine + eigene Implementierung, nicht unser eigener Code, der seine Hausaufgaben selbst korrigiert. +

    +
  • +
+

+ Jedes Format wiederholt sich außerdem bis aufs Byte: Dasselbe Rezept und derselbe Seed erzeugen auf + jedem Rechner identische Dateien, und genau das macht ein Rezept sicher einzuchecken statt der + Fixtures selbst. +

+
+ +
+

Einstellungen, die jedes Format kennt

+

+ Die meisten Formate haben eigene Einstellungen - Bildmaße, JPEG-Qualität, PDF-Seitenzahl, Zeilen und + Spalten in einer Tabelle, wie viele Einträge in ein Archiv kommen. Setze sie mit --set + key=value auf der Kommandozeile oder unter properties: in einem Rezept. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatEinstellungErlaubt
avifwidth1 - 16384 Pixel
height1 - 16384 Pixel
quality1 - 100
bmpwidth1 - 20000 Pixel
height1 - 20000 Pixel
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerwahr oder falsch
quote_styleall, minimal, none
columns2 - 32768 Spalten
docxparagraphs1 - 50000 Absätze
gifwidth1 - 20000 Pixel
height1 - 20000 Pixel
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 Pixel
height1 - 256 Pixel
embedbmp, png
jpgwidth1 - 20000 Pixel
height1 - 20000 Pixel
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 Pixel
height1 - 16384 Pixel
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 Einträge pro Sekunde
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomwahr oder falsch
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlebeliebiger Text
authorbeliebiger Text
subjectbeliebiger Text
keywordsbeliebiger Text
creatorbeliebiger Text
producerbeliebiger Text
createdein Datum wie 2024-02-29 oder 2024-02-29T13:45:00+02:00, oder none
modifiedein Datum wie 2024-02-29 oder 2024-02-29T13:45:00+02:00, oder none
pngwidth1 - 20000 Pixel
height1 - 20000 Pixel
pptxslides1 - 500 Folien
svgwidth1 - 20000 Pixel
height1 - 20000 Pixel
targzentries0 - 10000
entry_formatdie ID eines Formats, wie tfg formats sie auflistet
entry_sizeeine Größe wie 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entrieswahr oder falsch
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 Pixel
height1 - 20000 Pixel
txtencodingutf-16be, utf-16le, utf-8
bomwahr oder falsch
wavsample_rate8000 - 192000 Hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 Pixel
height1 - 16383 Pixel
xlsxrows1 - 200000 Zeilen
columns1 - 32768 Spalten
xmlencodingutf-16be, utf-16le, utf-8
bomwahr oder falsch
zipentries0 - 10000
entry_formatdie ID eines Formats, wie tfg formats sie auflistet
entry_sizeeine Größe wie 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entrieswahr oder falsch
passworddas Passwort im Klartext
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Ein Wert außerhalb dessen, was eine Einstellung zulässt, wird mit einer Meldung abgewiesen, die die + Einstellung, den erlaubten Bereich und eine Alternative nennt. Eine unbekannte Einstellung ist + ebenfalls ein Fehler, nie ein stiller Standardwert - ein stillschweigend akzeptierter Tippfehler + ergibt eine Datei mit den falschen Einstellungen und eine Stunde Rätselraten, warum der Test + besteht, obwohl er es nicht sollte. +

+

+ Mit tfg formats <id> siehst du genau, was ein Format in dem Build akzeptiert, den + du hast. +

+
+ +
+

Archive enthalten echte Dateien

+

+ targz und zip + lassen sich mit Einträgen füllen, statt als leere Hülle zu bleiben. Ein erzeugtes Archiv enthält + wirklich die Dokumente, die es zu enthalten vorgibt, sodass alles, was es während eines Tests + entpackt, echte Dateien darin findet. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/de/index.html b/web/public/de/index.html new file mode 100644 index 00000000..da15f7b6 --- /dev/null +++ b/web/public/de/index.html @@ -0,0 +1,457 @@ + + + + + + +Testdatei-Generator für QA - exakte Größe, 26 echte Formate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Echte Testdateien in jeder exakten Größe erzeugen

+

+ PDF, PNG, DOCX, ZIP - insgesamt 26 Formate, und jedes ist + eine echte Datei, die sich in der Software öffnet, zu der sie gehört, in genau der + Größe, die du verlangt hast. Jeder Lauf hält außerdem fest, was deine Anwendung mit + jeder Datei tun soll. Kommandozeile und Desktop-Fenster, kostenlos und Open Source, vollständig + auf deinem Rechner. +

+ + +

Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.

+
+ +
+ Das Desktop-Fenster von Testing Files Generator, eingerichtet für einen Stapel Testdateien +
Das Desktop-Fenster, eingerichtet für einen Stapel Dateien. Dieselbe Engine läuft hinter der Kommandozeile.
+
+
+ + + +
+

Das Problem

+

Eine Testdatei zu machen ist einfach. Die richtigen tausend zu machen ist das Mühsame

+

Du testest Software, die Dateien von Menschen annimmt. Früher oder später brauchst du:

+
    +
  • ein PDF von exakt 10 MB, um herauszufinden, ob das Upload-Limit echt ist
  • +
  • die drei Dateien beidseits dieses Limits, um Off-by-one-Fehler zu fangen
  • +
  • 10.000 Logdateien, um zu sehen, was der nächtliche Job tut, wenn der Ordner groß ist
  • +
  • ein ZIP, das wirklich 200 Dokumente enthält, keine Attrappe mit der richtigen Endung
  • +
  • eine 4-GB-Datei, ohne eine 4-GB-Datei in deinem Repository zu halten
  • +
  • die gleichen Fixtures auf deinem Laptop und auf dem Build-Server, Byte für Byte
  • +
+

+ Genau das ersetzt dieses Tool. Es ist gebaut für QA-Engineers, Testautomatisierung und alle, deren + Code ein Upload-Formular, eine Importroutine, einen Parser oder ein Speicherkontingent hinter + sich hat. +

+
+ +
+

Was es anders macht

+

Andere Generatoren hören bei den Bytes auf. Dieser beantwortet, was dein Test wirklich fragt

+

+ Ein Ordner voller Dateien lässt dich weiter entscheiden, was jede davon belegen soll. Jeder Lauf + schreibt hier ein manifest.json neben die Dateien - eine einfache Liste von allem, + was erzeugt wurde, und zu jedem Eintrag eine deklarierte Erwartung. +

+

Angenommen, dein Upload-Endpunkt erlaubt 1 MB. Fordere die drei Dateien an, die auf dieser Linie liegen:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
DateiBytesDein System sollWeil
1mb_under_1b.pdf1048575akzeptierensie liegt innerhalb des Limits
1mb_at_limit.pdf1048576akzeptierendas Limit selbst ist erlaubt
1mb_over_1b.pdf1048577ablehnensize_limit
+
+ +

Drei Dateien, drei verschiedene Antworten, in maschinenlesbarer Form. Dein Test liest das Manifest, statt dass du die Assertions von Hand schreibst:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Wo die Antwort von deiner eigenen Richtlinie abhängt, sagt das Manifest das

+

+ Es hält unspecified fest, statt eine Erwartung zu erfinden. Ein Generator, der rät, + erzeugt falsche Fehlschläge, und eine Testsuite, die ständig Alarm schlägt, wird abgeschaltet. +

+
+
+ +
+

Presets

+

Wähle die Frage, bekomme das ganze Set

+

+ Ein Preset ist ein Set aus Testdateien, das um eine Testfrage herum entworfen wurde, damit du nicht + selbst herausfinden musst, welche Dateien was belegen. Jedes hat eine eigene Seite mit dem, was + es meist findet, was im Set steckt und welche Einstellungen es kennt. +

+
    +
  • +

    Leer und minimal

    +

    Kommt eine gültige Datei durch, die so klein ist, wie das Format es erlaubt?

    +

    empty-and-minimal

    +
  • +
  • +

    Umgang mit Dateinamen

    +

    Speichert, zeigt und liefert mein System einen Dateinamen korrekt, mit dem es nicht gerechnet hat?

    +

    filename-handling

    +
  • +
  • +

    Größengrenzen

    +

    Wird ein Größenlimit genau dort durchgesetzt, wo es angegeben ist?

    +

    size-boundaries

    +
  • +
  • +

    Tabellenimport

    +

    Übersteht mein Tabellenimport das, was echte Tools exportieren?

    +

    tabular-import

    +
  • +
  • +

    Textkodierung

    +

    Weiß mein Leser, in welcher Kodierung eine Datei vorliegt, oder rät er?

    +

    text-encoding

    +
  • +
  • +

    Upload-Validierung

    +

    Nimmt mein Upload-Formular an, was es soll, und weist den Rest ab?

    +

    upload-validation

    +
  • +
+

Alle Presets und wie sie sich zu Rezepten verhalten

+
+ +
+

Schnellstart

+

Drei Befehle, um es in Aktion zu sehen

+
    +
  1. +

    Eine Datei erzeugen

    +

    Ein PNG, genau zwei Megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Viele Dateien erzeugen

    +

    + Zehntausend Logdateien, jede zwischen einem und acht Kilobyte, die Größen werden aus dem Seed + gezogen, sodass morgen dasselbe Set herauskommt. Gib jedem Lauf ein eigenes + Verzeichnis - das Manifest ist die einzige Aufzeichnung dessen, was ein Lauf + geschrieben hat, deshalb weigert sich das Tool, ein zweites darüber zu schreiben: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Prüfen und dann entfernen

    +

    verify sagt dir, dass sich nichts verändert hat. cleanup entfernt genau das, was geschrieben wurde, und sonst nichts:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Größen zählen in 1024ern, wie es dein Dateimanager tut, 2mb bedeutet also 2097152 + Bytes. Eine einfache Byte-Zahl funktioniert auch. Die + Dokumentation behandelt Rezepte, das Manifest und die + Exit-Codes. +

+
+ +
+

Was du bekommst

+

Gebaut für eine Testsuite, die unbeaufsichtigt läuft

+
    +
  • +

    Exakte Größe, auf das Byte genau

    +

    Verlange 10485761 Bytes und bekomme genau das. Eine Größe, die ein Format nicht erreichen kann, ist ein Fehler mit Begründung, nie eine Datei in der falschen Größe.

    +
  • +
  • +

    26 echte Formate

    +

    Keine aufgefüllten Nullen mit einer Endung. Ein erzeugtes PNG öffnet sich im Bildbetrachter, ein DOCX in Word, ein ZIP lässt sich entpacken. Jedes wird vor der Auslieferung mit unabhängigen Readern geprüft.

    +
  • +
  • +

    Ein Manifest, das ein Testorakel ist

    +

    Pfad, Größe, SHA-256, Format, Seed, Tool-Version - und was dein System mit der Datei tun soll.

    +
  • +
  • +

    Reproduzierbar

    +

    Gleiches Rezept und gleicher Seed, gleiche Bytes, auf jedem Rechner. Checke ein kleines YAML-Rezept ein statt großer binärer Fixtures.

    +
  • +
  • +

    Zwei Oberflächen, eine Engine

    +

    Eine Kommandozeile für die CI und ein Desktop-Fenster für exploratives Testen. Keine ist eine abgespeckte Version der anderen, und ein Test vergleicht sie Fähigkeit für Fähigkeit.

    +
  • +
  • +

    Komplett offline

    +

    Kein Konto, keine Cloud, keine Telemetrie, keine Update-Prüfung. In die Kommandozeilen-Binärdatei ist gar kein Netzwerkstack einkompiliert.

    +
  • +
+
+ +
+

Download

+

Wähle den Build für dein System

+

+ Entpacke das Archiv und starte es. tfg ist die Kommandozeile und tfg-gui + das Desktop-Fenster. Es gibt keinen Installer und nichts, was auf deinem Rechner hinzugefügt + werden müsste. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SystemKommandozeileDesktop-Fenster
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Was signiert ist und was nicht

+

+ Die Downloads für Windows und macOS sind signiert und starten daher ohne Warnung vor einem + unbekannten Entwickler. Die für Linux nicht, weil es unter Desktop-Linux nichts Vergleichbares + zum Signieren gibt. Jedes Archiv steht auf der Release-Seite in + verify-SHA256SUMS.txt, sodass du prüfen kannst, was du heruntergeladen hast. +

+
+ +

Kostenlos und Open Source, GPL-3.0. Keine Anmeldung nötig. Die Downloads für Windows und macOS sind signiert und starten ohne Warnung.

+
+ + +
+ + + + diff --git a/web/public/de/presets/empty-and-minimal/index.html b/web/public/de/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..8923dc01 --- /dev/null +++ b/web/public/de/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Kleinste gültige und leere Testdateien in jedem Format + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Leer und minimal

+

Kommt eine gültige Datei durch, die so klein ist, wie das Format es erlaubt?

+

+ Das Preset empty-and-minimal baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • eine gültige Datei, die als zu klein abgewiesen wird, weil die Prüfung Bytes zählt, statt sie zu lesen
  • +
  • eine leere Datei, die den Leser zum Absturz bringt, statt gemeldet zu werden
  • +
  • ein Bild mit einem Pixel Breite, das auf dem Weg zur Vorschau durch null teilt
  • +
  • ein Speicher, der null Bytes als fehlgeschlagenen Upload liest und immer wieder neu versucht
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show empty-and-minimal ausgibt:

+
+ + + + + + + +
Dateien28
Targets in seinem Rezept28
Gesamtgröße32 667 B
Formateavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.26
unspecifiedDas hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast.2
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--formatsFormat-IDs, durch Kommas getrennt, oder allallAus welchen Formaten das Set besteht. Mit all werden alle Formate dieses Builds verwendet, oder du nennst die, die dein System akzeptiert.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/de/presets/filename-handling/index.html b/web/public/de/presets/filename-handling/index.html new file mode 100644 index 00000000..95628413 --- /dev/null +++ b/web/public/de/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Problematische Dateinamen zum Testen - Unicode und Länge + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Umgang mit Dateinamen

+

Speichert, zeigt und liefert mein System einen Dateinamen korrekt, mit dem es nicht gerechnet hat?

+

+ Das Preset filename-handling baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • ein Name, der auf dem Bildschirm, in einem Log oder in einer Liste wie ein anderer aussieht
  • +
  • ein Name, der zwischen Upload und Speicherung abgeschnitten, gekürzt oder umgeschrieben wird
  • +
  • ein Längenlimit, das in Zeichen gezählt wird, obwohl der Speicher Bytes zählt
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show filename-handling ausgibt:

+
+ + + + + + + +
Dateien50
Targets in seinem Rezept50
Gesamtgröße51 200 B
Formatetxt
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.4
unspecifiedDas hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast.46
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--formateine Format-ID von der Formate-SeitetxtDas Format jeder Datei im Set. Es ist ein Flag des Tools selbst, das Preset gibt ihm nur einen Standardwert.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/de/presets/index.html b/web/public/de/presets/index.html new file mode 100644 index 00000000..c668bd3d --- /dev/null +++ b/web/public/de/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +Testdatei-Presets - fertige Sets für typische QA-Fragen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Testdatei-Presets, ein Set für jede Testfrage

+

+ Ein Preset ist ein ganzes Set aus Testdateien, das um eine Frage herum entworfen wurde, mit einem + Manifest, das beschreibt, wie dein System auf jede Datei reagieren soll. Du wählst die Frage, das + Tool baut das Set. Jedes Preset hat eine eigene Seite mit dem, was es meist findet, was im Set + steckt und welche Einstellungen es kennt. +

+ + + +
+

Worin unterscheidet sich ein Preset von einem Rezept?

+

+ Darunter gar nicht. Ein Preset ist ein Rezept, das das Tool aus ein paar Einstellungen für dich + schreibt. tfg preset eject gibt dieses Rezept aus, damit du es neben deinen Tests + aufbewahren und bearbeiten kannst, und ein eigenes Rezept kann mit einer Zeile auf einem Preset + aufbauen, extends: preset: gefolgt von seiner ID. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Kann ich den Standardwerten trauen?

+

+ Bei den Dateien ja. Bei einer Zahl, die nur dein System kennt, etwa dem Limit eines + Upload-Formulars, ist ein Standardwert ein Platzhalter von uns, und das Tool sagt es jedes Mal, + wenn es einen verwendet. Die Seite jedes Presets markiert diese Einstellungen, und tfg + preset show sagt es, bevor etwas geschrieben wird. +

+
+ +
+ + + + diff --git a/web/public/de/presets/size-boundaries/index.html b/web/public/de/presets/size-boundaries/index.html new file mode 100644 index 00000000..d9266d9e --- /dev/null +++ b/web/public/de/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Upload-Größenlimit testen - Dateien an der exakten Grenze + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Größengrenzen

+

Wird ein Größenlimit genau dort durchgesetzt, wo es angegeben ist?

+

+ Das Preset size-boundaries baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • Off-by-one-Fehler am Limit
  • +
  • MB mit MiB verwechselt, was 4,8 Prozent ausmacht und reicht, um eine Datei durchzulassen, die nicht durchkommen dürfte
  • +
  • ein Limit, das im Browser durchgesetzt wird und nicht auf dem Server
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show size-boundaries ausgibt:

+
+ + + + + + + +
Dateien7
Targets in seinem Rezept7
Gesamtgröße73 400 320 B
Formatepdf
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.4
rejectDein System soll die Datei abweisen.3
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--limiteine Größe wie 2mb10mbDas Größenlimit, das dein System angibt. Alles andere wird von hier aus gemessen. Dieser Standardwert ist unser Platzhalter, nicht der Wert deines Systems. Gib deinen eigenen an.
--spreadGrößen, durch Kommas getrennt1B,1kb,1mbWie weit auf beiden Seiten des Limits gegangen wird, als Liste von Größen.
--formateine Format-ID von der Formate-SeitepdfDas Format jeder Datei im Set. Es ist ein Flag des Tools selbst, das Preset gibt ihm nur einen Standardwert.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

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

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/de/presets/tabular-import/index.html b/web/public/de/presets/tabular-import/index.html new file mode 100644 index 00000000..f5b481f9 --- /dev/null +++ b/web/public/de/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Testdateien für CSV- und Excel-Import - Trennzeichen, Kopfzeilen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Tabellenimport

+

Übersteht mein Tabellenimport das, was echte Tools exportieren?

+

+ Das Preset tabular-import baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • eine CSV-Datei mit Semikolon, die als eine Spalte gelesen wird, weil das Trennzeichen angenommen statt gesucht wurde
  • +
  • eine CRLF-Datei, die in Zeilen mit einer leeren Zeile nach jeder zerlegt wird
  • +
  • eine Tabelle ohne Kopfzeile, deren erste Datenzeile als Spaltennamen verschluckt wird
  • +
  • ein Import, der die Spalten behält, die er anzeigen kann, und den Rest kommentarlos verwirft
  • +
  • ein Leser, der JSON-Datensätze Zeile für Zeile liest und beim ersten eingerückten Dokument aufgibt
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show tabular-import ausgibt:

+
+ + + + + + + +
Dateien13
Targets in seinem Rezept13
Gesamtgröße3 080 060 B
Formatecsv, json, xlsx
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.8
unspecifiedDas hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast.5
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--rows1 - 200000 Zeilen1000Wie viele Zeilen die Tabelle enthält. Die Datei wird in genau der Größe geschrieben, auf die sich so viele Zeilen verpacken lassen, daher verschiebt sich das Budget oben mit diesem Wert.
--columns1 - 32768 Spalten10Wie viele Spalten jede Zeile der Tabelle hat. Zeilen mal Spalten hat eine Obergrenze, und wer darüber hinausgeht, wird abgewiesen, bevor etwas geschrieben wird.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/de/presets/text-encoding/index.html b/web/public/de/presets/text-encoding/index.html new file mode 100644 index 00000000..f73ea99f --- /dev/null +++ b/web/public/de/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Testdateien für Textkodierung - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Textkodierung

+

Weiß mein Leser, in welcher Kodierung eine Datei vorliegt, oder rät er?

+

+ Das Preset text-encoding baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • ein Leser, der UTF-8 annimmt und eine UTF-16-Datei als jedes dritte Zeichen oder als Reihen von Kästchen anzeigt
  • +
  • eine Byte Order Mark, die als Inhalt gelesen wird, sodass das erste Feld eines Imports mit drei fremden Zeichen beginnt
  • +
  • ein Importer, der die Kodierung aus den ersten Bytes errät und bei einer längeren Datei anders rät
  • +
  • eine CRLF-Datei, die in Zeilen mit einer leeren Zeile nach jeder zerlegt wird, oder ein Wagenrücklauf, der im letzten Feld stehen bleibt
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show text-encoding ausgibt:

+
+ + + + + + + +
Dateien20
Targets in seinem Rezept20
Gesamtgröße81 920 B
Formatecsv, log, md, txt, xml
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.10
unspecifiedDas hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast.10
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--sampleeine Größe wie 2mb4kbWie groß jede Datei des Sets ist. UTF-16 speichert zwei Bytes pro Zeichen, daher wird eine ungerade Zahl abgewiesen.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/de/presets/upload-validation/index.html b/web/public/de/presets/upload-validation/index.html new file mode 100644 index 00000000..db8e5d6d --- /dev/null +++ b/web/public/de/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Testdateien für die Upload-Validierung - Typ, Größe und Name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Upload-Validierung

+

Nimmt mein Upload-Formular an, was es soll, und weist den Rest ab?

+

+ Das Preset upload-validation baut mit einem Befehl ein ganzes Set echter Testdateien für diese + Frage und ein manifest.json daneben, das beschreibt, wie dein System auf jede Datei + reagieren soll. Alles unten wird aus dem Programm gelesen, mit den Standardwerten dieser Version. +

+ + +
+

Was findet es meistens?

+
    +
  • ein Limit, das im Browser durchgesetzt wird und nicht auf dem Server
  • +
  • eine SVG- oder HTML-Datei, die für ein Bild oder für einfachen Text gehalten wird, womit sich ein Skript an einem Formular vorbeischleusen lässt
  • +
  • eine Datei, die nur an der Endung geprüft und nie geöffnet wird, sodass ein PDF namens .jpg durchgeht
  • +
  • ein Formular, das den ganzen Body in den Speicher liest, bevor es nachsieht, wie groß er ist
  • +
  • ein Upload namens PHOTO.JPG, der abgewiesen wird, während photo.jpg durchkommt, oder umgekehrt
  • +
  • ein Name mit Leerzeichen, Klammern oder Zeichen außerhalb von ASCII, der unverändert auf die Platte geschrieben wird
  • +
+
+ + +
+

Was steckt im Set?

+

Mit den Standardwerten, wie es tfg preset show upload-validation ausgibt:

+
+ + + + + + + +
Dateien71
Targets in seinem Rezept22
Gesamtgröße120 639 488 B
Formatehtml, jpg, pdf, png, svg, txt
+
+

Und was das Manifest dieses Sets von deinem System erwartet:

+
+ + + + + + + + + +
ErwartetBedeutungDateien
acceptDein System soll die Datei annehmen.56
rejectDein System soll die Datei abweisen.10
unspecifiedDas hängt von den Regeln deines Systems ab. Du entscheidest, dann prüfst du, ob das Ergebnis dem entspricht, was du gemeint hast.5
+
+
+ +
+

Was kannst du ändern?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EinstellungNimmtStandardWas es tut
--limiteine Größe wie 2mb10mbDas Größenlimit, das dein Upload-Formular angibt. Dieses Set geht je einen Schritt auf beiden Seiten davon - für eine Datei in jedem Abstand führe das Preset size-boundaries aus. Dieser Standardwert ist unser Platzhalter, nicht der Wert deines Systems. Gib deinen eigenen an.
--allowFormat-IDs, durch Kommas getrenntjpg,png,pdfWelche Typen dein Formular akzeptieren soll. Jeder wird zu einer echten Datei dieses Typs, und sie sind die positive Kontrolle des ganzen Sets.
--denyEndungen, durch Kommas getrenntsvg,html,exe,shWelche Endungen dein Formular abweisen soll. Für eine Endung, zu der dieser Build kein Format hat, wird trotzdem eine Datei mit diesem Namen geschrieben, die einfachen Text enthält.
--far-over10x, 2x, off2xWie weit über dem Limit die eine große Datei liegt. Schalte sie ab, wo es das Vielfache des Limits auf der Platte nicht wert ist.
--bulk0 - 10000 Dateien50Wie viele Dateien der Massen-Upload enthält. Bei null fällt diese Gruppe ganz aus dem Set.
+
+
+ +
+

Wie führst du es aus?

+

Sieh nach, was das Set kosten würde, baue es oder nimm sein Rezept zum Bearbeiten:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Oder baue in einem eigenen Rezept darauf auf, neben deinen Tests:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/de/testdateien-in-ci/index.html b/web/public/de/testdateien-in-ci/index.html new file mode 100644 index 00000000..f7ab3a33 --- /dev/null +++ b/web/public/de/testdateien-in-ci/index.html @@ -0,0 +1,382 @@ + + + + + + +Testdateien in CI - GitHub Actions, GitLab CI und PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Anwendungsfälle

+

So erzeugen Sie Testdateien in einer CI-Pipeline

+

+ Ein binäres Fixture in einem Repository bleibt für immer in dessen Verlauf, lässt sich in einem Diff + nicht prüfen und geht bei großen Dateien gar nicht mehr. Erzeugen Sie die Dateien stattdessen in + der Pipeline aus einem Rezept. Das Rezept ist Text, die Bytes sind jedes Mal dieselben, und ein + letzter Schritt beweist, dass sich nichts verändert hat. +

+ +
+

Die kurze Antwort

+

+ Installieren Sie tfg, führen Sie vor den Tests tfg generate fixtures.yaml --out + ./fixtures aus und danach tfg verify ./fixtures/manifest.json. Beide + Schritte lassen den Build von selbst scheitern, mit einem Exit-Code, der sagt, warum. +

+
+ +
+

Warum nicht einchecken

+

Warum ein Fixture nicht im Repository liegen sollte

+
    +
  • + Es bleibt im Verlauf. Eine Binärdatei später zu löschen macht einen Klon nicht + kleiner, denn jede ihrer Versionen ist weiterhin da. +
  • +
  • + Ein Diff zeigt nicht, was sich geändert hat. Der Reviewer sieht, dass eine PDF + anders ist, und sonst nichts. Ein Rezept ändert sich um eine Zeile. +
  • +
  • + Große Dateien passen nicht. GitHub lehnt einen Push mit einer Datei über 100 MB ab, + also gibt es für den Test eines Upload-Limits von 500 MB nichts einzuchecken. +
  • +
+

+ Einzuchecken ist das Rezept. Dasselbe Rezept mit demselben Seed schreibt auf jeder Maschine + dieselben Bytes, die in der Pipeline erzeugte Datei ist also die Datei, die Sie auf dem Laptop + hatten. +

+
+ +
+

Das Rezept

+

Ein Rezept, das neben den Tests liegt

+

+ Dieses schreibt fünfundzwanzig Rechnungen, die angenommen werden sollen, und zwei Bilder über einem + Limit, die abgewiesen werden sollen, und das Manifest hält beide Erwartungen fest: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml prüft es, ohne etwas zu schreiben, und nennt jedes Problem + auf einmal. +

+
+ +
+

GitHub Actions

+

Ein Workflow, der das Tool installiert und die Fixtures erzeugt

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Die Prüfsummenzeile vergleicht das Archiv mit verify-SHA256SUMS.txt aus demselben + Release. Die Version ist festgelegt, ein neues Release ändert also nie einen Build, den Sie + nicht angefasst haben. +

+
+ +
+

GitLab CI

+

Dasselbe als GitLab-Job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Wenn es rot wird

+

Was einen Schritt scheitern lässt, und warum

+

+ Jedes Ende hat seinen eigenen Exit-Code, der Schritt scheitert also von selbst, und das Log sagt, + welcher es war. Die, denen eine Pipeline begegnet: +

+
    +
  • 3 - das Rezept ist ungültig. Es wurde nichts geschrieben, und jedes Problem wird genannt
  • +
  • 4 - das Format kann nicht, was verlangt wurde, zum Beispiel eine Größe unter seinem Minimum
  • +
  • 6 - es ist nicht genug Speicherplatz da
  • +
  • 7 - tfg verify hat eine Datei gefunden, die nicht zu ihrem Manifest passt
  • +
  • 8 - der Lauf ist fertig, aber nicht alles wurde erzeugt
  • +
+

+ Ein fehlgeschlagener Lauf gibt nichts auf der Standardausgabe aus, sodass ein Log-Parser nie einen + Fehler für Daten hält. Die ganze Tabelle steht auf der + Dokumentationsseite. +

+
+ +
+

PowerShell

+

Ein PowerShell-Skript braucht eine Zeile mehr

+

+ PowerShell trägt den Exit-Code eines Programms nicht aus einer .ps1-Datei heraus. + Starten Sie eine mit -File, und das Skript antwortet 0, auch wenn das + Tool darin die Arbeit verweigert hat, sodass ein Build, der rot sein sollte, grün wird. Die + letzte Zeile ist die ganze Lösung: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ So verhält sich PowerShell, es liegt nicht an diesem Tool. cmd, bash und + zsh brauchen nichts zusätzlich. +

+
+ +
+

Mehrere Jobs

+

Fixtures zwischen Jobs teilen

+

+ Hochladen ist meist nicht nötig. Weil dasselbe Rezept dieselben Bytes schreibt, kann jeder Job sein + eigenes tfg generate ausführen, und das geht schneller als Hoch- und Herunterladen. + Muss ein Job Dateien von einem anderen erhalten, führen Sie nach der Übertragung tfg + verify auf dem Manifest aus, und es sagt, ob das Angekommene dem Geschriebenen + entspricht. +

+
+ +
+

Weiter

+

Wohin es von hier geht

+ +
+ +
+ + + + diff --git a/web/public/docs/index.html b/web/public/docs/index.html index 4b661efc..41188062 100644 --- a/web/public/docs/index.html +++ b/web/public/docs/index.html @@ -3,15 +3,36 @@ + Documentation - Commands, Recipes, Manifest, Exit Codes + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
@@ -171,6 +238,9 @@

How do I make a file that is broken on purpose?

dropped rather than written - the run carries on, says which file it was, and ends with the partial exit code.

+

+ Step by step, with a test that reads the manifest: how to make a corrupt file for testing. +

@@ -426,6 +496,9 @@

What do the exit codes mean?

A run stopped with Ctrl+C still leaves a manifest and never leaves a half written file behind, so a cancelled job can still be cleaned up by the next one.

+

+ Ready workflows for GitHub Actions and GitLab CI: how to generate test files in a CI pipeline. +

diff --git a/web/public/es/archivos-de-prueba-corruptos/index.html b/web/public/es/archivos-de-prueba-corruptos/index.html new file mode 100644 index 00000000..eff8fb9e --- /dev/null +++ b/web/public/es/archivos-de-prueba-corruptos/index.html @@ -0,0 +1,382 @@ + + + + + + +Archivos de prueba corruptos - archivos rotos de tamaño exacto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casos de uso

+

Cómo crear un archivo corrupto para pruebas

+

+ Un validador al que solo se le han mostrado archivos sanos no está realmente probado. Así se + consigue un archivo roto a propósito, que sale con exactamente el tamaño que + pides y trae un manifiesto que dice qué debe hacer tu sistema con él. +

+ +
+

La respuesta corta

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out escribe un PNG de + exactamente 2097152 bytes cuyos primeros bytes son ceros, y el manifiesto que lo acompaña + registra que tu sistema debe rechazarlo. +

+
+ +
+

La forma habitual

+

Por qué un archivo corrompido a mano es una mala prueba

+

+ Lo habitual es un editor hexadecimal, un script que cambia unos cuantos bytes al azar o cortar un + archivo con head o truncate. Funciona una vez y después sale caro: +

+
    +
  • + Es distinto cada vez. Un byte al azar cae en un sitio nuevo en cada ejecución, así + que un fallo del martes puede no volver el miércoles. +
  • +
  • + Cambia el tamaño. Un archivo cortado es más pequeño que el límite bajo el que debía + quedar, de modo que la comprobación de tamaño responde antes que la del contenido y la prueba + pasa por el motivo equivocado. +
  • +
  • + A menudo pasa inadvertido. El texto plano se sigue leyendo con un byte cambiado en + medio, y un lector de imágenes indulgente simplemente lo dibuja, así que el archivo que debía + estar roto se acepta. +
  • +
  • + No dice nada de lo que debe ocurrir. El archivo son solo bytes, y quien lea la + prueba después tiene que adivinar si se quería la aceptación o el rechazo. +
  • +
+
+ +
+

Lo que obtienes

+

Un archivo dañado conserva el tamaño que pediste

+

+ El archivo se genera con normalidad y se rompe después, de camino al disco. Conserva el tamaño que + pediste, y el mismo comando vuelve a escribir los mismos bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Los ajustes van después de dos puntos. La opción se puede repetir, y los daños se aplican en el + orden en que los escribes. Funciona con cada uno de los 26 formatos. +

+
+ +
+

Lo que puede hacer

+

¿Qué daños hay?

+

+ Esta es la lista que imprime el programa, leída de él al construir esta página. tfg + damage imprime la misma, y tfg damage <id> dice qué admite cada uno. +

+
+ + + + + + + + + + + + + + + + + +
DañoQué hace con los bytesArchivo más pequeñoAjustes
zero-headSobrescribe los primeros bytes del archivo con ceros sin tocar su longitud. La mayoría de los lectores miran ahí primero, así que casi todo nota este daño.8bytes
+
+

+ zero-head escribe ceros sobre el comienzo del archivo. La mayoría de los lectores miran + ahí primero, la firma y la cabecera que dicen qué es el archivo, así que casi cualquier lector + lo nota. El texto plano y los registros no tienen firma y también se rechazan, porque una serie + de bytes nulos no es texto. Por debajo de cuatro bytes algunos formatos salen con un daño del + que ningún lector se queja, por eso el ajuste empieza en cuatro. +

+
+ +
+

Lo que dice el manifiesto

+

Un manifiesto que dice lo que debe ocurrir

+

+ Cada archivo dañado recibe una entrada que dice que tu sistema debe rechazarlo, con el daño anotado + al lado: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Se rechazan dos peticiones antes de escribir nada, porque cada una dejaría en el disco un archivo + que el manifiesto describe mal: +

+
    +
  • un archivo más pequeño de lo que el daño necesita, que saldría intacto
  • +
  • + expected: accept junto a un daño, porque nada podría cumplirlo. Escribe + sanitize si tu sistema debe reparar el archivo, o unspecified si esa + es justo la pregunta que haces +
  • +
+
+ +
+

En una receta

+

Archivos sanos y rotos en una sola ejecución

+

+ Pon ambos en una receta y el manifiesto lleva lo esperado de cada archivo, así que la prueba no + necesita una lista de cuál es cuál: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

En una prueba

+

Convertirlo en una prueba

+

+ La prueba lee el manifiesto y comprueba que lo ocurrido es lo declarado. No necesita una lista de + nombres de archivo: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un buen rechazo es un rechazo limpio. Un mensaje que dice qué estaba mal es la respuesta que + quieres. Un error de servidor, un bloqueo o un archivo guardado a medias es el defecto que esta + prueba existe para encontrar. +

+
+ +
+

Siguiente

+

A dónde ir desde aquí

+ +
+ +
+ + + + diff --git a/web/public/es/archivos-de-prueba-en-ci/index.html b/web/public/es/archivos-de-prueba-en-ci/index.html new file mode 100644 index 00000000..1d6dd8bd --- /dev/null +++ b/web/public/es/archivos-de-prueba-en-ci/index.html @@ -0,0 +1,380 @@ + + + + + + +Archivos de prueba en CI - GitHub Actions, GitLab CI y PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casos de uso

+

Cómo generar archivos de prueba en un pipeline de CI

+

+ Un fixture binario en un repositorio se queda para siempre en su historial, no se puede revisar en + un diff y deja de ser posible cuando el archivo es grande. Genera los archivos dentro del pipeline + a partir de una receta. La receta es texto, los bytes salen iguales cada vez y un último paso + demuestra que nada se movió. +

+ +
+

La respuesta corta

+

+ Instala tfg, ejecuta tfg generate fixtures.yaml --out ./fixtures antes de + las pruebas y tfg verify ./fixtures/manifest.json después. Los dos pasos hacen + fallar la compilación por sí solos, con un código de salida que dice por qué. +

+
+ +
+

Por qué no subirlos

+

Por qué un fixture no debe vivir en el repositorio

+
    +
  • + Se queda en el historial. Borrar un binario más tarde no hace más pequeño un clon, + porque todas sus versiones siguen ahí. +
  • +
  • + Un diff no muestra qué cambió. El revisor ve que un PDF es distinto y nada más. Una + receta cambia en una línea. +
  • +
  • + Los archivos grandes no caben. GitHub rechaza un push que contenga un archivo de + más de 100 MB, así que una prueba de un límite de subida de 500 MB no tiene nada que subir. +
  • +
+

+ Lo que hay que subir es la receta. La misma receta y la misma semilla escriben los mismos bytes en + cualquier máquina, así que el archivo generado en el pipeline es el que tenías en tu portátil. +

+
+ +
+

La receta

+

Una receta que vive junto a las pruebas

+

+ Esta escribe veinticinco facturas que deben aceptarse y dos imágenes por encima de un límite que + deben rechazarse, y el manifiesto registra las dos expectativas: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la comprueba sin escribir nada y nombra todos los problemas + a la vez. +

+
+ +
+

GitHub Actions

+

Un workflow que instala la herramienta y construye los fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La línea de la suma de comprobación compara el archivo con verify-SHA256SUMS.txt de la + misma versión. La versión está fijada, así que una versión nueva nunca cambia una compilación + que no tocaste. +

+
+ +
+

GitLab CI

+

Lo mismo como job de GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Cuando se pone en rojo

+

Qué hace fallar un paso, y por qué

+

+ Cada final tiene su propio código de salida, así que el paso falla por sí solo y el registro dice + cuál fue. Los que encuentra un pipeline: +

+
    +
  • 3 - la receta no es válida. No se escribió nada y se nombra cada problema
  • +
  • 4 - el formato no puede hacer lo pedido, por ejemplo un tamaño por debajo de su mínimo
  • +
  • 6 - no hay suficiente espacio en disco
  • +
  • 7 - tfg verify encontró un archivo que no coincide con su manifiesto
  • +
  • 8 - la ejecución terminó, pero no se produjo todo
  • +
+

+ Una ejecución fallida no imprime nada en la salida estándar, así que un analizador de registros + nunca toma un error por datos. La tabla completa está en la + página de documentación. +

+
+ +
+

PowerShell

+

Un script de PowerShell necesita una línea más

+

+ PowerShell no saca el código de salida de un programa fuera de un archivo .ps1. Ejecuta + uno con -File y el script responde 0 incluso cuando la herramienta de + dentro rechazó el trabajo, así que una compilación que debería estar en rojo pasa a verde. La + última línea es toda la solución: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Así se comporta PowerShell, no es algo de esta herramienta. cmd, bash y + zsh no necesitan nada más. +

+
+ +
+

Varios jobs

+

Compartir los fixtures entre jobs

+

+ Normalmente no hace falta subirlos. Como la misma receta escribe los mismos bytes, cada job puede + ejecutar su propio tfg generate, que es más rápido que subir y bajar. Cuando un job + tiene que recibir archivos de otro, ejecuta tfg verify sobre el manifiesto tras la + transferencia y te dice si lo que llegó es lo que se escribió. +

+
+ +
+

Siguiente

+

A dónde ir desde aquí

+ +
+ +
+ + + + diff --git a/web/public/es/casos-de-uso/index.html b/web/public/es/casos-de-uso/index.html new file mode 100644 index 00000000..35d2c2f4 --- /dev/null +++ b/web/public/es/casos-de-uso/index.html @@ -0,0 +1,320 @@ + + + + + + +Casos de uso - límites de subida, fixtures, pruebas masivas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Para qué lo usa la gente

+

+ Cinco tareas que aparecen en casi todos los proyectos que aceptan archivos de personas, y el comando + que hace cada una. Cada ejemplo de abajo se ejecuta tal como está escrito. +

+ +
+

Límites de subida

+

Probar si un límite de tamaño de archivo se aplica donde dice que se aplica

+

+ Un límite son tres casos de prueba, no uno: justo por debajo, exactamente en él y justo por encima. + Conseguirlos a mano significa calcular números de bytes y esperar no haberte equivocado en uno. + Pide el conjunto en su lugar: +

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

+ Obtienes tres PDF reales de 1048575, 1048576 y 1048577 bytes, y un manifiesto que dice que los dos + primeros deben aceptarse y el tercero rechazarse por size_limit. Tu prueba lee la + expectativa en lugar de que escribas tres aserciones a mano - y cuando cambia el límite, cambias + un número y vuelves a ejecutar. +

+

+ Lo mismo funciona sin preset cuando quieres un único conjunto de límites en línea: +

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

Integración continua

+

Mantener los fixtures fuera del repositorio sin perderlos

+

+ Los fixtures binarios grandes hacen lento clonar un repositorio y incómodo revisarlo, y nadie puede + decir qué cambió cuando se sustituye uno. Una receta son unos cientos de caracteres de YAML que + reconstruyen los archivos idénticos - byte a byte, en cualquier máquina - + porque cada archivo se deriva de la semilla de la ejecución. +

+
- 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
+

+ Cada final tiene su propio código de salida, así que una canalización puede distinguir una receta + mala de un disco lleno y de una discrepancia de verificación. Una ejecución fallida no imprime + nada en la salida estándar, lo que evita que un analizador de registros lea un error como datos. +

+
+ +
+

Escala

+

Descubrir qué pasa cuando la carpeta es grande

+

+ Las rutinas de importación, los trabajos nocturnos y los listados de directorios se comportan + distinto con diez mil archivos que con diez. Los tamaños sacados de un intervalo hacen que el + conjunto parezca tráfico real en lugar de diez mil archivos idénticos, y el sorteo viene de la + semilla, así que el conjunto es el mismo mañana. +

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

+ Comprueba cuánto costaría una ejecución antes de que escriba nada, lo que importa cuando el total se + mide en gigabytes: +

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

+ Una ejecución mayor que el espacio libre del disco se rechaza antes de escribir el primer byte, en + lugar de llenar el disco y fallar a medias. +

+
+ +
+

Archivos comprimidos

+

Probar un descompresor con un archivo comprimido que de verdad contiene archivos

+

+ Un archivo comprimido vacío con la extensión correcta no demuestra nada sobre el código que lo abre + y recorre lo que hay dentro. Declara el contenido y el archivo comprimido lo contiene de verdad: +

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

+ La profundidad de anidamiento, el número de entradas y el tamaño de lo que hay dentro son cosas + sobre las que una rutina de importación tiene opiniones, y así descubres cuáles son. +

+
+ +
+

Analizadores y visores

+

Comprobar que tu propio código lee un formato como lo hace el software real

+

+ Cada formato de aquí se comprueba con un lector independiente antes de publicarse - un PNG se abre y + se comparan sus píxeles, un DOCX lo vuelven a leer bibliotecas distintas, un archivo comprimido + se extrae. Eso significa que un archivo que tu analizador rechaza es un hallazgo sobre tu + analizador, no sobre el generador. +

+
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
+

+ La página de formatos lista los ajustes que admite cada uno y el archivo + más pequeño que puede ser cada uno. +

+
+ +
+

Guías

+

Dos de ellos con más detalle

+
    +
  • + Archivos de prueba corruptos - un archivo roto a + propósito, con el tamaño exacto y con lo que debe ocurrirle escrito en el manifiesto. +
  • +
  • + Archivos de prueba en CI - un workflow de GitHub + Actions, un job de GitLab y los códigos de salida que hacen fallar una compilación. +
  • +
+
+ +
+

Para quién es

+

+ Ingenieros de QA, automatización de pruebas y cualquiera cuyo código tenga detrás un formulario de + subida, una rutina de importación, un analizador o una cuota de almacenamiento. Funciona en una + máquina sin red alguna, lo que importa en un entorno corporativo cerrado donde un generador + basado en navegador no es una opción. +

+ +

Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.

+
+ +
+ + + + diff --git a/web/public/es/crear-archivo-de-tamano-exacto/index.html b/web/public/es/crear-archivo-de-tamano-exacto/index.html new file mode 100644 index 00000000..e4ae0bb7 --- /dev/null +++ b/web/public/es/crear-archivo-de-tamano-exacto/index.html @@ -0,0 +1,331 @@ + + + + + + +Crear un archivo de un tamaño exacto - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cómo crear un archivo de un tamaño exacto

+

+ Cada sistema tiene un comando para ello, y los tres están abajo. Te dan un archivo con exactamente + el número correcto de bytes - y para muchas pruebas eso es todo lo que necesitas. Cada + comando de esta página se ejecutó antes de publicarse, en el sistema al que pertenece. +

+ +
+

La respuesta corta

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Los tamaños son en bytes, y 10 MB + contados como los cuenta tu gestor de archivos son 10485760. +

+
+ +
+

Windows

+

fsutil, y una versión de PowerShell que no necesita nada extra

+

+ fsutil viene con Windows. Toma el tamaño en bytes, así que calcula + antes el número - 10 MB son 10485760, 100 MB son 104857600, 1 GB es 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Medido en Windows 11: funciona desde un símbolo del sistema normal sin necesitar uno elevado, y el + archivo sale con exactamente 10485760 bytes. +

+

PowerShell puede hacer lo mismo sin llamar a otro programa, y entiende unidades:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB en PowerShell significa 10485760 bytes, el mismo recuento en base 1024 que usa el + Explorador, así que los dos comandos anteriores producen el mismo tamaño. +

+
+ +
+

Linux

+

dd, truncate y fallocate, y la diferencia que pilla a la gente

+

dd es el que todo el mundo conoce. Escribe los bytes de verdad:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate es instantáneo, y esa es la trampa. Medido en Alpine Linux, el archivo informa + de 10485760 bytes y ocupa cero bloques - es un archivo + disperso. Cualquier cosa que lo lea obtiene diez megabytes de ceros, pero el disco + nunca cedió el espacio: +

+
truncate -s 10M test10mb.bin
+

+ Eso sirve para probar un límite de subida y engaña para probar una cuota de disco. + fallocate es el que hay que usar cuando el espacio tiene que ser real: +

+
fallocate -l 10M test10mb.bin
+

Y cuando el contenido tiene que ser incompresible, para que un compresor no pueda volver a reducirlo:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, que no es disperso, y los dos que ya conoces

+

+ macOS incluye mkfile. Medido en macOS 26.6.2: 10485760 bytes y 20480 bloques, así que + el espacio está realmente asignado en lugar de prometido: +

+
mkfile 10m test10mb.bin
+

dd y truncate también están y se comportan como en Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Dónde esto deja de funcionar

+

Un archivo del tamaño correcto no es un archivo del tipo correcto

+

+ Todo lo anterior te da un bloque de ceros. Eso basta cuando lo que se prueba solo mira el tamaño - + un límite de subida, una cuota, una transferencia. Deja de bastar en cuanto algo + abre el archivo. +

+

+ Medido, y merece la pena que lo hagas tú: crea un archivo de 2 MB con fsutil, llámalo + photo.png y pásaselo a una biblioteca de imágenes. Pillow responde cannot + identify image file. No es un PNG. Nunca lo fue - solo lo decía el nombre. +

+

+ Eso importa más de lo que parece, por la forma en que la prueba falla entonces. Tu + endpoint de subida rechaza el archivo, tu prueba se pone en verde y concluyes que el límite de + tamaño funciona. No lo rechazó por el tamaño. Lo rechazó porque los bytes no eran una imagen, y + la regla que querías probar nunca se alcanzó. +

+
    +
  • un analizador lo rechaza antes de mirar ninguna regla de tamaño
  • +
  • falla un paso de miniaturas y el error que lees trata de la miniatura
  • +
  • un antivirus o una comprobación de contenido lo rechaza por un tercer motivo
  • +
  • un visor no muestra nada, y nadie puede saber si ese es el fallo
  • +
+
+ +
+

La otra vía

+

Un archivo real de ese formato, con exactamente el tamaño que pediste

+

+ Esto es lo que hace Testing Files Generator. El archivo es uno genuino de su formato - se abre en el + programa que le corresponde - y tiene el número exacto de bytes que pediste, al byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Pide un tamaño que un formato no puede alcanzar y obtienes un error que nombra el suelo y su motivo, + nunca un archivo del tamaño equivocado. La página de formatos lista + cada formato con el archivo más pequeño que puede producir. +

+

Y un límite son tres casos de prueba y no uno, así que la herramienta construye los tres:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Eso te da 10485759, 10485760 y 10485761 bytes, y un manifiesto que dice cuáles debe aceptar tu + sistema y cuáles rechazar. La página de casos de uso repasa eso + y otras cuatro tareas para las que está pensada. +

+ +

Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.

+
+ +
+

Entonces, ¿cuál debes usar?

+
    +
  • +

    Usa el comando del sistema

    +

    + Cuando nada abre el archivo. Probar un límite de tamaño en un endpoint que comprueba antes el + tamaño, una transferencia, una cuota, un disco lleno. Es una línea y ya está instalado. +

    +
  • +
  • +

    Usa un generador real

    +

    + Cuando algo analiza, renderiza, importa o extrae el archivo - y cuando necesitas los mismos fixtures + mañana, en otra máquina, byte a byte. +

    +
  • +
+

+ Ambos están en esta página porque ambos aciertan parte del tiempo. El error que conviene evitar es + usar el primero donde hace falta el segundo y leer la prueba en verde como una demostración. +

+
+ +
+ + + + diff --git a/web/public/es/documentacion/index.html b/web/public/es/documentacion/index.html new file mode 100644 index 00000000..b7fb0e1f --- /dev/null +++ b/web/public/es/documentacion/index.html @@ -0,0 +1,558 @@ + + + + + + +Documentación - comandos, recetas, manifiesto, códigos de salida + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentación

+

+ Todo lo que hace la herramienta, ordenado según las preguntas con las que la gente llega de verdad. + El README del repositorio es la referencia completa y siempre + coincide con la versión que descargaste. +

+ +
+

¿Qué comandos hay?

+

Cada uno hace una sola cosa:

+
tfg generate    producir archivos, desde una receta o desde opciones
+tfg validate    comprobar una receta sin escribir nada
+tfg verify      comprobar un directorio contra un manifiesto
+tfg cleanup     eliminar los archivos que lista un manifiesto
+tfg recipe fmt  imprimir una receta en su forma normalizada
+tfg preset      construir un conjunto de archivos a partir de una pregunta de prueba con nombre
+tfg formats     listar los formatos que admite esta versión
+tfg damage      listar las formas en que esta versión puede romper un archivo a propósito
+tfg tool        pequeñas utilidades para archivos que ya tienes
+tfg version     imprimir la versión de la herramienta
+tfg license     imprimir la licencia y qué significa para los archivos generados
+
+ +
+

¿Cómo genero un único archivo de tamaño exacto?

+

+ Indica el formato, el tamaño y dónde va. Los tamaños cuentan de 1024 en 1024, así que + 2mb son 2097152 bytes. Un número de bytes simple también sirve, de modo que + --size 10485761 pide exactamente esa cantidad. +

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

Las opciones útiles de generate:

+
+ + + + + + + + + + + + + + + + + +
OpciónQué hace
--format <id>formato de los archivos, por ejemplo txt
--size <size>tamaño exacto de cada archivo, como 10mb o un número de bytes simple
--size-range <a-b>un tamaño sacado por archivo de un intervalo, como 1kb-8kb. El sorteo viene de la semilla
--boundary <size>tres archivos alrededor de un límite: un byte por debajo, el límite, un byte por encima
--count <n>cuántos archivos producir. Por defecto 1
--name <template>plantilla de nombre, por ejemplo invoice_{index:04}.txt
--out <dir>directorio donde escribir
--seed <n>semilla de la ejecución. La misma semilla da los mismos bytes
--set <k>=<v>un ajuste de formato, repetible
--damage <name>romper los archivos a propósito, repetible y aplicado en orden. Ejecuta tfg damage para ver la lista
--expected <outcome>accept, reject, sanitize o unspecified
--dry-runcontar y mostrar, sin escribir absolutamente nada
--jsonescribir el manifiesto en la salida estándar
+
+
+ +
+

¿Cómo hago un archivo roto a propósito?

+

+ Todos los demás archivos que escribe esta herramienta son correctos por construcción, lo que + responde a dos de las tres preguntas que hace un validador de subidas. --damage + responde a la tercera - si el archivo se abre siquiera. El archivo se produce con normalidad y + luego se rompe, así que conserva el tamaño que pediste. +

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

+ Los ajustes van después de dos puntos. La opción se repite, y el orden en que las escribes es el + orden en que se aplican. tfg damage lista lo que puede hacer esta versión y qué + admite cada una. +

+

En una receta la clave es una lista, de nombres o de ajustes:

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

+ Un archivo dañado recibe expected: reject en el manifiesto, con el daño registrado a su + lado. Dos cosas se rechazan antes de escribir nada, porque cada una dejaría en disco un archivo + que el manifiesto describe mal: +

+
    +
  • un archivo más pequeño de lo que necesita el daño, porque saldría sin cambios
  • +
  • + expected: accept junto a un daño, porque nada podría cumplirlo. Escribe + sanitize si el sistema bajo prueba debe reparar el archivo, o + unspecified si esa es la pregunta que haces +
  • +
+

+ Una tercera no se puede saber de antemano. Si un daño se ejecuta y no mueve ningún byte, ese archivo + se descarta en lugar de escribirse - la ejecución continúa, dice de qué archivo se trató y + termina con el código de salida parcial. +

+

+ Paso a paso, con una prueba que lee el manifiesto: cómo + crear un archivo corrupto para pruebas. +

+
+ +
+

¿Qué aspecto tiene una receta?

+

+ Una receta es un archivo YAML que describe una ejecución completa. Súbela al repositorio junto a tus + pruebas y los fixtures dejan de ser binarios en tu repositorio - cualquiera puede + reconstruirlos, byte a byte, a partir de un archivo de unos cientos de caracteres. +

+
# 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
+

+ Cada target necesita exactamente una de estas claves: size, size-range, + boundary o contains. Dos es un error y ninguna también. Una receta + inválida escribe ningún archivo e informa de todos los problemas a la vez en + lugar de solo del primero, cada uno nombrando el ajuste al que se refiere. +

+
+ +
+

¿Cómo declaro qué debe hacer mi sistema con un archivo?

+

Forma corta cuando basta con el resultado, forma larga cuando importa el motivo:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Los resultados son accept, reject, sanitize y + unspecified. Los motivos son una lista cerrada para que un informe pueda + agruparlos: 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 y size_zero. +

+

+ Un motivo nombra la regla en juego, no el veredicto. Por eso el mismo motivo puede + estar bajo cualquiera de los dos resultados - un archivo un byte por debajo de un límite es + accept, y la regla de la que trata sigue siendo size_limit. +

+
+ +
+

¿Qué hay en el manifiesto?

+

+ Se escribe junto a los archivos al final de cada ejecución, incluida una ejecución interrumpida. Una + entrada por archivo: +

+
{
+  "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 añade un recipe_hash cuando la ejecución viene de una receta, y preset + con overrides cuando viene de un preset, de modo que un manifiesto siempre se puede + rastrear hasta lo que lo produjo. +

+

+ Cada entrada lleva también target_id, el id del target de la receta que produjo el + archivo, y summary.by_target cuenta los archivos a los que llegó cada target. Una + receta con varios targets se puede comprobar así target por target sin leer nombres de archivo. +

+
+ +
+

¿Qué es un preset?

+

+ Un conjunto de archivos listo que responde a una pregunta de prueba habitual, para que no tengas que + diseñar el conjunto tú. Los presets son recetas normales por debajo, y eject + imprime la receta para que la edites desde ahí. Cada preset tiene una + página propia con lo que suele encontrar, qué hay en el conjunto y cada ajuste que admite. +

+
    +
  • +

    Vacío y mínimo

    +

    ¿Pasa un archivo válido y tan pequeño como permite el formato?

    +

    empty-and-minimal

    +
  • +
  • +

    Manejo de nombres de archivo

    +

    ¿Mi sistema guardará, mostrará y devolverá un nombre de archivo que no esperaba?

    +

    filename-handling

    +
  • +
  • +

    Límites de tamaño

    +

    ¿Se aplica un límite de tamaño exactamente donde se declara?

    +

    size-boundaries

    +
  • +
  • +

    Importación de tablas

    +

    ¿Sobrevive mi importación de tablas a lo que exportan las herramientas reales?

    +

    tabular-import

    +
  • +
  • +

    Codificación de texto

    +

    ¿Sabe mi lector en qué codificación está un archivo, o lo adivina?

    +

    text-encoding

    +
  • +
  • +

    Validación de subida

    +

    ¿Mi formulario de subida acepta lo que debe y rechaza el resto?

    +

    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 te dice cuánto costaría el conjunto antes de construirlo, y dice sin rodeos cuándo + un número es un marcador nuestro en lugar de un límite tuyo. +

+
+ +
+

¿Qué significan los códigos de salida?

+

+ Cada final tiene su propio código, la salida legible por máquina va a la salida estándar, y una + ejecución fallida no imprime nada allí. La tabla es un contrato congelado - cambiar lo que + significa un código exige una versión mayor. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CódigoSignificado
0Todo ha funcionado.
1Un error inesperado dentro de la herramienta.
2Comando u opción incorrectos.
3La receta no es válida.
4El formato no puede hacer lo que se pidió.
5Ha fallado una lectura o una escritura.
6No hay espacio suficiente en disco.
7verify ha encontrado una discrepancia.
8La ejecución terminó, pero no se produjo todo.
130Interrumpido con Ctrl+C.
143Detenido por una señal, que es el aspecto de un tiempo de espera agotado en 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
+

+ Una ejecución detenida con Ctrl+C sigue dejando un manifiesto y nunca deja un archivo a medio + escribir, así que un trabajo cancelado aún puede limpiarlo el siguiente. +

+

+ Workflows listos para GitHub Actions y GitLab CI: cómo + generar archivos de prueba en un pipeline de CI. +

+
+ +
+

¿Hay una ventana de escritorio?

+

+ Sí, el mismo motor con una ventana encima, para las pruebas que no se automatizan. No es una versión + recortada: una prueba compara las dos interfaces capacidad por capacidad, y todo lo que solo una + de ellas puede hacer debe declararse y justificarse en lugar de divergir en silencio. +

+

+ Las pantallas son un lote, presets, varios lotes a la vez y Acerca de. Muestra lo que costaría una + ejecución antes de escribir nada, informa del progreso mientras corre y se puede cancelar a + medias sin dejar un archivo a medio escribir. Todavía no abre un archivo de receta - por ahora + las recetas son cosa de la línea de comandos, y la ventana construye sus lotes en el formulario. +

+
+ +
+ + + + diff --git a/web/public/es/formatos/index.html b/web/public/es/formatos/index.html new file mode 100644 index 00000000..e57b912f --- /dev/null +++ b/web/public/es/formatos/index.html @@ -0,0 +1,913 @@ + + + + + + +26 formatos de archivo - PDF, DOCX, PNG, ZIP y más + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formatos de archivo, cada uno generado a un tamaño exacto

+

+ Cada uno es un archivo real de ese formato. Se abre en el programa que le + corresponde y tiene exactamente el número de bytes que pediste. Ninguno es relleno de ceros con + una extensión pegada. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoNombreExtensiónArchivo más pequeñoFidelidadComprobado con
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullno aplicable
mdMarkdown.md0fullno aplicable
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullno aplicable
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Qué significan las columnas

+
    +
  • +

    Archivo más pequeño

    +

    + Los menos bytes que esta herramienta aceptará para ese formato, incluida la etiqueta que escribe + dentro del archivo. Pide menos y obtienes un error que nombra el suelo y su motivo, nunca un + archivo del tamaño equivocado. +

    +
  • +
  • +

    Fidelidad

    +

    + Cuán completo es el archivo. full significa que lo acepta un lector que analiza de + verdad el formato, no solo que la extensión coincida. +

    +
  • +
  • +

    Comprobado con

    +

    + El lector independiente que abre cada archivo generado antes de que el formato se publique - una + implementación aparte, no nuestro propio código corrigiendo sus propios deberes. +

    +
  • +
+

+ Cada formato también se repite byte a byte: la misma receta y la misma semilla producen archivos + idénticos en cualquier máquina, y eso es lo que hace seguro subir al repositorio una receta en + lugar de los fixtures mismos. +

+
+ +
+

Ajustes que admite cada formato

+

+ La mayoría de los formatos tienen ajustes propios - dimensiones de imagen, calidad JPEG, número de + páginas de PDF, filas y columnas de una hoja de cálculo, cuántas entradas van dentro de un + archivo comprimido. Defínelos con --set key=value en la línea de comandos, o bajo + properties: en una receta. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoAjusteAdmite
avifwidth1 - 16384 píxeles
height1 - 16384 píxeles
quality1 - 100
bmpwidth1 - 20000 píxeles
height1 - 20000 píxeles
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerverdadero o falso
quote_styleall, minimal, none
columns2 - 32768 columnas
docxparagraphs1 - 50000 párrafos
gifwidth1 - 20000 píxeles
height1 - 20000 píxeles
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 píxeles
height1 - 256 píxeles
embedbmp, png
jpgwidth1 - 20000 píxeles
height1 - 20000 píxeles
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 píxeles
height1 - 16384 píxeles
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 entradas por segundo
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomverdadero o falso
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlecualquier texto
authorcualquier texto
subjectcualquier texto
keywordscualquier texto
creatorcualquier texto
producercualquier texto
createduna fecha como 2024-02-29 o 2024-02-29T13:45:00+02:00, o none
modifieduna fecha como 2024-02-29 o 2024-02-29T13:45:00+02:00, o none
pngwidth1 - 20000 píxeles
height1 - 20000 píxeles
pptxslides1 - 500 diapositivas
svgwidth1 - 20000 píxeles
height1 - 20000 píxeles
targzentries0 - 10000
entry_formatel id de un formato, tal como lo lista tfg formats
entry_sizeun tamaño como 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesverdadero o falso
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 píxeles
height1 - 20000 píxeles
txtencodingutf-16be, utf-16le, utf-8
bomverdadero o falso
wavsample_rate8000 - 192000 hercios
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 píxeles
height1 - 16383 píxeles
xlsxrows1 - 200000 filas
columns1 - 32768 columnas
xmlencodingutf-16be, utf-16le, utf-8
bomverdadero o falso
zipentries0 - 10000
entry_formatel id de un formato, tal como lo lista tfg formats
entry_sizeun tamaño como 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesverdadero o falso
passwordla contraseña, en texto plano
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Un valor fuera de lo que admite un ajuste se rechaza con un mensaje que nombra el ajuste, el + intervalo permitido y qué usar en su lugar. Un ajuste desconocido también es un error, nunca un + valor por defecto silencioso - una errata aceptada en silencio da un archivo con los ajustes + equivocados y una hora preguntándote por qué la prueba pasa cuando no debería. +

+

+ Ejecuta tfg formats <id> para ver exactamente qué admite un formato en la versión + que tienes. +

+
+ +
+

Los archivos comprimidos contienen archivos reales

+

+ targz y zip se + pueden llenar de entradas en lugar de quedar como un cascarón vacío. Un archivo comprimido + generado contiene de verdad los documentos que dice contener, así que todo lo que lo descomprima + durante una prueba encuentra archivos reales dentro. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/es/index.html b/web/public/es/index.html new file mode 100644 index 00000000..87652844 --- /dev/null +++ b/web/public/es/index.html @@ -0,0 +1,456 @@ + + + + + + +Generador de archivos de prueba - tamaño exacto, 26 formatos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Genera archivos de prueba reales al tamaño exacto

+

+ PDF, PNG, DOCX, ZIP - 26 formatos en total, y cada uno es un + archivo real que se abre en el programa que le corresponde, con exactamente el tamaño + que pediste. Cada ejecución también anota qué debe hacer tu aplicación con cada + archivo. Línea de comandos y ventana de escritorio, gratis y de código abierto, funcionando por + completo en tu máquina. +

+ + +

Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.

+
+ +
+ La ventana de escritorio de Testing Files Generator, lista para escribir un lote de archivos de prueba +
La ventana de escritorio, lista para escribir un lote de archivos. El mismo motor funciona detrás de la línea de comandos.
+
+
+ + + +
+

El problema

+

Hacer un archivo de prueba es fácil. Hacer los mil correctos es la parte tediosa

+

Estás probando software que acepta archivos de personas. Tarde o temprano necesitas:

+
    +
  • un PDF de exactamente 10 MB, para saber si el límite de subida es real
  • +
  • los tres archivos a ambos lados de ese límite, para cazar errores de uno
  • +
  • 10 000 archivos de registro, para ver qué hace el trabajo nocturno cuando la carpeta es grande
  • +
  • un ZIP que de verdad contiene 200 documentos, no un cascarón con la extensión correcta
  • +
  • un archivo de 4 GB, sin guardar un archivo de 4 GB en tu repositorio
  • +
  • los mismos fixtures en tu portátil y en el servidor de compilación, byte a byte
  • +
+

+ Eso es lo que esto sustituye. Está pensado para ingenieros de QA, automatización de pruebas y + cualquiera cuyo código tenga detrás un formulario de subida, una rutina de importación, un + analizador o una cuota de almacenamiento. +

+
+ +
+

Qué lo hace distinto

+

Otros generadores se quedan en los bytes. Este responde a lo que tu prueba realmente pregunta

+

+ Una carpeta de archivos te deja aún decidiendo qué se supone que demuestra cada uno. Cada ejecución + escribe aquí un manifest.json junto a los archivos - una lista simple de todo lo + producido y, para cada entrada, una expectativa declarada. +

+

Supón que tu endpoint de subida permite 1 MB. Pide los tres archivos que están sobre esa línea:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ArchivoBytesTu sistema debePorque
1mb_under_1b.pdf1048575aceptarestá dentro del límite
1mb_at_limit.pdf1048576aceptarel propio límite está permitido
1mb_over_1b.pdf1048577rechazarsize_limit
+
+ +

Tres archivos, tres respuestas distintas, en forma legible por máquina. Tu prueba lee el manifiesto en lugar de que escribas las aserciones a mano:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Donde la respuesta depende de tu propia política, el manifiesto lo dice

+

+ Registra unspecified en lugar de inventar una expectativa. Un generador que adivina + produce falsos fallos, y un conjunto de pruebas que da falsas alarmas acaba apagado. +

+
+
+ +
+

Presets

+

Elige la pregunta, obtén el conjunto entero

+

+ Un preset es un conjunto de archivos de prueba diseñado en torno a una pregunta de prueba, para que + no tengas que averiguar qué archivos demuestran qué. Cada uno tiene una página que dice qué + suele encontrar, qué hay en el conjunto y cada ajuste que admite. +

+
    +
  • +

    Vacío y mínimo

    +

    ¿Pasa un archivo válido y tan pequeño como permite el formato?

    +

    empty-and-minimal

    +
  • +
  • +

    Manejo de nombres de archivo

    +

    ¿Mi sistema guardará, mostrará y devolverá un nombre de archivo que no esperaba?

    +

    filename-handling

    +
  • +
  • +

    Límites de tamaño

    +

    ¿Se aplica un límite de tamaño exactamente donde se declara?

    +

    size-boundaries

    +
  • +
  • +

    Importación de tablas

    +

    ¿Sobrevive mi importación de tablas a lo que exportan las herramientas reales?

    +

    tabular-import

    +
  • +
  • +

    Codificación de texto

    +

    ¿Sabe mi lector en qué codificación está un archivo, o lo adivina?

    +

    text-encoding

    +
  • +
  • +

    Validación de subida

    +

    ¿Mi formulario de subida acepta lo que debe y rechaza el resto?

    +

    upload-validation

    +
  • +
+

Todos los presets, y cómo se relacionan con las recetas

+
+ +
+

Inicio rápido

+

Tres comandos para verlo funcionar

+
    +
  1. +

    Crea un archivo

    +

    Un PNG, exactamente dos megabytes:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Crea muchos archivos

    +

    + Diez mil archivos de registro, cada uno de entre uno y ocho kilobytes, con los tamaños sacados de la + semilla para que mañana dé el mismo conjunto. Dale a cada ejecución su propio + directorio - el manifiesto es el único registro de lo que escribió una ejecución, + así que la herramienta se niega a escribir un segundo encima: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Compruébalos y luego elimínalos

    +

    verify te dice que nada se movió. cleanup elimina exactamente lo que se escribió y nada más:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Los tamaños cuentan de 1024 en 1024, como hace tu gestor de archivos, así que 2mb + significa 2097152 bytes. Un número de bytes simple también sirve. La + documentación cubre las recetas, el manifiesto y los códigos de + salida. +

+
+ +
+

Qué obtienes

+

Pensado para un conjunto de pruebas que corre sin supervisión

+
    +
  • +

    Tamaño exacto, al byte

    +

    Pide 10485761 bytes y obtén exactamente eso. Un tamaño que un formato no puede alcanzar es un error con un motivo, nunca un archivo del tamaño equivocado.

    +
  • +
  • +

    26 formatos reales

    +

    No ceros de relleno con una extensión. Un PNG generado se abre en un visor de imágenes, un DOCX se abre en Word, un ZIP se extrae. Cada uno se comprueba con lectores independientes antes de publicarse.

    +
  • +
  • +

    Un manifiesto que es un oráculo de pruebas

    +

    Ruta, tamaño, SHA-256, formato, semilla, versión de la herramienta - y qué debe hacer tu sistema con el archivo.

    +
  • +
  • +

    Reproducible

    +

    Misma receta y misma semilla, mismos bytes, en cualquier máquina. Sube al repositorio una receta YAML pequeña en lugar de fixtures binarios grandes.

    +
  • +
  • +

    Dos interfaces, un motor

    +

    Una línea de comandos pensada para CI y una ventana de escritorio para pruebas exploratorias. Ninguna es una versión recortada de la otra, y una prueba las compara capacidad por capacidad.

    +
  • +
  • +

    Completamente sin conexión

    +

    Sin cuenta, sin nube, sin telemetría, sin comprobación de actualizaciones. El binario de la línea de comandos no lleva compilada ninguna pila de red.

    +
  • +
+
+ +
+

Descarga

+

Elige la versión para tu sistema

+

+ Descomprime el archivo y ejecútalo. tfg es la línea de comandos y tfg-gui + es la ventana de escritorio. No hay instalador ni nada que añadir a tu máquina. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemaLínea de comandosVentana de escritorio
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Qué está firmado y qué no

+

+ Las descargas de Windows y macOS están firmadas, así que se inician sin advertencia de desarrollador + desconocido. Las de Linux no, porque Linux de escritorio no tiene un equivalente con el que + firmarlas. Cada archivo aparece en verify-SHA256SUMS.txt en la página de + versiones, para que puedas comprobar lo que descargaste. +

+
+ +

Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.

+
+ + +
+ + + + diff --git a/web/public/es/preguntas-frecuentes/index.html b/web/public/es/preguntas-frecuentes/index.html new file mode 100644 index 00000000..999a0bb6 --- /dev/null +++ b/web/public/es/preguntas-frecuentes/index.html @@ -0,0 +1,350 @@ + + + + + + +Preguntas frecuentes - generar archivos de prueba + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Preguntas frecuentes

+

+ Licencia, privacidad, reproducibilidad y lo que la gente comprueba antes de poner un generador en + una canalización de compilación. Si tu pregunta no está aquí, el + gestor de incidencias está abierto. +

+ +
+
+

¿En qué se diferencia de dd, fsutil o truncate?

+
+

Esos comandos te dan un archivo del tamaño correcto lleno de nada. Un archivo de 2 MB llamado photo.png hecho así no es un PNG, de modo que cualquier cosa que lo analice de verdad lo rechaza por el motivo equivocado, y tu prueba también pasa por el motivo equivocado. Esto produce un PNG real de exactamente 2 MB que se abre en un visor de imágenes, y llega con una declaración de cómo debe tratarlo tu sistema.

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

¿Es gratis, y puedo usarlo en el trabajo?

+
+

Sí a ambas. Se publica bajo GPL-3.0 y no cuesta nada. No hay cuenta, ni clave de licencia, ni nivel de pago.

+
+
+
+

¿Puedo usar los archivos generados en un producto de código cerrado?

+
+

Sí. La licencia cubre el código de la herramienta, no lo que la herramienta produce. Los archivos, recetas y manifiestos generados son una salida y no obras derivadas, así que puedes subirlos al repositorio y distribuirlos sin ninguna obligación.

+
+
+
+

¿Contienen los archivos generados datos personales reales?

+
+

No. Todo lo que hay dentro se sintetiza a partir de una semilla. No se lee ningún conjunto de datos, no se contacta con ningún servicio y no se incrusta contenido de terceros. Trata una dirección de correo generada como inutilizable en lugar de como no usada, porque cualquier cadena aleatoria puede coincidir por casualidad con una real.

+
+
+
+

¿Obtendré exactamente los mismos archivos en otra máquina?

+
+

Sí, byte a byte, con la misma receta y la misma semilla. El proyecto lo prueba en cada cambio, y romperlo exige una versión mayor. Eso es lo que te permite subir al repositorio una receta pequeña en lugar de fixtures binarios grandes.

+
+
+
+

¿Necesita conexión a internet?

+
+

Nunca. No hay telemetría, ni comprobación de actualizaciones, ni cliente en la nube, y el binario de la línea de comandos no lleva compilada ninguna pila de red. Funciona en una máquina sin red y dentro de un entorno corporativo cerrado.

+
+
+
+

¿Qué pasa si pido un tamaño que un formato no puede alcanzar?

+
+

Obtienes un error que nombra el formato, lo más pequeño que puede ser, el motivo de ese suelo y qué hacer en su lugar, y no se escribe ningún archivo. La herramienta nunca redondea un tamaño en silencio. Cada suelo aparece en la página de formatos.

+
tfg formats png
+
+
+
+

¿Puedo generar un archivo deliberadamente roto?

+
+

Sí. Añade --damage zero-head y el archivo sale con exactamente el tamaño pedido, con sus primeros bytes sobrescritos por ceros, de modo que un lector lo rechaza, y el manifiesto dice que tu sistema debe rechazarlo. La página sobre archivos de prueba corruptos tiene los detalles.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

¿Qué formatos vienen después?

+
+

7z, mp3 y mp4. Hoy funcionan de principio a fin 26 formatos.

+
+
+
+

¿En qué sistemas puedo ejecutarlo?

+
+

La línea de comandos funciona en Windows y Linux, tanto en Intel como en ARM, y en Mac con Apple Silicon. La ventana de escritorio se entrega para Windows en Intel, Linux en Intel y Mac con Apple Silicon. Los Mac Intel no son compatibles y no se compila nada para ellos.

+
+
+
+

¿Tengo que instalar algo?

+
+

No. Descarga el archivo de tu sistema, descomprímelo y ejecuta el binario. No hay instalador, ni entorno de ejecución que añadir, ni dependencia que resolver. Si tienes Go, también sirve un único comando go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

¿Por qué una ejecución sobre miles de archivos es más lenta en Windows?

+
+

Porque Windows cobra más por cada ruta que mira, y un comando que recorre miles de archivos mira miles de rutas. Medido en una máquina con 3000 archivos de 1 kB, verify tarda unos 0,9 segundos en Windows y unos 0,2 segundos en Linux dentro de un contenedor. Una ruta de salida más corta reduce la cifra de Windows, porque cada carpeta por encima de los archivos forma parte de lo que se mira.

+
+
+
+ + +
+

¿Aún lo estás pensando?

+

+ La página de casos de uso muestra las tareas para las que está + pensada, y la página de formatos lista cada formato con el archivo + más pequeño que puede producir. El README del repositorio es la + referencia completa. +

+ +

Gratuito y de código abierto, GPL-3.0. Sin registro. Las descargas de Windows y macOS están firmadas y se inician sin advertencias.

+
+ +
+ + + + diff --git a/web/public/es/presets/empty-and-minimal/index.html b/web/public/es/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..38dabc90 --- /dev/null +++ b/web/public/es/presets/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +Archivos de prueba válidos mínimos y vacíos en cada formato + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Vacío y mínimo

+

¿Pasa un archivo válido y tan pequeño como permite el formato?

+

+ El preset empty-and-minimal construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • un archivo válido rechazado por ser demasiado pequeño, porque la comprobación cuenta bytes en lugar de leerlos
  • +
  • un archivo vacío que hace caer al lector en vez de ser notificado
  • +
  • una imagen de un píxel de ancho que divide entre cero de camino a la miniatura
  • +
  • un almacenamiento que lee cero bytes como una subida fallida y sigue reintentando
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show empty-and-minimal:

+
+ + + + + + + +
Archivos28
Targets en su receta28
Tamaño total32 667 B
Formatosavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.26
unspecifiedDepende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías.2
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--formatsids de formato separados por comas, o allallDe qué formatos se compone el conjunto. Déjalo en all para todos los formatos de esta versión, o nombra los que acepta tu sistema.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/es/presets/filename-handling/index.html b/web/public/es/presets/filename-handling/index.html new file mode 100644 index 00000000..7c8e831a --- /dev/null +++ b/web/public/es/presets/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Nombres de archivo problemáticos para probar - Unicode y longitud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Manejo de nombres de archivo

+

¿Mi sistema guardará, mostrará y devolverá un nombre de archivo que no esperaba?

+

+ El preset filename-handling construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • un nombre que parece otro en pantalla, en un registro o en una lista
  • +
  • un nombre cortado, recortado o reescrito entre la subida y el almacenamiento
  • +
  • un límite de longitud contado en caracteres donde el almacenamiento cuenta bytes
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show filename-handling:

+
+ + + + + + + +
Archivos50
Targets en su receta50
Tamaño total51 200 B
Formatostxt
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.4
unspecifiedDepende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías.46
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--formatun id de formato de la página de formatostxtEl formato de cada archivo del conjunto. Es una opción de la propia herramienta, y el preset solo le da un valor por defecto.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/es/presets/index.html b/web/public/es/presets/index.html new file mode 100644 index 00000000..78dd8f9e --- /dev/null +++ b/web/public/es/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +Presets de archivos de prueba - conjuntos listos para QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Presets de archivos de prueba, un conjunto para cada pregunta de prueba

+

+ Un preset es un conjunto entero de archivos de prueba diseñado en torno a una pregunta, con un + manifiesto que dice cómo debe reaccionar tu sistema a cada archivo. Tú eliges la pregunta, la + herramienta construye el conjunto. Cada preset tiene su propia página con lo que suele encontrar, + qué hay en el conjunto y cada ajuste que admite. +

+ + + +
+

¿En qué se diferencia un preset de una receta?

+

+ Por debajo, en nada. Un preset es una receta que la herramienta escribe por ti a partir de unos + pocos ajustes. tfg preset eject imprime esa receta para que la guardes junto a tus + pruebas y la edites, y una receta tuya puede basarse en un preset con una línea, extends: + preset: seguido de su id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

¿Puedo fiarme de los valores por defecto?

+

+ Para los archivos, sí. Para un número que solo conoce tu sistema, como el límite de un formulario de + subida, un valor por defecto es un marcador nuestro, y la herramienta lo dice cada vez que usa + uno. La página de cada preset marca esos ajustes, y tfg preset show lo dice antes + de escribir nada. +

+
+ +
+ + + + diff --git a/web/public/es/presets/size-boundaries/index.html b/web/public/es/presets/size-boundaries/index.html new file mode 100644 index 00000000..c20e39f7 --- /dev/null +++ b/web/public/es/presets/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Probar un límite de tamaño de subida - archivos en el límite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Límites de tamaño

+

¿Se aplica un límite de tamaño exactamente donde se declara?

+

+ El preset size-boundaries construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • errores de uno en el límite
  • +
  • MB confundido con MiB, que son un 4,8 por ciento y bastan para dejar pasar un archivo que no debería pasar
  • +
  • un límite aplicado en el navegador y no en el servidor
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show size-boundaries:

+
+ + + + + + + +
Archivos7
Targets en su receta7
Tamaño total73 400 320 B
Formatospdf
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.4
rejectTu sistema debe rechazar el archivo.3
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--limitun tamaño como 2mb10mbEl límite de tamaño que declara tu sistema. Todo lo demás se mide a partir de él. Este valor por defecto es nuestro marcador, no el valor de tu sistema. Pasa el tuyo.
--spreadtamaños separados por comas1B,1kb,1mbHasta dónde llegar a cada lado del límite, como una lista de tamaños.
--formatun id de formato de la página de formatospdfEl formato de cada archivo del conjunto. Es una opción de la propia herramienta, y el preset solo le da un valor por defecto.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

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

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/es/presets/tabular-import/index.html b/web/public/es/presets/tabular-import/index.html new file mode 100644 index 00000000..2076d070 --- /dev/null +++ b/web/public/es/presets/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +Archivos de prueba para importar CSV y Excel - delimitadores + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Importación de tablas

+

¿Sobrevive mi importación de tablas a lo que exportan las herramientas reales?

+

+ El preset tabular-import construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • un archivo con punto y coma leído como una sola columna, porque el delimitador se supuso en lugar de buscarse
  • +
  • un archivo CRLF partido en filas con una fila vacía después de cada una
  • +
  • una tabla sin cabecera cuya primera fila de datos se come como nombres de columna
  • +
  • una importación que conserva las columnas que puede mostrar y descarta el resto sin decir nada
  • +
  • un lector que toma los registros JSON de uno en uno por línea y se detiene en el primer documento con sangría
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show tabular-import:

+
+ + + + + + + +
Archivos13
Targets en su receta13
Tamaño total3 080 060 B
Formatoscsv, json, xlsx
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.8
unspecifiedDepende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías.5
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--rows1 - 200000 filas1000Cuántas filas contiene la hoja de cálculo. Se escribe exactamente con el tamaño que ocupan tantas filas, así que el presupuesto de arriba se mueve con este valor.
--columns1 - 32768 columnas10Cuántas columnas tiene cada fila de la hoja de cálculo. Filas por columnas tiene un techo, y pedir más se rechaza antes de escribir nada.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/es/presets/text-encoding/index.html b/web/public/es/presets/text-encoding/index.html new file mode 100644 index 00000000..fc548131 --- /dev/null +++ b/web/public/es/presets/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +Archivos de prueba de codificación - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Codificación de texto

+

¿Sabe mi lector en qué codificación está un archivo, o lo adivina?

+

+ El preset text-encoding construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • un lector que supone UTF-8 y muestra un archivo UTF-16 con un carácter de cada tres, o como filas de cuadros
  • +
  • una marca de orden de bytes leída como contenido, de modo que el primer campo de una importación empieza con tres caracteres extraños
  • +
  • un importador que adivina la codificación por los primeros bytes y adivina distinto con un archivo más largo
  • +
  • un archivo CRLF partido en filas con una fila vacía después de cada una, o un retorno de carro que queda dentro del último campo
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show text-encoding:

+
+ + + + + + + +
Archivos20
Targets en su receta20
Tamaño total81 920 B
Formatoscsv, log, md, txt, xml
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.10
unspecifiedDepende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías.10
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--sampleun tamaño como 2mb4kbEl tamaño de cada archivo del conjunto. UTF-16 guarda dos bytes por carácter, así que un número impar se rechaza.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/es/presets/upload-validation/index.html b/web/public/es/presets/upload-validation/index.html new file mode 100644 index 00000000..ad0d9fa3 --- /dev/null +++ b/web/public/es/presets/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +Archivos de prueba de validación de subida - tipo, tamaño y nombre + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Validación de subida

+

¿Mi formulario de subida acepta lo que debe y rechaza el resto?

+

+ El preset upload-validation construye con un solo comando un conjunto entero de archivos de + prueba reales para esta pregunta, y un manifest.json a su lado que dice cómo debe + reaccionar tu sistema a cada archivo. Todo lo de abajo se lee del programa, con los valores por + defecto de esta versión. +

+ + +
+

¿Qué suele encontrar?

+
    +
  • un límite aplicado en el navegador y no en el servidor
  • +
  • un SVG o un HTML tomado por una imagen o por texto plano, que es una forma de colar un script por un formulario
  • +
  • un archivo comprobado por su extensión y nunca abierto, de modo que un PDF llamado .jpg pasa
  • +
  • un formulario que lee todo el cuerpo en memoria antes de mirar su tamaño
  • +
  • una subida llamada PHOTO.JPG rechazada donde photo.jpg se acepta, o al revés
  • +
  • un nombre con espacios, paréntesis o caracteres fuera de ASCII escrito en disco sin cambios
  • +
+
+ + +
+

¿Qué hay en el conjunto?

+

Con sus valores por defecto, tal como lo informa tfg preset show upload-validation:

+
+ + + + + + + +
Archivos71
Targets en su receta22
Tamaño total120 639 488 B
Formatoshtml, jpg, pdf, png, svg, txt
+
+

Y lo que el manifiesto de ese conjunto espera de tu sistema:

+
+ + + + + + + + + +
EsperadoSignificadoArchivos
acceptTu sistema debe aceptar el archivo.56
rejectTu sistema debe rechazar el archivo.10
unspecifiedDepende de las reglas de tu sistema. Tú decides y después compruebas que lo que ocurre es lo que querías.5
+
+
+ +
+

¿Qué puedes cambiar?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AjusteAdmitePor defectoQué hace
--limitun tamaño como 2mb10mbEl límite de tamaño que declara tu formulario de subida. Este conjunto da un paso a cada lado - para un archivo a cada distancia, ejecuta el preset size-boundaries. Este valor por defecto es nuestro marcador, no el valor de tu sistema. Pasa el tuyo.
--allowids de formato separados por comasjpg,png,pdfQué tipos debe aceptar tu formulario. Cada uno se convierte en un archivo real de ese tipo, y son el control positivo de todo el conjunto.
--denyextensiones separadas por comassvg,html,exe,shQué extensiones debe rechazar tu formulario. Una extensión para la que esta versión no tiene formato recibe igualmente un archivo con ese nombre, con texto plano.
--far-over10x, 2x, off2xCuánto se pasa del límite el único archivo grande. Desactívalo donde escribir varias veces el límite no compense el disco.
--bulk0 - 10000 archivos50Cuántos archivos contiene la subida masiva. Cero deja ese grupo fuera del conjunto por completo.
+
+
+ +
+

¿Cómo se ejecuta?

+

Mira cuánto costaría el conjunto, constrúyelo o toma su receta para editarla:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

O construye sobre él en una receta propia, junto a tus pruebas:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/faq/index.html b/web/public/faq/index.html index cda73d06..00071d5c 100644 --- a/web/public/faq/index.html +++ b/web/public/faq/index.html @@ -3,15 +3,36 @@ + FAQ - Questions About Generating Test Files + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
@@ -129,7 +196,8 @@

Frequently asked questions

Can I generate a file that is deliberately broken?

-

Not yet. Damaged and malformed files are a planned feature. Today every file the tool writes is a valid one of its format.

+

Yes. Add --damage zero-head and the file comes out at exactly the size you asked for with its first bytes overwritten by zeros, so a reader turns it away, and the manifest says your system should reject it. The page about corrupt test files has the details.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
@@ -201,7 +269,7 @@

Frequently asked questions

{ "@type": "Question", "name": "Can I generate a file that is deliberately broken?", - "acceptedAnswer": { "@type": "Answer", "text": "Not yet. Damaged and malformed files are a planned feature. Today every file the tool writes is a valid one of its format." } + "acceptedAnswer": { "@type": "Answer", "text": "Yes. Add --damage zero-head and the file comes out at exactly the size you asked for with its first bytes overwritten by zeros, so a reader turns it away, and the manifest says your system should reject it. The page about corrupt test files has the details." } }, { "@type": "Question", diff --git a/web/public/formats/index.html b/web/public/formats/index.html index 5f467709..dc6cfb55 100644 --- a/web/public/formats/index.html +++ b/web/public/formats/index.html @@ -3,15 +3,36 @@ + 26 Supported File Formats - PDF, DOCX, PNG, ZIP and More + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/fr/cas-d-usage/index.html b/web/public/fr/cas-d-usage/index.html new file mode 100644 index 00000000..5b15e99e --- /dev/null +++ b/web/public/fr/cas-d-usage/index.html @@ -0,0 +1,323 @@ + + + + + + +Cas d'usage - limites d'envoi, fixtures de CI, tests en masse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

À quoi les gens l'utilisent

+

+ Cinq tâches qui reviennent dans presque tous les projets qui reçoivent des fichiers de la part de + personnes, et la commande qui fait chacune. Chaque exemple ci-dessous s'exécute tel qu'il est + écrit. +

+ +
+

Limites d'envoi

+

Tester si une limite de taille de fichier est appliquée là où elle le dit

+

+ Une limite, ce sont trois cas de test, pas un : juste en dessous, pile dessus et juste + au-dessus. Les obtenir à la main revient à calculer des nombres d'octets en espérant ne pas + s'être trompé d'un. Demandez plutôt le jeu : +

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

+ Vous obtenez trois vrais PDF de 1048575, 1048576 et 1048577 octets, et un manifeste qui dit que les + deux premiers doivent être acceptés et le troisième refusé pour size_limit. Votre + test lit l'attente au lieu que vous écriviez trois assertions à la main - et quand la limite + change, vous changez un nombre et relancez. +

+

+ La même chose fonctionne sans préréglage quand vous voulez un seul jeu de limites en ligne : +

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

Intégration continue

+

Garder les fixtures hors du dépôt sans les perdre

+

+ De gros fixtures binaires rendent un dépôt lent à cloner et pénible à relire, et personne ne peut + dire ce qui a changé quand l'un est remplacé. Une recette, ce sont quelques centaines de + caractères de YAML qui reconstruisent les fichiers identiques - à l'octet près, sur + n'importe quelle machine - parce que chaque fichier est dérivé de la graine de + l'exécution. +

+
- 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
+

+ Chaque fin a son propre code de sortie, si bien qu'un pipeline peut distinguer une mauvaise recette + d'un disque plein et d'une différence de vérification. Une exécution échouée n'écrit rien sur la + sortie standard, ce qui évite qu'un analyseur de journaux lise une erreur comme une donnée. +

+
+ +
+

Volume

+

Découvrir ce qui se passe quand le dossier est gros

+

+ Les routines d'import, les tâches de nuit et les listages de répertoires se comportent autrement à + dix mille fichiers qu'à dix. Des tailles tirées dans une plage donnent au jeu l'allure d'un vrai + trafic plutôt que de dix mille fichiers identiques, et le tirage vient de la graine, donc le jeu + est le même demain. +

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

+ Vérifiez ce que coûterait une exécution avant qu'elle n'écrive quoi que ce soit, ce qui compte quand + le total se mesure en gigaoctets : +

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

+ Une exécution plus grande que l'espace libre du disque est refusée avant que le premier octet soit + écrit, au lieu de remplir le disque et d'échouer à mi-chemin. +

+
+ +
+

Archives

+

Tester un décompresseur avec une archive qui contient vraiment des fichiers

+

+ Une archive vide avec la bonne extension ne prouve rien sur le code qui l'ouvre et parcourt ce + qu'elle contient. Déclarez le contenu et l'archive le contient vraiment : +

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

+ La profondeur d'imbrication, le nombre d'entrées et la taille de ce qu'il y a dedans sont autant de + choses sur lesquelles une routine d'import a des opinions, et c'est ainsi que vous découvrez + lesquelles. +

+
+ +
+

Analyseurs et visionneuses

+

Vérifier que votre propre code lit un format comme le fait un vrai logiciel

+

+ Chaque format ici est vérifié avec un lecteur indépendant avant la livraison - un PNG est ouvert et + ses pixels comparés, un DOCX est relu par des bibliothèques distinctes, une archive est + extraite. Cela signifie qu'un fichier que votre analyseur refuse est une trouvaille sur votre + analyseur, pas sur le générateur. +

+
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
+

+ La page des formats liste les réglages que chacun accepte et le plus + petit fichier que chacun peut être. +

+
+ +
+

Guides

+

Deux d'entre eux en détail

+
    +
  • + Fichiers de test corrompus - un fichier cassé + volontairement, à la taille exacte, avec dans le manifeste ce qui doit lui arriver. +
  • +
  • + Fichiers de test en CI - un workflow GitHub Actions, un + job GitLab et les codes de sortie qui font échouer un build. +
  • +
+
+ +
+

À qui cela s'adresse

+

+ Les ingénieurs QA, l'automatisation de tests et tous ceux dont le code a derrière lui un formulaire + d'envoi, une routine d'import, un analyseur ou un quota de stockage. Il fonctionne sur une + machine sans aucun réseau, ce qui compte dans un environnement d'entreprise fermé où un + générateur dans le navigateur n'est pas une option. +

+ +

Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.

+
+ +
+ + + + diff --git a/web/public/fr/creer-fichier-taille-exacte/index.html b/web/public/fr/creer-fichier-taille-exacte/index.html new file mode 100644 index 00000000..5cc34be3 --- /dev/null +++ b/web/public/fr/creer-fichier-taille-exacte/index.html @@ -0,0 +1,334 @@ + + + + + + +Créer un fichier d'une taille précise - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Comment créer un fichier d'une taille exacte

+

+ Chaque système a une commande pour cela, et les trois sont ci-dessous. Elles donnent un fichier du + nombre d'octets exact - et pour beaucoup de tests, c'est tout ce qu'il faut. Chaque + commande de cette page a été exécutée avant publication, sur le système auquel elle + appartient. +

+ +
+

La réponse courte

+

+ Windows : fsutil file createnew name 10485760. Linux : dd if=/dev/zero + of=name bs=1M count=10. macOS : mkfile 10m name. Les tailles sont en + octets, et 10 Mo comptés comme les compte votre gestionnaire de fichiers font 10485760 octets. +

+
+ +
+

Windows

+

fsutil, et une version PowerShell qui n'a besoin de rien de plus

+

+ fsutil est fourni avec Windows. Il prend la taille en octets, calculez + donc le nombre d'abord - 10 Mo font 10485760, 100 Mo font 104857600, 1 Go fait 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Mesuré sous Windows 11 : cela fonctionne depuis une invite ordinaire sans exiger de droits + élevés, et le fichier fait exactement 10485760 octets. +

+

PowerShell sait faire la même chose sans appeler un autre programme, et il comprend les unités :

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB en PowerShell signifie 10485760 octets, le même comptage par 1024 qu'utilise + l'Explorateur, donc les deux commandes ci-dessus produisent la même taille. +

+
+ +
+

Linux

+

dd, truncate et fallocate, et la différence qui piège les gens

+

dd est celle que tout le monde connaît. Elle écrit vraiment les octets :

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate est instantané, et c'est là le piège. Mesuré sous Alpine Linux, le fichier + annonce 10485760 octets et occupe zéro bloc - c'est un fichier + creux. Tout ce qui le lit obtient dix mégaoctets de zéros, mais le disque n'a jamais + cédé la place : +

+
truncate -s 10M test10mb.bin
+

+ C'est correct pour tester une limite d'envoi et trompeur pour tester un quota de disque. + fallocate est celui à choisir quand l'espace doit être réel : +

+
fallocate -l 10M test10mb.bin
+

Et quand le contenu doit être incompressible, pour qu'un archiveur ne puisse pas le réduire à nouveau :

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, qui n'est pas creux, et les deux que vous connaissez déjà

+

+ macOS fournit mkfile. Mesuré sous macOS 26.6.2 : 10485760 octets et 20480 blocs, + donc l'espace est réellement alloué plutôt que promis : +

+
mkfile 10m test10mb.bin
+

dd et truncate sont là aussi et se comportent comme sous Linux :

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Là où cela cesse de suffire

+

Un fichier de la bonne taille n'est pas un fichier du bon type

+

+ Tout ce qui précède donne un bloc de zéros. C'est suffisant quand ce qui est testé ne regarde que la + taille - une limite d'envoi, un quota, un transfert. Cela cesse de l'être dès que quelque chose + ouvre le fichier. +

+

+ Mesuré, et cela vaut la peine de le faire vous-même : créez un fichier de 2 Mo avec + fsutil, appelez-le photo.png et donnez-le à une bibliothèque d'images. + Pillow répond cannot identify image file. Ce n'est pas un PNG. Cela n'en a jamais + été un - seul le nom le prétendait. +

+

+ Cela compte plus qu'il n'y paraît, à cause de la façon dont le test échoue ensuite. + Votre point d'envoi refuse le fichier, votre test passe au vert et vous concluez que la limite + de taille fonctionne. Il ne l'a pas refusé pour sa taille. Il l'a refusé parce que les octets + n'étaient pas une image, et la règle que vous vouliez tester n'a jamais été atteinte. +

+
    +
  • un analyseur le refuse avant qu'aucune règle de taille ne soit examinée
  • +
  • une étape de miniature échoue et l'erreur que vous lisez concerne la miniature
  • +
  • un antivirus ou un contrôle de contenu le refuse pour une troisième raison
  • +
  • une visionneuse n'affiche rien, et personne ne peut dire si c'est le bogue
  • +
+
+ +
+

L'autre voie

+

Un vrai fichier de ce format, à la taille exacte que vous avez demandée

+

+ C'est ce que fait Testing Files Generator. Le fichier est un vrai fichier de son format - il s'ouvre + dans le logiciel qui lui correspond - et il fait le nombre d'octets exact que vous avez demandé, + à l'octet près : +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Demandez une taille qu'un format ne peut pas atteindre et vous obtenez une erreur qui nomme le + plancher et sa raison, jamais un fichier de mauvaise taille. La page des + formats liste chaque format avec le plus petit fichier qu'il peut produire. +

+

Et une limite, ce sont trois cas de test et non un, donc l'outil construit les trois :

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Cela donne 10485759, 10485760 et 10485761 octets, et un manifeste qui dit lesquels votre système + doit accepter et lesquels il doit refuser. La page des cas + d'usage passe en revue cela et quatre autres tâches pour lesquelles il est conçu. +

+ +

Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.

+
+ +
+

Alors lequel utiliser ?

+
    +
  • +

    Utiliser la commande du système

    +

    + Quand rien n'ouvre le fichier. Tester une limite de taille sur un point d'entrée qui vérifie d'abord + la taille, un transfert, un quota, un disque plein. C'est une ligne et c'est déjà installé. +

    +
  • +
  • +

    Utiliser un vrai générateur

    +

    + Quand quoi que ce soit analyse, affiche, importe ou extrait le fichier - et quand vous avez besoin + des mêmes fixtures demain, sur une autre machine, à l'octet près. +

    +
  • +
+

+ Les deux sont sur cette page parce que les deux sont justes une partie du temps. L'erreur à éviter + est d'utiliser la première là où il faut la seconde et de lire le test vert comme une preuve. +

+
+ +
+ + + + diff --git a/web/public/fr/documentation/index.html b/web/public/fr/documentation/index.html new file mode 100644 index 00000000..43365b22 --- /dev/null +++ b/web/public/fr/documentation/index.html @@ -0,0 +1,565 @@ + + + + + + +Documentation - commandes, recettes, manifeste, codes de sortie + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentation

+

+ Tout ce que fait l'outil, rangé selon les questions avec lesquelles les gens arrivent vraiment. Le + README du dépôt est la référence complète et correspond toujours à + la version que vous avez téléchargée. +

+ +
+

Quelles commandes existe-t-il ?

+

Chacune fait une seule chose :

+
tfg generate    produire des fichiers, depuis une recette ou des options
+tfg validate    vérifier une recette sans rien écrire
+tfg verify      comparer un répertoire à un manifeste
+tfg cleanup     supprimer les fichiers qu'un manifeste liste
+tfg recipe fmt  afficher une recette sous sa forme normalisée
+tfg preset      construire un jeu de fichiers à partir d'une question de test nommée
+tfg formats     lister les formats pris en charge par cette version
+tfg damage      lister les façons dont cette version peut abîmer un fichier exprès
+tfg tool        de petits outils pour des fichiers que vous avez déjà
+tfg version     afficher la version de l'outil
+tfg license     afficher la licence et ce qu'elle implique pour les fichiers générés
+
+ +
+

Comment générer un seul fichier de taille exacte ?

+

+ Nommez le format, la taille et la destination. Les tailles se comptent par 1024, donc + 2mb font 2097152 octets. Un nombre d'octets brut fonctionne aussi, donc + --size 10485761 demande exactement ce nombre. +

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

Les options utiles de generate :

+
+ + + + + + + + + + + + + + + + + +
OptionCe qu'elle fait
--format <id>format des fichiers, par exemple txt
--size <size>taille exacte de chaque fichier, comme 10mb ou un nombre d'octets brut
--size-range <a-b>une taille tirée par fichier dans une plage, comme 1kb-8kb. Le tirage vient de la graine
--boundary <size>trois fichiers autour d'une limite : un octet en dessous, la limite, un octet au-dessus
--count <n>combien de fichiers produire. Par défaut 1
--name <template>modèle de nom, par exemple invoice_{index:04}.txt
--out <dir>répertoire où écrire
--seed <n>graine de l'exécution. La même graine donne les mêmes octets
--set <k>=<v>un réglage de format, répétable
--damage <name>abîmer les fichiers exprès, répétable et appliqué dans l'ordre. Lancez tfg damage pour la liste
--expected <outcome>accept, reject, sanitize ou unspecified
--dry-runcompter et montrer, sans rien écrire du tout
--jsonécrire le manifeste sur la sortie standard
+
+
+ +
+

Comment fabriquer un fichier volontairement cassé ?

+

+ Tout autre fichier écrit par cet outil est correct par construction, ce qui répond à deux des trois + questions que pose un validateur d'envoi. --damage répond à la troisième - le + fichier s'ouvre-t-il seulement. Le fichier est produit normalement puis abîmé, il garde donc la + taille demandée. +

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

+ Les réglages se placent après deux-points. L'option se répète, et l'ordre dans lequel vous les + écrivez est l'ordre dans lequel ils sont appliqués. tfg damage liste ce que cette + version sait faire et ce que chacun accepte. +

+

Dans une recette, la clé est une liste, de noms ou de réglages :

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

+ Un fichier abîmé reçoit expected: reject dans le manifeste, avec l'altération notée à + côté. Deux choses sont refusées avant que rien ne soit écrit, car chacune mettrait sinon sur le + disque un fichier que le manifeste décrit à tort : +

+
    +
  • un fichier plus petit que ce dont l'altération a besoin, car il ressortirait inchangé
  • +
  • + expected: accept à côté d'une altération, car rien ne pourrait y répondre. Écrivez + sanitize si le système testé doit réparer le fichier, ou unspecified + si c'est justement la question que vous posez +
  • +
+

+ Une troisième ne peut pas être connue à l'avance. Si une altération s'exécute sans déplacer un seul + octet, ce fichier est abandonné plutôt qu'écrit - l'exécution continue, dit de quel fichier il + s'agissait et se termine avec le code de sortie partiel. +

+

+ Pas à pas, avec un test qui lit le manifeste : + comment fabriquer un fichier corrompu pour les + tests. +

+
+ +
+

À quoi ressemble une recette ?

+

+ Une recette est un fichier YAML qui décrit toute une exécution. Commitez-la à côté de vos tests et + les fixtures cessent d'être des binaires dans votre dépôt - n'importe qui peut les reconstruire, + à l'octet près, à partir d'un fichier de quelques centaines de caractères. +

+
# 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
+

+ Chaque cible exige exactement une de ces clés : size, size-range, + boundary ou contains. Deux est une erreur, et aucune aussi. Une + recette invalide n'écrit aucun fichier et signale tous les problèmes d'un coup + plutôt que le premier seulement, chacun nommant le réglage concerné. +

+
+ +
+

Comment déclarer ce que mon système doit faire d'un fichier ?

+

Forme courte quand le résultat suffit, forme longue quand la raison compte :

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Les résultats sont accept, reject, sanitize et + unspecified. Les raisons forment une liste fermée pour qu'un rapport puisse les + regrouper : 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 et + size_zero. +

+

+ Une raison nomme la règle en jeu, pas le verdict. C'est pourquoi la même raison + peut se trouver sous l'un ou l'autre résultat - un fichier un octet sous une limite est + accept, et la règle concernée reste size_limit. +

+
+ +
+

Que contient le manifeste ?

+

+ Il est écrit à côté des fichiers à la fin de chaque exécution, y compris d'une exécution + interrompue. Une entrée par fichier : +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Un recipe_hash est ajouté quand l'exécution vient d'une recette, et preset + avec overrides quand elle vient d'un préréglage, de sorte qu'un manifeste peut + toujours être rattaché à ce qui l'a produit. +

+

+ Chaque entrée porte aussi target_id, l'identifiant de la cible de la recette qui a + produit le fichier, et summary.by_target compte les fichiers de chaque cible. Une + recette à plusieurs cibles peut donc être vérifiée cible par cible sans lire les noms de + fichiers. +

+
+ +
+

Qu'est-ce qu'un préréglage ?

+

+ Un jeu de fichiers prêt à l'emploi qui répond à une question de test courante, pour que vous n'ayez + pas à concevoir le jeu vous-même. Les préréglages sont des recettes ordinaires en dessous, et + eject affiche la recette pour que vous puissiez la modifier. Chaque préréglage a + sa propre page qui dit ce qu'il trouve d'habitude, ce que + contient le jeu et chaque réglage qu'il accepte. +

+
    +
  • +

    Vide et minimal

    +

    Un fichier valide et aussi petit que le format le permet passe-t-il ?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestion des noms de fichiers

    +

    Mon système va-t-il stocker, afficher et restituer un nom de fichier auquel il ne s'attendait pas ?

    +

    filename-handling

    +
  • +
  • +

    Limites de taille

    +

    Une limite de taille est-elle appliquée exactement là où elle est déclarée ?

    +

    size-boundaries

    +
  • +
  • +

    Import de tableaux

    +

    Mon import de tableaux résiste-t-il à ce qu'exportent les vrais outils ?

    +

    tabular-import

    +
  • +
  • +

    Encodage du texte

    +

    Mon lecteur sait-il dans quel encodage est un fichier, ou devine-t-il ?

    +

    text-encoding

    +
  • +
  • +

    Validation d'envoi

    +

    Mon formulaire d'envoi accepte-t-il ce qu'il doit et refuse-t-il le reste ?

    +

    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 vous dit ce que coûterait le jeu avant que vous ne le construisiez, et dit + franchement quand un nombre est un substitut de notre part plutôt qu'une limite de la vôtre. +

+
+ +
+

Que signifient les codes de sortie ?

+

+ Chaque fin a son propre code, la sortie lisible par machine va sur la sortie standard, et une + exécution échouée n'y écrit rien. Le tableau est un contrat figé - changer le sens d'un code + exige une version majeure. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeSignification
0Tout a fonctionné.
1Une erreur inattendue dans l'outil.
2Commande ou option incorrecte.
3La recette n'est pas valide.
4Le format ne peut pas faire ce qui était demandé.
5Une lecture ou une écriture a échoué.
6Espace disque insuffisant.
7verify a trouvé une différence.
8L'exécution s'est terminée mais tout n'a pas été produit.
130Interrompu avec Ctrl+C.
143Arrêté par un signal, ce qui ressemble à un délai dépassé en 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
+

+ Une exécution arrêtée avec Ctrl+C laisse quand même un manifeste et ne laisse jamais de fichier à + moitié écrit, si bien qu'une tâche annulée peut encore être nettoyée par la suivante. +

+

+ Des workflows prêts pour GitHub Actions et GitLab CI : + comment générer des fichiers de test dans un pipeline + CI. +

+
+ +
+

Y a-t-il une fenêtre de bureau ?

+

+ Oui, le même moteur avec une fenêtre, pour les tests qui ne sont pas scriptés. Ce n'est pas une + version amputée : un test compare les deux interfaces fonctionnalité par fonctionnalité, et + tout ce que seule l'une peut faire doit être déclaré et justifié au lieu de diverger + discrètement. +

+

+ Les écrans sont un lot, les préréglages, plusieurs lots à la fois et À propos. Elle montre ce que + coûterait une exécution avant d'écrire quoi que ce soit, indique la progression pendant + l'exécution et peut être annulée en cours de route sans laisser de fichier à moitié écrit. Elle + n'ouvre pas encore de fichier de recette - les recettes sont pour l'instant une affaire de ligne + de commande, et la fenêtre construit ses lots dans le formulaire. +

+
+ +
+ + + + diff --git a/web/public/fr/faq/index.html b/web/public/fr/faq/index.html new file mode 100644 index 00000000..d934848f --- /dev/null +++ b/web/public/fr/faq/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - questions sur la génération de fichiers de test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Questions fréquentes

+

+ Licence, vie privée, reproductibilité et ce que les gens vérifient avant de mettre un générateur + dans un pipeline de build. Si votre question n'est pas ici, le suivi + des tickets est ouvert. +

+ +
+
+

En quoi est-ce différent de dd, fsutil ou truncate ?

+
+

Ces commandes donnent un fichier de la bonne taille rempli de rien. Un fichier de 2 Mo nommé photo.png fabriqué ainsi n'est pas un PNG, donc tout ce qui l'analyse vraiment le refuse pour la mauvaise raison, et votre test réussit alors lui aussi pour la mauvaise raison. Cet outil produit un vrai PNG d'exactement 2 Mo, qui s'ouvre dans une visionneuse d'images, accompagné d'une déclaration sur la façon dont votre système doit le traiter.

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

Est-ce gratuit, et puis-je l'utiliser au travail ?

+
+

Oui aux deux. Il est publié sous GPL-3.0 et ne coûte rien. Il n'y a ni compte, ni clé de licence, ni offre payante.

+
+
+
+

Puis-je utiliser les fichiers générés dans un produit propriétaire ?

+
+

Oui. La licence couvre le code de l'outil, pas ce qu'il produit. Les fichiers, recettes et manifestes générés sont une sortie et non des œuvres dérivées, vous pouvez donc les commiter et les livrer sans aucune obligation.

+
+
+
+

Les fichiers générés contiennent-ils de vraies données personnelles ?

+
+

Non. Tout ce qu'ils contiennent est synthétisé à partir d'une graine. Aucun jeu de données n'est lu, aucun service n'est contacté et aucun contenu tiers n'est intégré. Considérez une adresse e-mail générée comme inutilisable plutôt que comme inutilisée, car n'importe quelle chaîne aléatoire peut coïncider par hasard avec une vraie.

+
+
+
+

Obtiendrai-je exactement les mêmes fichiers sur une autre machine ?

+
+

Oui, à l'octet près, avec la même recette et la même graine. Le projet le teste à chaque modification, et le casser exige un changement de version majeure. C'est ce qui vous permet de commiter une petite recette plutôt que de gros fixtures binaires.

+
+
+
+

Faut-il une connexion internet ?

+
+

Jamais. Il n'y a ni télémétrie, ni vérification de mises à jour, ni client cloud, et le binaire en ligne de commande n'a aucune pile réseau compilée dedans. Il fonctionne sur une machine sans réseau et dans un environnement d'entreprise fermé.

+
+
+
+

Que se passe-t-il si je demande une taille qu'un format ne peut pas atteindre ?

+
+

Vous obtenez une erreur qui nomme le format, la taille minimale possible, la raison de ce plancher et ce qu'il faut faire à la place, et aucun fichier n'est écrit. L'outil n'arrondit jamais une taille en silence. Chaque plancher est listé sur la page des formats.

+
tfg formats png
+
+
+
+

Puis-je générer un fichier volontairement cassé ?

+
+

Oui. Ajoutez --damage zero-head et le fichier sort à la taille exacte demandée, avec ses premiers octets écrasés par des zéros, si bien qu'un lecteur le refuse, et le manifeste dit que votre système doit le rejeter. La page sur les fichiers de test corrompus donne le détail.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Quels formats arrivent ensuite ?

+
+

7z, mp3 et mp4. 26 formats fonctionnent de bout en bout aujourd'hui.

+
+
+
+

Sur quels systèmes puis-je l'exécuter ?

+
+

La ligne de commande fonctionne sous Windows et Linux, sur Intel comme sur ARM, et sur les Mac Apple silicon. La fenêtre de bureau est fournie pour Windows sur Intel, Linux sur Intel et les Mac Apple silicon. Les Mac Intel ne sont pas pris en charge et rien n'est construit pour eux.

+
+
+
+

Dois-je installer quelque chose ?

+
+

Non. Téléchargez l'archive de votre système, décompressez-la et lancez le binaire. Il n'y a pas d'installateur, pas d'environnement d'exécution à ajouter et pas de dépendance à résoudre. Si vous avez Go, une seule commande go install fonctionne aussi.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Pourquoi une exécution sur des milliers de fichiers est-elle plus lente sous Windows ?

+
+

Parce que Windows facture plus cher chaque chemin qu'il examine, et une commande qui parcourt des milliers de fichiers examine des milliers de chemins. Mesuré sur une machine avec 3000 fichiers de 1 ko, verify prend environ 0,9 seconde sous Windows et environ 0,2 seconde sous Linux dans un conteneur. Un chemin de sortie plus court réduit le chiffre de Windows, car chaque dossier au-dessus des fichiers fait partie de ce qui est examiné.

+
+
+
+ + +
+

Encore indécis ?

+

+ La page des cas d'usage montre les tâches pour lesquelles il est + conçu, et la page des formats liste chaque format avec le plus petit + fichier qu'il peut produire. Le README du dépôt est la référence + complète. +

+ +

Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.

+
+ +
+ + + + diff --git a/web/public/fr/fichiers-de-test-corrompus/index.html b/web/public/fr/fichiers-de-test-corrompus/index.html new file mode 100644 index 00000000..1a1729ac --- /dev/null +++ b/web/public/fr/fichiers-de-test-corrompus/index.html @@ -0,0 +1,385 @@ + + + + + + +Fichiers de test corrompus - fichiers cassés à taille exacte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cas d'usage

+

Comment fabriquer un fichier corrompu pour les tests

+

+ Un validateur à qui l'on n'a jamais montré que des fichiers sains n'a pas vraiment été testé. Voici + comment obtenir un fichier cassé volontairement, qui sort à exactement la taille + demandée et qui porte un manifeste disant ce que votre système doit en faire. +

+ +
+

La réponse courte

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out écrit un PNG + d'exactement 2097152 octets dont les premiers octets sont des zéros, et le manifeste à côté note + que votre système doit le rejeter. +

+
+ +
+

La méthode habituelle

+

Pourquoi un fichier corrompu à la main fait un mauvais test

+

+ Les moyens habituels sont un éditeur hexadécimal, un script qui inverse quelques octets au hasard, + ou un fichier raccourci avec head ou truncate. Ça marche une fois, + puis ça coûte : +

+
    +
  • + C'est différent à chaque fois. Un octet tiré au hasard tombe ailleurs à chaque + exécution, donc un échec du mardi peut ne pas revenir le mercredi. +
  • +
  • + Ça change la taille. Un fichier coupé est plus petit que la limite sous laquelle il + devait se trouver, si bien que le contrôle de taille répond avant le contrôle du contenu et + que le test passe pour la mauvaise raison. +
  • +
  • + Ça passe souvent inaperçu. Un texte brut reste lisible avec un octet modifié au + milieu, et un lecteur d'images indulgent le dessine simplement, de sorte que le fichier censé + être cassé est accepté. +
  • +
  • + Ça ne dit rien de ce qui doit se passer. Le fichier n'est que des octets, et celui + qui lira le test ensuite doit deviner si l'acceptation ou le rejet était voulu. +
  • +
+
+ +
+

Ce que vous obtenez

+

Un fichier abîmé garde la taille demandée

+

+ Le fichier est généré normalement puis cassé, en route vers le disque. Il garde la taille demandée, + et la même commande écrit de nouveau les mêmes octets. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Les réglages se placent après deux-points. L'option peut être répétée, et les dommages s'appliquent + dans l'ordre où vous les écrivez. Ça marche avec chacun des 26 formats. +

+
+ +
+

Ce qu'il sait faire

+

Quels dommages existe-t-il ?

+

+ Voici la liste que le programme affiche, lue dans le programme au moment de construire cette page. + tfg damage affiche la même, et tfg damage <id> dit ce que prend + l'un d'eux. +

+
+ + + + + + + + + + + + + + + + + +
DommageCe qu'il fait aux octetsPlus petit fichierRéglages
zero-headÉcrase les premiers octets du fichier avec des zéros, sans toucher à sa longueur. La plupart des lecteurs regardent d'abord là, donc presque tout remarque ce dommage.8bytes
+
+

+ zero-head écrit des zéros sur le début du fichier. La plupart des lecteurs regardent + d'abord là, la signature et l'en-tête qui disent ce qu'est le fichier, donc presque tout lecteur + le remarque. Le texte brut et les journaux n'ont pas de signature et sont refusés eux aussi, car + une suite d'octets nuls n'est pas du texte. En dessous de quatre octets, certains formats + sortent avec un dommage dont aucun lecteur ne se plaint, c'est pourquoi le réglage commence à + quatre. +

+
+ +
+

Ce que dit le manifeste

+

Un manifeste qui dit ce qui doit se passer

+

+ Chaque fichier abîmé reçoit une entrée disant que votre système doit le rejeter, avec le dommage + noté à côté : +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Deux demandes sont refusées avant que rien ne soit écrit, car chacune laisserait sur le disque un + fichier que le manifeste décrit mal : +

+
    +
  • un fichier plus petit que ce dont le dommage a besoin, qui sortirait intact
  • +
  • + expected: accept à côté d'un dommage, car rien ne pourrait le satisfaire. Écrivez + sanitize si votre système doit réparer le fichier, ou unspecified si + c'est justement la question que vous posez +
  • +
+
+ +
+

Dans une recette

+

Fichiers sains et cassés dans une même exécution

+

+ Mettez les deux dans une seule recette, et le manifeste porte l'attente de chaque fichier, de sorte + que le test n'a pas besoin d'une liste disant lequel est lequel : +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Dans un test

+

En faire un test

+

+ Le test lit le manifeste et vérifie que ce qui s'est passé est ce qui a été déclaré. Il n'a pas + besoin d'une liste de noms de fichiers : +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un bon refus est un refus net. Un message qui dit ce qui n'allait pas est la réponse voulue. Une + erreur serveur, un blocage ou un fichier à moitié enregistré est le défaut que ce test existe + pour trouver. +

+
+ +
+

Suite

+

Où aller ensuite

+ +
+ +
+ + + + diff --git a/web/public/fr/fichiers-de-test-en-ci/index.html b/web/public/fr/fichiers-de-test-en-ci/index.html new file mode 100644 index 00000000..5e4526ed --- /dev/null +++ b/web/public/fr/fichiers-de-test-en-ci/index.html @@ -0,0 +1,382 @@ + + + + + + +Fichiers de test en CI - GitHub Actions, GitLab CI et PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cas d'usage

+

Comment générer des fichiers de test dans un pipeline CI

+

+ Une fixture binaire dans un dépôt reste à jamais dans son historique, ne se relit pas dans un diff + et devient impossible dès que le fichier est gros. Générez plutôt les fichiers dans le pipeline à + partir d'une recette. La recette est du texte, les octets sortent identiques à chaque fois, et une + dernière étape prouve que rien n'a bougé. +

+ +
+

La réponse courte

+

+ Installez tfg, lancez tfg generate fixtures.yaml --out ./fixtures avant + les tests et tfg verify ./fixtures/manifest.json après. Les deux étapes font + échouer le build d'elles-mêmes, avec un code de sortie qui dit pourquoi. +

+
+ +
+

Pourquoi ne pas les commiter

+

Pourquoi une fixture ne doit pas vivre dans le dépôt

+
    +
  • + Elle reste dans l'historique. Supprimer un binaire plus tard ne rend pas un clone + plus petit, car chacune de ses versions est toujours là. +
  • +
  • + Un diff ne montre pas ce qui a changé. Le relecteur voit qu'un PDF est différent, + et rien de plus. Une recette change d'une ligne. +
  • +
  • + Les gros fichiers ne tiennent pas. GitHub refuse un push qui contient un fichier de + plus de 100 Mo, donc un test d'une limite d'envoi de 500 Mo n'a rien à commiter. +
  • +
+

+ C'est la recette qu'il faut commiter. La même recette et la même graine écrivent les mêmes octets + sur toute machine, donc le fichier généré dans le pipeline est celui que vous aviez sur votre + portable. +

+
+ +
+

La recette

+

Une recette qui vit à côté des tests

+

+ Celle-ci écrit vingt-cinq factures qui doivent être acceptées et deux images au-dessus d'une limite + qui doivent être refusées, et le manifeste note les deux attentes : +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la vérifie sans rien écrire et nomme tous les problèmes d'un + coup. +

+
+ +
+

GitHub Actions

+

Un workflow qui installe l'outil et construit les fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La ligne de somme de contrôle compare l'archive à verify-SHA256SUMS.txt de la même + version. La version est épinglée, donc une nouvelle version ne change jamais un build que vous + n'avez pas touché. +

+
+ +
+

GitLab CI

+

La même chose en job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quand ça passe au rouge

+

Ce qui fait échouer une étape, et pourquoi

+

+ Chaque fin a son propre code de sortie, donc l'étape échoue d'elle-même et le journal dit lequel. + Ceux que rencontre un pipeline : +

+
    +
  • 3 - la recette n'est pas valide. Rien n'a été écrit, et chaque problème est nommé
  • +
  • 4 - le format ne sait pas faire ce qui a été demandé, par exemple une taille sous son minimum
  • +
  • 6 - il n'y a pas assez d'espace disque
  • +
  • 7 - tfg verify a trouvé un fichier qui ne correspond pas à son manifeste
  • +
  • 8 - l'exécution est terminée, mais tout n'a pas été produit
  • +
+

+ Une exécution échouée n'écrit rien sur la sortie standard, donc un analyseur de journaux ne prend + jamais une erreur pour des données. Le tableau complet est sur + la page de documentation. +

+
+ +
+

PowerShell

+

Un script PowerShell demande une ligne de plus

+

+ PowerShell ne fait pas sortir le code de sortie d'un programme d'un fichier .ps1. + Lancez-en un avec -File et le script répond 0 même quand l'outil à + l'intérieur a refusé le travail, si bien qu'un build qui devrait être rouge passe au vert. La + dernière ligne est toute la correction : +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ C'est ainsi que se comporte PowerShell, pas une particularité de cet outil. cmd, + bash et zsh n'ont besoin de rien de plus. +

+
+ +
+

Plusieurs jobs

+

Partager les fixtures entre les jobs

+

+ Il n'y a généralement pas besoin de les envoyer. Comme la même recette écrit les mêmes octets, + chaque job peut lancer son propre tfg generate, ce qui est plus rapide qu'un envoi + suivi d'un téléchargement. Quand un job doit recevoir des fichiers d'un autre, lancez tfg + verify sur le manifeste après le transfert, et il dit si ce qui est arrivé est ce qui a + été écrit. +

+
+ +
+

Suite

+

Où aller ensuite

+
    +
  • + Fichiers de test corrompus ajoute à la même recette + des fichiers cassés volontairement. +
  • +
  • + Les cas d'usage montrent ce qu'une exécution dans un pipeline peut + vérifier d'autre. +
  • +
  • + La documentation donne chaque commande, chaque clé de recette et + chaque code de sortie. +
  • +
+
+ +
+ + + + diff --git a/web/public/fr/formats/index.html b/web/public/fr/formats/index.html new file mode 100644 index 00000000..1cee288a --- /dev/null +++ b/web/public/fr/formats/index.html @@ -0,0 +1,913 @@ + + + + + + +26 formats de fichiers - PDF, DOCX, PNG, ZIP et plus + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formats de fichiers, chacun généré à une taille exacte

+

+ Chacun est un vrai fichier de ce format. Il s'ouvre dans le logiciel qui lui + correspond et fait exactement le nombre d'octets que vous avez demandé. Aucun n'est du remplissage + de zéros avec une extension collée dessus. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatNomExtensionPlus petit fichierFidélitéVérifié avec
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullsans objet
mdMarkdown.md0fullsans objet
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullsans objet
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Ce que signifient les colonnes

+
    +
  • +

    Plus petit fichier

    +

    + Le moins d'octets que cet outil accepte pour ce format, y compris l'étiquette qu'il écrit dans le + fichier. Demandez moins et vous obtenez une erreur qui nomme le plancher et sa raison, + jamais un fichier de mauvaise taille. +

    +
  • +
  • +

    Fidélité

    +

    + À quel point le fichier est complet. full signifie qu'un lecteur qui analyse vraiment + le format l'accepte, et pas seulement que l'extension correspond. +

    +
  • +
  • +

    Vérifié avec

    +

    + Le lecteur indépendant qui ouvre chaque fichier généré avant la livraison du format - une + implémentation distincte, pas notre propre code qui corrige ses propres devoirs. +

    +
  • +
+

+ Chaque format se répète aussi à l'octet près : la même recette et la même graine produisent des + fichiers identiques sur n'importe quelle machine, ce qui rend une recette sûre à commiter à la + place des fixtures elles-mêmes. +

+
+ +
+

Réglages que chaque format accepte

+

+ La plupart des formats ont des réglages propres - dimensions d'image, qualité JPEG, nombre de pages + PDF, lignes et colonnes d'un tableur, nombre d'entrées dans une archive. Définissez-les avec + --set key=value en ligne de commande, ou sous properties: dans une + recette. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatRéglageAccepte
avifwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
bmpwidth1 - 20000 pixels
height1 - 20000 pixels
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headervrai ou faux
quote_styleall, minimal, none
columns2 - 32768 colonnes
docxparagraphs1 - 50000 paragraphes
gifwidth1 - 20000 pixels
height1 - 20000 pixels
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixels
height1 - 256 pixels
embedbmp, png
jpgwidth1 - 20000 pixels
height1 - 20000 pixels
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 entrées par seconde
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomvrai ou faux
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlen'importe quel texte
authorn'importe quel texte
subjectn'importe quel texte
keywordsn'importe quel texte
creatorn'importe quel texte
producern'importe quel texte
createdune date comme 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none
modifiedune date comme 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none
pngwidth1 - 20000 pixels
height1 - 20000 pixels
pptxslides1 - 500 diapositives
svgwidth1 - 20000 pixels
height1 - 20000 pixels
targzentries0 - 10000
entry_formatl'identifiant d'un format, comme le liste tfg formats
entry_sizeune taille comme 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesvrai ou faux
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixels
height1 - 20000 pixels
txtencodingutf-16be, utf-16le, utf-8
bomvrai ou faux
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixels
height1 - 16383 pixels
xlsxrows1 - 200000 lignes
columns1 - 32768 colonnes
xmlencodingutf-16be, utf-16le, utf-8
bomvrai ou faux
zipentries0 - 10000
entry_formatl'identifiant d'un format, comme le liste tfg formats
entry_sizeune taille comme 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesvrai ou faux
passwordle mot de passe, en clair
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Une valeur hors de ce qu'un réglage accepte est refusée avec un message qui nomme le réglage, la + plage autorisée et quoi utiliser à la place. Un réglage inconnu est aussi une erreur, jamais une + valeur par défaut silencieuse - une faute de frappe acceptée en silence donne un fichier aux + mauvais réglages et une heure à se demander pourquoi le test passe alors qu'il ne devrait pas. +

+

+ Lancez tfg formats <id> pour voir exactement ce qu'un format accepte dans la + version que vous avez. +

+
+ +
+

Les archives contiennent de vrais fichiers

+

+ targz et zip + peuvent être remplis d'entrées plutôt que laissés en coquille vide. Une archive générée contient + réellement les documents qu'elle prétend contenir, si bien que tout ce qui la décompresse + pendant un test y trouve de vrais fichiers. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/fr/index.html b/web/public/fr/index.html new file mode 100644 index 00000000..ea4cfa6d --- /dev/null +++ b/web/public/fr/index.html @@ -0,0 +1,457 @@ + + + + + + +Générateur de fichiers de test - taille exacte, 26 vrais formats + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Générez de vrais fichiers de test à la taille exacte

+

+ PDF, PNG, DOCX, ZIP - 26 formats au total, et chacun est un + vrai fichier qui s'ouvre dans le logiciel qui lui correspond, à la taille exacte que + vous avez demandée. Chaque exécution note aussi ce que votre application doit faire de + chaque fichier. Ligne de commande et fenêtre de bureau, gratuit et open source, entièrement sur + votre machine. +

+ + +

Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.

+
+ +
+ La fenêtre de bureau de Testing Files Generator, prête à écrire un lot de fichiers de test +
La fenêtre de bureau, prête à écrire un lot de fichiers. Le même moteur fonctionne derrière la ligne de commande.
+
+
+ +
    +
  • + 26 +

    vrais formats, chacun s'ouvrant dans le logiciel qui lui correspond

    +
  • +
  • + 1 octet +

    la précision de chaque taille demandée, jamais arrondie en silence

    +
  • +
  • + 0 +

    connexions vers où que ce soit - pas de compte, pas de télémétrie, pas de vérification de mises à jour

    +
  • +
+ +
+

Le problème

+

Fabriquer un fichier de test est facile. Fabriquer les mille bons est la partie fastidieuse

+

Vous testez un logiciel qui reçoit des fichiers de la part de personnes. Tôt ou tard, il vous faut :

+
    +
  • un PDF de exactement 10 Mo, pour savoir si la limite d'envoi est réelle
  • +
  • les trois fichiers de part et d'autre de cette limite, pour attraper les erreurs d'un
  • +
  • 10 000 fichiers journaux, pour voir ce que fait la tâche de nuit quand le dossier est gros
  • +
  • un ZIP qui contient vraiment 200 documents, pas une coquille vide avec la bonne extension
  • +
  • un fichier de 4 Go, sans garder un fichier de 4 Go dans votre dépôt
  • +
  • les mêmes fixtures sur votre portable et sur le serveur de build, à l'octet près
  • +
+

+ C'est ce que cela remplace. C'est conçu pour les ingénieurs QA, l'automatisation de tests et tous + ceux dont le code a derrière lui un formulaire d'envoi, une routine d'import, un analyseur ou un + quota de stockage. +

+
+ +
+

Ce qui le distingue

+

Les autres générateurs s'arrêtent aux octets. Celui-ci répond à ce que votre test demande vraiment

+

+ Un dossier de fichiers vous laisse encore décider ce que chacun est censé prouver. Chaque exécution + écrit ici un manifest.json à côté des fichiers - une simple liste de tout ce qui a + été produit et, pour chaque entrée, une attente déclarée. +

+

Admettons que votre point d'envoi accepte 1 Mo. Demandez les trois fichiers situés sur cette ligne :

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FichierOctetsVotre système doitParce que
1mb_under_1b.pdf1048575accepteril est dans la limite
1mb_at_limit.pdf1048576accepterla limite elle-même est permise
1mb_over_1b.pdf1048577refusersize_limit
+
+ +

Trois fichiers, trois réponses différentes, sous forme lisible par machine. Votre test lit le manifeste au lieu que vous écriviez les assertions à la main :

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Quand la réponse dépend de votre propre politique, le manifeste le dit

+

+ Il consigne unspecified plutôt que d'inventer une attente. Un générateur qui devine + produit de faux échecs, et une suite qui crie au loup finit par être désactivée. +

+
+
+ +
+

Préréglages

+

Choisissez la question, obtenez tout le jeu

+

+ Un préréglage est un jeu de fichiers de test conçu autour d'une question de test, pour que vous + n'ayez pas à chercher quels fichiers prouvent quoi. Chacun a une page qui dit ce qu'il trouve + d'habitude, ce que contient le jeu et chaque réglage qu'il accepte. +

+
    +
  • +

    Vide et minimal

    +

    Un fichier valide et aussi petit que le format le permet passe-t-il ?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestion des noms de fichiers

    +

    Mon système va-t-il stocker, afficher et restituer un nom de fichier auquel il ne s'attendait pas ?

    +

    filename-handling

    +
  • +
  • +

    Limites de taille

    +

    Une limite de taille est-elle appliquée exactement là où elle est déclarée ?

    +

    size-boundaries

    +
  • +
  • +

    Import de tableaux

    +

    Mon import de tableaux résiste-t-il à ce qu'exportent les vrais outils ?

    +

    tabular-import

    +
  • +
  • +

    Encodage du texte

    +

    Mon lecteur sait-il dans quel encodage est un fichier, ou devine-t-il ?

    +

    text-encoding

    +
  • +
  • +

    Validation d'envoi

    +

    Mon formulaire d'envoi accepte-t-il ce qu'il doit et refuse-t-il le reste ?

    +

    upload-validation

    +
  • +
+

Tous les préréglages, et leur rapport avec les recettes

+
+ +
+

Démarrage rapide

+

Trois commandes pour le voir fonctionner

+
    +
  1. +

    Créer un fichier

    +

    Un PNG, exactement deux mégaoctets :

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Créer beaucoup de fichiers

    +

    + Dix mille fichiers journaux, chacun entre un et huit kilooctets, avec des tailles tirées de la + graine pour que demain donne le même jeu. Donnez à chaque exécution son propre + répertoire - le manifeste est la seule trace de ce qu'une exécution a écrit, donc + l'outil refuse d'en écrire un second par-dessus : +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Les vérifier, puis les supprimer

    +

    verify vous dit que rien n'a bougé. cleanup supprime exactement ce qui a été écrit et rien d'autre :

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Les tailles se comptent par 1024, comme le fait votre gestionnaire de fichiers, donc + 2mb signifie 2097152 octets. Un nombre d'octets brut fonctionne aussi. La + documentation couvre les recettes, le manifeste et les codes de + sortie. +

+
+ +
+

Ce que vous obtenez

+

Conçu pour une suite qui tourne sans surveillance

+
    +
  • +

    Taille exacte, à l'octet près

    +

    Demandez 10485761 octets et obtenez exactement cela. Une taille qu'un format ne peut pas atteindre est une erreur avec une raison, jamais un fichier de mauvaise taille.

    +
  • +
  • +

    26 vrais formats

    +

    Pas des zéros de remplissage avec une extension. Un PNG généré s'ouvre dans une visionneuse d'images, un DOCX s'ouvre dans Word, un ZIP se décompresse. Chacun est vérifié avec des lecteurs indépendants avant d'être livré.

    +
  • +
  • +

    Un manifeste qui fait office d'oracle de test

    +

    Chemin, taille, SHA-256, format, graine, version de l'outil - et ce que votre système doit faire du fichier.

    +
  • +
  • +

    Reproductible

    +

    Même recette et même graine, mêmes octets, sur n'importe quelle machine. Commitez une petite recette YAML plutôt que de gros fixtures binaires.

    +
  • +
  • +

    Deux interfaces, un seul moteur

    +

    Une ligne de commande conçue pour la CI et une fenêtre de bureau pour les tests exploratoires. Aucune n'est une version amputée de l'autre, et un test les compare fonctionnalité par fonctionnalité.

    +
  • +
  • +

    Entièrement hors ligne

    +

    Pas de compte, pas de cloud, pas de télémétrie, pas de vérification de mises à jour. Le binaire en ligne de commande n'a aucune pile réseau compilée dedans.

    +
  • +
+
+ +
+

Téléchargement

+

Choisissez la version pour votre système

+

+ Décompressez l'archive et lancez-la. tfg est la ligne de commande et + tfg-gui est la fenêtre de bureau. Il n'y a pas d'installateur et rien à ajouter à + votre machine. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SystèmeLigne de commandeFenêtre de bureau
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Ce qui est signé, et ce qui ne l'est pas

+

+ Les téléchargements Windows et macOS sont signés, ils démarrent donc sans avertissement sur un + développeur inconnu. Ceux de Linux ne le sont pas, car Linux de bureau n'a pas d'équivalent + pour les signer. Chaque archive est listée dans verify-SHA256SUMS.txt sur la page + des versions, pour que vous puissiez vérifier ce que vous avez téléchargé. +

+
+ +

Gratuit et open source, GPL-3.0. Aucune inscription. Les téléchargements Windows et macOS sont signés et démarrent sans avertissement.

+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/empty-and-minimal/index.html b/web/public/fr/prereglages/empty-and-minimal/index.html new file mode 100644 index 00000000..6c34b819 --- /dev/null +++ b/web/public/fr/prereglages/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +Fichiers de test valides minimaux et vides, dans chaque format + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Vide et minimal

+

Un fichier valide et aussi petit que le format le permet passe-t-il ?

+

+ Le préréglage empty-and-minimal construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • un fichier valide refusé parce que trop petit, quand le contrôle compte les octets au lieu de les lire
  • +
  • un fichier vide qui fait tomber le lecteur au lieu d'être signalé
  • +
  • une image d'un pixel de large qui divise par zéro en route vers la miniature
  • +
  • un stockage qui lit zéro octet comme un envoi échoué et recommence sans fin
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show empty-and-minimal :

+
+ + + + + + + +
Fichiers28
Cibles dans sa recette28
Taille totale32 667 B
Formatsavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.26
unspecifiedCela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu.2
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--formatsidentifiants de format séparés par des virgules, ou allallLes formats dont le jeu est fait. Laissez all pour tous les formats de cette version, ou nommez ceux que votre système accepte.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/filename-handling/index.html b/web/public/fr/prereglages/filename-handling/index.html new file mode 100644 index 00000000..8cda905b --- /dev/null +++ b/web/public/fr/prereglages/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Noms de fichiers problématiques pour tester - Unicode et longueur + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Gestion des noms de fichiers

+

Mon système va-t-il stocker, afficher et restituer un nom de fichier auquel il ne s'attendait pas ?

+

+ Le préréglage filename-handling construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • un nom qui ressemble à un autre à l'écran, dans un journal ou dans une liste
  • +
  • un nom coupé, rogné ou réécrit entre l'envoi et le stockage
  • +
  • une limite de longueur comptée en caractères là où le stockage compte en octets
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show filename-handling :

+
+ + + + + + + +
Fichiers50
Cibles dans sa recette50
Taille totale51 200 B
Formatstxt
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.4
unspecifiedCela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu.46
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--formatun identifiant de format de la page des formatstxtLe format de chaque fichier du jeu. C'est une option de l'outil lui-même, et le préréglage ne fait que lui donner une valeur par défaut.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/index.html b/web/public/fr/prereglages/index.html new file mode 100644 index 00000000..6529192d --- /dev/null +++ b/web/public/fr/prereglages/index.html @@ -0,0 +1,245 @@ + + + + + + +Préréglages de fichiers de test - jeux prêts à l'emploi pour la QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Préréglages de fichiers de test, un jeu pour chaque question de test

+

+ Un préréglage est tout un jeu de fichiers de test conçu autour d'une question, avec un manifeste qui + dit comment votre système doit réagir à chaque fichier. Vous choisissez la question, l'outil + construit le jeu. Chaque préréglage a sa propre page qui dit ce qu'il trouve d'habitude, ce que + contient le jeu et chaque réglage qu'il accepte. +

+ +
    +
  • +

    Vide et minimal

    +

    Un fichier valide et aussi petit que le format le permet passe-t-il ?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestion des noms de fichiers

    +

    Mon système va-t-il stocker, afficher et restituer un nom de fichier auquel il ne s'attendait pas ?

    +

    filename-handling

    +
  • +
  • +

    Limites de taille

    +

    Une limite de taille est-elle appliquée exactement là où elle est déclarée ?

    +

    size-boundaries

    +
  • +
  • +

    Import de tableaux

    +

    Mon import de tableaux résiste-t-il à ce qu'exportent les vrais outils ?

    +

    tabular-import

    +
  • +
  • +

    Encodage du texte

    +

    Mon lecteur sait-il dans quel encodage est un fichier, ou devine-t-il ?

    +

    text-encoding

    +
  • +
  • +

    Validation d'envoi

    +

    Mon formulaire d'envoi accepte-t-il ce qu'il doit et refuse-t-il le reste ?

    +

    upload-validation

    +
  • +
+ +
+

En quoi un préréglage diffère-t-il d'une recette ?

+

+ En dessous, il n'en diffère pas. Un préréglage est une recette que l'outil écrit pour vous à partir + de quelques réglages. tfg preset eject affiche cette recette pour que vous la + gardiez à côté de vos tests et la modifiiez, et une recette à vous peut s'appuyer sur un + préréglage en une ligne, extends: preset: suivi de son identifiant. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Puis-je me fier aux valeurs par défaut ?

+

+ Pour les fichiers, oui. Pour un nombre que seul votre système connaît, comme la limite d'un + formulaire d'envoi, une valeur par défaut est un substitut de notre part, et l'outil le dit + chaque fois qu'il en utilise une. La page de chaque préréglage marque ces réglages, et tfg + preset show le dit avant que rien ne soit écrit. +

+
+ +
+ + + + diff --git a/web/public/fr/prereglages/size-boundaries/index.html b/web/public/fr/prereglages/size-boundaries/index.html new file mode 100644 index 00000000..a3b6237c --- /dev/null +++ b/web/public/fr/prereglages/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Tester une limite de taille d'envoi - fichiers à la limite exacte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Limites de taille

+

Une limite de taille est-elle appliquée exactement là où elle est déclarée ?

+

+ Le préréglage size-boundaries construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • des erreurs d'un à la limite
  • +
  • Mo confondu avec Mio, soit 4,8 pour cent, assez pour laisser passer un fichier qui ne devrait pas passer
  • +
  • une limite appliquée dans le navigateur et pas sur le serveur
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show size-boundaries :

+
+ + + + + + + +
Fichiers7
Cibles dans sa recette7
Taille totale73 400 320 B
Formatspdf
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.4
rejectVotre système doit refuser le fichier.3
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--limitune taille comme 2mb10mbLa limite de taille que déclare votre système. Tout le reste se mesure à partir d'elle. Cette valeur par défaut est notre substitut, pas la valeur de votre système. Passez la vôtre.
--spreadtailles séparées par des virgules1B,1kb,1mbJusqu'où aller de part et d'autre de la limite, sous forme de liste de tailles.
--formatun identifiant de format de la page des formatspdfLe format de chaque fichier du jeu. C'est une option de l'outil lui-même, et le préréglage ne fait que lui donner une valeur par défaut.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

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

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/tabular-import/index.html b/web/public/fr/prereglages/tabular-import/index.html new file mode 100644 index 00000000..9eeb898a --- /dev/null +++ b/web/public/fr/prereglages/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +Fichiers de test d'import CSV et Excel - séparateurs, en-têtes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Import de tableaux

+

Mon import de tableaux résiste-t-il à ce qu'exportent les vrais outils ?

+

+ Le préréglage tabular-import construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • un fichier à point-virgule lu comme une seule colonne, parce que le séparateur a été supposé au lieu d'être cherché
  • +
  • un fichier CRLF découpé en lignes avec une ligne vide après chacune
  • +
  • un tableau sans en-tête dont la première ligne de données est avalée comme noms de colonnes
  • +
  • un import qui garde les colonnes qu'il peut afficher et abandonne le reste sans un mot
  • +
  • un lecteur qui prend les enregistrements JSON une ligne à la fois et s'arrête au premier document indenté
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show tabular-import :

+
+ + + + + + + +
Fichiers13
Cibles dans sa recette13
Taille totale3 080 060 B
Formatscsv, json, xlsx
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.8
unspecifiedCela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu.5
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--rows1 - 200000 lignes1000Le nombre de lignes du tableur. Il est écrit exactement à la taille que font autant de lignes, donc le budget ci-dessus bouge avec cette valeur.
--columns1 - 32768 colonnes10Le nombre de colonnes de chaque ligne du tableur. Lignes fois colonnes a un plafond, et le dépasser est refusé avant que rien ne soit écrit.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/text-encoding/index.html b/web/public/fr/prereglages/text-encoding/index.html new file mode 100644 index 00000000..ec96b4ed --- /dev/null +++ b/web/public/fr/prereglages/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +Fichiers de test d'encodage de texte - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Encodage du texte

+

Mon lecteur sait-il dans quel encodage est un fichier, ou devine-t-il ?

+

+ Le préréglage text-encoding construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • un lecteur qui suppose de l'UTF-8 et montre un fichier UTF-16 avec un caractère sur trois, ou en rangées de carrés
  • +
  • une marque d'ordre des octets lue comme du contenu, si bien que le premier champ d'un import commence par trois caractères parasites
  • +
  • un importeur qui devine l'encodage d'après les premiers octets et devine autrement pour un fichier plus long
  • +
  • un fichier CRLF découpé en lignes avec une ligne vide après chacune, ou un retour chariot resté dans le dernier champ
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show text-encoding :

+
+ + + + + + + +
Fichiers20
Cibles dans sa recette20
Taille totale81 920 B
Formatscsv, log, md, txt, xml
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.10
unspecifiedCela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu.10
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--sampleune taille comme 2mb4kbLa taille de chaque fichier du jeu. L'UTF-16 stocke deux octets par caractère, donc un nombre impair est refusé.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/fr/prereglages/upload-validation/index.html b/web/public/fr/prereglages/upload-validation/index.html new file mode 100644 index 00000000..227e2dd3 --- /dev/null +++ b/web/public/fr/prereglages/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +Fichiers de test de validation d'envoi - type, taille et nom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Préréglages

+

Validation d'envoi

+

Mon formulaire d'envoi accepte-t-il ce qu'il doit et refuse-t-il le reste ?

+

+ Le préréglage upload-validation construit en une commande tout un jeu de vrais fichiers de test + pour cette question, avec un manifest.json à côté qui dit comment votre système doit + réagir à chaque fichier. Tout ce qui suit est lu depuis le programme, aux valeurs par défaut de + cette version. +

+ + +
+

Que trouve-t-il d'habitude ?

+
    +
  • une limite appliquée dans le navigateur et pas sur le serveur
  • +
  • un SVG ou un HTML pris pour une image ou pour du texte brut, un moyen de faire passer un script à travers un formulaire
  • +
  • un fichier contrôlé par son extension et jamais ouvert, si bien qu'un PDF nommé .jpg passe
  • +
  • un formulaire qui lit tout le corps en mémoire avant de regarder sa taille
  • +
  • un envoi nommé PHOTO.JPG refusé là où photo.jpg est accepté, ou l'inverse
  • +
  • un nom avec des espaces, des parenthèses ou des caractères hors ASCII écrit sur le disque tel quel
  • +
+
+ + +
+

Que contient le jeu ?

+

Aux valeurs par défaut, comme le rapporte tfg preset show upload-validation :

+
+ + + + + + + +
Fichiers71
Cibles dans sa recette22
Taille totale120 639 488 B
Formatshtml, jpg, pdf, png, svg, txt
+
+

Et ce que le manifeste de ce jeu attend de votre système :

+
+ + + + + + + + + +
AttenduSignificationFichiers
acceptVotre système doit accepter le fichier.56
rejectVotre système doit refuser le fichier.10
unspecifiedCela dépend des règles de votre système. Vous décidez, puis vous vérifiez que ce qui se passe est ce que vous aviez voulu.5
+
+
+ +
+

Que pouvez-vous modifier ?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RéglageAcceptePar défautCe qu'il fait
--limitune taille comme 2mb10mbLa limite de taille que déclare votre formulaire d'envoi. Ce jeu fait un pas de chaque côté - pour un fichier à chaque distance, lancez le préréglage size-boundaries. Cette valeur par défaut est notre substitut, pas la valeur de votre système. Passez la vôtre.
--allowidentifiants de format séparés par des virgulesjpg,png,pdfLes types que votre formulaire doit accepter. Chacun devient un vrai fichier de ce type, et ils forment le témoin positif de tout le jeu.
--denyextensions séparées par des virgulessvg,html,exe,shLes extensions que votre formulaire doit refuser. Une extension pour laquelle cette version n'a pas de format reçoit quand même un fichier à ce nom, contenant du texte brut.
--far-over10x, 2x, off2xJusqu'où le grand fichier dépasse la limite. Désactivez-le là où écrire plusieurs fois la limite ne vaut pas le disque.
--bulk0 - 10000 fichiers50Le nombre de fichiers de l'envoi en masse. Zéro retire complètement ce groupe du jeu.
+
+
+ +
+

Comment le lancer ?

+

Voyez ce que coûterait le jeu, construisez-le ou prenez sa recette pour la modifier :

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Ou bâtissez dessus dans une recette à vous, à côté de vos tests :

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/hi/corrupt-test-files/index.html b/web/public/hi/corrupt-test-files/index.html new file mode 100644 index 00000000..bcbbec4f --- /dev/null +++ b/web/public/hi/corrupt-test-files/index.html @@ -0,0 +1,378 @@ + + + + + + +खराब टेस्ट फ़ाइलें - सटीक आकार की बिगड़ी फ़ाइलें + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

उपयोग के मामले

+

परीक्षण के लिए खराब फ़ाइल कैसे बनाएँ

+

+ जिस वैलिडेटर को केवल स्वस्थ फ़ाइलें दिखाई गई हों, उसे सचमुच परखा नहीं गया है। यहाँ बताया गया है कि + ऐसी फ़ाइल कैसे पाएँ जो जानबूझकर बिगाड़ी गई हो, ठीक उतने आकार की निकले जितना आपने + माँगा, और ऐसा मैनिफ़ेस्ट साथ लाए जो बताता है कि आपके सिस्टम को उसका क्या करना चाहिए। +

+ +
+

छोटा जवाब

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out ठीक 2097152 बाइट की + एक PNG लिखता है जिसके शुरुआती बाइट शून्य हैं, और उसके बगल का मैनिफ़ेस्ट दर्ज करता है कि आपके + सिस्टम को उसे अस्वीकार करना चाहिए। +

+
+ +
+

आम तरीका

+

हाथ से बिगाड़ी गई फ़ाइल खराब टेस्ट क्यों है

+

+ आम तरीके हैं हेक्स एडिटर, कुछ यादृच्छिक बाइट पलटने वाली स्क्रिप्ट, या head अथवा + truncate से फ़ाइल को छोटा काट देना। ये एक बार चलते हैं, फिर महँगे पड़ते हैं: +

+
    +
  • + हर बार अलग होता है। यादृच्छिक बाइट हर रन में नई जगह पड़ता है, इसलिए मंगलवार की + विफलता बुधवार को लौटे, यह ज़रूरी नहीं। +
  • +
  • + यह आकार बदल देता है। कटी हुई फ़ाइल उस सीमा से छोटी होती है जिसके नीचे उसे रहना था, + इसलिए आकार की जाँच सामग्री की जाँच से पहले जवाब दे देती है और टेस्ट गलत कारण से पास हो जाता + है। +
  • +
  • + यह अक्सर किसी की नज़र में नहीं आता। सादा पाठ बीच में एक बाइट बदलने पर भी पढ़ा जाता + है, और उदार इमेज रीडर उसे बस बना देता है, इसलिए जो फ़ाइल खराब होनी थी वह स्वीकार हो जाती है। +
  • +
  • + यह नहीं बताता कि क्या होना चाहिए। फ़ाइल सिर्फ़ बाइट है, और जो बाद में टेस्ट पढ़ेगा + उसे अंदाज़ा लगाना पड़ेगा कि इरादा स्वीकार करने का था या अस्वीकार करने का। +
  • +
+
+ +
+

आपको क्या मिलता है

+

खराब फ़ाइल का आकार वही रहता है जो आपने माँगा था

+

+ फ़ाइल सामान्य रूप से बनती है और बाद में, डिस्क तक जाते समय, बिगाड़ी जाती है। वह माँगा हुआ आकार बनाए + रखती है, और वही कमांड फिर वही बाइट लिखता है। +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ सेटिंग कोलन के बाद लिखी जाती है। विकल्प दोहराया जा सकता है, और बिगाड़ आपके लिखे क्रम में लागू होते + हैं। यह सभी 26 फ़ॉर्मैट के साथ चलता है। +

+
+ +
+

यह क्या कर सकता है

+

कौन-कौन से बिगाड़ हैं?

+

+ यह वह सूची है जो प्रोग्राम छापता है, इस पेज को बनाते समय उसी से पढ़ी गई। tfg damage यही + सूची छापता है, और tfg damage <id> बताता है कि उनमें से एक क्या लेता है। +

+
+ + + + + + + + + + + + + + + + + +
बिगाड़बाइट के साथ क्या करता हैसबसे छोटी फ़ाइलसेटिंग
zero-headफ़ाइल के शुरुआती बाइट को शून्य से ढक देता है और लंबाई नहीं छेड़ता। ज़्यादातर रीडर सबसे पहले वहीं देखते हैं, इसलिए यह बिगाड़ लगभग हर चीज़ पकड़ लेती है।8bytes
+
+

+ zero-head फ़ाइल की शुरुआत पर शून्य लिख देता है। ज़्यादातर रीडर सबसे पहले वहीं देखते + हैं, उस सिग्नेचर और हेडर पर जो बताते हैं कि फ़ाइल क्या है, इसलिए लगभग हर रीडर इसे भाँप लेता है। + सादे पाठ और लॉग में सिग्नेचर नहीं होता और वे भी अस्वीकार होते हैं, क्योंकि शून्य बाइट की कतार + पाठ नहीं है। चार बाइट से नीचे कुछ फ़ॉर्मैट ऐसे बिगाड़ के साथ निकलते हैं जिसकी कोई रीडर शिकायत + नहीं करता, इसीलिए सेटिंग चार से शुरू होती है। +

+
+ +
+

मैनिफ़ेस्ट क्या कहता है

+

एक मैनिफ़ेस्ट जो बताता है कि क्या होना चाहिए

+

+ हर खराब फ़ाइल को एक प्रविष्टि मिलती है जो कहती है कि आपके सिस्टम को उसे अस्वीकार करना चाहिए, और + बिगाड़ उसके बगल में दर्ज रहता है: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ दो अनुरोध कुछ भी लिखे जाने से पहले ठुकरा दिए जाते हैं, क्योंकि हर एक डिस्क पर ऐसी फ़ाइल छोड़ देता + जिसका मैनिफ़ेस्ट गलत वर्णन करता: +

+
    +
  • बिगाड़ को जितना चाहिए उससे छोटी फ़ाइल, जो ज्यों की त्यों निकलती
  • +
  • + बिगाड़ के साथ expected: accept, क्योंकि कोई भी उसे पूरा नहीं कर सकता। अगर आपके सिस्टम + को फ़ाइल सुधारनी है तो sanitize लिखें, या अगर आप यही सवाल पूछ रहे हैं तो + unspecified +
  • +
+
+ +
+

रेसिपी में

+

एक रन में स्वस्थ और खराब फ़ाइलें

+

+ दोनों को एक रेसिपी में रखें, और मैनिफ़ेस्ट हर फ़ाइल की अपेक्षा साथ रखता है, इसलिए टेस्ट को यह बताने + वाली सूची नहीं चाहिए कि कौन-सी कौन-सी है: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

टेस्ट में

+

इसे टेस्ट बनाना

+

+ टेस्ट मैनिफ़ेस्ट पढ़ता है और जाँचता है कि जो हुआ वही है जो घोषित किया गया था। उसे फ़ाइल नामों की + सूची नहीं चाहिए: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ अच्छा इनकार साफ़ इनकार होता है। जो संदेश बताए कि क्या गलत था, वही वह जवाब है जो आप चाहते हैं। सर्वर + त्रुटि, अटक जाना या आधी सहेजी फ़ाइल वह खराबी है जिसे ढूँढ़ने के लिए यह टेस्ट है। +

+
+ +
+

आगे

+

यहाँ से कहाँ जाएँ

+ +
+ +
+ + + + diff --git a/web/public/hi/create-file-exact-size/index.html b/web/public/hi/create-file-exact-size/index.html new file mode 100644 index 00000000..0c639f90 --- /dev/null +++ b/web/public/hi/create-file-exact-size/index.html @@ -0,0 +1,330 @@ + + + + + + +तय आकार की फ़ाइल कैसे बनाएँ - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

सटीक आकार की फ़ाइल कैसे बनाएँ

+

+ हर सिस्टम में इसके लिए एक कमांड है, और तीनों नीचे हैं। वे आपको ठीक सही बाइट संख्या की फ़ाइल देती हैं + - और बहुत से टेस्ट के लिए आपको बस यही चाहिए। इस पेज की हर कमांड प्रकाशित करने से पहले उस + सिस्टम पर चलाई गई जिसकी वह है। +

+ +
+

छोटा जवाब

+

+ Windows: fsutil file createnew name 10485760। Linux: dd if=/dev/zero of=name + bs=1M count=10। macOS: mkfile 10m name। आकार बाइट में होते हैं, और आपके + फ़ाइल मैनेजर के गिनने के तरीके से 10 MB यानी 10485760। +

+
+ +
+

Windows

+

fsutil, और बिना किसी अतिरिक्त चीज़ वाला PowerShell रूप

+

+ fsutil Windows के साथ आता है। यह आकार बाइट में लेता है, इसलिए पहले + संख्या निकाल लें - 10 MB यानी 10485760, 100 MB यानी 104857600, 1 GB यानी 1073741824। +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11 पर मापा गया: यह सामान्य प्रॉम्प्ट से चलता है और उन्नत प्रॉम्प्ट नहीं माँगता, और फ़ाइल ठीक + 10485760 बाइट की बनती है। +

+

PowerShell बिना किसी दूसरे प्रोग्राम को बुलाए यही कर सकता है, और इकाइयाँ समझता है:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell में 10MB का मतलब 10485760 बाइट है, वही 1024 आधारित गिनती जो एक्सप्लोरर + इस्तेमाल करता है, इसलिए ऊपर की दोनों कमांड एक ही आकार बनाती हैं। +

+
+ +
+

Linux

+

dd, truncate और fallocate, और वह अंतर जो लोगों को फँसाता है

+

dd वह है जिसे सब जानते हैं। यह बाइट सच में लिखता है:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate तुरंत होता है, और यही पेंच है। Alpine Linux पर मापने पर फ़ाइल 10485760 बाइट + बताती है और शून्य ब्लॉक घेरती है - यह एक स्पार्स फ़ाइल है। जो + भी इसे पढ़ता है उसे दस मेगाबाइट शून्य मिलते हैं, पर डिस्क ने जगह कभी दी ही नहीं: +

+
truncate -s 10M test10mb.bin
+

+ अपलोड सीमा परखने के लिए यह ठीक है और डिस्क कोटा परखने के लिए भ्रामक। जब जगह असली होनी चाहिए तब + fallocate की ओर जाएँ: +

+
fallocate -l 10M test10mb.bin
+

और जब सामग्री असंपीड्य होनी चाहिए, ताकि कोई आर्काइवर उसे फिर से छोटा न कर सके:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, जो स्पार्स नहीं है, और वे दो जिन्हें आप पहले से जानते हैं

+

+ macOS में mkfile आता है। macOS 26.6.2 पर मापा गया: 10485760 बाइट और 20480 ब्लॉक, यानी + जगह वादे से नहीं, सच में आवंटित होती है: +

+
mkfile 10m test10mb.bin
+

dd और truncate भी वहाँ हैं और Linux की तरह ही चलते हैं:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

यह कहाँ काम करना बंद कर देता है

+

सही आकार की फ़ाइल सही क़िस्म की फ़ाइल नहीं होती

+

+ ऊपर की सारी चीज़ें आपको शून्यों का एक ब्लॉक देती हैं। जब जाँचा जा रहा हिस्सा सिर्फ़ आकार देखता है - + अपलोड सीमा, कोटा, ट्रांसफ़र - तब यह काफ़ी है। जिस पल कोई चीज़ फ़ाइल को खोलती + है, यह काफ़ी नहीं रहता। +

+

+ मापा गया, और खुद करके देखना लायक है: fsutil से 2 MB की फ़ाइल बनाएँ, उसका नाम + photo.png रखें, और किसी इमेज लाइब्रेरी को दें। Pillow जवाब देता है cannot + identify image file। यह PNG नहीं है। यह कभी था ही नहीं - सिर्फ़ नाम ऐसा कहता था। +

+

+ यह सुनने में जितना लगता है उससे ज़्यादा मायने रखता है, क्योंकि टेस्ट फिर किस तरफ़ विफल होता + है यही सवाल है। आपका अपलोड एंडपॉइंट फ़ाइल ठुकरा देता है, आपका टेस्ट हरा हो जाता है, और + आप मान लेते हैं कि आकार सीमा काम करती है। उसने फ़ाइल आकार की वजह से नहीं ठुकराई। उसने इसलिए + ठुकराई कि बाइट तस्वीर नहीं थे, और जिस नियम को आप जाँचना चाहते थे वह कभी छुआ ही नहीं गया। +

+
    +
  • कोई पार्सर आकार का कोई नियम देखे जाने से पहले ही उसे ठुकरा देता है
  • +
  • थंबनेल का चरण विफल होता है और जो त्रुटि आप पढ़ते हैं वह थंबनेल के बारे में होती है
  • +
  • कोई एंटीवायरस या सामग्री जाँच उसे तीसरे कारण से मना कर देती है
  • +
  • कोई व्यूअर कुछ नहीं दिखाता, और कोई नहीं बता सकता कि यही बग है या नहीं
  • +
+
+ +
+

दूसरा रास्ता

+

उस फ़ॉर्मैट की असली फ़ाइल, ठीक उसी आकार में जो आपने माँगा

+

+ Testing Files Generator यही करता है। फ़ाइल अपने फ़ॉर्मैट की सच्ची फ़ाइल है - वह अपने सॉफ़्टवेयर में + खुलती है - और उसमें ठीक उतने बाइट हैं जितने आपने माँगे, बाइट तक: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ ऐसा आकार माँगें जिस तक कोई फ़ॉर्मैट नहीं पहुँच सकता और आपको न्यूनतम सीमा और उसका कारण बताने वाली + त्रुटि मिलती है, गलत आकार की फ़ाइल कभी नहीं। फ़ॉर्मैट पेज हर फ़ॉर्मैट + को उसकी सबसे छोटी संभव फ़ाइल के साथ सूचीबद्ध करता है। +

+

और एक सीमा एक नहीं, तीन टेस्ट केस होती है, इसलिए टूल तीनों बनाता है:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ इससे आपको 10485759, 10485760 और 10485761 बाइट की फ़ाइलें मिलती हैं, और एक मैनिफ़ेस्ट जो बताता है कि + आपके सिस्टम को किन्हें स्वीकार करना चाहिए और किन्हें अस्वीकार। उपयोग के + मामलों का पेज इसे और चार दूसरे काम समझाता है जिनके लिए यह बना है। +

+ +

मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।

+
+ +
+

तो कौन सा इस्तेमाल करें?

+
    +
  • +

    सिस्टम की कमांड इस्तेमाल करें

    +

    + जब कुछ भी फ़ाइल नहीं खोलता। ऐसे एंडपॉइंट पर आकार सीमा की जाँच जो पहले आकार देखता है, कोई ट्रांसफ़र, + कोटा, डिस्क भरने की स्थिति। यह एक पंक्ति है और पहले से इंस्टॉल है। +

    +
  • +
  • +

    असली जनरेटर इस्तेमाल करें

    +

    + जब कुछ भी फ़ाइल को पार्स, रेंडर, इंपोर्ट या एक्सट्रैक्ट करता है - और जब आपको कल दूसरी मशीन पर वही + फ़िक्स्चर बाइट-दर-बाइट फिर से चाहिए। +

    +
  • +
+

+ दोनों इस पेज पर इसलिए हैं क्योंकि दोनों कभी-कभी सही होते हैं। जिस गलती से बचना है वह है दूसरे की + ज़रूरत वाली जगह पहले को इस्तेमाल करना और हरे टेस्ट को सबूत मान लेना। +

+
+ +
+ + + + diff --git a/web/public/hi/docs/index.html b/web/public/hi/docs/index.html new file mode 100644 index 00000000..c17c77c1 --- /dev/null +++ b/web/public/hi/docs/index.html @@ -0,0 +1,556 @@ + + + + + + +दस्तावेज़ीकरण - कमांड, रेसिपी, मैनिफ़ेस्ट, एग्ज़िट कोड + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

दस्तावेज़ीकरण

+

+ टूल जो कुछ भी करता है, उन सवालों के रूप में सजाया गया जिन्हें लेकर लोग सच में आते हैं। + रिपॉज़िटरी का README पूरा संदर्भ है और हमेशा आपके डाउनलोड किए + बिल्ड से मेल खाता है। +

+ +
+

कौन सी कमांड हैं?

+

हर एक सिर्फ़ एक काम करती है:

+
tfg generate    रेसिपी या फ़्लैग से फ़ाइलें बनाएँ
+tfg validate    रेसिपी जाँचें और कुछ न लिखें
+tfg verify      किसी डायरेक्टरी को मैनिफ़ेस्ट से मिलाकर जाँचें
+tfg cleanup     मैनिफ़ेस्ट में सूचीबद्ध फ़ाइलें हटाएँ
+tfg recipe fmt  रेसिपी को उसके स्थिर रूप में छापें
+tfg preset      किसी नामित टेस्ट सवाल से फ़ाइलों का सेट बनाएँ
+tfg formats     इस बिल्ड के समर्थित फ़ॉर्मैट सूचीबद्ध करें
+tfg damage      इस बिल्ड द्वारा किसी फ़ाइल को जानबूझकर बिगाड़ने के तरीके सूचीबद्ध करें
+tfg tool        आपके पास पहले से मौजूद फ़ाइलों के लिए छोटे टूल
+tfg version     टूल का संस्करण छापें
+tfg license     लाइसेंस और बनाई गई फ़ाइलों के लिए उसका अर्थ छापें
+
+ +
+

सटीक आकार की एक फ़ाइल कैसे बनाऊँ?

+

+ फ़ॉर्मैट, आकार और जगह बताएँ। आकार 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>सीमा के आसपास तीन फ़ाइलें: एक बाइट नीचे, सीमा, एक बाइट ऊपर
--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मैनिफ़ेस्ट को स्टैंडर्ड आउटपुट पर लिखें
+
+
+ +
+

जानबूझकर टूटी फ़ाइल कैसे बनाऊँ?

+

+ यह टूल जो भी दूसरी फ़ाइल लिखता है वह बनावट से सही होती है, और इससे अपलोड वैलिडेटर के तीन सवालों में + से दो का जवाब मिल जाता है। --damage तीसरे का जवाब देता है - क्या फ़ाइल खुलती भी है। + फ़ाइल सामान्य रूप से बनती है और फिर बिगाड़ी जाती है, इसलिए उसका आकार वही रहता है जो आपने माँगा। +

+
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 मिलता है, और बिगाड़ने का ब्योरा + उसके बगल में दर्ज होता है। दो चीज़ें कुछ भी लिखे जाने से पहले ठुकरा दी जाती हैं, क्योंकि हर एक + डिस्क पर ऐसी फ़ाइल छोड़ देती जिसे मैनिफ़ेस्ट गलत बताता: +

+
    +
  • बिगाड़ने के लिए ज़रूरी से छोटी फ़ाइल, क्योंकि वह बिना बदले निकल आती
  • +
  • + बिगाड़ के बगल में expected: accept, क्योंकि कुछ भी उसे पूरा नहीं कर सकता। अगर जाँचे जा + रहे सिस्टम को फ़ाइल सुधारनी है तो sanitize लिखें, या अगर आप यही सवाल पूछ रहे हैं + तो unspecified +
  • +
+

+ तीसरी बात पहले से नहीं जानी जा सकती। अगर कोई बिगाड़ चलता है और एक भी बाइट नहीं हिलाता, तो वह फ़ाइल + लिखे जाने के बजाय छोड़ दी जाती है - रन चलता रहता है, बताता है कि वह कौन सी फ़ाइल थी, और आंशिक + एग्ज़िट कोड के साथ ख़त्म होता है। +

+

+ कदम दर कदम, मैनिफ़ेस्ट पढ़ने वाले एक टेस्ट के साथ: परीक्षण के लिए + खराब फ़ाइल कैसे बनाएँ। +

+
+ +
+

रेसिपी कैसी दिखती है?

+

+ रेसिपी एक 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 में से ठीक एक चाहिए। दो होना त्रुटि है और एक भी न होना भी। अमान्य रेसिपी + कोई फ़ाइल नहीं लिखती और सिर्फ़ पहली नहीं, सारी समस्याएँ एक साथ बताती है, हर एक + उस सेटिंग का नाम लेकर जिससे वह जुड़ी है। +

+
+ +
+

मैं कैसे बताऊँ कि मेरे सिस्टम को किसी फ़ाइल के साथ क्या करना चाहिए?

+

जब नतीजा काफ़ी हो तो छोटा रूप, जब कारण मायने रखे तो लंबा रूप:

+
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। +

+

+ कारण काम कर रहे नियम का नाम लेता है, फ़ैसले का नहीं। इसीलिए एक ही कारण किसी भी + नतीजे के नीचे आ सकता है - सीमा से एक बाइट नीचे की फ़ाइल accept है, और जिस नियम की + बात है वह फिर भी size_limit है। +

+
+ +
+

मैनिफ़ेस्ट में क्या है?

+

+ यह हर रन के अंत में फ़ाइलों के बगल में लिखा जाता है, बीच में रोके गए रन में भी। हर फ़ाइल के लिए एक + प्रविष्टि: +

+
{
+  "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 जुड़ता है, और प्रीसेट से आया हो तो + overrides के साथ preset, इसलिए मैनिफ़ेस्ट को हमेशा उसके स्रोत तक खोजा + जा सकता है। +

+

+ हर प्रविष्टि में target_id भी होता है, यानी रेसिपी के उस टार्गेट का id जिसने फ़ाइल + बनाई, और summary.by_target गिनता है कि हर टार्गेट के हिस्से कितनी फ़ाइलें आईं। + इसलिए कई टार्गेट वाली रेसिपी को फ़ाइल नाम पढ़े बिना टार्गेट-दर-टार्गेट जाँचा जा सकता है। +

+
+ +
+

प्रीसेट क्या है?

+

+ किसी आम टेस्ट सवाल का जवाब देने वाला फ़ाइलों का तैयार सेट, ताकि आपको सेट खुद डिज़ाइन न करना पड़े। + प्रीसेट अंदर से सामान्य रेसिपी हैं, और eject रेसिपी छापता है ताकि आप वहीं से उसे + संपादित कर सकें। हर प्रीसेट का अपना पेज है जो बताता है कि वह आम तौर + पर क्या पकड़ता है, सेट में क्या है और वह कौन सी सेटिंग लेता है। +

+
    +
  • +

    खाली और न्यूनतम

    +

    क्या फ़ॉर्मैट की अनुमति जितनी छोटी वैध फ़ाइल पास हो जाती है?

    +

    empty-and-minimal

    +
  • +
  • +

    फ़ाइल नाम का प्रबंधन

    +

    क्या मेरा सिस्टम ऐसा फ़ाइल नाम सहेजेगा, दिखाएगा और लौटाएगा जिसकी उसे उम्मीद नहीं थी?

    +

    filename-handling

    +
  • +
  • +

    आकार की सीमाएँ

    +

    क्या आकार की सीमा ठीक वहीं लागू होती है जहाँ उसकी घोषणा की गई है?

    +

    size-boundaries

    +
  • +
  • +

    टेबल इंपोर्ट

    +

    क्या मेरा टेबल इंपोर्ट वह झेल पाता है जो असली टूल एक्सपोर्ट करते हैं?

    +

    tabular-import

    +
  • +
  • +

    टेक्स्ट एन्कोडिंग

    +

    क्या मेरा रीडर जानता है कि फ़ाइल किस एन्कोडिंग में है, या अंदाज़ा लगा रहा है?

    +

    text-encoding

    +
  • +
  • +

    अपलोड सत्यापन

    +

    क्या मेरा अपलोड फ़ॉर्म वह लेता है जो उसे लेना चाहिए और बाकी को लौटा देता है?

    +

    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 सेट बनाने से पहले बताता है कि उसकी क़ीमत क्या होगी, और साफ़ कहता है जब कोई संख्या + आपकी सीमा नहीं बल्कि हमारी अस्थायी जगह-धारक संख्या हो। +

+
+ +
+

एग्ज़िट कोड का क्या अर्थ है?

+

+ हर अंत का अपना कोड है, मशीन के पढ़ने लायक आउटपुट स्टैंडर्ड आउटपुट पर जाता है, और विफल रन वहाँ कुछ + नहीं छापता। तालिका एक जमाया हुआ अनुबंध है - किसी कोड का अर्थ बदलने के लिए मुख्य संस्करण बढ़ाना + पड़ता है। +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
कोडअर्थ
0सब कुछ ठीक चला।
1टूल के अंदर एक अप्रत्याशित त्रुटि।
2गलत कमांड या फ़्लैग।
3रेसिपी मान्य नहीं है।
4फ़ॉर्मैट वह नहीं कर सकता जो माँगा गया।
5पढ़ना या लिखना विफल रहा।
6डिस्क पर पर्याप्त जगह नहीं है।
7verify को असंगति मिली।
8रन पूरा हुआ, पर सब कुछ नहीं बना।
130Ctrl+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 पाइपलाइन में + टेस्ट फ़ाइलें कैसे बनाएँ। +

+
+ +
+

क्या डेस्कटॉप विंडो है?

+

+ हाँ, वही इंजन जिस पर एक विंडो लगी है, उस टेस्टिंग के लिए जो स्क्रिप्ट से नहीं होती। यह घटाया हुआ रूप + नहीं है: एक टेस्ट दोनों इंटरफ़ेस की क्षमता-दर-क्षमता तुलना करता है, और जो सिर्फ़ एक ही कर सकता + है उसे चुपचाप अलग होने देने के बजाय घोषित और उचित ठहराना पड़ता है। +

+

+ स्क्रीन हैं एक बैच, प्रीसेट, एक साथ कई बैच, और परिचय। यह कुछ भी लिखने से पहले रन की क़ीमत दिखाती है, + चलते समय प्रगति बताती है, और बीच में रद्द की जा सकती है बिना आधी लिखी फ़ाइल छोड़े। यह अभी रेसिपी + फ़ाइल नहीं खोलती - फ़िलहाल रेसिपी कमांड लाइन की चीज़ हैं, और विंडो अपने बैच फ़ॉर्म में बनाती है। +

+
+ +
+ + + + diff --git a/web/public/hi/faq/index.html b/web/public/hi/faq/index.html new file mode 100644 index 00000000..4e09e4ac --- /dev/null +++ b/web/public/hi/faq/index.html @@ -0,0 +1,348 @@ + + + + + + +FAQ - टेस्ट फ़ाइलें बनाने के बारे में सवाल + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

अक्सर पूछे जाने वाले सवाल

+

+ लाइसेंस, निजता, दोहराव, और वे बातें जो लोग जनरेटर को बिल्ड पाइपलाइन में लगाने से पहले जाँचते हैं। + अगर आपका सवाल यहाँ नहीं है, तो इश्यू ट्रैकर खुला है। +

+ +
+
+

यह dd, fsutil या truncate से कैसे अलग है?

+
+

वे आपको सही आकार की फ़ाइल देते हैं जो खालीपन से भरी होती है। इस तरह बनी photo.png नाम की 2 MB की फ़ाइल PNG नहीं होती, इसलिए जो भी उसे सच में पार्स करता है वह गलत कारण से उसे ठुकरा देता है, और आपका टेस्ट भी गलत कारण से पास हो जाता है। यह टूल ठीक 2 MB की असली PNG बनाता है जो इमेज व्यूअर में खुलती है, और उसके साथ यह घोषणा आती है कि आपके सिस्टम को उसके साथ क्या करना चाहिए।

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

क्या यह मुफ़्त है, और क्या मैं इसे काम पर इस्तेमाल कर सकता हूँ?

+
+

दोनों के लिए हाँ। यह GPL-3.0 के तहत जारी है और इसकी कोई कीमत नहीं। कोई खाता, लाइसेंस कुंजी या सशुल्क स्तर नहीं है।

+
+
+
+

क्या मैं बनाई गई फ़ाइलें क्लोज़्ड सोर्स उत्पाद में इस्तेमाल कर सकता हूँ?

+
+

हाँ। लाइसेंस टूल के कोड पर लागू होता है, उस पर नहीं जो टूल बनाता है। बनाई गई फ़ाइलें, रेसिपी और मैनिफ़ेस्ट आउटपुट हैं, व्युत्पन्न कृतियाँ नहीं, इसलिए आप उन्हें बिना किसी बाध्यता के कमिट और वितरित कर सकते हैं।

+
+
+
+

क्या बनाई गई फ़ाइलों में असली निजी डेटा होता है?

+
+

नहीं। अंदर का सब कुछ एक सीड से बनाया जाता है। कोई डेटासेट नहीं पढ़ा जाता, किसी सेवा से संपर्क नहीं किया जाता और किसी तीसरे पक्ष की सामग्री नहीं जोड़ी जाती। बनाए गए ईमेल पते को अप्रयुक्त नहीं, बल्कि अनुपयोगी मानें, क्योंकि कोई भी यादृच्छिक स्ट्रिंग संयोग से किसी असली पते से मेल खा सकती है।

+
+
+
+

क्या मुझे दूसरी मशीन पर ठीक वही फ़ाइलें मिलेंगी?

+
+

हाँ, बाइट-दर-बाइट, उसी रेसिपी और उसी सीड के साथ। प्रोजेक्ट हर बदलाव पर इसका परीक्षण करता है, और इसे तोड़ने के लिए मुख्य संस्करण बढ़ाना पड़ता है। इसी वजह से आप बड़े बाइनरी फ़िक्स्चर की जगह एक छोटी रेसिपी कमिट कर सकते हैं।

+
+
+
+

क्या इसे इंटरनेट कनेक्शन चाहिए?

+
+

कभी नहीं। कोई टेलीमेट्री नहीं, कोई अपडेट जाँच नहीं और कोई क्लाउड क्लाइंट नहीं, और कमांड लाइन बाइनरी में नेटवर्क स्टैक कंपाइल ही नहीं किया गया है। यह बिना नेटवर्क की मशीन पर और बंद कॉर्पोरेट माहौल में भी चलता है।

+
+
+
+

अगर मैं ऐसा आकार माँगूँ जो कोई फ़ॉर्मैट हासिल नहीं कर सकता, तो क्या होता है?

+
+

आपको एक त्रुटि मिलती है जो फ़ॉर्मैट, सबसे छोटा संभव आकार, उस न्यूनतम सीमा का कारण और इसके बदले क्या करें यह बताती है, और कोई फ़ाइल नहीं लिखी जाती। टूल कभी आकार को चुपचाप राउंड नहीं करता। हर न्यूनतम सीमा फ़ॉर्मैट पेज पर सूचीबद्ध है।

+
tfg formats png
+
+
+
+

क्या मैं जानबूझकर टूटी हुई फ़ाइल बना सकता हूँ?

+
+

हाँ। --damage zero-head जोड़ें और फ़ाइल ठीक माँगे गए आकार में निकलती है, शुरुआती बाइट शून्य से ढके हुए, इसलिए रीडर उसे ठुकरा देता है, और मैनिफ़ेस्ट कहता है कि आपके सिस्टम को उसे अस्वीकार करना चाहिए। ब्योरा खराब टेस्ट फ़ाइलों वाले पेज पर है।

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

आगे कौन से फ़ॉर्मैट आ रहे हैं?

+
+

7z, mp3 और mp4। आज 26 फ़ॉर्मैट शुरू से अंत तक काम करते हैं।

+
+
+
+

मैं इसे किन सिस्टम पर चला सकता हूँ?

+
+

कमांड लाइन Windows और Linux पर Intel और ARM दोनों पर, और Apple Silicon Mac पर चलती है। डेस्कटॉप विंडो Intel पर Windows, Intel पर Linux और Apple Silicon Mac के लिए आती है। Intel Mac समर्थित नहीं हैं और उनके लिए कुछ नहीं बनाया जाता।

+
+
+
+

क्या मुझे कुछ इंस्टॉल करना होगा?

+
+

नहीं। अपने सिस्टम का आर्काइव डाउनलोड करें, खोलें और बाइनरी चलाएँ। कोई इंस्टॉलर नहीं, जोड़ने के लिए कोई रनटाइम नहीं और सुलझाने के लिए कोई निर्भरता नहीं। अगर आपके पास Go है तो एक ही go install कमांड भी काम करती है।

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

हज़ारों फ़ाइलों पर रन Windows पर धीमा क्यों है?

+
+

क्योंकि Windows हर उस पाथ के लिए ज़्यादा वसूलता है जिसे वह देखता है, और हज़ारों फ़ाइलों से गुज़रने वाली कमांड हज़ारों पाथ देखती है। 1 kB की 3000 फ़ाइलों वाली एक मशीन पर मापने पर, verify को Windows पर लगभग 0.9 सेकंड और कंटेनर में Linux पर लगभग 0.2 सेकंड लगे। छोटा आउटपुट पाथ Windows का आँकड़ा घटाता है, क्योंकि फ़ाइलों के ऊपर का हर फ़ोल्डर उसमें शामिल होता है जिसे देखा जाता है।

+
+
+
+ + +
+

अभी तय कर रहे हैं?

+

+ उपयोग के मामलों का पेज वे काम दिखाता है जिनके लिए यह बना है, और + फ़ॉर्मैट पेज हर फ़ॉर्मैट को उसकी सबसे छोटी संभव फ़ाइल के साथ सूचीबद्ध + करता है। रिपॉज़िटरी का README पूरा संदर्भ है। +

+ +

मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।

+
+ +
+ + + + diff --git a/web/public/hi/formats/index.html b/web/public/hi/formats/index.html new file mode 100644 index 00000000..c3a20686 --- /dev/null +++ b/web/public/hi/formats/index.html @@ -0,0 +1,911 @@ + + + + + + +26 समर्थित फ़ाइल फ़ॉर्मैट - PDF, DOCX, PNG, ZIP और अन्य + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 फ़ाइल फ़ॉर्मैट, हर एक सटीक आकार में बनाया गया

+

+ इनमें से हर एक उस फ़ॉर्मैट की असली फ़ाइल है। वह अपने सॉफ़्टवेयर में खुलती है और + उसमें ठीक उतने बाइट हैं जितने आपने माँगे। इनमें से कोई भी एक्सटेंशन चिपकाए गए भराव के शून्य नहीं + है। +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
फ़ॉर्मैटनामएक्सटेंशनसबसे छोटी फ़ाइलपूर्णताजाँच का साधन
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullलागू नहीं
mdMarkdown.md0fullलागू नहीं
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullलागू नहीं
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

कॉलम का अर्थ

+
    +
  • +

    सबसे छोटी फ़ाइल

    +

    + उस फ़ॉर्मैट के लिए यह टूल जितने कम से कम बाइट स्वीकार करेगा, उस लेबल समेत जो वह फ़ाइल के अंदर लिखता + है। इससे कम माँगें और आपको न्यूनतम सीमा और उसका कारण बताने वाली त्रुटि मिलती है, गलत आकार की + फ़ाइल कभी नहीं। +

    +
  • +
  • +

    पूर्णता

    +

    + फ़ाइल कितनी पूरी है। full का मतलब है कि फ़ॉर्मैट को सच में पार्स करने वाला रीडर उसे + स्वीकार करता है, सिर्फ़ यह नहीं कि एक्सटेंशन मिलता है। +

    +
  • +
  • +

    जाँच का साधन

    +

    + वह स्वतंत्र रीडर जो फ़ॉर्मैट भेजे जाने से पहले हर बनाई गई फ़ाइल खोलता है - एक अलग कार्यान्वयन, हमारा + अपना कोड नहीं जो अपना ही गृहकार्य जाँचे। +

    +
  • +
+

+ हर फ़ॉर्मैट बाइट तक दोहराया भी जाता है: वही रेसिपी और वही सीड किसी भी मशीन पर एक जैसी फ़ाइलें बनाते + हैं, और इसी से फ़िक्स्चर की जगह रेसिपी कमिट करना सुरक्षित होता है। +

+
+ +
+

हर फ़ॉर्मैट की स्वीकार की जाने वाली सेटिंग

+

+ ज़्यादातर फ़ॉर्मैट की अपनी सेटिंग होती हैं - इमेज के आयाम, JPEG गुणवत्ता, PDF के पेज, स्प्रेडशीट की + पंक्तियाँ और कॉलम, आर्काइव के अंदर कितनी प्रविष्टियाँ जाएँ। इन्हें कमांड लाइन पर --set + key=value से, या रेसिपी में properties: के नीचे सेट करें। +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
फ़ॉर्मैटसेटिंगस्वीकार्य मान
avifwidth1 - 16384 पिक्सेल
height1 - 16384 पिक्सेल
quality1 - 100
bmpwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerसही या गलत
quote_styleall, minimal, none
columns2 - 32768 कॉलम
docxparagraphs1 - 50000 अनुच्छेद
gifwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 पिक्सेल
height1 - 256 पिक्सेल
embedbmp, png
jpgwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 पिक्सेल
height1 - 16384 पिक्सेल
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 प्रति सेकंड प्रविष्टियाँ
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomसही या गलत
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleकोई भी टेक्स्ट
authorकोई भी टेक्स्ट
subjectकोई भी टेक्स्ट
keywordsकोई भी टेक्स्ट
creatorकोई भी टेक्स्ट
producerकोई भी टेक्स्ट
created2024-02-29 या 2024-02-29T13:45:00+02:00 जैसी तारीख, या none
modified2024-02-29 या 2024-02-29T13:45:00+02:00 जैसी तारीख, या none
pngwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
pptxslides1 - 500 स्लाइड
svgwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
targzentries0 - 10000
entry_formatकिसी फ़ॉर्मैट का id, जैसा tfg formats सूचीबद्ध करता है
entry_size2mb जैसा आकार
compressionbest, default, fast, none
depth0 - 50
directory_entriesसही या गलत
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 पिक्सेल
height1 - 20000 पिक्सेल
txtencodingutf-16be, utf-16le, utf-8
bomसही या गलत
wavsample_rate8000 - 192000 हर्ट्ज़
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 पिक्सेल
height1 - 16383 पिक्सेल
xlsxrows1 - 200000 पंक्तियाँ
columns1 - 32768 कॉलम
xmlencodingutf-16be, utf-16le, utf-8
bomसही या गलत
zipentries0 - 10000
entry_formatकिसी फ़ॉर्मैट का id, जैसा tfg formats सूचीबद्ध करता है
entry_size2mb जैसा आकार
compressionbest, default, fast, none
depth0 - 50
directory_entriesसही या गलत
passwordपासवर्ड, सादे टेक्स्ट में
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ किसी सेटिंग की स्वीकार्य सीमा से बाहर का मान एक संदेश के साथ ठुकरा दिया जाता है जो सेटिंग, मान्य + सीमा और इसके बदले क्या इस्तेमाल करें यह बताता है। अज्ञात सेटिंग भी त्रुटि है, कभी चुपचाप + डिफ़ॉल्ट नहीं - चुपचाप मान ली गई टाइपो गलत सेटिंग की फ़ाइल देती है और एक घंटा यह सोचने में जाता + है कि जिस टेस्ट को विफल होना था वह पास क्यों हो रहा है। +

+

+ जो बिल्ड आपके पास है उसमें कोई फ़ॉर्मैट ठीक क्या स्वीकार करता है, यह देखने के लिए tfg formats + <id> चलाएँ। +

+
+ +
+

आर्काइव में असली फ़ाइलें होती हैं

+

+ targz और zip को + खाली खोल छोड़ने के बजाय प्रविष्टियों से भरा जा सकता है। बनाया गया आर्काइव सच में वे दस्तावेज़ + रखता है जिनका वह दावा करता है, इसलिए टेस्ट के दौरान उसे खोलने वाली कोई भी चीज़ अंदर असली फ़ाइलें + पाती है। +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/hi/index.html b/web/public/hi/index.html new file mode 100644 index 00000000..daf4d895 --- /dev/null +++ b/web/public/hi/index.html @@ -0,0 +1,452 @@ + + + + + + +QA के लिए टेस्ट फ़ाइल जनरेटर - सटीक आकार, 26 असली फ़ॉर्मैट + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

सटीक आकार की असली टेस्ट फ़ाइलें बनाएँ

+

+ PDF, PNG, DOCX, ZIP - कुल 26 फ़ॉर्मैट, और हर एक असली फ़ाइल है + जो अपने सॉफ़्टवेयर में खुलती है, ठीक उसी आकार में जो आपने माँगा। हर रन यह भी + लिखता है कि आपके एप्लिकेशन को हर फ़ाइल के साथ क्या करना चाहिए। कमांड लाइन और डेस्कटॉप विंडो, + मुफ़्त और ओपन सोर्स, पूरी तरह आपकी मशीन पर चलता है। +

+ + +

मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।

+
+ +
+ Testing Files Generator की डेस्कटॉप विंडो, टेस्ट फ़ाइलों का बैच लिखने के लिए तैयार +
फ़ाइलों का बैच लिखने के लिए तैयार डेस्कटॉप विंडो। कमांड लाइन के पीछे वही इंजन चलता है।
+
+
+ +
    +
  • + 26 +

    असली फ़ॉर्मैट, हर एक अपने सॉफ़्टवेयर में खुलता है

    +
  • +
  • + 1 बाइट +

    आपके माँगे हर आकार की सटीकता, कभी चुपचाप राउंड नहीं की जाती

    +
  • +
  • + 0 +

    कहीं भी कनेक्शन - न खाता, न टेलीमेट्री, न अपडेट जाँच

    +
  • +
+ +
+

समस्या

+

एक टेस्ट फ़ाइल बनाना आसान है। सही हज़ार बनाना थकाऊ हिस्सा है

+

आप ऐसे सॉफ़्टवेयर को टेस्ट कर रहे हैं जो लोगों से फ़ाइलें लेता है। देर-सबेर आपको चाहिए होगा:

+
    +
  • ठीक 10 MB की एक PDF, यह पता करने के लिए कि अपलोड सीमा असली है या नहीं
  • +
  • उस सीमा के दोनों ओर की तीन फ़ाइलें, एक से चूकने वाली गलतियाँ पकड़ने के लिए
  • +
  • 10,000 लॉग फ़ाइलें, यह देखने के लिए कि फ़ोल्डर बड़ा होने पर रात का जॉब क्या करता है
  • +
  • एक ZIP जिसमें सच में 200 दस्तावेज़ हों, सही एक्सटेंशन वाला खोखला खोल नहीं
  • +
  • एक 4 GB की फ़ाइल, बिना अपनी रिपॉज़िटरी में 4 GB की फ़ाइल रखे
  • +
  • आपके लैपटॉप और बिल्ड सर्वर पर एक जैसे फ़िक्स्चर, बाइट-दर-बाइट
  • +
+

+ यही वह है जिसे यह बदलता है। यह QA इंजीनियरों, टेस्ट ऑटोमेशन और हर उस व्यक्ति के लिए बना है जिसके कोड + के पीछे अपलोड फ़ॉर्म, इंपोर्ट रूटीन, पार्सर या स्टोरेज कोटा है। +

+
+ +
+

यह अलग क्यों है

+

दूसरे जनरेटर बाइट पर रुक जाते हैं। यह वह बताता है जो आपका टेस्ट असल में पूछता है

+

+ फ़ाइलों से भरा फ़ोल्डर आपको फिर भी तय करने देता है कि हर फ़ाइल क्या साबित करे। यहाँ हर रन फ़ाइलों के + बगल में एक manifest.json लिखता है - जो कुछ बना उसकी सादी सूची, और हर प्रविष्टि के + लिए एक घोषित अपेक्षा। +

+

मान लें कि आपका अपलोड एंडपॉइंट 1 MB की अनुमति देता है। उस रेखा पर आने वाली तीन फ़ाइलें माँगें:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
फ़ाइलबाइटआपके सिस्टम को चाहिएक्योंकि
1mb_under_1b.pdf1048575मंज़ूर करनायह सीमा के अंदर है
1mb_at_limit.pdf1048576मंज़ूर करनासीमा ख़ुद अनुमत है
1mb_over_1b.pdf1048577अस्वीकार करनाsize_limit
+
+ +

तीन फ़ाइलें, तीन अलग जवाब, मशीन के पढ़ने लायक रूप में। आपका टेस्ट असर्शन हाथ से लिखने के बजाय मैनिफ़ेस्ट पढ़ता है:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

जहाँ जवाब आपकी अपनी नीति पर निर्भर है, वहाँ मैनिफ़ेस्ट यही कहता है

+

+ वह कोई अपेक्षा गढ़ने के बजाय unspecified दर्ज करता है। अंदाज़ा लगाने वाला जनरेटर झूठी + विफलताएँ पैदा करता है, और झूठा शोर मचाने वाला टेस्ट सूट आख़िरकार बंद कर दिया जाता है। +

+
+
+ +
+

प्रीसेट

+

सवाल चुनें, पूरा सेट पाएँ

+

+ प्रीसेट एक टेस्ट सवाल के इर्द-गिर्द बनाया गया टेस्ट फ़ाइलों का सेट है, ताकि आपको खुद न सोचना पड़े कि + कौन सी फ़ाइल क्या साबित करती है। हर एक का एक पेज है जो बताता है कि वह आम तौर पर क्या पकड़ता है, + सेट में क्या है और वह कौन सी सेटिंग लेता है। +

+
    +
  • +

    खाली और न्यूनतम

    +

    क्या फ़ॉर्मैट की अनुमति जितनी छोटी वैध फ़ाइल पास हो जाती है?

    +

    empty-and-minimal

    +
  • +
  • +

    फ़ाइल नाम का प्रबंधन

    +

    क्या मेरा सिस्टम ऐसा फ़ाइल नाम सहेजेगा, दिखाएगा और लौटाएगा जिसकी उसे उम्मीद नहीं थी?

    +

    filename-handling

    +
  • +
  • +

    आकार की सीमाएँ

    +

    क्या आकार की सीमा ठीक वहीं लागू होती है जहाँ उसकी घोषणा की गई है?

    +

    size-boundaries

    +
  • +
  • +

    टेबल इंपोर्ट

    +

    क्या मेरा टेबल इंपोर्ट वह झेल पाता है जो असली टूल एक्सपोर्ट करते हैं?

    +

    tabular-import

    +
  • +
  • +

    टेक्स्ट एन्कोडिंग

    +

    क्या मेरा रीडर जानता है कि फ़ाइल किस एन्कोडिंग में है, या अंदाज़ा लगा रहा है?

    +

    text-encoding

    +
  • +
  • +

    अपलोड सत्यापन

    +

    क्या मेरा अपलोड फ़ॉर्म वह लेता है जो उसे लेना चाहिए और बाकी को लौटा देता है?

    +

    upload-validation

    +
  • +
+

सभी प्रीसेट, और रेसिपी से उनका संबंध

+
+ +
+

जल्दी शुरू करें

+

इसे चलते देखने के लिए तीन कमांड

+
    +
  1. +

    एक फ़ाइल बनाएँ

    +

    एक PNG, ठीक दो मेगाबाइट की:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    बहुत सी फ़ाइलें बनाएँ

    +

    + दस हज़ार लॉग फ़ाइलें, हर एक एक से आठ किलोबाइट के बीच, आकार सीड से निकाले गए ताकि कल वही सेट मिले। + हर रन को उसकी अपनी डायरेक्टरी दें - रन ने जो लिखा उसका एकमात्र रिकॉर्ड + मैनिफ़ेस्ट है, इसलिए टूल उसके ऊपर दूसरा लिखने से इनकार कर देता है: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    उन्हें जाँचें, फिर हटाएँ

    +

    verify बताता है कि कुछ नहीं खिसका। cleanup जो लिखा गया था उसे ही हटाता है, और कुछ नहीं:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ आकार 1024 के गुणकों में गिने जाते हैं, जैसा आपका फ़ाइल मैनेजर करता है, इसलिए 2mb का + मतलब 2097152 बाइट है। सादी बाइट संख्या भी चलती है। दस्तावेज़ीकरण में + रेसिपी, मैनिफ़ेस्ट और एग्ज़िट कोड समझाए गए हैं। +

+
+ +
+

आपको क्या मिलता है

+

बिना निगरानी के चलने वाले सूट के लिए बना

+
    +
  • +

    सटीक आकार, बाइट तक

    +

    10485761 बाइट माँगें और ठीक वही पाएँ। जिस आकार तक कोई फ़ॉर्मैट नहीं पहुँच सकता, वह कारण सहित त्रुटि है, गलत आकार की फ़ाइल कभी नहीं।

    +
  • +
  • +

    26 असली फ़ॉर्मैट

    +

    एक्सटेंशन वाले भराव के शून्य नहीं। बनाई गई PNG इमेज व्यूअर में खुलती है, DOCX Word में खुलता है, ZIP खुल जाता है। हर एक को भेजने से पहले स्वतंत्र रीडरों से जाँचा जाता है।

    +
  • +
  • +

    टेस्ट ऑरेकल जैसा मैनिफ़ेस्ट

    +

    पाथ, आकार, SHA-256, फ़ॉर्मैट, सीड, टूल का संस्करण - और आपके सिस्टम को फ़ाइल के साथ क्या करना चाहिए।

    +
  • +
  • +

    दोहराए जा सकने वाला

    +

    वही रेसिपी और वही सीड, वही बाइट, किसी भी मशीन पर। बड़े बाइनरी फ़िक्स्चर की जगह एक छोटी YAML रेसिपी कमिट करें।

    +
  • +
  • +

    दो इंटरफ़ेस, एक इंजन

    +

    CI के लिए बनी कमांड लाइन और खोजपरक टेस्टिंग के लिए डेस्कटॉप विंडो। कोई भी दूसरे का घटाया हुआ रूप नहीं है, और एक टेस्ट दोनों की क्षमता-दर-क्षमता तुलना करता है।

    +
  • +
  • +

    पूरी तरह ऑफ़लाइन

    +

    कोई खाता नहीं, कोई क्लाउड नहीं, कोई टेलीमेट्री नहीं, कोई अपडेट जाँच नहीं। कमांड लाइन बाइनरी में नेटवर्क स्टैक कंपाइल ही नहीं किया गया है।

    +
  • +
+
+ +
+

डाउनलोड

+

अपने सिस्टम का बिल्ड चुनें

+

+ आर्काइव खोलें और चलाएँ। tfg कमांड लाइन है और tfg-gui डेस्कटॉप विंडो। कोई + इंस्टॉलर नहीं और आपकी मशीन पर जोड़ने को कुछ नहीं। +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
सिस्टमकमांड लाइनडेस्कटॉप विंडो
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

क्या हस्ताक्षरित है, और क्या नहीं

+

+ Windows और macOS के डाउनलोड हस्ताक्षरित हैं, इसलिए वे अज्ञात डेवलपर की चेतावनी के बिना शुरू होते + हैं। Linux वाले नहीं हैं, क्योंकि डेस्कटॉप Linux में उन पर हस्ताक्षर करने का कोई समकक्ष तरीका + नहीं है। हर आर्काइव रिलीज़ पेज पर verify-SHA256SUMS.txt में सूचीबद्ध है, ताकि आप + जाँच सकें कि आपने क्या डाउनलोड किया। +

+
+ +

मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।

+
+ + +
+ + + + diff --git a/web/public/hi/presets/empty-and-minimal/index.html b/web/public/hi/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..ef2ed19a --- /dev/null +++ b/web/public/hi/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +हर फ़ॉर्मैट की सबसे छोटी वैध और खाली टेस्ट फ़ाइलें + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

खाली और न्यूनतम

+

क्या फ़ॉर्मैट की अनुमति जितनी छोटी वैध फ़ाइल पास हो जाती है?

+

+ empty-and-minimal प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • एक वैध फ़ाइल जो बहुत छोटी होने के कारण ठुकरा दी जाती है, क्योंकि जाँच बाइट पढ़ने के बजाय गिनती है
  • +
  • एक खाली फ़ाइल जो रिपोर्ट होने के बजाय रीडर को क्रैश कर देती है
  • +
  • एक पिक्सेल चौड़ी तस्वीर जो थंबनेल तक के रास्ते में शून्य से भाग देती है
  • +
  • ऐसा स्टोरेज जो शून्य बाइट को असफल अपलोड समझकर बार-बार कोशिश करता रहता है
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show empty-and-minimal बताता है:

+
+ + + + + + + +
फ़ाइलें28
इसकी रेसिपी में टार्गेट28
कुल आकार32 667 B
फ़ॉर्मैटavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।26
unspecifiedयह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।2
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--formatsअल्पविराम से अलग किए गए फ़ॉर्मैट id, या allallसेट किन फ़ॉर्मैट से बना है। इस बिल्ड के सभी फ़ॉर्मैट के लिए all रहने दें, या वे फ़ॉर्मैट लिखें जिन्हें आपका सिस्टम स्वीकार करता है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/hi/presets/filename-handling/index.html b/web/public/hi/presets/filename-handling/index.html new file mode 100644 index 00000000..f4890d01 --- /dev/null +++ b/web/public/hi/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +टेस्टिंग के लिए समस्या वाले फ़ाइल नाम - Unicode और लंबाई + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

फ़ाइल नाम का प्रबंधन

+

क्या मेरा सिस्टम ऐसा फ़ाइल नाम सहेजेगा, दिखाएगा और लौटाएगा जिसकी उसे उम्मीद नहीं थी?

+

+ filename-handling प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • ऐसा नाम जो स्क्रीन, लॉग या सूची में किसी और नाम जैसा दिखता है
  • +
  • ऐसा नाम जो अपलोड और स्टोरेज के बीच कट जाता है, छँट जाता है या दोबारा लिख दिया जाता है
  • +
  • अक्षरों में गिनी जाने वाली लंबाई की सीमा, जबकि स्टोरेज बाइट गिनता है
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show filename-handling बताता है:

+
+ + + + + + + +
फ़ाइलें50
इसकी रेसिपी में टार्गेट50
कुल आकार51 200 B
फ़ॉर्मैटtxt
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।4
unspecifiedयह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।46
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--formatफ़ॉर्मैट पेज से एक फ़ॉर्मैट idtxtसेट की हर फ़ाइल का फ़ॉर्मैट। यह टूल का अपना फ़्लैग है, और प्रीसेट बस उसे एक डिफ़ॉल्ट देता है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/hi/presets/index.html b/web/public/hi/presets/index.html new file mode 100644 index 00000000..f0ec2de0 --- /dev/null +++ b/web/public/hi/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +टेस्ट फ़ाइल प्रीसेट - QA के सवालों के लिए तैयार सेट + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

टेस्ट फ़ाइल प्रीसेट, हर टेस्ट सवाल के लिए एक सेट

+

+ प्रीसेट एक सवाल के इर्द-गिर्द बनाया गया टेस्ट फ़ाइलों का पूरा सेट है, एक मैनिफ़ेस्ट के साथ जो बताता + है कि आपके सिस्टम को हर फ़ाइल पर क्या प्रतिक्रिया देनी चाहिए। आप सवाल चुनते हैं, टूल सेट बनाता है। + हर प्रीसेट का अपना पेज है जो बताता है कि वह आम तौर पर क्या पकड़ता है, सेट में क्या है और वह कौन सी + सेटिंग लेता है। +

+ +
    +
  • +

    खाली और न्यूनतम

    +

    क्या फ़ॉर्मैट की अनुमति जितनी छोटी वैध फ़ाइल पास हो जाती है?

    +

    empty-and-minimal

    +
  • +
  • +

    फ़ाइल नाम का प्रबंधन

    +

    क्या मेरा सिस्टम ऐसा फ़ाइल नाम सहेजेगा, दिखाएगा और लौटाएगा जिसकी उसे उम्मीद नहीं थी?

    +

    filename-handling

    +
  • +
  • +

    आकार की सीमाएँ

    +

    क्या आकार की सीमा ठीक वहीं लागू होती है जहाँ उसकी घोषणा की गई है?

    +

    size-boundaries

    +
  • +
  • +

    टेबल इंपोर्ट

    +

    क्या मेरा टेबल इंपोर्ट वह झेल पाता है जो असली टूल एक्सपोर्ट करते हैं?

    +

    tabular-import

    +
  • +
  • +

    टेक्स्ट एन्कोडिंग

    +

    क्या मेरा रीडर जानता है कि फ़ाइल किस एन्कोडिंग में है, या अंदाज़ा लगा रहा है?

    +

    text-encoding

    +
  • +
  • +

    अपलोड सत्यापन

    +

    क्या मेरा अपलोड फ़ॉर्म वह लेता है जो उसे लेना चाहिए और बाकी को लौटा देता है?

    +

    upload-validation

    +
  • +
+ +
+

प्रीसेट और रेसिपी में क्या अंतर है?

+

+ अंदर से, कोई नहीं। प्रीसेट वह रेसिपी है जो टूल कुछ सेटिंग से आपके लिए लिखता है। tfg preset + eject उस रेसिपी को छापता है ताकि आप उसे अपने टेस्ट के बगल में रखकर संपादित कर सकें, और + आपकी अपनी रेसिपी एक पंक्ति से प्रीसेट पर आगे बन सकती है, extends: preset: और उसके + बाद उसका id। +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

क्या मैं डिफ़ॉल्ट पर भरोसा कर सकता हूँ?

+

+ फ़ाइलों के लिए, हाँ। ऐसी संख्या के लिए जो सिर्फ़ आपका सिस्टम जानता है, जैसे अपलोड फ़ॉर्म की सीमा, + डिफ़ॉल्ट हमारी अस्थायी जगह-धारक संख्या होती है, और टूल जब भी ऐसा कोई इस्तेमाल करता है तब यह + बताता है। हर प्रीसेट का पेज उन सेटिंग पर निशान लगाता है, और tfg preset show कुछ भी + लिखे जाने से पहले यह बता देता है। +

+
+ +
+ + + + diff --git a/web/public/hi/presets/size-boundaries/index.html b/web/public/hi/presets/size-boundaries/index.html new file mode 100644 index 00000000..1100657c --- /dev/null +++ b/web/public/hi/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +अपलोड आकार सीमा की जाँच - ठीक सीमा पर की फ़ाइलें + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

आकार की सीमाएँ

+

क्या आकार की सीमा ठीक वहीं लागू होती है जहाँ उसकी घोषणा की गई है?

+

+ size-boundaries प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • सीमा पर एक से चूकने वाली गलतियाँ
  • +
  • MB और MiB का घालमेल, जो 4.8 प्रतिशत का फ़र्क है और ऐसी फ़ाइल निकल जाने देने के लिए काफ़ी है जिसे नहीं निकलना चाहिए
  • +
  • सीमा जो ब्राउज़र में लागू होती है, सर्वर पर नहीं
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show size-boundaries बताता है:

+
+ + + + + + + +
फ़ाइलें7
इसकी रेसिपी में टार्गेट7
कुल आकार73 400 320 B
फ़ॉर्मैटpdf
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।4
rejectआपके सिस्टम को फ़ाइल अस्वीकार करनी चाहिए।3
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--limit2mb जैसा आकार10mbआपके सिस्टम की घोषित आकार सीमा। बाकी सब कुछ इसी से नापा जाता है। यह डिफ़ॉल्ट हमारी अस्थायी जगह-धारक संख्या है, आपके सिस्टम का मान नहीं। अपना मान दें।
--spreadअल्पविराम से अलग किए गए आकार1B,1kb,1mbसीमा के दोनों ओर कितनी दूर तक जाना है, आकारों की सूची के रूप में।
--formatफ़ॉर्मैट पेज से एक फ़ॉर्मैट idpdfसेट की हर फ़ाइल का फ़ॉर्मैट। यह टूल का अपना फ़्लैग है, और प्रीसेट बस उसे एक डिफ़ॉल्ट देता है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

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

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/hi/presets/tabular-import/index.html b/web/public/hi/presets/tabular-import/index.html new file mode 100644 index 00000000..9d9dea42 --- /dev/null +++ b/web/public/hi/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +CSV और Excel इंपोर्ट टेस्ट फ़ाइलें - डेलिमिटर, हेडर + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

टेबल इंपोर्ट

+

क्या मेरा टेबल इंपोर्ट वह झेल पाता है जो असली टूल एक्सपोर्ट करते हैं?

+

+ tabular-import प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • अर्धविराम वाली फ़ाइल जो एक ही कॉलम की तरह पढ़ी जाती है, क्योंकि डेलिमिटर खोजा नहीं गया, मान लिया गया
  • +
  • CRLF फ़ाइल जो पंक्तियों में बँट जाती है और हर पंक्ति के बाद एक खाली पंक्ति आ जाती है
  • +
  • बिना हेडर की टेबल जिसकी डेटा की पहली पंक्ति कॉलम नाम समझकर निगल ली जाती है
  • +
  • ऐसा इंपोर्ट जो दिखा सकने वाले कॉलम रखता है और बाकी चुपचाप गिरा देता है
  • +
  • ऐसा रीडर जो JSON रिकॉर्ड एक-एक पंक्ति में लेता है और पहले इंडेंट वाले दस्तावेज़ पर रुक जाता है
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show tabular-import बताता है:

+
+ + + + + + + +
फ़ाइलें13
इसकी रेसिपी में टार्गेट13
कुल आकार3 080 060 B
फ़ॉर्मैटcsv, json, xlsx
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।8
unspecifiedयह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।5
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--rows1 - 200000 पंक्तियाँ1000स्प्रेडशीट में कितनी पंक्तियाँ हैं। फ़ाइल ठीक उसी आकार में लिखी जाती है जितने में उतनी पंक्तियाँ पैक होती हैं, इसलिए ऊपर का बजट इस मान के साथ खिसकता है।
--columns1 - 32768 कॉलम10स्प्रेडशीट की हर पंक्ति में कितने कॉलम हैं। पंक्तियों गुणा कॉलम की एक ऊपरी सीमा है, और उससे आगे माँगने पर कुछ भी लिखे जाने से पहले ही इनकार कर दिया जाता है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/hi/presets/text-encoding/index.html b/web/public/hi/presets/text-encoding/index.html new file mode 100644 index 00000000..f3892960 --- /dev/null +++ b/web/public/hi/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +टेक्स्ट एन्कोडिंग टेस्ट फ़ाइलें - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

टेक्स्ट एन्कोडिंग

+

क्या मेरा रीडर जानता है कि फ़ाइल किस एन्कोडिंग में है, या अंदाज़ा लगा रहा है?

+

+ text-encoding प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • ऐसा रीडर जो UTF-8 मान लेता है और UTF-16 फ़ाइल को तीन में से एक अक्षर या डिब्बों की पंक्तियों की तरह दिखाता है
  • +
  • बाइट ऑर्डर मार्क जो सामग्री की तरह पढ़ा जाता है, जिससे इंपोर्ट का पहला फ़ील्ड तीन अनजान अक्षरों से शुरू होता है
  • +
  • ऐसा इंपोर्टर जो शुरुआती बाइट से एन्कोडिंग का अंदाज़ा लगाता है और लंबी फ़ाइल पर अलग अंदाज़ा लगाता है
  • +
  • CRLF फ़ाइल जो हर पंक्ति के बाद खाली पंक्ति के साथ बँट जाती है, या कैरिज रिटर्न जो आख़िरी फ़ील्ड में रह जाता है
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show text-encoding बताता है:

+
+ + + + + + + +
फ़ाइलें20
इसकी रेसिपी में टार्गेट20
कुल आकार81 920 B
फ़ॉर्मैटcsv, log, md, txt, xml
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।10
unspecifiedयह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।10
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--sample2mb जैसा आकार4kbसेट की हर फ़ाइल कितनी बड़ी है। UTF-16 हर अक्षर के लिए दो बाइट रखता है, इसलिए विषम संख्या अस्वीकार हो जाती है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/hi/presets/upload-validation/index.html b/web/public/hi/presets/upload-validation/index.html new file mode 100644 index 00000000..49b3e474 --- /dev/null +++ b/web/public/hi/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +अपलोड सत्यापन टेस्ट फ़ाइलें - प्रकार, आकार और नाम + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

प्रीसेट

+

अपलोड सत्यापन

+

क्या मेरा अपलोड फ़ॉर्म वह लेता है जो उसे लेना चाहिए और बाकी को लौटा देता है?

+

+ upload-validation प्रीसेट एक कमांड में इस सवाल के लिए असली टेस्ट फ़ाइलों का पूरा सेट बनाता है, + और उनके बगल में एक manifest.json जो बताता है कि आपके सिस्टम को हर फ़ाइल पर क्या + प्रतिक्रिया देनी चाहिए। नीचे सब कुछ इस संस्करण के डिफ़ॉल्ट पर प्रोग्राम से पढ़ा गया है। +

+ + +
+

यह आम तौर पर क्या पकड़ता है?

+
    +
  • सीमा जो ब्राउज़र में लागू होती है, सर्वर पर नहीं
  • +
  • SVG या HTML फ़ाइल जिसे तस्वीर या सादा टेक्स्ट समझ लिया जाता है, जो फ़ॉर्म से स्क्रिप्ट निकाल ले जाने का एक तरीका है
  • +
  • फ़ाइल जो सिर्फ़ एक्सटेंशन से जाँची जाती है और कभी खोली नहीं जाती, इसलिए .jpg नाम की PDF निकल जाती है
  • +
  • ऐसा फ़ॉर्म जो आकार देखने से पहले पूरी बॉडी मेमोरी में पढ़ लेता है
  • +
  • PHOTO.JPG नाम का अपलोड जो ठुकरा दिया जाता है जबकि photo.jpg ले लिया जाता है, या उल्टा
  • +
  • रिक्त स्थान, कोष्ठक या ASCII से बाहर के अक्षरों वाला नाम जो बिना बदले डिस्क पर लिख दिया जाता है
  • +
+
+ + +
+

सेट में क्या है?

+

डिफ़ॉल्ट पर, जैसा tfg preset show upload-validation बताता है:

+
+ + + + + + + +
फ़ाइलें71
इसकी रेसिपी में टार्गेट22
कुल आकार120 639 488 B
फ़ॉर्मैटhtml, jpg, pdf, png, svg, txt
+
+

और उस सेट का मैनिफ़ेस्ट आपके सिस्टम से क्या अपेक्षा रखता है:

+
+ + + + + + + + + +
अपेक्षितअर्थफ़ाइलें
acceptआपके सिस्टम को फ़ाइल मंज़ूर करनी चाहिए।56
rejectआपके सिस्टम को फ़ाइल अस्वीकार करनी चाहिए।10
unspecifiedयह आपके सिस्टम के नियमों पर निर्भर है। आप तय करें, फिर जाँचें कि जो होता है वही है जो आप चाहते थे।5
+
+
+ +
+

आप क्या बदल सकते हैं?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
सेटिंगलेती हैडिफ़ॉल्टक्या करती है
--limit2mb जैसा आकार10mbआपके अपलोड फ़ॉर्म की घोषित आकार सीमा। यह सेट इसके दोनों ओर एक-एक क़दम लेता है - हर दूरी की फ़ाइल के लिए size-boundaries प्रीसेट चलाएँ। यह डिफ़ॉल्ट हमारी अस्थायी जगह-धारक संख्या है, आपके सिस्टम का मान नहीं। अपना मान दें।
--allowअल्पविराम से अलग किए गए फ़ॉर्मैट idjpg,png,pdfआपका फ़ॉर्म किन प्रकारों को स्वीकार करे। हर प्रकार उसी प्रकार की असली फ़ाइल बन जाता है, और ये पूरे सेट का सकारात्मक नियंत्रण हैं।
--denyअल्पविराम से अलग किए गए एक्सटेंशनsvg,html,exe,shआपका फ़ॉर्म किन एक्सटेंशन को ठुकराए। जिस एक्सटेंशन का इस बिल्ड में कोई फ़ॉर्मैट नहीं है, उसे भी उसी नाम की एक फ़ाइल मिलती है जिसमें सादा टेक्स्ट होता है।
--far-over10x, 2x, off2xएकमात्र बड़ी फ़ाइल सीमा से कितनी आगे जाती है। जहाँ सीमा के कई गुना लिखना डिस्क के लायक न हो, वहाँ इसे बंद कर दें।
--bulk0 - 10000 फ़ाइलें50एक साथ अपलोड में कितनी फ़ाइलें हैं। शून्य होने पर वह समूह सेट से पूरी तरह हट जाता है।
+
+
+ +
+

इसे कैसे चलाएँ?

+

देखें कि सेट की क़ीमत क्या होगी, उसे बनाएँ, या संपादन के लिए उसकी रेसिपी लें:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

या अपनी रेसिपी में, अपने टेस्ट के बगल में, इस पर आगे बनाएँ:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/hi/test-files-in-ci/index.html b/web/public/hi/test-files-in-ci/index.html new file mode 100644 index 00000000..cc6887c7 --- /dev/null +++ b/web/public/hi/test-files-in-ci/index.html @@ -0,0 +1,375 @@ + + + + + + +CI में टेस्ट फ़ाइलें - GitHub Actions, GitLab CI और PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

उपयोग के मामले

+

CI पाइपलाइन में टेस्ट फ़ाइलें कैसे बनाएँ

+

+ रिपॉज़िटरी में बाइनरी फ़िक्स्चर उसके इतिहास में हमेशा के लिए रह जाता है, diff में उसकी समीक्षा नहीं + हो सकती, और फ़ाइल बड़ी हो तो वह संभव ही नहीं रहता। इसके बजाय फ़ाइलें पाइपलाइन के भीतर रेसिपी से + बनाएँ। रेसिपी पाठ है, बाइट हर बार एक जैसे निकलते हैं, और आख़िरी कदम साबित करता है कि कुछ नहीं + खिसका। +

+ +
+

छोटा जवाब

+

+ tfg इंस्टॉल करें, टेस्ट से पहले tfg generate fixtures.yaml --out + ./fixtures चलाएँ और उनके बाद tfg verify ./fixtures/manifest.json। दोनों कदम + अपने आप बिल्ड को विफल करते हैं, एक ऐसे एग्ज़िट कोड के साथ जो कारण बताता है। +

+
+ +
+

कमिट क्यों न करें

+

फ़िक्स्चर रिपॉज़िटरी में क्यों नहीं रहना चाहिए

+
    +
  • + यह इतिहास में रह जाता है। बाद में बाइनरी हटाने से क्लोन छोटा नहीं होता, क्योंकि + उसका हर संस्करण अब भी वहीं है। +
  • +
  • + diff नहीं दिखाता कि क्या बदला। समीक्षक को बस दिखता है कि PDF अलग है, और कुछ नहीं। + रेसिपी एक पंक्ति से बदलती है। +
  • +
  • + बड़ी फ़ाइलें समाती नहीं। GitHub 100 MB से बड़ी फ़ाइल वाले पुश को ठुकरा देता है, + इसलिए 500 MB की अपलोड सीमा के टेस्ट के पास कमिट करने को कुछ नहीं है। +
  • +
+

+ कमिट करने की चीज़ रेसिपी है। वही रेसिपी और वही सीड हर मशीन पर वही बाइट लिखते हैं, इसलिए पाइपलाइन में + बनी फ़ाइल वही फ़ाइल है जो आपके लैपटॉप पर थी। +

+
+ +
+

रेसिपी

+

टेस्ट के बगल में रहने वाली रेसिपी

+

+ यह पच्चीस चालान लिखती है जिन्हें स्वीकार होना चाहिए और सीमा से ऊपर की दो छवियाँ जिन्हें अस्वीकार + होना चाहिए, और मैनिफ़ेस्ट दोनों अपेक्षाएँ दर्ज करता है: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml उसे बिना कुछ लिखे जाँचता है और सारी समस्याएँ एक साथ बता देता + है। +

+
+ +
+

GitHub Actions

+

एक वर्कफ़्लो जो टूल इंस्टॉल करता है और फ़िक्स्चर बनाता है

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ चेकसम वाली पंक्ति संग्रह को उसी रिलीज़ की verify-SHA256SUMS.txt से मिलाती है। संस्करण + तय कर दिया गया है, इसलिए नई रिलीज़ कभी ऐसे बिल्ड को नहीं बदलती जिसे आपने छुआ नहीं। +

+
+ +
+

GitLab CI

+

वही बात GitLab जॉब के रूप में

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

जब यह लाल हो जाए

+

क्या किसी कदम को विफल करता है, और क्यों

+

+ हर अंत का अपना एग्ज़िट कोड है, इसलिए कदम अपने आप विफल होता है और लॉग बताता है कि कौन-सा था। जो + पाइपलाइन को मिलते हैं: +

+
    +
  • 3 - रेसिपी मान्य नहीं है। कुछ नहीं लिखा गया, और हर समस्या का नाम लिया गया है
  • +
  • 4 - फ़ॉर्मैट वह नहीं कर सकता जो माँगा गया, जैसे अपने न्यूनतम से नीचे का आकार
  • +
  • 6 - डिस्क पर पर्याप्त जगह नहीं है
  • +
  • 7 - tfg verify को एक फ़ाइल मिली जो अपने मैनिफ़ेस्ट से मेल नहीं खाती
  • +
  • 8 - रन पूरा हुआ, पर सब कुछ बना नहीं
  • +
+

+ विफल रन स्टैंडर्ड आउटपुट पर कुछ नहीं छापता, इसलिए लॉग पार्सर कभी किसी त्रुटि को डेटा नहीं समझता। + पूरी तालिका दस्तावेज़ के पेज पर है। +

+
+ +
+

PowerShell

+

PowerShell स्क्रिप्ट को एक पंक्ति और चाहिए

+

+ PowerShell किसी प्रोग्राम का एग्ज़िट कोड .ps1 फ़ाइल से बाहर नहीं ले जाता। एक को + -File से चलाएँ तो स्क्रिप्ट 0 देती है, चाहे भीतर के टूल ने काम से + इनकार कर दिया हो, और जो बिल्ड लाल होना चाहिए वह हरा हो जाता है। आख़िरी पंक्ति ही पूरा सुधार है: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell ऐसा ही बरतता है, यह इस टूल की बात नहीं है। cmd, bash और + zsh को कुछ अतिरिक्त नहीं चाहिए। +

+
+ +
+

कई जॉब

+

जॉब के बीच फ़िक्स्चर साझा करना

+

+ आम तौर पर उन्हें अपलोड करने की ज़रूरत नहीं होती। क्योंकि वही रेसिपी वही बाइट लिखती है, हर जॉब अपना + tfg generate चला सकता है, जो अपलोड और डाउनलोड से तेज़ है। जब किसी जॉब को दूसरे से + फ़ाइलें लेनी हों, तो ट्रांसफ़र के बाद मैनिफ़ेस्ट पर tfg verify चलाएँ, और वह बताएगा + कि जो पहुँचा वही है जो लिखा गया था। +

+
+ +
+

आगे

+

यहाँ से कहाँ जाएँ

+ +
+ +
+ + + + diff --git a/web/public/hi/use-cases/index.html b/web/public/hi/use-cases/index.html new file mode 100644 index 00000000..5e000dac --- /dev/null +++ b/web/public/hi/use-cases/index.html @@ -0,0 +1,317 @@ + + + + + + +उपयोग के मामले - अपलोड सीमा, CI फ़िक्स्चर, बड़े पैमाने पर टेस्ट + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

लोग इसका इस्तेमाल किसलिए करते हैं

+

+ पाँच काम जो लोगों से फ़ाइलें लेने वाले लगभग हर प्रोजेक्ट में आते हैं, और हर एक को करने वाली कमांड। + नीचे का हर उदाहरण जैसा लिखा है वैसा चलता है। +

+ +
+

अपलोड सीमाएँ

+

यह जाँचना कि फ़ाइल आकार सीमा वहीं लागू होती है जहाँ वह कहती है

+

+ एक सीमा एक नहीं, तीन टेस्ट केस है: ठीक नीचे, ठीक पर, और ठीक ऊपर। इन्हें हाथ से बनाने का मतलब बाइट + संख्या निकालना और उम्मीद करना है कि आप एक से नहीं चूके। इसके बजाय सेट माँगें: +

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

+ आपको 1048575, 1048576 और 1048577 बाइट की तीन असली PDF मिलती हैं, और एक मैनिफ़ेस्ट जो कहता है कि पहली + दो स्वीकार होनी चाहिए और तीसरी size_limit के कारण अस्वीकार। आपका टेस्ट तीन असर्शन + हाथ से लिखने के बजाय अपेक्षा पढ़ता है - और जब सीमा बदलती है तो आप एक संख्या बदलकर दोबारा चलाते + हैं। +

+

+ जब आप इनलाइन एक ही सीमा सेट चाहें तो यही प्रीसेट के बिना भी चलता है: +

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

सतत एकीकरण

+

फ़िक्स्चर को खोए बिना रिपॉज़िटरी से बाहर रखना

+

+ बड़े बाइनरी फ़िक्स्चर रिपॉज़िटरी क्लोन करना धीमा और रिव्यू करना कठिन बनाते हैं, और किसी एक के बदले + जाने पर कोई नहीं बता सकता कि क्या बदला। रेसिपी कुछ सौ अक्षरों की YAML है जो वही फ़ाइलें दोबारा + बना देती है - किसी भी मशीन पर बाइट-दर-बाइट - क्योंकि हर फ़ाइल रन के सीड से + निकलती है। +

+
- 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
+

+ हर अंत का अपना एग्ज़िट कोड है, इसलिए पाइपलाइन खराब रेसिपी, भरी डिस्क और सत्यापन असंगति में अंतर कर + सकती है। विफल रन स्टैंडर्ड आउटपुट पर कुछ नहीं छापता, जिससे लॉग पार्सर किसी त्रुटि को डेटा नहीं + पढ़ता। +

+
+ +
+

पैमाना

+

यह जानना कि फ़ोल्डर बड़ा होने पर क्या होता है

+

+ इंपोर्ट रूटीन, रात के जॉब और डायरेक्टरी सूचियाँ दस हज़ार फ़ाइलों पर दस की तुलना में अलग व्यवहार करती + हैं। किसी सीमा से निकाले गए आकार सेट को दस हज़ार एक जैसी फ़ाइलों के बजाय असली ट्रैफ़िक जैसा + दिखाते हैं, और निकालना सीड से होता है, इसलिए सेट कल भी वही रहता है। +

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

+ कुछ भी लिखे जाने से पहले देखें कि रन की क़ीमत क्या होगी, जो तब मायने रखता है जब कुल गीगाबाइट में + नापा जाए: +

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

+ डिस्क की खाली जगह से बड़ा रन पहला बाइट लिखे जाने से पहले ठुकरा दिया जाता है, डिस्क भरकर बीच में विफल + होने के बजाय। +

+
+ +
+

आर्काइव

+

ऐसे आर्काइव से अनपैकर का परीक्षण जिसमें सच में फ़ाइलें हैं

+

+ सही एक्सटेंशन वाला खाली आर्काइव उस कोड के बारे में कुछ साबित नहीं करता जो उसे खोलकर अंदर की चीज़ों + से गुज़रता है। सामग्री घोषित करें और आर्काइव सच में उसे रखता है: +

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

+ नेस्टिंग की गहराई, प्रविष्टियों की संख्या और अंदर की चीज़ों का आकार, ये सब वे बातें हैं जिन पर + इंपोर्ट रूटीन की अपनी राय होती है, और इसी तरह आप जानते हैं कि वह राय क्या है। +

+
+ +
+

पार्सर और व्यूअर

+

यह जाँचना कि आपका अपना कोड फ़ॉर्मैट को असली सॉफ़्टवेयर की तरह पढ़ता है

+

+ यहाँ का हर फ़ॉर्मैट भेजे जाने से पहले स्वतंत्र रीडर से जाँचा जाता है - PNG खोली जाती है और उसके + पिक्सेल मिलाए जाते हैं, DOCX अलग लाइब्रेरी से वापस पढ़ा जाता है, आर्काइव खोला जाता है। इसका मतलब + है कि जो फ़ाइल आपका पार्सर ठुकराता है वह आपके पार्सर के बारे में एक खोज है, जनरेटर के बारे में + नहीं। +

+
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
+

+ फ़ॉर्मैट पेज हर एक की स्वीकार की जाने वाली सेटिंग और हर एक की सबसे छोटी + संभव फ़ाइल सूचीबद्ध करता है। +

+
+ +
+

गाइड

+

इनमें से दो, विस्तार से

+
    +
  • + खराब टेस्ट फ़ाइलें - जानबूझकर बिगाड़ी गई, ठीक-ठीक आकार की + फ़ाइल, जिसके साथ क्या होना चाहिए वह मैनिफ़ेस्ट में लिखा है। +
  • +
  • + CI में टेस्ट फ़ाइलें - GitHub Actions का वर्कफ़्लो, GitLab का + जॉब और वे एग्ज़िट कोड जो बिल्ड को विफल करते हैं। +
  • +
+
+ +
+

यह किसके लिए है

+

+ QA इंजीनियर, टेस्ट ऑटोमेशन और हर वह व्यक्ति जिसके कोड के पीछे अपलोड फ़ॉर्म, इंपोर्ट रूटीन, पार्सर या + स्टोरेज कोटा है। यह बिना किसी नेटवर्क की मशीन पर चलता है, जो बंद कॉर्पोरेट माहौल में मायने रखता + है जहाँ ब्राउज़र आधारित जनरेटर विकल्प नहीं होता। +

+ +

मुफ़्त और ओपन सोर्स, GPL-3.0। साइन अप की ज़रूरत नहीं। Windows और macOS के डाउनलोड हस्ताक्षरित हैं और बिना चेतावनी के शुरू होते हैं।

+
+ +
+ + + + diff --git a/web/public/id/dokumentasi/index.html b/web/public/id/dokumentasi/index.html new file mode 100644 index 00000000..93230cf9 --- /dev/null +++ b/web/public/id/dokumentasi/index.html @@ -0,0 +1,561 @@ + + + + + + +Dokumentasi - Perintah, Resep, Manifes, Kode Keluar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Dokumentasi

+

+ Semua yang dilakukan alat ini, disusun sebagai pertanyaan yang benar-benar dibawa orang. + README di repositori adalah referensi lengkap dan selalu sesuai + dengan build yang Anda unduh. +

+ +
+

Perintah apa saja yang ada?

+

Masing-masing melakukan satu hal:

+
tfg generate    menghasilkan file, dari resep atau dari opsi
+tfg validate    memeriksa resep tanpa menulis apa pun
+tfg verify      memeriksa direktori terhadap manifes
+tfg cleanup     menghapus file yang tercantum dalam manifes
+tfg recipe fmt  mencetak resep dalam bentuk bakunya
+tfg preset      membuat set file dari pertanyaan pengujian bernama
+tfg formats     mendaftar format yang didukung build ini
+tfg damage      mendaftar cara build ini dapat merusak file dengan sengaja
+tfg tool        alat kecil untuk file yang sudah Anda miliki
+tfg version     mencetak versi alat
+tfg license     mencetak lisensi dan artinya bagi file yang dihasilkan
+
+ +
+

Bagaimana cara membuat satu file dengan ukuran tepat?

+

+ Sebutkan format, ukuran, dan tujuannya. Ukuran dihitung dalam kelipatan 1024, jadi 2mb + adalah 2097152 byte. Jumlah byte biasa juga bisa, jadi --size 10485761 meminta + persis sebanyak itu. +

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

Opsi yang berguna pada generate:

+
+ + + + + + + + + + + + + + + + + +
OpsiFungsinya
--format <id>format file, misalnya txt
--size <size>ukuran tepat setiap file, seperti 10mb atau jumlah byte biasa
--size-range <a-b>ukuran yang diundi per file dari suatu rentang, seperti 1kb-8kb. Undiannya berasal dari seed
--boundary <size>tiga file di sekitar batas: satu byte di bawah, batas itu sendiri, satu byte di atas
--count <n>berapa banyak file yang dibuat. Bawaan 1
--name <template>templat nama, misalnya invoice_{index:04}.txt
--out <dir>direktori tujuan penulisan
--seed <n>seed run. Seed yang sama menghasilkan byte yang sama
--set <k>=<v>pengaturan format, dapat diulang
--damage <name>merusak file dengan sengaja, dapat diulang dan diterapkan berurutan. Jalankan tfg damage untuk daftarnya
--expected <outcome>accept, reject, sanitize, atau unspecified
--dry-runmenghitung dan menampilkan, tidak menulis apa pun
--jsonmenulis manifes ke keluaran standar
+
+
+ +
+

Bagaimana membuat file yang sengaja dirusak?

+

+ Setiap file lain yang ditulis alat ini benar menurut konstruksinya, yang menjawab dua dari tiga + pertanyaan yang diajukan validator unggahan. --damage menjawab yang ketiga - apakah + file itu dapat dibuka sama sekali. File dibuat secara normal lalu dirusak, sehingga ukurannya + tetap seperti yang Anda minta. +

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

+ Pengaturan ditulis setelah titik dua. Opsinya dapat diulang, dan urutan penulisannya adalah urutan + penerapannya. tfg damage mendaftar apa yang bisa dilakukan build ini dan apa yang + diterima masing-masing. +

+

Dalam resep, kuncinya adalah daftar, berisi nama atau pengaturan:

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

+ File yang dirusak mendapat expected: reject di manifes, dengan kerusakan dicatat di + sampingnya. Dua hal ditolak sebelum apa pun ditulis, karena masing-masing akan menaruh file di + disk yang digambarkan manifes secara keliru: +

+
    +
  • file yang lebih kecil dari yang dibutuhkan kerusakan, karena akan keluar tanpa perubahan
  • +
  • + expected: accept di samping kerusakan, karena tidak ada yang dapat memenuhinya. Tulis + sanitize bila sistem yang diuji dimaksudkan memperbaiki file, atau + unspecified bila itulah pertanyaan yang Anda ajukan +
  • +
+

+ Yang ketiga tidak dapat diketahui sebelumnya. Bila suatu kerusakan berjalan dan tidak menggeser satu + byte pun, file itu dibuang alih-alih ditulis - run berlanjut, menyebut file mana itu, dan + berakhir dengan kode keluar parsial. +

+

+ Langkah demi langkah, dengan tes yang membaca manifes: cara membuat + file rusak untuk pengujian. +

+
+ +
+

Seperti apa bentuk sebuah resep?

+

+ Resep adalah file YAML yang menggambarkan satu run utuh. Commit di samping pengujian Anda dan + fixture berhenti menjadi biner di repositori Anda - siapa pun dapat membangunnya kembali, byte + demi byte, dari file berisi beberapa ratus karakter. +

+
# 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
+

+ Setiap target memerlukan tepat satu dari size, size-range, + boundary, atau contains. Dua adalah galat dan tidak ada juga galat. + Resep yang tidak valid menulis tidak ada file sama sekali dan melaporkan semua + masalah sekaligus, bukan hanya yang pertama, masing-masing menyebut pengaturan yang dimaksud. +

+
+ +
+

Bagaimana menyatakan apa yang harus dilakukan sistem saya terhadap sebuah file?

+

Bentuk pendek bila hasilnya sudah cukup, bentuk panjang bila alasannya penting:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Hasilnya adalah accept, reject, sanitize, dan + unspecified. Alasannya adalah daftar tertutup agar laporan dapat mengelompokkan + berdasarkan itu: 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, dan + size_zero. +

+

+ Alasan menyebut aturan yang berlaku, bukan putusannya. Itulah sebabnya alasan yang + sama dapat berada di bawah kedua hasil - file satu byte di bawah batas adalah + accept, dan aturan yang dimaksud tetap size_limit. +

+
+ +
+

Apa isi manifes?

+

+ Manifes ditulis di samping file pada akhir setiap run, termasuk run yang terhenti. Satu entri per + file: +

+
{
+  "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 ditambahkan bila run berasal dari resep, dan preset dengan + overrides bila berasal dari preset, sehingga manifes selalu dapat ditelusuri ke apa + yang menghasilkannya. +

+

+ Setiap entri juga membawa target_id, id target dalam resep yang menghasilkan file, dan + summary.by_target menghitung file yang dihasilkan tiap target. Resep dengan + beberapa target dapat diperiksa target demi target tanpa membaca nama file. +

+
+ +
+

Apa itu preset?

+

+ Set file siap pakai yang menjawab pertanyaan pengujian umum, sehingga Anda tidak perlu merancang + setnya sendiri. Preset pada dasarnya resep biasa, dan eject mencetak resepnya agar + dapat Anda sunting dari sana. Setiap preset memiliki halamannya + sendiri berisi apa yang biasanya ditemukan, isi set, dan setiap pengaturan yang diterimanya. +

+
    +
  • +

    Kosong dan minimal

    +

    Apakah file valid yang sekecil yang diizinkan format dapat lolos?

    +

    empty-and-minimal

    +
  • +
  • +

    Penanganan nama file

    +

    Apakah sistem saya akan menyimpan, menampilkan, dan mengembalikan nama file yang tidak diduganya?

    +

    filename-handling

    +
  • +
  • +

    Batas ukuran

    +

    Apakah batas ukuran ditegakkan tepat di tempat batas itu dinyatakan?

    +

    size-boundaries

    +
  • +
  • +

    Impor tabel

    +

    Apakah impor tabel saya tahan terhadap apa yang diekspor alat sungguhan?

    +

    tabular-import

    +
  • +
  • +

    Enkoding teks

    +

    Apakah pembaca saya tahu enkoding suatu file, atau hanya menebak?

    +

    text-encoding

    +
  • +
  • +

    Validasi unggahan

    +

    Apakah formulir unggah saya menerima yang seharusnya dan menolak sisanya?

    +

    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 memberi tahu berapa biaya set sebelum Anda membuatnya, dan menyatakan terus terang + bila sebuah angka adalah nilai sementara dari kami, bukan batas dari Anda. +

+
+ +
+

Apa arti kode keluar?

+

+ Setiap akhir punya kodenya sendiri, keluaran yang terbaca mesin masuk ke keluaran standar, dan run + yang gagal tidak mencetak apa pun di sana. Tabelnya adalah kontrak beku - mengubah arti sebuah + kode memerlukan kenaikan versi mayor. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KodeArti
0Semuanya berjalan.
1Kesalahan tak terduga di dalam alat.
2Perintah atau opsi salah.
3Resep tidak valid.
4Format tidak dapat melakukan yang diminta.
5Pembacaan atau penulisan gagal.
6Ruang disk tidak cukup.
7verify menemukan ketidakcocokan.
8Run selesai tetapi tidak semuanya dihasilkan.
130Dihentikan dengan Ctrl+C.
143Dihentikan oleh sinyal, seperti tampilan batas waktu 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
+

+ Run yang dihentikan dengan Ctrl+C tetap meninggalkan manifes dan tidak pernah meninggalkan file yang + tertulis setengah, sehingga job yang dibatalkan masih dapat dibersihkan oleh yang berikutnya. +

+

+ Workflow siap pakai untuk GitHub Actions dan GitLab CI: cara membuat + file uji di pipeline CI. +

+
+ +
+

Apakah ada jendela desktop?

+

+ Ada, mesin yang sama dengan jendela di atasnya, untuk pengujian yang tidak diskripkan. Ini bukan + versi terpangkas: sebuah pengujian membandingkan kedua antarmuka kemampuan demi kemampuan, dan + apa pun yang hanya dapat dilakukan salah satunya harus dinyatakan dan dibenarkan alih-alih + diam-diam menyimpang. +

+

+ Layarnya adalah satu batch, preset, beberapa batch sekaligus, dan tentang. Jendela ini menunjukkan + biaya sebuah run sebelum menulis apa pun, melaporkan kemajuan selama berjalan, dan dapat + dibatalkan di tengah jalan tanpa meninggalkan file yang tertulis setengah. Jendela ini belum + membuka file resep - untuk saat ini resep urusan baris perintah, dan jendela membangun batch-nya + di formulir. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/faq/index.html b/web/public/id/faq/index.html new file mode 100644 index 00000000..5a072fbc --- /dev/null +++ b/web/public/id/faq/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - Pertanyaan tentang Membuat File Uji + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Pertanyaan yang sering diajukan

+

+ Lisensi, privasi, reproduksibilitas, dan hal-hal yang diperiksa orang sebelum memasukkan generator + ke pipeline build. Bila pertanyaan Anda tidak ada di sini, pelacak + isu terbuka. +

+ +
+
+

Apa bedanya dengan dd, fsutil, atau truncate?

+
+

Perintah itu memberi Anda file berukuran benar yang berisi kekosongan. File 2 MB bernama photo.png yang dibuat begitu bukanlah PNG, sehingga apa pun yang benar-benar mem-parsing-nya akan menolaknya karena alasan yang salah, dan pengujian Anda pun lolos karena alasan yang salah juga. Alat ini menghasilkan PNG asli berukuran tepat 2 MB yang terbuka di penampil gambar, dan disertai pernyataan tentang bagaimana sistem Anda harus memperlakukannya.

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

Apakah gratis, dan bisakah saya pakai di tempat kerja?

+
+

Ya untuk keduanya. Dirilis di bawah GPL-3.0 dan tidak berbayar. Tidak ada akun, kunci lisensi, atau tingkat berbayar.

+
+
+
+

Bisakah saya memakai file yang dihasilkan dalam produk closed source?

+
+

Bisa. Lisensi mencakup kode alatnya, bukan apa yang dihasilkan alat itu. File, resep, dan manifes yang dihasilkan adalah keluaran, bukan karya turunan, sehingga Anda dapat meng-commit dan mendistribusikannya tanpa kewajiban apa pun.

+
+
+
+

Apakah file yang dihasilkan berisi data pribadi sungguhan?

+
+

Tidak. Semua isinya disintesis dari sebuah seed. Tidak ada dataset yang dibaca, tidak ada layanan yang dihubungi, dan tidak ada konten pihak ketiga yang disematkan. Perlakukan alamat e-mail yang dihasilkan sebagai tidak dapat dipakai, bukan sekadar belum dipakai, karena string acak apa pun bisa kebetulan sama dengan alamat sungguhan.

+
+
+
+

Apakah saya akan mendapat file yang persis sama di mesin lain?

+
+

Ya, byte demi byte, dengan resep dan seed yang sama. Proyek ini mengujinya pada setiap perubahan, dan melanggarnya memerlukan kenaikan versi mayor. Itulah yang memungkinkan Anda meng-commit resep kecil alih-alih fixture biner besar.

+
+
+
+

Apakah memerlukan koneksi internet?

+
+

Tidak pernah. Tidak ada telemetri, pemeriksaan pembaruan, atau klien cloud, dan biner baris perintah sama sekali tidak memiliki stack jaringan yang dikompilasi di dalamnya. Alat ini berjalan di mesin tanpa jaringan dan di lingkungan korporat yang tertutup.

+
+
+
+

Apa yang terjadi bila saya meminta ukuran yang tidak dapat dicapai suatu format?

+
+

Anda mendapat galat yang menyebut format, ukuran terkecilnya, alasan batas bawah itu, dan apa yang harus dilakukan sebagai gantinya, dan tidak ada file yang ditulis. Alat ini tidak pernah membulatkan ukuran secara diam-diam. Setiap batas bawah tercantum di halaman format.

+
tfg formats png
+
+
+
+

Bisakah saya membuat file yang sengaja dirusak?

+
+

Ya. Tambahkan --damage zero-head dan file keluar dengan ukuran tepat seperti yang diminta, dengan byte pertamanya ditimpa nol, sehingga pembaca menolaknya, dan manifes menyatakan sistem Anda harus menolaknya. Rinciannya ada di halaman tentang file uji yang rusak.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Format apa yang akan hadir berikutnya?

+
+

7z, mp3, dan mp4. Saat ini 26 format bekerja dari ujung ke ujung.

+
+
+
+

Di sistem apa saya bisa menjalankannya?

+
+

Baris perintah berjalan di Windows dan Linux pada Intel maupun ARM, dan di Mac Apple Silicon. Jendela desktop disediakan untuk Windows di Intel, Linux di Intel, dan Mac Apple Silicon. Mac Intel tidak didukung dan tidak ada build untuknya.

+
+
+
+

Apakah saya harus menginstal sesuatu?

+
+

Tidak. Unduh arsip untuk sistem Anda, ekstrak, dan jalankan binernya. Tidak ada installer, tidak ada runtime yang harus ditambahkan, dan tidak ada dependensi yang harus diselesaikan. Bila Anda punya Go, satu perintah go install juga bisa.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Mengapa run atas ribuan file lebih lambat di Windows?

+
+

Karena Windows membebankan lebih banyak untuk setiap path yang diperiksanya, dan perintah yang menelusuri ribuan file memeriksa ribuan path. Diukur di satu mesin dengan 3000 file berukuran 1 kB, verify memakan sekitar 0,9 detik di Windows dan sekitar 0,2 detik di Linux dalam container. Path keluaran yang lebih pendek memperkecil angka Windows, karena setiap folder di atas file ikut diperiksa.

+
+
+
+ + +
+

Masih menimbang?

+

+ Halaman kasus penggunaan menunjukkan pekerjaan yang untuknya + alat ini dibuat, dan halaman format mencantumkan setiap format beserta + file terkecil yang dapat dibuatnya. README di repositori adalah + referensi lengkap. +

+ +

Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/file-uji-di-ci/index.html b/web/public/id/file-uji-di-ci/index.html new file mode 100644 index 00000000..15db825c --- /dev/null +++ b/web/public/id/file-uji-di-ci/index.html @@ -0,0 +1,377 @@ + + + + + + +File uji di CI - GitHub Actions, GitLab CI, dan PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Kasus Penggunaan

+

Cara membuat file uji di pipeline CI

+

+ Fixture biner di repositori tinggal selamanya dalam riwayatnya, tidak bisa ditinjau di diff, dan + menjadi mustahil ketika filenya besar. Buat file di dalam pipeline dari sebuah resep. Resep adalah + teks, byte keluar sama setiap kali, dan langkah terakhir membuktikan tidak ada yang bergeser. +

+ +
+

Jawaban singkat

+

+ Pasang tfg, jalankan tfg generate fixtures.yaml --out ./fixtures sebelum + tes dan tfg verify ./fixtures/manifest.json sesudahnya. Kedua langkah menggagalkan + build dengan sendirinya, dengan kode keluar yang menyebut alasannya. +

+
+ +
+

Mengapa tidak di-commit

+

Mengapa fixture tidak seharusnya tinggal di repositori

+
    +
  • + Ia tetap ada di riwayat. Menghapus file biner kemudian tidak mengecilkan klon, + karena setiap versinya masih ada. +
  • +
  • + Diff tidak menunjukkan apa yang berubah. Peninjau hanya melihat bahwa sebuah PDF + berbeda, tidak lebih. Resep berubah satu baris. +
  • +
  • + File besar tidak muat. GitHub menolak push yang berisi file lebih dari 100 MB, jadi + tes batas unggah 500 MB tidak punya apa pun untuk di-commit. +
  • +
+

+ Yang di-commit adalah resepnya. Resep dan seed yang sama menulis byte yang sama di setiap mesin, + jadi file yang dibuat di pipeline adalah file yang Anda punya di laptop. +

+
+ +
+

Resep

+

Resep yang tinggal di samping tes

+

+ Resep ini menulis dua puluh lima faktur yang harus diterima dan dua gambar di atas batas yang harus + ditolak, dan manifes mencatat kedua harapan itu: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml memeriksanya tanpa menulis apa pun, dan menyebut semua + masalah sekaligus. +

+
+ +
+

GitHub Actions

+

Workflow yang memasang alat dan membangun fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Baris checksum membandingkan arsip dengan verify-SHA256SUMS.txt dari rilis yang sama. + Versinya dikunci, jadi rilis baru tidak pernah mengubah build yang tidak Anda sentuh. +

+
+ +
+

GitLab CI

+

Hal yang sama sebagai job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Saat berubah merah

+

Apa yang membuat sebuah langkah gagal, dan mengapa

+

+ Setiap akhir punya kode keluarnya sendiri, jadi langkah gagal dengan sendirinya dan log menyebut + yang mana. Yang dijumpai pipeline: +

+
    +
  • 3 - resep tidak valid. Tidak ada yang ditulis, dan setiap masalah disebut
  • +
  • 4 - format tidak bisa melakukan yang diminta, misalnya ukuran di bawah minimumnya
  • +
  • 6 - ruang disk tidak cukup
  • +
  • 7 - tfg verify menemukan file yang tidak cocok dengan manifesnya
  • +
  • 8 - proses selesai, tetapi tidak semuanya dihasilkan
  • +
+

+ Proses yang gagal tidak mencetak apa pun ke keluaran standar, sehingga parser log tidak pernah salah + mengira error sebagai data. Tabel lengkapnya ada di halaman + dokumentasi. +

+
+ +
+

PowerShell

+

Skrip PowerShell butuh satu baris lagi

+

+ PowerShell tidak membawa kode keluar sebuah program keluar dari file .ps1. Jalankan + satu dengan -File dan skrip menjawab 0 bahkan ketika alat di dalamnya + menolak pekerjaan, sehingga build yang seharusnya merah menjadi hijau. Baris terakhir adalah + seluruh perbaikannya: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Begitulah PowerShell bekerja, bukan sesuatu dari alat ini. cmd, bash, dan + zsh tidak butuh tambahan apa pun. +

+
+ +
+

Beberapa job

+

Berbagi fixture antar job

+

+ Biasanya tidak perlu mengunggahnya. Karena resep yang sama menulis byte yang sama, setiap job bisa + menjalankan tfg generate sendiri, yang lebih cepat daripada mengunggah lalu + mengunduh. Ketika sebuah job harus menerima file dari job lain, jalankan tfg verify + pada manifes setelah transfer, dan ia menyatakan apakah yang tiba sama dengan yang ditulis. +

+
+ +
+

Berikutnya

+

Ke mana dari sini

+
    +
  • + File uji yang rusak menambahkan file yang sengaja dirusak ke resep + yang sama. +
  • +
  • + Kasus penggunaan menunjukkan apa lagi yang bisa diperiksa sebuah + proses di pipeline. +
  • +
  • + Dokumentasi memuat setiap perintah, kunci resep, dan kode keluar. +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/file-uji-rusak/index.html b/web/public/id/file-uji-rusak/index.html new file mode 100644 index 00000000..62a04892 --- /dev/null +++ b/web/public/id/file-uji-rusak/index.html @@ -0,0 +1,381 @@ + + + + + + +File uji yang rusak - file rusak dengan ukuran tepat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Kasus Penggunaan

+

Cara membuat file rusak untuk pengujian

+

+ Validator yang hanya pernah diberi file sehat belum benar-benar diuji. Inilah cara mendapatkan file + yang sengaja dirusak, keluar dengan tepat sebesar yang Anda minta, dan membawa + manifes yang menyatakan apa yang harus dilakukan sistem Anda terhadapnya. +

+ +
+

Jawaban singkat

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out menulis PNG + berukuran tepat 2097152 byte yang byte pertamanya nol, dan manifes di sebelahnya mencatat bahwa + sistem Anda harus menolaknya. +

+
+ +
+

Cara yang biasa

+

Mengapa file yang dirusak dengan tangan adalah tes yang buruk

+

+ Cara yang biasa adalah editor hex, skrip yang membalik beberapa byte acak, atau memotong file dengan + head atau truncate. Berhasil sekali, lalu merugikan Anda: +

+
    +
  • + Hasilnya berbeda setiap kali. Byte acak jatuh di tempat baru pada setiap proses, + jadi kegagalan hari Selasa mungkin tidak muncul lagi hari Rabu. +
  • +
  • + Ukurannya berubah. File yang dipotong lebih kecil daripada batas yang seharusnya + tidak dilewatinya, sehingga pemeriksaan ukuran menjawab sebelum pemeriksaan isi dan tes lulus + karena alasan yang salah. +
  • +
  • + Sering tidak terdeteksi. Teks biasa masih terbaca dengan satu byte berubah di + tengah, dan pembaca gambar yang toleran hanya menggambarnya, sehingga file yang seharusnya + rusak malah diterima. +
  • +
  • + Tidak mengatakan apa yang seharusnya terjadi. File hanyalah byte, dan siapa pun + yang membaca tes itu kemudian harus menebak apakah yang dimaksud penerimaan atau penolakan. +
  • +
+
+ +
+

Yang Anda dapatkan

+

File yang rusak tetap berukuran seperti yang Anda minta

+

+ File dibuat seperti biasa lalu dirusak, dalam perjalanan ke disk. Ukurannya tetap seperti yang Anda + minta, dan perintah yang sama menulis byte yang sama lagi. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Pengaturan ditulis setelah titik dua. Opsi ini bisa diulang, dan kerusakan diterapkan menurut urutan + yang Anda tulis. Berlaku untuk semua 26 format. +

+
+ +
+

Yang bisa dilakukan

+

Kerusakan apa saja yang ada?

+

+ Ini daftar yang dicetak program, dibaca darinya saat halaman ini dibangun. tfg damage + mencetak daftar yang sama, dan tfg damage <id> menjelaskan apa yang diterima + salah satunya. +

+
+ + + + + + + + + + + + + + + + + +
KerusakanYang dilakukannya pada byteFile terkecilPengaturan
zero-headMenimpa byte pertama file dengan nol tanpa mengubah panjangnya. Sebagian besar pembaca melihat ke sana lebih dulu, jadi hampir semua hal menyadari kerusakan ini.8bytes
+
+

+ zero-head menulis nol di atas awal file. Sebagian besar pembaca melihat ke sana lebih + dulu, ke tanda pengenal dan header yang menyatakan file itu apa, jadi hampir semua pembaca + menyadarinya. Teks biasa dan log tidak punya tanda pengenal dan juga ditolak, karena deretan + byte nol bukan teks. Di bawah empat byte, sebagian format keluar dengan kerusakan yang tidak + dikeluhkan pembaca mana pun, itulah sebabnya pengaturan dimulai dari empat. +

+
+ +
+

Yang dikatakan manifes

+

Manifes yang menyatakan apa yang harus terjadi

+

+ Setiap file yang rusak mendapat catatan yang menyatakan sistem Anda harus menolaknya, dengan + kerusakannya dicatat di sampingnya: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dua permintaan ditolak sebelum apa pun ditulis, karena masing-masing akan meninggalkan file di disk + yang dijelaskan keliru oleh manifes: +

+
    +
  • file yang lebih kecil dari yang dibutuhkan kerusakan, yang akan keluar tanpa perubahan
  • +
  • + expected: accept di samping kerusakan, karena tidak ada yang bisa memenuhinya. Tulis + sanitize jika sistem Anda memang harus memperbaiki file itu, atau + unspecified jika justru itu pertanyaan Anda +
  • +
+
+ +
+

Dalam resep

+

File sehat dan rusak dalam satu proses

+

+ Taruh keduanya dalam satu resep, dan manifes membawa harapan setiap file, sehingga tes tidak butuh + daftar mana yang mana: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Dalam tes

+

Menjadikannya tes

+

+ Tes membaca manifes dan memeriksa bahwa yang terjadi sama dengan yang dinyatakan. Tidak perlu daftar + nama file: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Penolakan yang baik adalah penolakan yang bersih. Pesan yang menyebut apa yang salah adalah jawaban + yang Anda inginkan. Kesalahan server, macet, atau file yang tersimpan setengah adalah cacat yang + ingin ditemukan tes ini. +

+
+ +
+

Berikutnya

+

Ke mana dari sini

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/id/format/index.html b/web/public/id/format/index.html new file mode 100644 index 00000000..0a4e71ba --- /dev/null +++ b/web/public/id/format/index.html @@ -0,0 +1,912 @@ + + + + + + +26 Format File yang Didukung - PDF, DOCX, PNG, ZIP, dan Lainnya + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 format file, masing-masing dibuat dengan ukuran tepat

+

+ Masing-masing adalah file asli dari format itu. File terbuka di aplikasi yang + memilikinya dan persis berjumlah byte yang Anda minta. Tidak ada yang berupa nol pengisi dengan + ekstensi yang ditempelkan. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatNamaEkstensiFile terkecilKelengkapanDiperiksa dengan
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fulltidak berlaku
mdMarkdown.md0fulltidak berlaku
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fulltidak berlaku
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Arti kolom-kolom

+
    +
  • +

    File terkecil

    +

    + Jumlah byte paling sedikit yang akan diterima alat ini untuk format itu, termasuk label yang + ditulisnya di dalam file. Minta lebih kecil dan Anda mendapat galat yang menyebut batas + bawah dan alasannya, tidak pernah file berukuran salah. +

    +
  • +
  • +

    Kelengkapan

    +

    + Seberapa lengkap file itu. full berarti pembaca yang benar-benar mem-parsing format + menerimanya, bukan sekadar ekstensinya cocok. +

    +
  • +
  • +

    Diperiksa dengan

    +

    + Pembaca independen yang membuka setiap file yang dihasilkan sebelum format dirilis - implementasi + terpisah, bukan kode kami sendiri yang menilai pekerjaan rumahnya sendiri. +

    +
  • +
+

+ Setiap format juga berulang sampai ke byte: resep dan seed yang sama menghasilkan file identik di + mesin mana pun, dan itulah yang membuat resep aman di-commit menggantikan fixture-nya. +

+
+ +
+

Pengaturan yang diterima setiap format

+

+ Sebagian besar format punya pengaturan sendiri - dimensi gambar, kualitas JPEG, jumlah halaman PDF, + baris dan kolom spreadsheet, berapa banyak entri di dalam arsip. Atur dengan --set + key=value di baris perintah, atau di bawah properties: dalam resep. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatPengaturanMenerima
avifwidth1 - 16384 piksel
height1 - 16384 piksel
quality1 - 100
bmpwidth1 - 20000 piksel
height1 - 20000 piksel
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerbenar atau salah
quote_styleall, minimal, none
columns2 - 32768 kolom
docxparagraphs1 - 50000 paragraf
gifwidth1 - 20000 piksel
height1 - 20000 piksel
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 piksel
height1 - 256 piksel
embedbmp, png
jpgwidth1 - 20000 piksel
height1 - 20000 piksel
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 piksel
height1 - 16384 piksel
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 entri per detik
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bombenar atau salah
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleteks apa pun
authorteks apa pun
subjectteks apa pun
keywordsteks apa pun
creatorteks apa pun
producerteks apa pun
createdtanggal seperti 2024-02-29 atau 2024-02-29T13:45:00+02:00, atau none
modifiedtanggal seperti 2024-02-29 atau 2024-02-29T13:45:00+02:00, atau none
pngwidth1 - 20000 piksel
height1 - 20000 piksel
pptxslides1 - 500 slide
svgwidth1 - 20000 piksel
height1 - 20000 piksel
targzentries0 - 10000
entry_formatid sebuah format, seperti yang didaftar tfg formats
entry_sizeukuran seperti 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesbenar atau salah
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 piksel
height1 - 20000 piksel
txtencodingutf-16be, utf-16le, utf-8
bombenar atau salah
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 piksel
height1 - 16383 piksel
xlsxrows1 - 200000 baris
columns1 - 32768 kolom
xmlencodingutf-16be, utf-16le, utf-8
bombenar atau salah
zipentries0 - 10000
entry_formatid sebuah format, seperti yang didaftar tfg formats
entry_sizeukuran seperti 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesbenar atau salah
passwordkata sandi, dalam teks biasa
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Nilai di luar yang diterima suatu pengaturan ditolak dengan pesan yang menyebut pengaturan, rentang + yang diizinkan, dan apa yang dipakai sebagai gantinya. Pengaturan yang tidak dikenal juga galat, + tidak pernah nilai bawaan diam-diam - salah ketik yang diterima diam-diam menghasilkan file + dengan pengaturan yang salah dan satu jam bertanya-tanya mengapa pengujian lolos padahal + seharusnya tidak. +

+

+ Jalankan tfg formats <id> untuk melihat persis apa yang diterima satu format pada + build yang Anda miliki. +

+
+ +
+

Arsip berisi file asli

+

+ targz dan zip + dapat diisi dengan entri alih-alih dibiarkan sebagai cangkang kosong. Arsip yang dihasilkan + benar-benar berisi dokumen yang diklaimnya, sehingga apa pun yang mengekstraknya selama + pengujian menemukan file asli di dalamnya. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/index.html b/web/public/id/index.html new file mode 100644 index 00000000..d57d9e57 --- /dev/null +++ b/web/public/id/index.html @@ -0,0 +1,455 @@ + + + + + + +Generator File Uji untuk QA - Ukuran Tepat, 26 Format Asli + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Buat file uji asli dengan ukuran tepat

+

+ PDF, PNG, DOCX, ZIP - 26 format seluruhnya, dan setiap file + adalah file asli yang terbuka di aplikasi yang memilikinya, dengan ukuran persis seperti + yang Anda minta. Setiap run juga mencatat apa yang harus dilakukan aplikasi Anda + terhadap tiap file. Baris perintah dan jendela desktop, gratis dan open source, bekerja + sepenuhnya di mesin Anda. +

+ + +

Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.

+
+ +
+ Jendela desktop Testing Files Generator, siap menulis sekumpulan file uji +
Jendela desktop, siap menulis sekumpulan file. Mesin yang sama berjalan di balik baris perintah.
+
+
+ +
    +
  • + 26 +

    format asli, masing-masing terbuka di aplikasi yang memilikinya

    +
  • +
  • + 1 byte +

    ketepatan setiap ukuran yang Anda minta, tidak pernah dibulatkan diam-diam

    +
  • +
  • + 0 +

    koneksi ke mana pun - tanpa akun, tanpa telemetri, tanpa pemeriksaan pembaruan

    +
  • +
+ +
+

Masalahnya

+

Membuat satu file uji itu mudah. Membuat seribu yang tepat adalah bagian yang membosankan

+

Anda menguji perangkat lunak yang menerima file dari orang. Cepat atau lambat Anda memerlukan:

+
    +
  • PDF berukuran tepat 10 MB, untuk mengetahui apakah batas unggahan itu nyata
  • +
  • tiga file di kedua sisi batas itu, untuk menangkap kesalahan selisih satu
  • +
  • 10.000 file log, untuk melihat apa yang dilakukan job malam saat foldernya besar
  • +
  • ZIP yang benar-benar berisi 200 dokumen, bukan cangkang kosong dengan ekstensi yang tepat
  • +
  • file 4 GB, tanpa menyimpan file 4 GB di repositori Anda
  • +
  • fixture yang sama di laptop Anda dan di server build, byte demi byte
  • +
+

+ Itulah yang digantikan oleh alat ini. Dibuat untuk insinyur QA, otomasi pengujian, dan siapa pun + yang kodenya memiliki formulir unggah, rutinitas impor, parser, atau kuota penyimpanan di + baliknya. +

+
+ +
+

Apa yang membuatnya berbeda

+

Generator lain berhenti di byte. Alat ini menjawab apa yang sebenarnya ditanyakan pengujian Anda

+

+ Sebuah folder berisi file masih membuat Anda yang memutuskan apa yang seharusnya dibuktikan tiap + file. Setiap run di sini menulis manifest.json di samping file - daftar sederhana + semua yang dihasilkan, dan untuk tiap entri sebuah ekspektasi yang dinyatakan. +

+

Misalkan endpoint unggah Anda mengizinkan 1 MB. Mintalah tiga file yang berada di garis itu:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FileByteSistem Anda harusKarena
1mb_under_1b.pdf1048575menerimaberada di dalam batas
1mb_at_limit.pdf1048576menerimabatas itu sendiri diizinkan
1mb_over_1b.pdf1048577menolaksize_limit
+
+ +

Tiga file, tiga jawaban berbeda, dalam bentuk yang terbaca mesin. Pengujian Anda membaca manifes alih-alih Anda menulis asersi secara manual:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Bila jawabannya bergantung pada kebijakan Anda sendiri, manifes mengatakannya

+

+ Alat ini mencatat unspecified alih-alih mengarang ekspektasi. Generator yang menebak + menghasilkan kegagalan palsu, dan suite yang berteriak serigala akhirnya dimatikan. +

+
+
+ +
+

Preset

+

Pilih pertanyaannya, dapatkan seluruh setnya

+

+ Preset adalah set file uji yang dirancang di sekitar satu pertanyaan pengujian, sehingga Anda tidak + perlu mencari tahu file mana yang membuktikan apa. Masing-masing punya halaman yang menjelaskan + apa yang biasanya ditemukan, isi set, dan setiap pengaturan yang diterimanya. +

+
    +
  • +

    Kosong dan minimal

    +

    Apakah file valid yang sekecil yang diizinkan format dapat lolos?

    +

    empty-and-minimal

    +
  • +
  • +

    Penanganan nama file

    +

    Apakah sistem saya akan menyimpan, menampilkan, dan mengembalikan nama file yang tidak diduganya?

    +

    filename-handling

    +
  • +
  • +

    Batas ukuran

    +

    Apakah batas ukuran ditegakkan tepat di tempat batas itu dinyatakan?

    +

    size-boundaries

    +
  • +
  • +

    Impor tabel

    +

    Apakah impor tabel saya tahan terhadap apa yang diekspor alat sungguhan?

    +

    tabular-import

    +
  • +
  • +

    Enkoding teks

    +

    Apakah pembaca saya tahu enkoding suatu file, atau hanya menebak?

    +

    text-encoding

    +
  • +
  • +

    Validasi unggahan

    +

    Apakah formulir unggah saya menerima yang seharusnya dan menolak sisanya?

    +

    upload-validation

    +
  • +
+

Semua preset, dan hubungannya dengan resep

+
+ +
+

Mulai cepat

+

Tiga perintah untuk melihatnya bekerja

+
    +
  1. +

    Buat satu file

    +

    Satu PNG, tepat dua megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Buat banyak file

    +

    + Sepuluh ribu file log, masing-masing antara satu dan delapan kilobyte, dengan ukuran diundi dari + seed sehingga besok menghasilkan set yang sama. Beri setiap run direktorinya + sendiri - manifes adalah satu-satunya catatan tentang apa yang ditulis sebuah run, + sehingga alat ini menolak menulis manifes kedua di atasnya: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Periksa, lalu hapus

    +

    verify memberi tahu bahwa tidak ada yang bergeser. cleanup menghapus persis apa yang ditulis dan tidak lebih:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Ukuran dihitung dalam kelipatan 1024, seperti pengelola file Anda, jadi 2mb berarti + 2097152 byte. Jumlah byte biasa juga bisa. Dokumentasi membahas + resep, manifes, dan kode keluar. +

+
+ +
+

Yang Anda dapatkan

+

Dibuat untuk suite yang berjalan tanpa pengawasan

+
    +
  • +

    Ukuran tepat, sampai ke byte

    +

    Minta 10485761 byte dan dapatkan persis itu. Ukuran yang tidak dapat dicapai format adalah galat dengan alasan, tidak pernah file berukuran salah.

    +
  • +
  • +

    26 format asli

    +

    Bukan nol pengisi dengan ekstensi. PNG yang dihasilkan terbuka di penampil gambar, DOCX terbuka di Word, ZIP bisa diekstrak. Masing-masing diperiksa dengan pembaca independen sebelum dirilis.

    +
  • +
  • +

    Manifes yang menjadi oracle pengujian

    +

    Path, ukuran, SHA-256, format, seed, versi alat - dan apa yang harus dilakukan sistem Anda terhadap file itu.

    +
  • +
  • +

    Dapat direproduksi

    +

    Resep dan seed yang sama, byte yang sama, di mesin mana pun. Commit resep YAML kecil alih-alih fixture biner besar.

    +
  • +
  • +

    Dua antarmuka, satu mesin

    +

    Baris perintah yang dibuat untuk CI dan jendela desktop untuk pengujian eksploratif. Tidak ada yang merupakan versi terpangkas dari yang lain, dan sebuah pengujian membandingkannya kemampuan demi kemampuan.

    +
  • +
  • +

    Sepenuhnya offline

    +

    Tanpa akun, tanpa cloud, tanpa telemetri, tanpa pemeriksaan pembaruan. Biner baris perintah sama sekali tidak memiliki stack jaringan yang dikompilasi di dalamnya.

    +
  • +
+
+ +
+

Unduh

+

Pilih build untuk sistem Anda

+

+ Ekstrak arsip dan jalankan. tfg adalah baris perintah dan tfg-gui adalah + jendela desktop. Tidak ada installer dan tidak ada yang perlu ditambahkan ke mesin Anda. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemBaris perintahJendela desktop
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Apa yang ditandatangani, dan apa yang tidak

+

+ Unduhan Windows dan macOS ditandatangani, sehingga berjalan tanpa peringatan tentang pengembang tak + dikenal. Yang untuk Linux tidak, karena Linux desktop tidak punya padanan untuk + menandatanganinya. Setiap arsip tercantum di verify-SHA256SUMS.txt pada halaman + rilis, sehingga Anda dapat memeriksa apa yang Anda unduh. +

+
+ +

Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.

+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/kasus-penggunaan/index.html b/web/public/id/kasus-penggunaan/index.html new file mode 100644 index 00000000..8b9c3a19 --- /dev/null +++ b/web/public/id/kasus-penggunaan/index.html @@ -0,0 +1,318 @@ + + + + + + +Kasus Penggunaan - Batas Unggahan, Fixture CI, Pengujian Massal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Untuk apa orang memakainya

+

+ Lima pekerjaan yang muncul di hampir setiap proyek yang menerima file dari orang, dan perintah yang + melakukan masing-masing. Setiap contoh di bawah berjalan sebagaimana tertulis. +

+ +
+

Batas unggahan

+

Menguji apakah batas ukuran file ditegakkan di tempat yang dinyatakan

+

+ Sebuah batas adalah tiga kasus uji, bukan satu: tepat di bawah, tepat pada, dan tepat di atas. + Mendapatkannya secara manual berarti menghitung jumlah byte dan berharap tidak salah selisih + satu. Mintalah setnya: +

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

+ Anda mendapat tiga PDF asli berukuran 1048575, 1048576, dan 1048577 byte, serta manifes yang + menyatakan dua yang pertama harus diterima dan yang ketiga ditolak karena + size_limit. Pengujian Anda membaca ekspektasi alih-alih Anda menulis tiga asersi + secara manual - dan bila batas berubah, Anda mengganti satu angka dan menjalankan ulang. +

+

+ Hal yang sama berfungsi tanpa preset bila Anda menginginkan satu set batas inline: +

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

Integrasi berkelanjutan

+

Menjaga fixture di luar repositori tanpa kehilangannya

+

+ Fixture biner besar membuat repositori lambat di-clone dan sulit di-review, dan tak seorang pun tahu + apa yang berubah saat satu diganti. Resep adalah beberapa ratus karakter YAML yang membangun + ulang file identik - byte demi byte, di mesin mana pun - karena setiap file + diturunkan dari seed run. +

+
- 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
+

+ Setiap akhir punya kode keluarnya sendiri, sehingga pipeline dapat membedakan resep yang buruk dari + disk penuh dan dari ketidakcocokan verifikasi. Run yang gagal tidak mencetak apa pun di keluaran + standar, sehingga parser log tidak membaca galat sebagai data. +

+
+ +
+

Skala

+

Mencari tahu apa yang terjadi saat folder besar

+

+ Rutinitas impor, job malam, dan daftar direktori berperilaku berbeda pada sepuluh ribu file + dibanding sepuluh. Ukuran yang diundi dari suatu rentang membuat set tampak seperti lalu lintas + nyata alih-alih sepuluh ribu file identik, dan undiannya berasal dari seed, sehingga set itu + sama besok. +

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

+ Periksa berapa biaya sebuah run sebelum menulis apa pun, yang penting bila totalnya diukur dalam + gigabyte: +

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

+ Run yang lebih besar dari ruang kosong di disk ditolak sebelum byte pertama ditulis, alih-alih + memenuhi disk dan gagal di tengah jalan. +

+
+ +
+

Arsip

+

Menguji pengekstrak dengan arsip yang benar-benar berisi file

+

+ Arsip kosong dengan ekstensi yang tepat tidak membuktikan apa pun tentang kode yang membukanya dan + menelusuri isinya. Nyatakan isinya dan arsip benar-benar memuatnya: +

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

+ Kedalaman bersarang, jumlah entri, dan ukuran isinya adalah hal-hal yang dipersoalkan rutinitas + impor, dan begitulah cara Anda mengetahui apa persoalan itu. +

+
+ +
+

Parser dan penampil

+

Memeriksa bahwa kode Anda sendiri membaca format seperti perangkat lunak sungguhan

+

+ Setiap format di sini diperiksa dengan pembaca independen sebelum dirilis - PNG dibuka dan pikselnya + dibandingkan, DOCX dibaca kembali oleh pustaka terpisah, arsip diekstrak. Artinya file yang + ditolak parser Anda adalah temuan tentang parser Anda, bukan tentang 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
+

+ Halaman format mencantumkan pengaturan yang diterima tiap format dan file + terkecil yang dapat dibuat tiap format. +

+
+ +
+

Panduan

+

Dua di antaranya lebih rinci

+
    +
  • + File uji yang rusak - file yang sengaja dirusak, berukuran tepat, + dengan apa yang harus terjadi padanya tertulis di manifes. +
  • +
  • + File uji di CI - workflow GitHub Actions, job GitLab, dan kode + keluar yang menggagalkan build. +
  • +
+
+ +
+

Untuk siapa ini

+

+ Insinyur QA, otomasi pengujian, dan siapa pun yang kodenya memiliki formulir unggah, rutinitas + impor, parser, atau kuota penyimpanan di baliknya. Berjalan di mesin tanpa jaringan sama sekali, + yang penting di lingkungan korporat tertutup di mana generator berbasis browser bukan pilihan. +

+ +

Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/membuat-file-ukuran-tepat/index.html b/web/public/id/membuat-file-ukuran-tepat/index.html new file mode 100644 index 00000000..48838a59 --- /dev/null +++ b/web/public/id/membuat-file-ukuran-tepat/index.html @@ -0,0 +1,333 @@ + + + + + + +Cara Membuat File dengan Ukuran Tertentu - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cara membuat file dengan ukuran tepat

+

+ Setiap sistem punya perintah untuk itu, dan ketiganya ada di bawah. Perintah-perintah itu memberi + Anda file dengan jumlah byte yang tepat - dan untuk banyak pengujian itu sudah cukup. + Setiap perintah di halaman ini dijalankan sebelum dipublikasikan, di sistem + tempat perintah itu berada. +

+ +
+

Jawaban singkat

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Ukuran dalam byte, dan 10 MB yang + dihitung seperti pengelola file Anda menghitung adalah 10485760. +

+
+ +
+

Windows

+

fsutil, dan versi PowerShell yang tidak memerlukan tambahan apa pun

+

+ fsutil disertakan dengan Windows. Perintah ini menerima ukuran dalam + byte, jadi hitung dulu angkanya - 10 MB adalah 10485760, 100 MB adalah 104857600, 1 GB + adalah 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Diukur di Windows 11: berjalan dari prompt biasa dan tidak memerlukan prompt dengan hak istimewa, + dan file keluar tepat 10485760 byte. +

+

PowerShell dapat melakukan hal yang sama tanpa memanggil program lain, dan memahami satuan:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB di PowerShell berarti 10485760 byte, hitungan berbasis 1024 yang sama dengan yang + dipakai Explorer, sehingga kedua perintah di atas menghasilkan ukuran yang sama. +

+
+ +
+

Linux

+

dd, truncate, dan fallocate, dan perbedaan yang menjebak orang

+

dd adalah yang dikenal semua orang. Perintah ini benar-benar menulis byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate instan, dan di situlah jebakannya. Diukur di Alpine Linux, file melaporkan + 10485760 byte dan menempati nol blok - ini adalah sparse file. + Apa pun yang membacanya mendapat sepuluh megabyte nol, tetapi disk tidak pernah menyerahkan + ruangnya: +

+
truncate -s 10M test10mb.bin
+

+ Itu baik untuk menguji batas unggahan dan menyesatkan untuk menguji kuota disk. + fallocate adalah yang dipakai bila ruangnya harus nyata: +

+
fallocate -l 10M test10mb.bin
+

Dan bila isinya harus tak dapat dikompres, agar pengarsip tidak bisa memadatkannya kembali:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, yang bukan sparse, dan dua yang sudah Anda kenal

+

+ macOS menyertakan mkfile. Diukur di macOS 26.6.2: 10485760 byte dan 20480 blok, + sehingga ruangnya benar-benar dialokasikan, bukan dijanjikan: +

+
mkfile 10m test10mb.bin
+

dd dan truncate juga ada dan berperilaku seperti di Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Di mana ini berhenti berfungsi

+

File dengan ukuran yang benar bukan file dengan jenis yang benar

+

+ Semua di atas memberi Anda blok nol. Itu cukup bila yang diuji hanya melihat ukuran - batas + unggahan, kuota, transfer. Itu berhenti cukup begitu ada yang membuka file itu. +

+

+ Diukur, dan layak Anda coba sendiri: buat file 2 MB dengan fsutil, namai + photo.png, dan serahkan ke pustaka gambar. Pillow menjawab cannot identify + image file. Itu bukan PNG. Tidak pernah - hanya namanya yang berkata begitu. +

+

+ Itu lebih penting daripada kedengarannya, karena arah kegagalan pengujian itu + kemudian. Endpoint unggah Anda menolak file, pengujian Anda hijau, dan Anda + menyimpulkan batas ukuran berfungsi. Endpoint itu tidak menolaknya karena ukuran. Ia menolaknya + karena byte-nya bukan gambar, dan aturan yang ingin Anda uji tidak pernah tercapai. +

+
    +
  • parser menolaknya sebelum aturan ukuran apa pun diperiksa
  • +
  • langkah thumbnail gagal dan galat yang Anda baca adalah tentang thumbnail
  • +
  • antivirus atau pemeriksaan konten menolaknya karena alasan ketiga
  • +
  • penampil tidak menampilkan apa pun, dan tak seorang pun tahu apakah itu bug-nya
  • +
+
+ +
+

Jalan lainnya

+

File asli dari format itu, dengan ukuran persis seperti yang Anda minta

+

+ Inilah yang dilakukan Testing Files Generator. File itu adalah file asli dari formatnya - terbuka di + aplikasi yang memilikinya - dan berjumlah byte persis seperti yang Anda minta, sampai ke byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Minta ukuran yang tidak dapat dicapai suatu format dan Anda mendapat galat yang menyebut batas bawah + dan alasannya, tidak pernah file berukuran salah. Halaman format + mencantumkan setiap format beserta file terkecil yang dapat dibuatnya. +

+

Dan sebuah batas adalah tiga kasus uji, bukan satu, jadi alat ini membuat ketiganya:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Itu memberi Anda 10485759, 10485760, dan 10485761 byte, dan manifes yang menyatakan mana yang harus + diterima sistem Anda dan mana yang harus ditolak. Halaman kasus + penggunaan membahas itu dan empat pekerjaan lain yang untuknya alat ini dibuat. +

+ +

Gratis dan open source, GPL-3.0. Tanpa pendaftaran. Unduhan Windows dan macOS sudah ditandatangani dan berjalan tanpa peringatan.

+
+ +
+

Jadi mana yang sebaiknya dipakai?

+
    +
  • +

    Pakai perintah sistem

    +

    + Bila tidak ada yang membuka file. Menguji batas ukuran pada endpoint yang memeriksa ukuran lebih + dulu, transfer, kuota, disk penuh. Hanya satu baris dan sudah terpasang. +

    +
  • +
  • +

    Pakai generator sungguhan

    +

    + Bila ada yang mem-parsing, merender, mengimpor, atau mengekstrak file - dan bila Anda memerlukan + fixture yang sama besok, di mesin lain, byte demi byte. +

    +
  • +
+

+ Keduanya ada di halaman ini karena keduanya benar sebagian waktu. Kesalahan yang perlu dihindari + adalah memakai yang pertama di tempat yang kedua dibutuhkan dan membaca pengujian hijau sebagai + bukti. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/preset/empty-and-minimal/index.html b/web/public/id/preset/empty-and-minimal/index.html new file mode 100644 index 00000000..1880b560 --- /dev/null +++ b/web/public/id/preset/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +File Uji Valid Terkecil dan Kosong di Setiap Format + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Kosong dan minimal

+

Apakah file valid yang sekecil yang diizinkan format dapat lolos?

+

+ Preset empty-and-minimal membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • file valid yang ditolak karena terlalu kecil, ketika pemeriksaan menghitung byte alih-alih membacanya
  • +
  • file kosong yang membuat pembaca crash alih-alih dilaporkan
  • +
  • gambar selebar satu piksel yang membagi dengan nol dalam perjalanan ke thumbnail
  • +
  • penyimpanan yang membaca nol byte sebagai unggahan gagal dan terus mencoba ulang
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show empty-and-minimal:

+
+ + + + + + + +
File28
Target dalam resepnya28
Ukuran total32 667 B
Formatavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.26
unspecifiedTergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda.2
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--formatsid format dipisahkan koma, atau allallDari format apa set dibuat. Biarkan all untuk setiap format build ini, atau sebutkan format yang diterima sistem Anda.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/preset/filename-handling/index.html b/web/public/id/preset/filename-handling/index.html new file mode 100644 index 00000000..9cf8954e --- /dev/null +++ b/web/public/id/preset/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Nama File Bermasalah untuk Pengujian - Unicode dan Panjang + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Penanganan nama file

+

Apakah sistem saya akan menyimpan, menampilkan, dan mengembalikan nama file yang tidak diduganya?

+

+ Preset filename-handling membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • nama yang tampak seperti nama lain di layar, di log, atau dalam daftar
  • +
  • nama yang dipotong, dipangkas, atau ditulis ulang antara unggahan dan penyimpanan
  • +
  • batas panjang yang dihitung dalam karakter padahal penyimpanan menghitung byte
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show filename-handling:

+
+ + + + + + + +
File50
Target dalam resepnya50
Ukuran total51 200 B
Formattxt
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.4
unspecifiedTergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda.46
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--formatid format dari halaman formattxtFormat setiap file dalam set. Ini adalah opsi alat itu sendiri, dan preset hanya memberinya nilai bawaan.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/preset/index.html b/web/public/id/preset/index.html new file mode 100644 index 00000000..4abe1cbf --- /dev/null +++ b/web/public/id/preset/index.html @@ -0,0 +1,245 @@ + + + + + + +Preset File Uji - Set Siap Pakai untuk QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Preset file uji, satu set untuk setiap pertanyaan pengujian

+

+ Preset adalah satu set lengkap file uji yang dirancang di sekitar satu pertanyaan, dengan manifes + yang menyatakan bagaimana sistem Anda harus bereaksi terhadap tiap file. Anda memilih pertanyaan, + alat membuat setnya. Setiap preset punya halamannya sendiri berisi apa yang biasanya ditemukan, + isi set, dan setiap pengaturan yang diterimanya. +

+ +
    +
  • +

    Kosong dan minimal

    +

    Apakah file valid yang sekecil yang diizinkan format dapat lolos?

    +

    empty-and-minimal

    +
  • +
  • +

    Penanganan nama file

    +

    Apakah sistem saya akan menyimpan, menampilkan, dan mengembalikan nama file yang tidak diduganya?

    +

    filename-handling

    +
  • +
  • +

    Batas ukuran

    +

    Apakah batas ukuran ditegakkan tepat di tempat batas itu dinyatakan?

    +

    size-boundaries

    +
  • +
  • +

    Impor tabel

    +

    Apakah impor tabel saya tahan terhadap apa yang diekspor alat sungguhan?

    +

    tabular-import

    +
  • +
  • +

    Enkoding teks

    +

    Apakah pembaca saya tahu enkoding suatu file, atau hanya menebak?

    +

    text-encoding

    +
  • +
  • +

    Validasi unggahan

    +

    Apakah formulir unggah saya menerima yang seharusnya dan menolak sisanya?

    +

    upload-validation

    +
  • +
+ +
+

Apa bedanya preset dengan resep?

+

+ Pada dasarnya tidak ada. Preset adalah resep yang ditulis alat untuk Anda dari beberapa pengaturan. + tfg preset eject mencetak resep itu agar dapat Anda simpan di samping pengujian dan + sunting, dan resep Anda sendiri dapat dibangun di atas preset dengan satu baris, extends: + preset: diikuti id-nya. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Bisakah saya memercayai nilai bawaan?

+

+ Untuk file, ya. Untuk angka yang hanya diketahui sistem Anda, seperti batas formulir unggah, nilai + bawaan adalah nilai sementara dari kami, dan alat menyatakannya setiap kali memakainya. Halaman + setiap preset menandai pengaturan itu, dan tfg preset show menyatakannya sebelum + apa pun ditulis. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/id/preset/size-boundaries/index.html b/web/public/id/preset/size-boundaries/index.html new file mode 100644 index 00000000..6398e2ca --- /dev/null +++ b/web/public/id/preset/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Menguji Batas Ukuran Unggahan - File di Batas Tepat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Batas ukuran

+

Apakah batas ukuran ditegakkan tepat di tempat batas itu dinyatakan?

+

+ Preset size-boundaries membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • kesalahan selisih satu di batas
  • +
  • MB tertukar dengan MiB, yaitu 4,8 persen dan cukup untuk meloloskan file yang seharusnya tidak lolos
  • +
  • batas yang ditegakkan di browser dan tidak di server
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show size-boundaries:

+
+ + + + + + + +
File7
Target dalam resepnya7
Ukuran total73 400 320 B
Formatpdf
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.4
rejectSistem Anda harus menolak file ini.3
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--limitukuran seperti 2mb10mbBatas ukuran yang dinyatakan sistem Anda. Semua yang lain diukur dari sini. Nilai bawaan ini adalah nilai sementara dari kami, bukan nilai sistem Anda. Berikan nilai Anda sendiri.
--spreadukuran dipisahkan koma1B,1kb,1mbSeberapa jauh menjangkau di kedua sisi batas, sebagai daftar ukuran.
--formatid format dari halaman formatpdfFormat setiap file dalam set. Ini adalah opsi alat itu sendiri, dan preset hanya memberinya nilai bawaan.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

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

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/preset/tabular-import/index.html b/web/public/id/preset/tabular-import/index.html new file mode 100644 index 00000000..d1b63387 --- /dev/null +++ b/web/public/id/preset/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +File Uji Impor CSV dan Excel - Pemisah, Header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Impor tabel

+

Apakah impor tabel saya tahan terhadap apa yang diekspor alat sungguhan?

+

+ Preset tabular-import membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • file titik koma yang terbaca sebagai satu kolom, karena pemisah diasumsikan alih-alih dicari
  • +
  • file CRLF yang terpecah menjadi baris dengan baris kosong setelah masing-masing
  • +
  • tabel tanpa header yang baris data pertamanya termakan sebagai nama kolom
  • +
  • impor yang mempertahankan kolom yang bisa ditampilkan dan membuang sisanya tanpa kata
  • +
  • pembaca yang mengambil record JSON satu baris sekaligus dan berhenti di dokumen berindentasi pertama
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show tabular-import:

+
+ + + + + + + +
File13
Target dalam resepnya13
Ukuran total3 080 060 B
Formatcsv, json, xlsx
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.8
unspecifiedTergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda.5
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--rows1 - 200000 baris1000Berapa banyak baris yang dimuat spreadsheet. File ditulis tepat pada ukuran sebanyak itu baris, sehingga anggaran di atas bergeser mengikuti nilai ini.
--columns1 - 32768 kolom10Berapa banyak kolom di setiap baris spreadsheet. Baris kali kolom memiliki batas atas, dan meminta melebihinya ditolak sebelum apa pun ditulis.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/preset/text-encoding/index.html b/web/public/id/preset/text-encoding/index.html new file mode 100644 index 00000000..9874cb48 --- /dev/null +++ b/web/public/id/preset/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +File Uji Enkoding Teks - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Enkoding teks

+

Apakah pembaca saya tahu enkoding suatu file, atau hanya menebak?

+

+ Preset text-encoding membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • pembaca yang mengasumsikan UTF-8 dan menampilkan file UTF-16 sebagai satu karakter dari tiga, atau sebagai deretan kotak
  • +
  • byte order mark terbaca sebagai isi, sehingga kolom pertama impor dimulai dengan tiga karakter asing
  • +
  • importer yang menebak enkoding dari byte pembuka dan menebak berbeda untuk file yang lebih panjang
  • +
  • file CRLF yang terpecah menjadi baris dengan baris kosong setelah masing-masing, atau carriage return yang tertinggal di kolom terakhir
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show text-encoding:

+
+ + + + + + + +
File20
Target dalam resepnya20
Ukuran total81 920 B
Formatcsv, log, md, txt, xml
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.10
unspecifiedTergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda.10
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--sampleukuran seperti 2mb4kbSeberapa besar setiap file dalam set. UTF-16 menyimpan dua byte untuk setiap karakter, sehingga angka ganjil ditolak.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/id/preset/upload-validation/index.html b/web/public/id/preset/upload-validation/index.html new file mode 100644 index 00000000..773b0037 --- /dev/null +++ b/web/public/id/preset/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +File Uji Validasi Unggahan - Tipe, Ukuran, dan Nama + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Validasi unggahan

+

Apakah formulir unggah saya menerima yang seharusnya dan menolak sisanya?

+

+ Preset upload-validation membuat satu set lengkap file uji asli untuk pertanyaan ini dengan + satu perintah, dan manifest.json di sampingnya yang menyatakan bagaimana sistem Anda + harus bereaksi terhadap tiap file. Semua di bawah dibaca dari program, pada nilai bawaan versi + ini. +

+ + +
+

Apa yang biasanya ditemukan?

+
    +
  • batas yang ditegakkan di browser dan tidak di server
  • +
  • file SVG atau HTML yang dikira gambar atau teks biasa, yang merupakan cara meloloskan skrip lewat formulir
  • +
  • file yang diperiksa dari ekstensinya dan tak pernah dibuka, sehingga PDF bernama .jpg lolos
  • +
  • formulir yang membaca seluruh isi ke memori sebelum melihat seberapa besar isinya
  • +
  • unggahan bernama PHOTO.JPG yang ditolak sementara photo.jpg diterima, atau sebaliknya
  • +
  • nama dengan spasi, tanda kurung, atau karakter di luar ASCII yang ditulis ke disk tanpa perubahan
  • +
+
+ + +
+

Apa isi set?

+

Pada nilai bawaan, seperti yang dilaporkan tfg preset show upload-validation:

+
+ + + + + + + +
File71
Target dalam resepnya22
Ukuran total120 639 488 B
Formathtml, jpg, pdf, png, svg, txt
+
+

Dan apa yang diharapkan manifes set itu dari sistem Anda:

+
+ + + + + + + + + +
DiharapkanArtiFile
acceptSistem Anda harus menerima file ini.56
rejectSistem Anda harus menolak file ini.10
unspecifiedTergantung pada aturan sistem Anda. Anda yang memutuskan, lalu memeriksa apakah yang terjadi sesuai maksud Anda.5
+
+
+ +
+

Apa yang dapat Anda ubah?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PengaturanMenerimaBawaanFungsinya
--limitukuran seperti 2mb10mbBatas ukuran yang dinyatakan formulir unggah Anda. Set ini mengambil satu langkah di tiap sisinya - untuk file di setiap jarak, jalankan preset size-boundaries. Nilai bawaan ini adalah nilai sementara dari kami, bukan nilai sistem Anda. Berikan nilai Anda sendiri.
--allowid format dipisahkan komajpg,png,pdfTipe apa yang seharusnya diterima formulir Anda. Masing-masing menjadi file asli bertipe itu, dan menjadi kontrol positif bagi seluruh set.
--denyekstensi dipisahkan komasvg,html,exe,shEkstensi apa yang seharusnya ditolak formulir Anda. Ekstensi yang tidak punya format di build ini tetap mendapat file bernama itu, berisi teks biasa.
--far-over10x, 2x, off2xSeberapa jauh di atas batas file besar tunggal itu. Matikan bila menulis beberapa kali batas tidak sepadan dengan disknya.
--bulk0 - 10000 file50Berapa banyak file dalam unggahan massal. Nol membuang kelompok itu dari set sepenuhnya.
+
+
+ +
+

Bagaimana menjalankannya?

+

Lihat biaya set, buat, atau ambil resepnya untuk disunting:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Atau bangun di atasnya dalam resep Anda sendiri, di samping pengujian Anda:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/index.html b/web/public/index.html index aca1dbbf..365ce19e 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -3,15 +3,36 @@ + Test File Generator for QA - Exact Size, 26 Real Formats + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -77,9 +118,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/it/casi-d-uso/index.html b/web/public/it/casi-d-uso/index.html new file mode 100644 index 00000000..4cfd3617 --- /dev/null +++ b/web/public/it/casi-d-uso/index.html @@ -0,0 +1,320 @@ + + + + + + +Casi d'uso - limiti di upload, fixture per la CI, test di massa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

A cosa lo usano le persone

+

+ Cinque compiti che ricorrono in quasi ogni progetto che accetta file dalle persone, e il comando che + esegue ciascuno. Ogni esempio qui sotto funziona così com'è scritto. +

+ +
+

Limiti di upload

+

Testare se un limite di dimensione dei file è applicato dove dice di esserlo

+

+ Un limite sono tre casi di test, non uno: appena sotto, esattamente sul limite e appena sopra. + Ottenerli a mano significa calcolare numeri di byte sperando di non sbagliare di uno. Chiedi + invece il set: +

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

+ Ottieni tre PDF reali da 1048575, 1048576 e 1048577 byte, e un manifest che dice che i primi due + vanno accettati e il terzo rifiutato per size_limit. Il tuo test legge + l'aspettativa invece che tu scriva tre asserzioni a mano - e quando il limite cambia, cambi un + numero e riesegui. +

+

+ Lo stesso funziona senza preset quando vuoi un singolo set di limiti in linea: +

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

Integrazione continua

+

Tenere le fixture fuori dal repository senza perderle

+

+ Grandi fixture binarie rendono un repository lento da clonare e scomodo da rivedere, e nessuno sa + dire cosa è cambiato quando una viene sostituita. Una ricetta è qualche centinaio di caratteri + di YAML che ricostruiscono i file identici - byte per byte, su qualsiasi + macchina - perché ogni file deriva dal seed dell'esecuzione. +

+
- 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
+

+ Ogni conclusione ha il suo codice di uscita, quindi una pipeline distingue una ricetta sbagliata da + un disco pieno e da una discrepanza di verifica. Un'esecuzione fallita non stampa nulla sullo + standard output, il che evita che un parser di log legga un errore come dato. +

+
+ +
+

Scala

+

Scoprire cosa succede quando la cartella è grande

+

+ Routine di importazione, job notturni ed elenchi di directory si comportano diversamente con + diecimila file che con dieci. Dimensioni estratte da un intervallo fanno sembrare il set + traffico reale anziché diecimila file identici, e l'estrazione viene dal seed, quindi il set è + lo stesso domani. +

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

+ Controlla quanto costerebbe un'esecuzione prima che scriva qualsiasi cosa, il che conta quando il + totale si misura in gigabyte: +

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

+ Un'esecuzione più grande dello spazio libero sul disco viene rifiutata prima che sia scritto il + primo byte, invece di riempire il disco e fallire a metà. +

+
+ +
+

Archivi

+

Testare un decompressore con un archivio che contiene davvero dei file

+

+ Un archivio vuoto con l'estensione giusta non dimostra nulla sul codice che lo apre e percorre ciò + che c'è dentro. Dichiara il contenuto e l'archivio lo contiene davvero: +

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

+ Profondità di annidamento, numero di voci e dimensione di ciò che c'è dentro sono tutte cose su cui + una routine di importazione ha opinioni, ed è così che scopri quali sono. +

+
+ +
+

Parser e visualizzatori

+

Verificare che il tuo codice legga un formato come fa il software reale

+

+ Ogni formato qui è verificato con un lettore indipendente prima del rilascio - un PNG viene aperto e + i suoi pixel confrontati, un DOCX viene riletto da librerie separate, un archivio viene + estratto. Ciò significa che un file che il tuo parser rifiuta è una scoperta sul tuo parser, non + sul generatore. +

+
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
+

+ La pagina dei formati elenca le impostazioni che ciascuno accetta e il + file più piccolo che ciascuno può essere. +

+
+ +
+

Guide

+

Due di questi più in dettaglio

+
    +
  • + File di test corrotti - un file rotto di proposito, della + dimensione esatta, con nel manifest ciò che deve succedergli. +
  • +
  • + File di test in CI - un workflow GitHub Actions, un job GitLab + e i codici di uscita che fanno fallire una build. +
  • +
+
+ +
+

Per chi è

+

+ Ingegneri QA, automazione dei test e chiunque abbia dietro al proprio codice un modulo di upload, + una routine di importazione, un parser o una quota di storage. Gira su una macchina senza alcuna + rete, il che conta in un ambiente aziendale chiuso dove un generatore basato su browser non è + un'opzione. +

+ +

Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/creare-file-di-dimensione-esatta/index.html b/web/public/it/creare-file-di-dimensione-esatta/index.html new file mode 100644 index 00000000..72c8c984 --- /dev/null +++ b/web/public/it/creare-file-di-dimensione-esatta/index.html @@ -0,0 +1,331 @@ + + + + + + +Creare un file di dimensione esatta - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Come creare un file di dimensione esatta

+

+ Ogni sistema ha un comando per farlo, e tutti e tre sono qui sotto. Ti danno un file con esattamente + il numero giusto di byte - e per molti test è tutto ciò che serve. Ogni comando di questa + pagina è stato eseguito prima della pubblicazione, sul sistema a cui appartiene. +

+ +
+

La risposta breve

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Le dimensioni sono in byte, e 10 MB + contati come li conta il tuo file manager sono 10485760. +

+
+ +
+

Windows

+

fsutil, e una versione PowerShell che non richiede nulla di extra

+

+ fsutil è incluso in Windows. Prende la dimensione in byte, quindi + calcola prima il numero - 10 MB sono 10485760, 100 MB sono 104857600, 1 GB è 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Misurato su Windows 11: funziona da un prompt normale senza richiederne uno con privilegi elevati, e + il file esce di esattamente 10485760 byte. +

+

PowerShell può fare lo stesso senza chiamare un altro programma, e capisce le unità:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB in PowerShell significa 10485760 byte, lo stesso conteggio in base 1024 che usa + Esplora risorse, quindi i due comandi qui sopra producono la stessa dimensione. +

+
+ +
+

Linux

+

dd, truncate e fallocate, e la differenza che frega le persone

+

dd è quello che conoscono tutti. Scrive davvero i byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate è istantaneo, ed è questa la trappola. Misurato su Alpine Linux, il file + riporta 10485760 byte e occupa zero blocchi - è un file + sparso. Qualsiasi cosa lo legga ottiene dieci megabyte di zeri, ma il disco non ha mai + ceduto lo spazio: +

+
truncate -s 10M test10mb.bin
+

+ Va bene per testare un limite di upload ed è fuorviante per testare una quota di disco. + fallocate è quello da usare quando lo spazio deve essere reale: +

+
fallocate -l 10M test10mb.bin
+

E quando il contenuto deve essere incomprimibile, così un archiviatore non può ridurlo di nuovo:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, che non è sparso, e i due che conosci già

+

+ macOS include mkfile. Misurato su macOS 26.6.2: 10485760 byte e 20480 blocchi, quindi + lo spazio è davvero allocato invece che promesso: +

+
mkfile 10m test10mb.bin
+

Ci sono anche dd e truncate, e si comportano come su Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Dove questo smette di funzionare

+

Un file della dimensione giusta non è un file del tipo giusto

+

+ Tutto quanto sopra ti dà un blocco di zeri. Basta quando ciò che è sotto test guarda solo la + dimensione - un limite di upload, una quota, un trasferimento. Smette di bastare nel momento in + cui qualcosa apre il file. +

+

+ Misurato, e vale la pena provarlo di persona: crea un file da 2 MB con fsutil, chiamalo + photo.png e passalo a una libreria di immagini. Pillow risponde cannot + identify image file. Non è un PNG. Non lo è mai stato - lo diceva solo il nome. +

+

+ Conta più di quanto sembri, per via di come il test fallisce a quel punto. Il tuo + endpoint di upload rifiuta il file, il tuo test diventa verde e concludi che il limite di + dimensione funziona. Non lo ha rifiutato per la dimensione. Lo ha rifiutato perché i byte non + erano un'immagine, e la regola che volevi testare non è mai stata raggiunta. +

+
    +
  • un parser lo rifiuta prima che venga guardata qualsiasi regola di dimensione
  • +
  • un passaggio di miniatura fallisce e l'errore che leggi riguarda la miniatura
  • +
  • un antivirus o un controllo del contenuto lo rifiuta per un terzo motivo
  • +
  • un visualizzatore non mostra nulla, e nessuno sa dire se sia quello il bug
  • +
+
+ +
+

L'altra strada

+

Un file reale di quel formato, della dimensione esatta che hai chiesto

+

+ È ciò che fa Testing Files Generator. Il file è un vero file del suo formato - si apre nel programma + che gli appartiene - e ha l'esatto numero di byte che hai chiesto, al byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Chiedi una dimensione che un formato non può raggiungere e ottieni un errore che nomina il minimo e + il suo motivo, mai un file della dimensione sbagliata. La pagina dei + formati elenca ogni formato con il file più piccolo che può produrre. +

+

E un limite sono tre casi di test anziché uno, quindi lo strumento li costruisce tutti e tre:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Ti dà 10485759, 10485760 e 10485761 byte, e un manifest che dice quali il tuo sistema deve accettare + e quali rifiutare. La pagina dei casi d'uso ripercorre questo e + altri quattro compiti per cui è pensato. +

+ +

Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.

+
+ +
+

Quindi, quale usare?

+
    +
  • +

    Usa il comando di sistema

    +

    + Quando nulla apre il file. Testare un limite di dimensione su un endpoint che controlla prima la + dimensione, un trasferimento, una quota, un disco pieno. È una riga ed è già installato. +

    +
  • +
  • +

    Usa un generatore vero

    +

    + Quando qualcosa analizza, renderizza, importa o estrae il file - e quando ti servono le stesse + fixture domani, su un'altra macchina, byte per byte. +

    +
  • +
+

+ Entrambi sono su questa pagina perché entrambi hanno ragione una parte del tempo. L'errore da + evitare è usare il primo dove serve il secondo e leggere il test verde come una prova. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/documentazione/index.html b/web/public/it/documentazione/index.html new file mode 100644 index 00000000..74194f9b --- /dev/null +++ b/web/public/it/documentazione/index.html @@ -0,0 +1,559 @@ + + + + + + +Documentazione - comandi, ricette, manifest, codici di uscita + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentazione

+

+ Tutto ciò che fa lo strumento, organizzato come le domande con cui le persone arrivano davvero. Il + README nel repository è il riferimento completo e corrisponde + sempre alla build che hai scaricato. +

+ +
+

Quali comandi esistono?

+

Ognuno fa una cosa sola:

+
tfg generate    produrre file, da una ricetta o da opzioni
+tfg validate    controllare una ricetta senza scrivere nulla
+tfg verify      controllare una directory rispetto a un manifest
+tfg cleanup     rimuovere i file elencati da un manifest
+tfg recipe fmt  stampare una ricetta nella sua forma normalizzata
+tfg preset      costruire un set di file a partire da una domanda di test con nome
+tfg formats     elencare i formati supportati da questa versione
+tfg damage      elencare i modi in cui questa versione può rompere un file di proposito
+tfg tool        piccole utilità per file che hai già
+tfg version     stampare la versione dello strumento
+tfg license     stampare la licenza e cosa significa per i file generati
+
+ +
+

Come genero un singolo file di dimensione esatta?

+

+ Indica il formato, la dimensione e la destinazione. Le dimensioni si contano a 1024, quindi + 2mb sono 2097152 byte. Funziona anche un semplice numero di byte, quindi + --size 10485761 chiede esattamente quel numero. +

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

Le opzioni utili di generate:

+
+ + + + + + + + + + + + + + + + + +
OpzioneCosa fa
--format <id>formato dei file, per esempio txt
--size <size>dimensione esatta di ogni file, come 10mb o un semplice numero di byte
--size-range <a-b>una dimensione estratta per file da un intervallo, come 1kb-8kb. L'estrazione viene dal seed
--boundary <size>tre file attorno a un limite: un byte sotto, il limite, un byte sopra
--count <n>quanti file produrre. Predefinito 1
--name <template>modello del nome, per esempio invoice_{index:04}.txt
--out <dir>directory in cui scrivere
--seed <n>seed dell'esecuzione. Lo stesso seed dà gli stessi byte
--set <k>=<v>un'impostazione di formato, ripetibile
--damage <name>rompere i file di proposito, ripetibile e applicato in ordine. Esegui tfg damage per l'elenco
--expected <outcome>accept, reject, sanitize oppure unspecified
--dry-runcontare e mostrare, senza scrivere assolutamente nulla
--jsonscrivere il manifest sullo standard output
+
+
+ +
+

Come faccio un file rotto di proposito?

+

+ Ogni altro file che questo strumento scrive è corretto per costruzione, il che risponde a due delle + tre domande che pone un validatore di upload. --damage risponde alla terza - il + file si apre, almeno. Il file viene prodotto normalmente e poi rotto, quindi ha ancora la + dimensione che hai chiesto. +

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

+ Le impostazioni vanno dopo i due punti. L'opzione si ripete, e l'ordine in cui le scrivi è l'ordine + in cui vengono applicate. tfg damage elenca cosa può fare questa versione e cosa + accetta ciascuno. +

+

In una ricetta la chiave è un elenco, di nomi o di impostazioni:

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

+ Un file danneggiato riceve expected: reject nel manifest, con il danno registrato + accanto. Due cose vengono rifiutate prima di scrivere qualsiasi cosa, perché ciascuna metterebbe + su disco un file che il manifest descrive in modo sbagliato: +

+
    +
  • un file più piccolo di quanto serve al danno, perché uscirebbe invariato
  • +
  • + expected: accept accanto a un danno, perché nulla potrebbe soddisfarlo. Scrivi + sanitize se il sistema sotto test deve riparare il file, oppure + unspecified se è proprio la domanda che stai ponendo +
  • +
+

+ Una terza non si può sapere in anticipo. Se un danno viene eseguito e non sposta alcun byte, quel + file viene scartato invece di essere scritto - l'esecuzione prosegue, dice di quale file si + trattava e termina con il codice di uscita parziale. +

+

+ Passo dopo passo, con un test che legge il manifest: come + creare un file corrotto per i test. +

+
+ +
+

Che aspetto ha una ricetta?

+

+ Una ricetta è un file YAML che descrive un'intera esecuzione. Committala accanto ai tuoi test e le + fixture smettono di essere binari nel tuo repository - chiunque può ricostruirle, byte per byte, + da un file di poche centinaia di caratteri. +

+
# 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
+

+ Ogni target richiede esattamente una di queste chiavi: size, size-range, + boundary o contains. Due è un errore, e anche nessuna. Una ricetta non + valida scrive nessun file e segnala tutti i problemi insieme invece del solo + primo, ognuno con il nome dell'impostazione a cui si riferisce. +

+
+ +
+

Come dichiaro cosa deve fare il mio sistema con un file?

+

Forma breve quando basta l'esito, forma lunga quando conta il motivo:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Gli esiti sono accept, reject, sanitize e + unspecified. I motivi sono un elenco chiuso così un report può raggrupparli: + 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 e size_zero. +

+

+ Un motivo nomina la regola in gioco, non il verdetto. Ecco perché lo stesso motivo + può stare sotto l'uno o l'altro esito - un file un byte sotto un limite è accept, e + la regola in questione resta size_limit. +

+
+ +
+

Cosa c'è nel manifest?

+

+ Viene scritto accanto ai file alla fine di ogni esecuzione, compresa un'esecuzione interrotta. Una + voce per file: +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Un recipe_hash viene aggiunto quando l'esecuzione viene da una ricetta, e + preset con overrides quando viene da un preset, così un manifest si + può sempre ricondurre a ciò che lo ha prodotto. +

+

+ Ogni voce porta anche target_id, l'id del target della ricetta che ha prodotto il file, + e summary.by_target conta i file a cui è arrivato ciascun target. Una ricetta con + più target si può quindi controllare target per target senza leggere i nomi dei file. +

+
+ +
+

Cos'è un preset?

+

+ Un set di file pronto che risponde a una domanda di test comune, così non devi progettare il set tu. + I preset sono ricette ordinarie sotto il cofano, e eject stampa la ricetta così + puoi modificarla da lì. Ogni preset ha una pagina tutta sua con cosa + trova di solito, cosa c'è nel set e ogni impostazione che accetta. +

+
    +
  • +

    Vuoto e minimo

    +

    Un file valido e piccolo quanto il formato consente passa?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestione dei nomi di file

    +

    Il mio sistema salverà, mostrerà e restituirà un nome di file che non si aspettava?

    +

    filename-handling

    +
  • +
  • +

    Limiti di dimensione

    +

    Un limite di dimensione viene applicato esattamente dove è dichiarato?

    +

    size-boundaries

    +
  • +
  • +

    Importazione di tabelle

    +

    La mia importazione di tabelle regge a ciò che esportano gli strumenti reali?

    +

    tabular-import

    +
  • +
  • +

    Codifica del testo

    +

    Il mio lettore sa in quale codifica è un file, o tira a indovinare?

    +

    text-encoding

    +
  • +
  • +

    Validazione dell'upload

    +

    Il mio modulo di upload accetta ciò che deve e respinge il resto?

    +

    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 ti dice quanto costerebbe il set prima di costruirlo, e dice apertamente quando un + numero è un segnaposto nostro anziché un limite tuo. +

+
+ +
+

Cosa significano i codici di uscita?

+

+ Ogni conclusione ha il suo codice, l'output leggibile da macchina va sullo standard output, e + un'esecuzione fallita non vi stampa nulla. La tabella è un contratto congelato - cambiare il + significato di un codice richiede una versione maggiore. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodiceSignificato
0Tutto ha funzionato.
1Un errore imprevisto dentro lo strumento.
2Comando od opzione errati.
3La ricetta non è valida.
4Il formato non può fare ciò che è stato chiesto.
5Una lettura o una scrittura è fallita.
6Spazio su disco insufficiente.
7verify ha trovato una discrepanza.
8L'esecuzione è terminata ma non tutto è stato prodotto.
130Interrotto con Ctrl+C.
143Fermato da un segnale, che è l'aspetto di un timeout della 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
+

+ Un'esecuzione fermata con Ctrl+C lascia comunque un manifest e non lascia mai un file scritto a + metà, così un job annullato può ancora essere ripulito dal successivo. +

+

+ Workflow pronti per GitHub Actions e GitLab CI: come generare file + di test in una pipeline CI. +

+
+ +
+

Esiste una finestra desktop?

+

+ Sì, lo stesso motore con una finestra sopra, per il test che non è automatizzato. Non è una versione + ridotta: un test confronta le due interfacce capacità per capacità, e tutto ciò che può fare + solo una delle due va dichiarato e giustificato invece di divergere in silenzio. +

+

+ Le schermate sono un lotto, i preset, più lotti insieme e Informazioni. Mostra quanto costerebbe + un'esecuzione prima di scrivere qualsiasi cosa, riporta l'avanzamento mentre gira e si può + annullare a metà senza lasciare un file scritto a metà. Non apre ancora un file di ricetta - per + ora le ricette sono una faccenda da riga di comando, e la finestra costruisce i suoi lotti nel + modulo. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/domande-frequenti/index.html b/web/public/it/domande-frequenti/index.html new file mode 100644 index 00000000..89d76ba3 --- /dev/null +++ b/web/public/it/domande-frequenti/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - domande sulla generazione di file di test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Domande frequenti

+

+ Licenza, privacy, riproducibilità e le cose che le persone controllano prima di mettere un + generatore in una pipeline di build. Se la tua domanda non c'è, il + tracker delle issue è aperto. +

+ +
+
+

In cosa è diverso da dd, fsutil o truncate?

+
+

Quei comandi ti danno un file della dimensione giusta pieno di niente. Un file da 2 MB chiamato photo.png fatto così non è un PNG, quindi qualsiasi cosa lo analizzi davvero lo rifiuta per il motivo sbagliato, e anche il tuo test passa per il motivo sbagliato. Questo produce un vero PNG di esattamente 2 MB che si apre in un visualizzatore di immagini, e arriva con una dichiarazione su come il tuo sistema deve trattarlo.

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

È gratuito, e posso usarlo al lavoro?

+
+

Sì a entrambe. È rilasciato sotto GPL-3.0 e non costa nulla. Non c'è un account, né una chiave di licenza, né un livello a pagamento.

+
+
+
+

Posso usare i file generati in un prodotto closed source?

+
+

Sì. La licenza copre il codice dello strumento, non ciò che lo strumento produce. File, ricette e manifest generati sono output e non opere derivate, quindi puoi committarli e distribuirli senza alcun obbligo.

+
+
+
+

I file generati contengono dati personali reali?

+
+

No. Tutto ciò che contengono è sintetizzato da un seed. Nessun dataset viene letto, nessun servizio viene contattato e nessun contenuto di terzi è incorporato. Considera un indirizzo e-mail generato inutilizzabile anziché inutilizzato, perché qualsiasi stringa casuale può coincidere per caso con uno reale.

+
+
+
+

Otterrò esattamente gli stessi file su un'altra macchina?

+
+

Sì, byte per byte, con la stessa ricetta e lo stesso seed. Il progetto lo verifica a ogni modifica, e romperlo richiede una versione maggiore. È ciò che ti permette di committare una piccola ricetta invece di grandi fixture binarie.

+
+
+
+

Serve una connessione a internet?

+
+

Mai. Non c'è telemetria, né controllo degli aggiornamenti, né client cloud, e il binario della riga di comando non ha alcuno stack di rete compilato al suo interno. Funziona su una macchina senza rete e in un ambiente aziendale chiuso.

+
+
+
+

Cosa succede se chiedo una dimensione che un formato non può raggiungere?

+
+

Ottieni un errore che nomina il formato, il minimo possibile, il motivo di quel limite inferiore e cosa fare invece, e nessun file viene scritto. Lo strumento non arrotonda mai una dimensione in silenzio. Ogni minimo è elencato nella pagina dei formati.

+
tfg formats png
+
+
+
+

Posso generare un file deliberatamente rotto?

+
+

Sì. Aggiungi --damage zero-head e il file esce con esattamente la dimensione richiesta, con i primi byte sovrascritti da zeri, così un lettore lo rifiuta, e il manifest dice che il tuo sistema deve rifiutarlo. I dettagli sono nella pagina sui file di test corrotti.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Quali formati arrivano dopo?

+
+

7z, mp3 e mp4. Oggi 26 formati funzionano da un capo all'altro.

+
+
+
+

Su quali sistemi posso eseguirlo?

+
+

La riga di comando gira su Windows e Linux sia su Intel sia su ARM, e sui Mac con Apple Silicon. La finestra desktop è fornita per Windows su Intel, Linux su Intel e Mac con Apple Silicon. I Mac Intel non sono supportati e non viene compilato nulla per loro.

+
+
+
+

Devo installare qualcosa?

+
+

No. Scarica l'archivio per il tuo sistema, decomprimilo ed esegui il binario. Non c'è un installer, né un runtime da aggiungere, né una dipendenza da risolvere. Se hai Go, funziona anche un solo comando go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Perché un'esecuzione su migliaia di file è più lenta su Windows?

+
+

Perché Windows fa pagare di più ogni percorso che esamina, e un comando che passa su migliaia di file esamina migliaia di percorsi. Misurato su una macchina con 3000 file da 1 kB, verify impiega circa 0,9 secondi su Windows e circa 0,2 secondi su Linux in un container. Un percorso di output più corto abbassa il valore di Windows, perché ogni cartella sopra i file fa parte di ciò che viene esaminato.

+
+
+
+ + +
+

Ancora indeciso?

+

+ La pagina dei casi d'uso mostra i compiti per cui è pensato, e la + pagina dei formati elenca ogni formato con il file più piccolo che + può produrre. Il README nel repository è il riferimento + completo. +

+ +

Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/file-di-test-corrotti/index.html b/web/public/it/file-di-test-corrotti/index.html new file mode 100644 index 00000000..2303bbb9 --- /dev/null +++ b/web/public/it/file-di-test-corrotti/index.html @@ -0,0 +1,383 @@ + + + + + + +File di test corrotti - file rotti di dimensione esatta + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casi d'uso

+

Come creare un file corrotto per i test

+

+ Un validatore a cui sono stati mostrati solo file sani non è stato davvero testato. Ecco come + ottenere un file rotto di proposito, che esce con esattamente la dimensione + richiesta e porta un manifest che dice cosa il tuo sistema deve farne. +

+ +
+

La risposta breve

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out scrive un PNG di + esattamente 2097152 byte i cui primi byte sono zeri, e il manifest accanto registra che il tuo + sistema deve rifiutarlo. +

+
+ +
+

Il modo solito

+

Perché un file corrotto a mano è un cattivo test

+

+ I modi soliti sono un editor esadecimale, uno script che cambia qualche byte a caso o un file + accorciato con head o truncate. Funzionano una volta, poi costano: +

+
    +
  • + È diverso ogni volta. Un byte casuale cade in un punto nuovo a ogni esecuzione, + quindi un errore del martedì può non ripresentarsi il mercoledì. +
  • +
  • + Cambia la dimensione. Un file tagliato è più piccolo del limite sotto cui doveva + stare, quindi il controllo della dimensione risponde prima di quello del contenuto e il test + passa per il motivo sbagliato. +
  • +
  • + Spesso passa inosservato. Il testo semplice si legge ancora con un byte cambiato + nel mezzo, e un lettore di immagini indulgente lo disegna e basta, così il file che doveva + essere rotto viene accettato. +
  • +
  • + Non dice nulla su cosa deve succedere. Il file è solo byte, e chi legge il test + dopo deve indovinare se si voleva l'accettazione o il rifiuto. +
  • +
+
+ +
+

Cosa ottieni

+

Un file danneggiato ha ancora la dimensione richiesta

+

+ Il file viene generato normalmente e rotto dopo, mentre va verso il disco. Mantiene la dimensione + richiesta, e lo stesso comando riscrive gli stessi byte. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Le impostazioni vanno dopo i due punti. L'opzione si può ripetere, e i danni vengono applicati + nell'ordine in cui li scrivi. Funziona con ognuno dei 26 formati. +

+
+ +
+

Cosa sa fare

+

Quali danni ci sono?

+

+ Questa è la lista che il programma stampa, letta da lui quando si costruisce questa pagina. + tfg damage stampa la stessa, e tfg damage <id> dice cosa accetta + ciascuno. +

+
+ + + + + + + + + + + + + + + + + +
DannoCosa fa ai byteFile più piccoloImpostazioni
zero-headSovrascrive con zeri i primi byte del file, lasciandone intatta la lunghezza. La maggior parte dei lettori guarda prima lì, quindi quasi tutto si accorge di questo danno.8bytes
+
+

+ zero-head scrive zeri sull'inizio del file. La maggior parte dei lettori guarda prima + lì, la firma e l'intestazione che dicono cos'è il file, quindi quasi ogni lettore se ne accorge. + Il testo semplice e i log non hanno firma e vengono rifiutati lo stesso, perché una serie di + byte nulli non è testo. Sotto i quattro byte alcuni formati escono con un danno di cui nessun + lettore si lamenta, ed è per questo che l'impostazione parte da quattro. +

+
+ +
+

Cosa dice il manifest

+

Un manifest che dice cosa deve succedere

+

+ Ogni file danneggiato riceve una voce che dice che il tuo sistema deve rifiutarlo, con il danno + registrato accanto: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Due richieste vengono rifiutate prima che venga scritto qualcosa, perché ciascuna lascerebbe su + disco un file che il manifest descrive male: +

+
    +
  • un file più piccolo di quanto serve al danno, che uscirebbe intatto
  • +
  • + expected: accept accanto a un danno, perché nulla potrebbe soddisfarlo. Scrivi + sanitize se il tuo sistema deve riparare il file, oppure unspecified + se è proprio questa la domanda che poni +
  • +
+
+ +
+

In una ricetta

+

File sani e rotti in una sola esecuzione

+

+ Metti entrambi in una ricetta, e il manifest porta l'aspettativa di ogni file, così il test non ha + bisogno di un elenco di quale sia quale: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In un test

+

Trasformarlo in un test

+

+ Il test legge il manifest e controlla che ciò che è successo sia ciò che era stato dichiarato. Non + ha bisogno di un elenco di nomi di file: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Un buon rifiuto è un rifiuto pulito. Un messaggio che dice cosa non andava è la risposta che vuoi. + Un errore del server, un blocco o un file salvato a metà è il difetto che questo test esiste per + trovare. +

+
+ +
+

Avanti

+

Dove andare da qui

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/it/file-di-test-in-ci/index.html b/web/public/it/file-di-test-in-ci/index.html new file mode 100644 index 00000000..0bf35231 --- /dev/null +++ b/web/public/it/file-di-test-in-ci/index.html @@ -0,0 +1,380 @@ + + + + + + +File di test in CI - GitHub Actions, GitLab CI e PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casi d'uso

+

Come generare file di test in una pipeline CI

+

+ Una fixture binaria in un repository resta per sempre nella sua cronologia, non si può rivedere in + un diff e diventa impossibile quando il file è grande. Genera invece i file dentro la pipeline a + partire da una ricetta. La ricetta è testo, i byte escono uguali ogni volta e un ultimo passo + dimostra che nulla si è mosso. +

+ +
+

La risposta breve

+

+ Installa tfg, esegui tfg generate fixtures.yaml --out ./fixtures prima dei + test e tfg verify ./fixtures/manifest.json dopo. Entrambi i passi fanno fallire la + build da soli, con un codice di uscita che dice perché. +

+
+ +
+

Perché non committarli

+

Perché una fixture non deve stare nel repository

+
    +
  • + Resta nella cronologia. Cancellare un binario in seguito non rende più piccolo un + clone, perché ogni sua versione è ancora lì. +
  • +
  • + Un diff non mostra cosa è cambiato. Chi rivede vede che un PDF è diverso e + nient'altro. Una ricetta cambia di una riga. +
  • +
  • + I file grandi non ci stanno. GitHub rifiuta un push che contiene un file sopra i + 100 MB, quindi un test di un limite di upload di 500 MB non ha nulla da committare. +
  • +
+

+ Quello da committare è la ricetta. La stessa ricetta con lo stesso seme scrive gli stessi byte su + ogni macchina, quindi il file generato nella pipeline è il file che avevi sul portatile. +

+
+ +
+

La ricetta

+

Una ricetta che vive accanto ai test

+

+ Questa scrive venticinque fatture che devono essere accettate e due immagini oltre un limite che + devono essere rifiutate, e il manifest registra entrambe le aspettative: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml la controlla senza scrivere nulla e nomina tutti i problemi + in una volta. +

+
+ +
+

GitHub Actions

+

Un workflow che installa lo strumento e costruisce le fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ La riga della somma di controllo confronta l'archivio con verify-SHA256SUMS.txt della + stessa versione. La versione è fissata, quindi una nuova versione non cambia mai una build che + non hai toccato. +

+
+ +
+

GitLab CI

+

Lo stesso come job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quando diventa rosso

+

Cosa fa fallire un passo, e perché

+

+ Ogni conclusione ha il suo codice di uscita, quindi il passo fallisce da solo e il log dice quale. + Quelli che incontra una pipeline: +

+
    +
  • 3 - la ricetta non è valida. Non è stato scritto nulla e ogni problema è nominato
  • +
  • 4 - il formato non può fare ciò che è stato chiesto, per esempio una dimensione sotto il suo minimo
  • +
  • 6 - non c'è abbastanza spazio su disco
  • +
  • 7 - tfg verify ha trovato un file che non corrisponde al suo manifest
  • +
  • 8 - l'esecuzione è finita, ma non tutto è stato prodotto
  • +
+

+ Un'esecuzione fallita non stampa nulla sullo standard output, così un parser di log non scambia mai + un errore per dati. La tabella completa è nella pagina della + documentazione. +

+
+ +
+

PowerShell

+

Uno script PowerShell richiede una riga in più

+

+ PowerShell non porta fuori da un file .ps1 il codice di uscita di un programma. + Eseguine uno con -File e lo script risponde 0 anche quando lo + strumento al suo interno ha rifiutato il lavoro, così una build che dovrebbe essere rossa + diventa verde. L'ultima riga è tutta la correzione: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ È così che si comporta PowerShell, non qualcosa di questo strumento. cmd, + bash e zsh non richiedono nulla di più. +

+
+ +
+

Più job

+

Condividere le fixture tra i job

+

+ Di solito non serve caricarle. Poiché la stessa ricetta scrive gli stessi byte, ogni job può + eseguire il proprio tfg generate, che è più rapido di un upload e di un download. + Quando un job deve ricevere file da un altro, esegui tfg verify sul manifest dopo + il trasferimento, e ti dice se ciò che è arrivato è ciò che è stato scritto. +

+
+ +
+

Avanti

+

Dove andare da qui

+
    +
  • + File di test corrotti aggiunge alla stessa ricetta file + rotti di proposito. +
  • +
  • + I casi d'uso mostrano cos'altro può controllare un'esecuzione in una + pipeline. +
  • +
  • + La documentazione riporta ogni comando, ogni chiave della ricetta + e ogni codice di uscita. +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/formati/index.html b/web/public/it/formati/index.html new file mode 100644 index 00000000..921092a4 --- /dev/null +++ b/web/public/it/formati/index.html @@ -0,0 +1,914 @@ + + + + + + +26 formati di file supportati - PDF, DOCX, PNG, ZIP e altri + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formati di file, ognuno generato a una dimensione esatta

+

+ Ognuno è un file reale di quel formato. Si apre nel programma che gli appartiene ed + è esattamente il numero di byte che hai chiesto. Nessuno è riempimento di zeri con un'estensione + appiccicata. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoNomeEstensioneFile più piccoloFedeltàVerificato con
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullnon applicabile
mdMarkdown.md0fullnon applicabile
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullnon applicabile
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Cosa significano le colonne

+
    +
  • +

    File più piccolo

    +

    + Il minimo di byte che questo strumento accetta per quel formato, compresa l'etichetta che scrive + dentro il file. Chiedi meno e ottieni un errore che nomina il minimo e il suo motivo, mai un + file della dimensione sbagliata. +

    +
  • +
  • +

    Fedeltà

    +

    + Quanto è completo il file. full significa che un lettore che analizza davvero il + formato lo accetta, non solo che l'estensione corrisponde. +

    +
  • +
  • +

    Verificato con

    +

    + Il lettore indipendente che apre ogni file generato prima che il formato venga rilasciato - + un'implementazione separata, non il nostro codice che corregge i propri compiti. +

    +
  • +
+

+ Ogni formato si ripete anche al byte: la stessa ricetta e lo stesso seed producono file identici su + qualsiasi macchina, ed è ciò che rende sicuro committare una ricetta al posto delle fixture + stesse. +

+
+ +
+

Impostazioni che ogni formato accetta

+

+ La maggior parte dei formati ha impostazioni proprie - dimensioni dell'immagine, qualità JPEG, + numero di pagine PDF, righe e colonne di un foglio di calcolo, quante voci vanno dentro un + archivio. Impostale con --set key=value dalla riga di comando, o sotto + properties: in una ricetta. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoImpostazioneAccetta
avifwidth1 - 16384 pixel
height1 - 16384 pixel
quality1 - 100
bmpwidth1 - 20000 pixel
height1 - 20000 pixel
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headervero o falso
quote_styleall, minimal, none
columns2 - 32768 colonne
docxparagraphs1 - 50000 paragrafi
gifwidth1 - 20000 pixel
height1 - 20000 pixel
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixel
height1 - 256 pixel
embedbmp, png
jpgwidth1 - 20000 pixel
height1 - 20000 pixel
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixel
height1 - 16384 pixel
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 voci al secondo
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomvero o falso
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlequalsiasi testo
authorqualsiasi testo
subjectqualsiasi testo
keywordsqualsiasi testo
creatorqualsiasi testo
producerqualsiasi testo
createduna data come 2024-02-29 o 2024-02-29T13:45:00+02:00, oppure none
modifieduna data come 2024-02-29 o 2024-02-29T13:45:00+02:00, oppure none
pngwidth1 - 20000 pixel
height1 - 20000 pixel
pptxslides1 - 500 diapositive
svgwidth1 - 20000 pixel
height1 - 20000 pixel
targzentries0 - 10000
entry_formatl'id di un formato, come lo elenca tfg formats
entry_sizeuna dimensione come 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesvero o falso
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixel
height1 - 20000 pixel
txtencodingutf-16be, utf-16le, utf-8
bomvero o falso
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixel
height1 - 16383 pixel
xlsxrows1 - 200000 righe
columns1 - 32768 colonne
xmlencodingutf-16be, utf-16le, utf-8
bomvero o falso
zipentries0 - 10000
entry_formatl'id di un formato, come lo elenca tfg formats
entry_sizeuna dimensione come 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesvero o falso
passwordla password, in chiaro
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Un valore fuori da ciò che un'impostazione accetta viene rifiutato con un messaggio che nomina + l'impostazione, l'intervallo consentito e cosa usare al suo posto. Anche un'impostazione + sconosciuta è un errore, mai un valore predefinito silenzioso - un refuso accettato in silenzio + dà un file con le impostazioni sbagliate e un'ora a chiedersi perché il test passa quando non + dovrebbe. +

+

+ Esegui tfg formats <id> per vedere esattamente cosa accetta un formato nella + build che hai. +

+
+ +
+

Gli archivi contengono file reali

+

+ targz e zip + possono essere riempiti di voci invece di restare un guscio vuoto. Un archivio generato contiene + davvero i documenti che dichiara di contenere, quindi qualsiasi cosa lo decomprima durante un + test trova file reali al suo interno. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/index.html b/web/public/it/index.html new file mode 100644 index 00000000..c72068c0 --- /dev/null +++ b/web/public/it/index.html @@ -0,0 +1,455 @@ + + + + + + +Generatore di file di test - dimensione esatta, 26 formati reali + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Genera file di test reali della dimensione esatta

+

+ PDF, PNG, DOCX, ZIP - 26 formati in tutto, e ognuno è un file + reale che si apre nel programma che gli appartiene, di esattamente la dimensione che hai + chiesto. Ogni esecuzione annota anche cosa la tua applicazione deve fare con ogni file. + Riga di comando e finestra desktop, gratuito e open source, interamente sulla tua macchina. +

+ + +

Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.

+
+ +
+ La finestra desktop di Testing Files Generator, pronta a scrivere un lotto di file di test +
La finestra desktop, pronta a scrivere un lotto di file. Lo stesso motore gira dietro la riga di comando.
+
+
+ +
    +
  • + 26 +

    formati reali, ognuno si apre nel programma che gli appartiene

    +
  • +
  • + 1 byte +

    la precisione di ogni dimensione che chiedi, mai arrotondata in silenzio

    +
  • +
  • + 0 +

    connessioni verso chiunque - nessun account, nessuna telemetria, nessun controllo degli aggiornamenti

    +
  • +
+ +
+

Il problema

+

Fare un file di test è facile. Fare i mille giusti è la parte noiosa

+

Stai testando software che accetta file dalle persone. Prima o poi ti servono:

+
    +
  • un PDF di esattamente 10 MB, per scoprire se il limite di upload è reale
  • +
  • i tre file ai due lati di quel limite, per scovare errori di uno in più o in meno
  • +
  • 10.000 file di log, per vedere cosa fa il job notturno quando la cartella è grande
  • +
  • uno ZIP che contiene davvero 200 documenti, non un guscio vuoto con l'estensione giusta
  • +
  • un file da 4 GB, senza tenere un file da 4 GB nel tuo repository
  • +
  • le stesse fixture sul tuo portatile e sul server di build, byte per byte
  • +
+

+ È ciò che questo sostituisce. È pensato per ingegneri QA, automazione dei test e chiunque abbia + dietro al proprio codice un modulo di upload, una routine di importazione, un parser o una quota + di storage. +

+
+ +
+

Cosa lo rende diverso

+

Gli altri generatori si fermano ai byte. Questo risponde a ciò che il tuo test chiede davvero

+

+ Una cartella di file ti lascia ancora a decidere cosa dovrebbe dimostrare ciascuno. Ogni esecuzione + qui scrive un manifest.json accanto ai file - un semplice elenco di tutto ciò che è + stato prodotto e, per ogni voce, un'aspettativa dichiarata. +

+

Poniamo che il tuo endpoint di upload permetta 1 MB. Chiedi i tre file che stanno su quella linea:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FileByteIl tuo sistema devePerché
1mb_under_1b.pdf1048575accettareè dentro il limite
1mb_at_limit.pdf1048576accettareil limite stesso è consentito
1mb_over_1b.pdf1048577rifiutaresize_limit
+
+ +

Tre file, tre risposte diverse, in forma leggibile da macchina. Il tuo test legge il manifest invece che tu scriva le asserzioni a mano:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Dove la risposta dipende dalla tua politica, il manifest lo dice

+

+ Registra unspecified invece di inventare un'aspettativa. Un generatore che tira a + indovinare produce falsi fallimenti, e una suite che grida al lupo finisce spenta. +

+
+
+ +
+

Preset

+

Scegli la domanda, ottieni l'intero set

+

+ Un preset è un set di file di test progettato attorno a una domanda di test, così non devi capire tu + quali file dimostrano cosa. Ognuno ha una pagina che dice cosa trova di solito, cosa c'è nel set + e ogni impostazione che accetta. +

+
    +
  • +

    Vuoto e minimo

    +

    Un file valido e piccolo quanto il formato consente passa?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestione dei nomi di file

    +

    Il mio sistema salverà, mostrerà e restituirà un nome di file che non si aspettava?

    +

    filename-handling

    +
  • +
  • +

    Limiti di dimensione

    +

    Un limite di dimensione viene applicato esattamente dove è dichiarato?

    +

    size-boundaries

    +
  • +
  • +

    Importazione di tabelle

    +

    La mia importazione di tabelle regge a ciò che esportano gli strumenti reali?

    +

    tabular-import

    +
  • +
  • +

    Codifica del testo

    +

    Il mio lettore sa in quale codifica è un file, o tira a indovinare?

    +

    text-encoding

    +
  • +
  • +

    Validazione dell'upload

    +

    Il mio modulo di upload accetta ciò che deve e respinge il resto?

    +

    upload-validation

    +
  • +
+

Tutti i preset, e come si rapportano alle ricette

+
+ +
+

Guida rapida

+

Tre comandi per vederlo funzionare

+
    +
  1. +

    Crea un file

    +

    Un PNG, esattamente due megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Crea molti file

    +

    + Diecimila file di log, ciascuno tra uno e otto kilobyte, con le dimensioni estratte dal seed così + domani dà lo stesso set. Dai a ogni esecuzione la sua directory - il + manifest è l'unica traccia di ciò che un'esecuzione ha scritto, quindi lo strumento si + rifiuta di scriverne un secondo sopra: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Controllali, poi rimuovili

    +

    verify ti dice che nulla si è mosso. cleanup rimuove esattamente ciò che è stato scritto e nient'altro:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Le dimensioni si contano a 1024, come fa il tuo file manager, quindi 2mb significa + 2097152 byte. Funziona anche un semplice numero di byte. La + documentazione copre le ricette, il manifest e i codici di + uscita. +

+
+ +
+

Cosa ottieni

+

Costruito per una suite che gira senza supervisione

+
    +
  • +

    Dimensione esatta, al byte

    +

    Chiedi 10485761 byte e ottieni esattamente quelli. Una dimensione che un formato non può raggiungere è un errore con un motivo, mai un file della dimensione sbagliata.

    +
  • +
  • +

    26 formati reali

    +

    Non zeri di riempimento con un'estensione. Un PNG generato si apre in un visualizzatore di immagini, un DOCX si apre in Word, uno ZIP si estrae. Ognuno è verificato con lettori indipendenti prima del rilascio.

    +
  • +
  • +

    Un manifest che è un oracolo di test

    +

    Percorso, dimensione, SHA-256, formato, seed, versione dello strumento - e cosa il tuo sistema deve fare con il file.

    +
  • +
  • +

    Riproducibile

    +

    Stessa ricetta e stesso seed, stessi byte, su qualsiasi macchina. Committa una piccola ricetta YAML invece di grandi fixture binarie.

    +
  • +
  • +

    Due interfacce, un solo motore

    +

    Una riga di comando pensata per la CI e una finestra desktop per il test esplorativo. Nessuna è una versione ridotta dell'altra, e un test le confronta capacità per capacità.

    +
  • +
  • +

    Completamente offline

    +

    Nessun account, nessun cloud, nessuna telemetria, nessun controllo degli aggiornamenti. Il binario della riga di comando non ha alcuno stack di rete compilato al suo interno.

    +
  • +
+
+ +
+

Download

+

Scegli la build per il tuo sistema

+

+ Decomprimi l'archivio ed eseguilo. tfg è la riga di comando e tfg-gui è la + finestra desktop. Non c'è un installer e nulla da aggiungere alla tua macchina. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemaRiga di comandoFinestra desktop
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Cosa è firmato e cosa no

+

+ I download per Windows e macOS sono firmati, quindi si avviano senza l'avviso di sviluppatore + sconosciuto. Quelli per Linux no, perché Linux desktop non ha un equivalente con cui firmarli. + Ogni archivio è elencato in verify-SHA256SUMS.txt nella pagina delle release, + così puoi controllare cosa hai scaricato. +

+
+ +

Gratuito e open source, GPL-3.0. Nessuna registrazione. I download per Windows e macOS sono firmati e si avviano senza avvisi.

+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/empty-and-minimal/index.html b/web/public/it/preset/empty-and-minimal/index.html new file mode 100644 index 00000000..ba42fdf5 --- /dev/null +++ b/web/public/it/preset/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +File di test validi minimi e vuoti in ogni formato + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Vuoto e minimo

+

Un file valido e piccolo quanto il formato consente passa?

+

+ Il preset empty-and-minimal costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • un file valido respinto perché troppo piccolo, quando il controllo conta i byte invece di leggerli
  • +
  • un file vuoto che manda in crash il lettore invece di essere segnalato
  • +
  • un'immagine larga un pixel che divide per zero lungo la strada verso la miniatura
  • +
  • uno storage che legge zero byte come un upload fallito e continua a riprovare
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show empty-and-minimal:

+
+ + + + + + + +
File28
Target nella sua ricetta28
Dimensione totale32 667 B
Formatiavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.26
unspecifiedDipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi.2
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--formatsid di formato separati da virgole, oppure allallDa quali formati è composto il set. Lascia all per tutti i formati di questa versione, oppure indica quelli che il tuo sistema accetta.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/filename-handling/index.html b/web/public/it/preset/filename-handling/index.html new file mode 100644 index 00000000..3d785519 --- /dev/null +++ b/web/public/it/preset/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Nomi di file problematici da testare - Unicode e lunghezza + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Gestione dei nomi di file

+

Il mio sistema salverà, mostrerà e restituirà un nome di file che non si aspettava?

+

+ Il preset filename-handling costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • un nome che sembra un altro sullo schermo, in un log o in un elenco
  • +
  • un nome tagliato, accorciato o riscritto tra l'upload e il salvataggio
  • +
  • un limite di lunghezza contato in caratteri dove lo storage conta byte
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show filename-handling:

+
+ + + + + + + +
File50
Target nella sua ricetta50
Dimensione totale51 200 B
Formatitxt
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.4
unspecifiedDipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi.46
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--formatun id di formato dalla pagina dei formatitxtIl formato di ogni file del set. È un'opzione dello strumento stesso, e il preset le dà solo un valore predefinito.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/index.html b/web/public/it/preset/index.html new file mode 100644 index 00000000..75d1c9f5 --- /dev/null +++ b/web/public/it/preset/index.html @@ -0,0 +1,245 @@ + + + + + + +Preset di file di test - set pronti per la QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Preset di file di test, un set per ogni domanda di test

+

+ Un preset è un intero set di file di test progettato attorno a una domanda, con un manifest che dice + come il tuo sistema deve reagire a ogni file. Scegli la domanda, lo strumento costruisce il set. + Ogni preset ha una pagina tutta sua con cosa trova di solito, cosa c'è nel set e ogni impostazione + che accetta. +

+ +
    +
  • +

    Vuoto e minimo

    +

    Un file valido e piccolo quanto il formato consente passa?

    +

    empty-and-minimal

    +
  • +
  • +

    Gestione dei nomi di file

    +

    Il mio sistema salverà, mostrerà e restituirà un nome di file che non si aspettava?

    +

    filename-handling

    +
  • +
  • +

    Limiti di dimensione

    +

    Un limite di dimensione viene applicato esattamente dove è dichiarato?

    +

    size-boundaries

    +
  • +
  • +

    Importazione di tabelle

    +

    La mia importazione di tabelle regge a ciò che esportano gli strumenti reali?

    +

    tabular-import

    +
  • +
  • +

    Codifica del testo

    +

    Il mio lettore sa in quale codifica è un file, o tira a indovinare?

    +

    text-encoding

    +
  • +
  • +

    Validazione dell'upload

    +

    Il mio modulo di upload accetta ciò che deve e respinge il resto?

    +

    upload-validation

    +
  • +
+ +
+

In cosa un preset è diverso da una ricetta?

+

+ Sotto il cofano, in niente. Un preset è una ricetta che lo strumento scrive per te a partire da + poche impostazioni. tfg preset eject stampa quella ricetta così puoi tenerla + accanto ai tuoi test e modificarla, e una ricetta tua può basarsi su un preset con una riga, + extends: preset: seguito dal suo id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Posso fidarmi dei valori predefiniti?

+

+ Per i file, sì. Per un numero che solo il tuo sistema conosce, come il limite di un modulo di + upload, un valore predefinito è un nostro segnaposto, e lo strumento lo dice ogni volta che ne + usa uno. La pagina di ogni preset marca queste impostazioni, e tfg preset show lo + dice prima che venga scritto qualsiasi cosa. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/it/preset/size-boundaries/index.html b/web/public/it/preset/size-boundaries/index.html new file mode 100644 index 00000000..65caaa73 --- /dev/null +++ b/web/public/it/preset/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Testare un limite di dimensione dell'upload - file al limite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Limiti di dimensione

+

Un limite di dimensione viene applicato esattamente dove è dichiarato?

+

+ Il preset size-boundaries costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • errori di uno in più o in meno al limite
  • +
  • MB confuso con MiB, che fa il 4,8 per cento e basta a far passare un file che non dovrebbe passare
  • +
  • un limite applicato nel browser e non sul server
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show size-boundaries:

+
+ + + + + + + +
File7
Target nella sua ricetta7
Dimensione totale73 400 320 B
Formatipdf
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.4
rejectIl tuo sistema deve rifiutare il file.3
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--limituna dimensione come 2mb10mbIl limite di dimensione dichiarato dal tuo sistema. Tutto il resto si misura a partire da esso. Questo valore predefinito è un nostro segnaposto, non il valore del tuo sistema. Passa il tuo.
--spreaddimensioni separate da virgole1B,1kb,1mbFin dove spingersi ai due lati del limite, come elenco di dimensioni.
--formatun id di formato dalla pagina dei formatipdfIl formato di ogni file del set. È un'opzione dello strumento stesso, e il preset le dà solo un valore predefinito.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

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

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/tabular-import/index.html b/web/public/it/preset/tabular-import/index.html new file mode 100644 index 00000000..ab2e39b6 --- /dev/null +++ b/web/public/it/preset/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +File di test per importare CSV ed Excel - delimitatori + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Importazione di tabelle

+

La mia importazione di tabelle regge a ciò che esportano gli strumenti reali?

+

+ Il preset tabular-import costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • un file con punto e virgola letto come una sola colonna, perché il delimitatore è stato dato per scontato invece di cercarlo
  • +
  • un file CRLF diviso in righe con una riga vuota dopo ciascuna
  • +
  • una tabella senza intestazione la cui prima riga di dati viene mangiata come nomi di colonna
  • +
  • un'importazione che tiene le colonne che sa mostrare e scarta il resto senza dire nulla
  • +
  • un lettore che prende i record JSON una riga alla volta e si ferma al primo documento indentato
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show tabular-import:

+
+ + + + + + + +
File13
Target nella sua ricetta13
Dimensione totale3 080 060 B
Formaticsv, json, xlsx
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.8
unspecifiedDipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi.5
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--rows1 - 200000 righe1000Quante righe contiene il foglio di calcolo. Viene scritto esattamente alla dimensione che occupano tante righe, quindi il budget qui sopra si sposta con questo valore.
--columns1 - 32768 colonne10Quante colonne ha ogni riga del foglio di calcolo. Righe per colonne ha un tetto, e chiedere oltre viene rifiutato prima di scrivere qualsiasi cosa.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/text-encoding/index.html b/web/public/it/preset/text-encoding/index.html new file mode 100644 index 00000000..1f91cd8e --- /dev/null +++ b/web/public/it/preset/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +File di test per la codifica del testo - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Codifica del testo

+

Il mio lettore sa in quale codifica è un file, o tira a indovinare?

+

+ Il preset text-encoding costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • un lettore che presume UTF-8 e mostra un file UTF-16 con un carattere ogni tre, o come file di quadratini
  • +
  • un byte order mark letto come contenuto, così il primo campo di un'importazione inizia con tre caratteri estranei
  • +
  • un importatore che indovina la codifica dai primi byte e indovina in modo diverso con un file più lungo
  • +
  • un file CRLF diviso in righe con una riga vuota dopo ciascuna, o un ritorno a capo rimasto nell'ultimo campo
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show text-encoding:

+
+ + + + + + + +
File20
Target nella sua ricetta20
Dimensione totale81 920 B
Formaticsv, log, md, txt, xml
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.10
unspecifiedDipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi.10
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--sampleuna dimensione come 2mb4kbQuanto è grande ogni file del set. UTF-16 memorizza due byte per carattere, quindi un numero dispari viene rifiutato.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/it/preset/upload-validation/index.html b/web/public/it/preset/upload-validation/index.html new file mode 100644 index 00000000..057dd2a2 --- /dev/null +++ b/web/public/it/preset/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +File di test per la validazione dell'upload - tipo e nome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Validazione dell'upload

+

Il mio modulo di upload accetta ciò che deve e respinge il resto?

+

+ Il preset upload-validation costruisce con un solo comando un intero set di file di test reali + per questa domanda, e un manifest.json accanto che dice come il tuo sistema deve + reagire a ogni file. Tutto ciò che segue è letto dal programma, ai valori predefiniti di questa + versione. +

+ + +
+

Cosa trova di solito?

+
    +
  • un limite applicato nel browser e non sul server
  • +
  • un SVG o un HTML scambiato per un'immagine o per testo semplice, che è un modo per far passare uno script attraverso un modulo
  • +
  • un file controllato dall'estensione e mai aperto, così un PDF chiamato .jpg passa
  • +
  • un modulo che legge l'intero corpo in memoria prima di guardare quanto è grande
  • +
  • un upload chiamato PHOTO.JPG respinto dove photo.jpg viene accettato, o il contrario
  • +
  • un nome con spazi, parentesi o caratteri fuori dall'ASCII scritto su disco senza modifiche
  • +
+
+ + +
+

Cosa c'è nel set?

+

Ai valori predefiniti, come lo riporta tfg preset show upload-validation:

+
+ + + + + + + +
File71
Target nella sua ricetta22
Dimensione totale120 639 488 B
Formatihtml, jpg, pdf, png, svg, txt
+
+

E ciò che il manifest di quel set si aspetta dal tuo sistema:

+
+ + + + + + + + + +
AttesoSignificatoFile
acceptIl tuo sistema deve accettare il file.56
rejectIl tuo sistema deve rifiutare il file.10
unspecifiedDipende dalle regole del tuo sistema. Decidi tu, poi controlli che ciò che accade sia ciò che intendevi.5
+
+
+ +
+

Cosa puoi cambiare?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ImpostazioneAccettaPredefinitoCosa fa
--limituna dimensione come 2mb10mbIl limite di dimensione dichiarato dal tuo modulo di upload. Questo set fa un passo per lato - per un file a ogni distanza, esegui il preset size-boundaries. Questo valore predefinito è un nostro segnaposto, non il valore del tuo sistema. Passa il tuo.
--allowid di formato separati da virgolejpg,png,pdfQuali tipi il tuo modulo deve accettare. Ognuno diventa un file reale di quel tipo, e sono il controllo positivo dell'intero set.
--denyestensioni separate da virgolesvg,html,exe,shQuali estensioni il tuo modulo deve respingere. Un'estensione per cui questa versione non ha un formato riceve comunque un file con quel nome, contenente testo semplice.
--far-over10x, 2x, off2xQuanto oltre il limite arriva l'unico file grande. Disattivalo dove scrivere diverse volte il limite non vale il disco.
--bulk0 - 10000 file50Quanti file contiene l'upload di massa. Zero lascia del tutto fuori dal set quel gruppo.
+
+
+ +
+

Come si esegue?

+

Guarda quanto costerebbe il set, costruiscilo o prendi la sua ricetta da modificare:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Oppure costruiscici sopra in una ricetta tua, accanto ai tuoi test:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/corrupt-test-files/index.html b/web/public/ja/corrupt-test-files/index.html new file mode 100644 index 00000000..763ee629 --- /dev/null +++ b/web/public/ja/corrupt-test-files/index.html @@ -0,0 +1,356 @@ + + + + + + +破損したテストファイル - サイズが正確な壊れたファイル + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

利用例

+

テスト用の破損ファイルを作る方法

+

+ 健全なファイルしか見せたことのない検証は、本当にはテストされていません。ここでは、意図的に壊してあり、求めたとおりのサイズで出てきて、システムがそれをどう扱うべきかを示すマニフェストを伴うファイルの作り方を説明します。 +

+ +
+

短い答え

+

+ tfg generate --format png --size 2mb --damage zero-head --out + ./outは、ちょうど2097152バイトで先頭のバイトがゼロのPNGを書き出し、隣のマニフェストにはシステムがそれを拒否すべきだと記録されます。 +

+
+ +
+

よくあるやり方

+

手作業で壊したファイルがよくないテストになる理由

+

+ よくあるのは、16進エディタ、いくつかのランダムなバイトを反転させるスクリプト、headやtruncateでファイルを短く切る方法です。一度は使えますが、あとで手間がかかります。 +

+
    +
  • + 毎回違います。ランダムなバイトは実行のたびに別の場所に当たるので、火曜日の失敗が水曜日には再現しないことがあります。 +
  • +
  • + サイズが変わります。切り詰めたファイルは、本来下回るはずだった上限よりも小さくなるため、サイズの検査が内容の検査より先に答えてしまい、テストは誤った理由で通ります。 +
  • +
  • + 気づかれないことが多くあります。プレーンテキストは途中の1バイトが変わっても読めますし、寛容な画像リーダーはそのまま描画するので、壊れているはずのファイルが受け入れられてしまいます。 +
  • +
  • + 何が起こるべきかを伝えません。ファイルはただのバイト列で、後からテストを読む人は、受け入れと拒否のどちらが意図だったのかを推測するしかありません。 +
  • +
+
+ +
+

得られるもの

+

破損したファイルも、求めたサイズのままです

+

+ ファイルは通常どおり生成され、ディスクへ向かう途中で壊されます。求めたサイズは保たれ、同じコマンドは同じバイトをもう一度書き出します。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 設定はコロンの後ろに書きます。オプションは繰り返せて、破損は書いた順に適用されます。26種類すべての形式で使えます。 +

+
+ +
+

できること

+

どんな破損がありますか。

+

+ これはプログラムが出力する一覧で、このページを作るときにプログラムから読み取っています。tfg damageは同じ一覧を出力し、tfg damage + <id>はそのうちの1つが受け取る設定を示します。 +

+
+ + + + + + + + + + + + + + + + + +
破損バイトへの作用最小ファイル設定
zero-headファイルの先頭のバイトをゼロで上書きし、長さは変えません。ほとんどのリーダーはまずそこを見るので、この破損にはほぼどれも気づきます。8bytes
+
+

+ zero-headはファイルの先頭をゼロで上書きします。ほとんどのリーダーはまずそこを見ます。ファイルが何であるかを示すシグネチャとヘッダーです。そのため、ほぼどのリーダーでも気づきます。プレーンテキストやログにはシグネチャがありませんが、これらも拒否されます。ゼロのバイトの連なりはテキストではないからです。4バイト未満では、どのリーダーも文句を言わない破損になる形式があります。設定が4から始まるのはそのためです。 +

+
+ +
+

マニフェストの内容

+

何が起こるべきかを示すマニフェスト

+

+ 破損したファイルにはそれぞれ、システムがそれを拒否すべきことを示す項目が付き、破損の内容がその横に記録されます。 +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 2種類のリクエストは、何かが書き込まれる前に拒否されます。どちらもマニフェストの記述が誤ったファイルをディスクに残してしまうからです。 +

+
    +
  • 破損に必要なサイズより小さいファイル。そのままの状態で出てきてしまいます
  • +
  • + 破損と並べたexpected: + accept。何もそれを満たせないためです。システムがファイルを修復するはずならsanitizeを、まさにそれを確かめたいならunspecifiedを書いてください +
  • +
+
+ +
+

レシピで

+

1回の実行に健全なファイルと壊れたファイルを

+

+ 両方を1つのレシピに入れると、マニフェストが各ファイルの期待を持つので、テストにどれがどれかの一覧は要りません。 +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

テストで

+

テストにする

+

+ テストはマニフェストを読み、起きたことが宣言どおりかどうかを確かめます。ファイル名の一覧は要りません。 +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ よい拒否は、きれいな拒否です。何が悪かったかを伝えるメッセージが、求めている答えです。サーバーエラー、ハング、書きかけで保存されたファイルは、このテストが見つけるために存在する欠陥です。 +

+
+ +
+

次へ

+

ここからどこへ

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/create-file-exact-size/index.html b/web/public/ja/create-file-exact-size/index.html new file mode 100644 index 00000000..f0b3f3ae --- /dev/null +++ b/web/public/ja/create-file-exact-size/index.html @@ -0,0 +1,308 @@ + + + + + + +指定サイズのファイルを作る方法 - Windows、Linux、macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

正確なサイズのファイルを作る方法

+

+ どのOSにもそのためのコマンドがあり、3つとも以下に載せています。正確なバイト数のファイルが作れ、多くのテストではそれで十分です。このページのコマンドはすべて、公開前に対応するOS上で実行しました。 +

+ +
+

短い答え

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。サイズはバイトで指定し、ファイルマネージャーの数え方での10MBは10485760です。 +

+
+ +
+

Windows

+

fsutilと、追加不要のPowerShell版

+

+ fsutilはWindowsに付属しています。サイズはバイト単位で指定するため、先に数値を計算してください。10MBは10485760、100MBは104857600、1GBは1073741824です。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11で実測しました。通常のプロンプトから実行でき、管理者権限は不要で、ファイルはちょうど10485760バイトになります。 +

+

PowerShellは別のプログラムを呼び出さずに同じことができ、単位も理解します。

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShellの10MBは、エクスプローラーと同じ1024基準の数え方で10485760バイトを意味するため、上の2つのコマンドは同じサイズになります。 +

+
+ +
+

Linux

+

dd、truncate、fallocate、そして人がつまずく違い

+

ddは誰もが知っているコマンドです。実際にバイトを書き込みます。

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncateは一瞬で終わりますが、そこが落とし穴です。Alpine + Linuxで実測すると、ファイルは10485760バイトと報告されるのに、占有するのは0ブロックで、スパースファイルになっています。読み込むものには10メガバイトのゼロが返りますが、ディスクは領域を実際には確保していません。 +

+
truncate -s 10M test10mb.bin
+

+ アップロード制限のテストには問題ありませんが、ディスク容量の制限のテストでは誤解を招きます。領域が実際に必要なときはfallocateを使います。 +

+
fallocate -l 10M test10mb.bin
+

圧縮できない内容が必要で、アーカイバーが再び小さくできないようにしたいときは:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

スパースではないmkfileと、すでにご存じの2つ

+

+ macOSにはmkfileが付属しています。macOS + 26.6.2で実測したところ、10485760バイトで20480ブロックでした。領域は約束だけでなく実際に確保されています。 +

+
mkfile 10m test10mb.bin
+

ddとtruncateもあり、Linuxと同じように動作します。

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

これが通用しなくなる場所

+

正しいサイズのファイルは、正しい種類のファイルではありません

+

+ 上記はどれも、ゼロのかたまりを作ります。テスト対象がサイズだけを見る場合、たとえばアップロード制限、割り当て、転送なら、それで十分です。何かがそのファイルを開いた瞬間に、十分ではなくなります。 +

+

+ 実測しましたので、ぜひご自身でも試してください。fsutilで2MBのファイルを作り、photo.pngという名前を付けて、画像ライブラリに渡します。Pillowはcannot + identify image fileと答えます。それはPNGではありません。最初からそうではなく、名前がそう言っていただけです。 +

+

+ これは見た目以上に重要です。テストがどちらの向きで失敗するかが関わるからです。アップロードのエンドポイントがファイルを拒否し、テストが緑になり、サイズ制限は機能していると結論します。しかし、サイズが理由で拒否したのではありません。バイトが画像ではなかったから拒否したのであり、テストしたかったルールには届いていません。 +

+
    +
  • サイズのルールを見る前に、パーサーが拒否する
  • +
  • サムネイル作成が失敗し、読むエラーがサムネイルに関するものになる
  • +
  • ウイルス対策ソフトやコンテンツ検査が、3つ目の理由で拒否する
  • +
  • ビューアーが何も表示せず、それがバグなのか誰にも分からない
  • +
+
+ +
+

もう1つの方法

+

その形式の本物のファイルを、要求したとおりのサイズで

+

+ これがTesting Files Generatorの役割です。ファイルはその形式の本物で、対応するソフトウェアで開け、要求したバイト数とぴったり一致します。 +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 形式が到達できないサイズを要求すると、下限とその理由を示すエラーが返り、サイズの違うファイルが作られることはありません。形式ページに、各形式と、生成できる最小のファイルを載せています。 +

+

そして制限は1つではなく3つのテストケースなので、ツールは3つとも作ります。

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 10485759、10485760、10485761バイトのファイルと、システムがどれを受け入れどれを拒否するべきかを示すマニフェストが得られます。利用例のページでは、これと、このツールが想定する他の4つの用途を紹介しています。 +

+ +

無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。

+
+ +
+

では、どちらを使うべきでしょうか。

+
    +
  • +

    OSのコマンドを使う場合

    +

    + 何もそのファイルを開かないとき。先にサイズを確認するエンドポイントでのサイズ制限のテスト、転送、割り当て、ディスク満杯の状況。1行で済み、すでにインストールされています。 +

    +
  • +
  • +

    本物の生成ツールを使う場合

    +

    + 何かがファイルを解析、描画、取り込み、展開するとき。そして、明日別のマシンで同じフィクスチャをバイト単位で再び必要とするとき。 +

    +
  • +
+

+ どちらも状況によって正しいため、このページに両方載せています。避けるべき間違いは、後者が必要な場面で前者を使い、緑になったテストを証明と受け取ることです。 +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/docs/index.html b/web/public/ja/docs/index.html new file mode 100644 index 00000000..31befa9b --- /dev/null +++ b/web/public/ja/docs/index.html @@ -0,0 +1,514 @@ + + + + + + +ドキュメント - コマンド、レシピ、マニフェスト、終了コード + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

ドキュメント

+

+ ツールの機能を、実際に寄せられる質問の形で整理しています。リポジトリの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つは、何かを書き込む前に拒否されます。どちらもマニフェストの記述と食い違うファイルをディスクに残してしまうためです。 +

+
    +
  • 破壊に必要なサイズより小さいファイル。変更されないまま出てきてしまうため
  • +
  • + 破壊と併記されたexpected: + accept。どのファイルもそれを満たせないためです。テスト対象のシステムがファイルを修復する想定ならsanitizeを、まさにそれが調べたい点ならunspecifiedを書いてください +
  • +
+

+ 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がそのレシピを出力するので、そこから編集できます。各プリセットには、普通は何を見つけるか、セットの内容、受け付ける設定をまとめた専用ページがあります。 +

+
    +
  • +

    空ファイルと最小ファイル

    +

    形式が許す最小サイズの有効なファイルは通るでしょうか。

    +

    empty-and-minimal

    +
  • +
  • +

    ファイル名の扱い

    +

    想定外のファイル名を、システムは保存し、表示し、返せるでしょうか。

    +

    filename-handling

    +
  • +
  • +

    サイズの境界

    +

    サイズ制限は、宣言された位置ちょうどで適用されているでしょうか。

    +

    size-boundaries

    +
  • +
  • +

    表の取り込み

    +

    実際のツールが出力する表を、取り込みは正しく処理できるでしょうか。

    +

    tabular-import

    +
  • +
  • +

    文字コード

    +

    読み取り側はファイルの文字コードを知っているのでしょうか。それとも推測でしょうか。

    +

    text-encoding

    +
  • +
  • +

    アップロードの検証

    +

    アップロードフォームは、受け入れるべきものを受け入れ、それ以外を拒否できるでしょうか。

    +

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

+
+ +
+

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

+

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

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
コード意味
0すべて正常に動作しました。
1ツール内部で予期しないエラーが発生しました。
2コマンドまたはフラグが正しくありません。
3レシピが正しくありません。
4その形式では要求された処理ができません。
5読み取りまたは書き込みに失敗しました。
6ディスクの空き容量が足りません。
7verifyが不一致を見つけました。
8実行は終了しましたが、すべてが生成されたわけではありません。
130Ctrl+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つのインターフェースを機能ごとに比較しており、片方にしかできないことは、静かに食い違うのではなく、宣言して理由を示す必要があります。 +

+

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

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/faq/index.html b/web/public/ja/faq/index.html new file mode 100644 index 00000000..6a4bc798 --- /dev/null +++ b/web/public/ja/faq/index.html @@ -0,0 +1,345 @@ + + + + + + +FAQ - テストファイルの生成に関する質問 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

よくある質問

+

+ ライセンス、プライバシー、再現性、そして生成ツールをビルドパイプラインに組み込む前に人々が確認すること。質問がここにない場合は、イシュートラッカーをご利用ください。 +

+ +
+
+

ddやfsutil、truncateとは何が違いますか。

+
+

それらが作るのは、サイズだけ正しい中身のないファイルです。そうして作ったphoto.pngという2MBのファイルはPNGではないため、実際に解析するものはすべて誤った理由で拒否し、あなたのテストも誤った理由で通ります。このツールはちょうど2MBの本物のPNGを作ります。画像ビューアーで開け、システムがどう扱うべきかという宣言も付いてきます。

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

無料ですか。仕事で使えますか。

+
+

どちらも可能です。GPL-3.0で公開されており、費用はかかりません。アカウントもライセンスキーも有料プランもありません。

+
+
+
+

生成したファイルをクローズドソースの製品で使えますか。

+
+

はい。ライセンスが対象とするのはツールのコードであり、ツールが生成するものではありません。生成されたファイル、レシピ、マニフェストは派生物ではなく出力ですので、コミットして配布しても何の義務も生じません。

+
+
+
+

生成されたファイルに実在の個人情報は含まれますか。

+
+

いいえ。中身はすべてシードから合成されます。データセットは読み込まず、サービスにも接続せず、第三者のコンテンツも埋め込みません。生成されたメールアドレスは、未使用ではなく使用不可と見なしてください。ランダムな文字列がたまたま実在のものと一致することがあるからです。

+
+
+
+

別のマシンでもまったく同じファイルになりますか。

+
+

はい。レシピとシードが同じなら、バイト単位で同じです。プロジェクトは変更のたびにこれをテストしており、破るにはメジャーバージョンを上げる必要があります。だからこそ、大きなバイナリのフィクスチャの代わりに小さなレシピをコミットできます。

+
+
+
+

インターネット接続は必要ですか。

+
+

一切不要です。テレメトリも更新確認もクラウドクライアントもなく、コマンドラインのバイナリにはネットワークスタックがそもそもコンパイルされていません。ネットワークのないマシンでも、閉じた社内環境でも動きます。

+
+
+
+

形式が到達できないサイズを要求するとどうなりますか。

+
+

形式名、可能な最小サイズ、その下限の理由、代わりにすべきことを示すエラーが返り、ファイルは書き込まれません。ツールがサイズを黙って丸めることはありません。各下限は形式ページに載っています。

+
tfg formats png
+
+
+
+

意図的に壊れたファイルを生成できますか。

+
+

はい。--damage zero-headを加えると、ファイルは求めたとおりのサイズで、先頭のバイトがゼロで上書きされて出てきます。そのためリーダーはそれを拒否し、マニフェストにはシステムがそれを拒否すべきことが記録されます。詳細は破損したテストファイルのページにあります。

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

次に対応する形式は何ですか。

+
+

7z、mp3、mp4です。現在、26種類の形式がエンドツーエンドで動作します。

+
+
+
+

どのOSで動かせますか。

+
+

コマンドラインは、WindowsとLinuxのIntelとARM、およびApple SiliconのMacで動作します。デスクトップウィンドウは、WindowsのIntel、LinuxのIntel、Apple SiliconのMac向けに提供されます。IntelのMacは非対応で、ビルドもされません。

+
+
+
+

何かインストールする必要はありますか。

+
+

いいえ。お使いのOS向けのアーカイブをダウンロードして展開し、バイナリを実行するだけです。インストーラーも、追加するランタイムも、解決すべき依存関係もありません。Goをお持ちなら、go installコマンド1つでも動きます。

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

数千ファイルの実行がWindowsで遅いのはなぜですか。

+
+

Windowsは調べるパス1つあたりのコストが高く、数千ファイルを走査するコマンドは数千のパスを調べるからです。1kBのファイル3000個があるマシンで測定したところ、verifyはWindowsで約0.9秒、コンテナ内のLinuxで約0.2秒かかりました。出力パスを短くするとWindowsの数値は小さくなります。ファイルより上のフォルダーもすべて調べる対象に含まれるためです。

+
+
+
+ + +
+

まだ迷っていますか。

+

+ 利用例のページでは、このツールが想定する用途を、形式ページでは、各形式と生成できる最小のファイルを紹介しています。リポジトリのREADMEが完全なリファレンスです。 +

+ +

無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/formats/index.html b/web/public/ja/formats/index.html new file mode 100644 index 00000000..3c5ffaf9 --- /dev/null +++ b/web/public/ja/formats/index.html @@ -0,0 +1,896 @@ + + + + + + +対応する26種類のファイル形式 - PDF、DOCX、PNG、ZIPほか + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26種類のファイル形式、どれも正確なサイズで生成

+

+ どれもその形式の本物のファイルです。対応するソフトウェアで開け、要求したバイト数とぴったり一致します。拡張子を貼り付けただけのゼロ埋めはひとつもありません。 +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
形式名前拡張子最小ファイル完全性検証に使うもの
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155full該当なし
mdMarkdown.md0full該当なし
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0full該当なし
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

各列の意味

+
    +
  • +

    最小ファイル

    +

    + その形式でこのツールが受け付ける最小のバイト数で、ファイル内に書き込むラベルを含みます。それより小さく要求すると、下限とその理由を示すエラーが返り、サイズの違うファイルが作られることはありません。 +

    +
  • +
  • +

    完全性

    +

    + ファイルがどれだけ完全かを示します。fullは、形式を本当に解析するリーダーが受け入れるという意味で、拡張子が合っているだけではありません。 +

    +
  • +
  • +

    検証に使うもの

    +

    + 形式を出荷する前に、生成されたすべてのファイルを開く独立したリーダーです。自分たちのコードが自分たちの宿題を採点するのではなく、別の実装を使います。 +

    +
  • +
+

+ どの形式もバイト単位で再現できます。同じレシピとシードなら、どのマシンでも同じファイルが生成されるため、フィクスチャ自体の代わりにレシピをコミットしても安全です。 +

+
+ +
+

形式ごとに受け付ける設定

+

+ ほとんどの形式には固有の設定があります。画像のサイズ、JPEGの品質、PDFのページ数、スプレッドシートの行数と列数、アーカイブに入れるエントリ数など。コマンドラインでは--set + key=value、レシピではproperties:の下で設定します。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
形式設定受け付ける値
avifwidth1 - 16384 ピクセル
height1 - 16384 ピクセル
quality1 - 100
bmpwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
header真または偽
quote_styleall, minimal, none
columns2 - 32768 列
docxparagraphs1 - 50000 段落
gifwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 ピクセル
height1 - 256 ピクセル
embedbmp, png
jpgwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 ピクセル
height1 - 16384 ピクセル
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 1秒あたりのエントリ数
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bom真または偽
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
title任意のテキスト
author任意のテキスト
subject任意のテキスト
keywords任意のテキスト
creator任意のテキスト
producer任意のテキスト
created2024-02-29や2024-02-29T13:45:00+02:00のような日付、またはnone
modified2024-02-29や2024-02-29T13:45:00+02:00のような日付、またはnone
pngwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
pptxslides1 - 500 スライド
svgwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
targzentries0 - 10000
entry_formattfg formatsが一覧表示する形式のID
entry_size2mbのようなサイズ
compressionbest, default, fast, none
depth0 - 50
directory_entries真または偽
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 ピクセル
height1 - 20000 ピクセル
txtencodingutf-16be, utf-16le, utf-8
bom真または偽
wavsample_rate8000 - 192000 ヘルツ
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 ピクセル
height1 - 16383 ピクセル
xlsxrows1 - 200000 行
columns1 - 32768 列
xmlencodingutf-16be, utf-16le, utf-8
bom真または偽
zipentries0 - 10000
entry_formattfg formatsが一覧表示する形式のID
entry_size2mbのようなサイズ
compressionbest, default, fast, none
depth0 - 50
directory_entries真または偽
passwordパスワード(平文)
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ 設定が受け付ける範囲外の値は、設定名、許可される範囲、代わりに使うものを示すメッセージとともに拒否されます。未知の設定もエラーで、黙って既定値になることはありません。黙って受け入れられた打ち間違いは、設定の誤ったファイルを生み、通るはずのないテストがなぜ通るのかと悩む1時間を生みます。 +

+

+ tfg formats <id>を実行すると、お使いのビルドで1つの形式が受け付ける内容を正確に確認できます。 +

+
+ +
+

アーカイブには本物のファイルが入ります

+

+ targzとzipは、空の殻のままではなく、エントリで満たせます。生成されたアーカイブは、含むと言っているドキュメントを実際に含むため、テスト中にそれを展開するものは、中に本物のファイルを見つけます。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/index.html b/web/public/ja/index.html new file mode 100644 index 00000000..60f3f886 --- /dev/null +++ b/web/public/ja/index.html @@ -0,0 +1,435 @@ + + + + + + +テストファイル生成ツール - 正確なサイズ、26種類の本物の形式 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

正確なサイズの本物のテストファイルを生成

+

+ PDF、PNG、DOCX、ZIPなど、全26種類の形式に対応し、どれも対応するソフトウェアで開ける本物のファイルで、サイズは要求したとおりちょうどです。各実行では、アプリが各ファイルをどう扱うべきかも書き出します。コマンドラインとデスクトップウィンドウの両方に対応し、無料のオープンソースで、すべてあなたのマシン上で動きます。 +

+ + +

無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。

+
+ +
+ テストファイルのバッチを書き出す準備ができたTesting Files Generatorのデスクトップウィンドウ +
ファイルのバッチを書き出す準備ができたデスクトップウィンドウ。コマンドラインの裏でも同じエンジンが動いています。
+
+
+ +
    +
  • + 26 +

    種類の本物の形式、どれも対応するソフトウェアで開けます

    +
  • +
  • + 1バイト +

    要求したすべてのサイズの正確さ。黙って丸められることはありません

    +
  • +
  • + 0 +

    外部への接続。アカウント、テレメトリ、更新確認はありません

    +
  • +
+ +
+

課題

+

テストファイルを1つ作るのは簡単です。適切な1000個を作るのが面倒な部分です

+

あなたは、人からファイルを受け取るソフトウェアをテストしています。遅かれ早かれ、次のものが必要になります。

+
    +
  • アップロード制限が本物かどうかを確かめるための、ちょうど10MBのPDF
  • +
  • 1つずれのバグを見つけるための、その制限の両側にある3つのファイル
  • +
  • フォルダーが大きいとき夜間ジョブがどうなるかを見るための、1万個のログファイル
  • +
  • 拡張子だけ合わせた空の殻ではなく、実際に200個のドキュメントが入ったZIP
  • +
  • リポジトリに4GBのファイルを置かずに用意する4GBのファイル
  • +
  • ノートPCとビルドサーバーで同じフィクスチャをバイト単位で
  • +
+

+ これが置き換える対象です。QAエンジニア、テスト自動化、そしてコードの先にアップロードフォーム、取り込み処理、パーサー、ストレージの割り当てがあるすべての人のために作られています。 +

+
+ +
+

他とどう違うか

+

他の生成ツールはバイトで終わります。これは、あなたのテストが本当に問うことに答えます

+

+ ファイルが入ったフォルダーだけでは、各ファイルが何を証明すべきかを自分で決めることになります。ここでは実行のたびに、ファイルの横にmanifest.jsonを書き出します。生成物の単純な一覧で、各項目に宣言された期待値が付きます。 +

+

アップロードのエンドポイントが1MBまでを許可するとします。その線上にある3つのファイルを要求します。

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ファイルバイトシステムの対応理由
1mb_under_1b.pdf1048575受け入れる制限の内側にあるため
1mb_at_limit.pdf1048576受け入れる制限値ちょうどは許可されるため
1mb_over_1b.pdf1048577拒否するsize_limit
+
+ +

3つのファイル、3つの異なる答えを、機械可読な形で示します。アサーションを手書きする代わりに、テストがマニフェストを読みます。

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

答えが自分たちのポリシー次第の場合、マニフェストはそう述べます

+

+ 期待値をでっち上げず、unspecifiedと記録します。推測する生成ツールは誤検出を生み、狼少年のようなテストスイートは最終的に無効にされます。 +

+
+
+ +
+

プリセット

+

疑問を選べば、セット一式が手に入ります

+

+ プリセットは、1つのテストの疑問を軸に設計したテストファイルのセットです。どのファイルが何を証明するのかを自分で考える必要はありません。それぞれに、普通は何を見つけるか、セットの内容、受け付ける設定をまとめたページがあります。 +

+
    +
  • +

    空ファイルと最小ファイル

    +

    形式が許す最小サイズの有効なファイルは通るでしょうか。

    +

    empty-and-minimal

    +
  • +
  • +

    ファイル名の扱い

    +

    想定外のファイル名を、システムは保存し、表示し、返せるでしょうか。

    +

    filename-handling

    +
  • +
  • +

    サイズの境界

    +

    サイズ制限は、宣言された位置ちょうどで適用されているでしょうか。

    +

    size-boundaries

    +
  • +
  • +

    表の取り込み

    +

    実際のツールが出力する表を、取り込みは正しく処理できるでしょうか。

    +

    tabular-import

    +
  • +
  • +

    文字コード

    +

    読み取り側はファイルの文字コードを知っているのでしょうか。それとも推測でしょうか。

    +

    text-encoding

    +
  • +
  • +

    アップロードの検証

    +

    アップロードフォームは、受け入れるべきものを受け入れ、それ以外を拒否できるでしょうか。

    +

    upload-validation

    +
  • +
+

すべてのプリセットと、レシピとの関係

+
+ +
+

クイックスタート

+

動作を確かめる3つのコマンド

+
    +
  1. +

    ファイルを1つ作る

    +

    PNGを1つ、ちょうど2メガバイトで:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    たくさんのファイルを作る

    +

    + 1KBから8KBの間で、シードから決めたサイズのログファイルを1万個。明日も同じセットになります。実行ごとに専用のディレクトリを使ってください。マニフェストは実行が書いた内容の唯一の記録なので、ツールはその上に2つ目を書くことを拒否します。 +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    検証してから削除する

    +

    verifyは何も動いていないことを伝えます。cleanupは書き込まれたものだけを正確に削除します。

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ サイズはファイルマネージャーと同じく1024単位で数えるため、2mbは2097152バイトです。バイト数をそのまま指定することもできます。ドキュメントで、レシピ、マニフェスト、終了コードを説明しています。 +

+
+ +
+

得られるもの

+

無人で動くテストスイートのために作られています

+
    +
  • +

    正確なサイズ、1バイト単位で

    +

    10485761バイトを要求すれば、ちょうどその大きさになります。形式が到達できないサイズは理由付きのエラーになり、サイズの違うファイルが作られることはありません。

    +
  • +
  • +

    26種類の本物の形式

    +

    拡張子を付けただけのゼロ埋めではありません。生成したPNGは画像ビューアーで開け、DOCXはWordで開け、ZIPは展開できます。どれも出荷前に独立したリーダーで検証されます。

    +
  • +
  • +

    テストオラクルとしてのマニフェスト

    +

    パス、サイズ、SHA-256、形式、シード、ツールのバージョン、そしてシステムがそのファイルをどう扱うべきか。

    +
  • +
  • +

    再現可能

    +

    レシピとシードが同じなら、どのマシンでもバイトまで同じです。大きなバイナリのフィクスチャの代わりに、小さなYAMLレシピをコミットしてください。

    +
  • +
  • +

    2つのインターフェース、1つのエンジン

    +

    CI向けに作られたコマンドラインと、探索的テスト向けのデスクトップウィンドウ。どちらも一方の機能削減版ではなく、テストが機能ごとに両者を比較しています。

    +
  • +
  • +

    完全オフライン

    +

    アカウント、クラウド、テレメトリ、更新確認はありません。コマンドラインのバイナリには、ネットワークスタックがそもそもコンパイルされていません。

    +
  • +
+
+ +
+

ダウンロード

+

お使いのOS向けのビルドを選んでください

+

+ アーカイブを展開して実行します。tfgがコマンドライン、tfg-guiがデスクトップウィンドウです。インストーラーはなく、マシンに追加するものもありません。 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
OSコマンドラインデスクトップウィンドウ
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

署名済みのものと、そうでないもの

+

+ WindowsとmacOS向けのダウンロードは署名されているため、未確認の開発元という警告なしで起動します。Linux向けは、デスクトップLinuxに署名できる仕組みがないため署名されていません。すべてのアーカイブはリリースページのverify-SHA256SUMS.txtに載っているので、ダウンロードしたものを確認できます。 +

+
+ +

無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。

+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/empty-and-minimal/index.html b/web/public/ja/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..c1876025 --- /dev/null +++ b/web/public/ja/presets/empty-and-minimal/index.html @@ -0,0 +1,265 @@ + + + + + + +全形式の最小の有効ファイルと空ファイル + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

空ファイルと最小ファイル

+

形式が許す最小サイズの有効なファイルは通るでしょうか。

+

+ empty-and-minimalプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • 検査がバイトを読まずバイト数だけを数えるため、小さすぎると拒否される有効なファイル
  • +
  • 報告されずに、読み取り側をクラッシュさせる空ファイル
  • +
  • サムネイル作成の途中でゼロ除算を起こす幅1ピクセルの画像
  • +
  • 0バイトを失敗したアップロードと見なして再試行し続けるストレージ
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show empty-and-minimalが報告するとおりです。

+
+ + + + + + + +
ファイル数28
レシピ内のターゲット数28
合計サイズ32 667 B
形式avif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。26
unspecifiedシステムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。2
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + +
設定値既定値動作
--formatsカンマ区切りの形式ID、またはallallセットを構成する形式です。このビルドのすべての形式にするにはallのままにし、システムが受け付ける形式だけを指定することもできます。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/filename-handling/index.html b/web/public/ja/presets/filename-handling/index.html new file mode 100644 index 00000000..9a801a98 --- /dev/null +++ b/web/public/ja/presets/filename-handling/index.html @@ -0,0 +1,264 @@ + + + + + + +テスト用の厄介なファイル名 - Unicodeと長さ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

ファイル名の扱い

+

想定外のファイル名を、システムは保存し、表示し、返せるでしょうか。

+

+ filename-handlingプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • 画面やログ、一覧で別の名前に見えるファイル名
  • +
  • アップロードから保存までの間に切り詰められたり書き換えられたりするファイル名
  • +
  • ストレージがバイトで数えるのに、文字数で数えている長さ制限
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show filename-handlingが報告するとおりです。

+
+ + + + + + + +
ファイル数50
レシピ内のターゲット数50
合計サイズ51 200 B
形式txt
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。4
unspecifiedシステムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。46
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + +
設定値既定値動作
--format形式ページにある形式IDtxtセット内のすべてのファイルの形式です。ツール自体のフラグで、プリセットは既定値を与えるだけです。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/index.html b/web/public/ja/presets/index.html new file mode 100644 index 00000000..c4f4cf92 --- /dev/null +++ b/web/public/ja/presets/index.html @@ -0,0 +1,239 @@ + + + + + + +テストファイルのプリセット - QAの疑問に答える既製セット + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

テストファイルのプリセット、テストの疑問ごとに1セット

+

+ プリセットは、1つの疑問を軸に設計したテストファイルのセット一式で、システムが各ファイルにどう反応すべきかを示すマニフェストが付きます。疑問を選べば、ツールがセットを作ります。各プリセットには、普通は何を見つけるか、セットの内容、受け付ける設定をまとめた専用ページがあります。 +

+ +
    +
  • +

    空ファイルと最小ファイル

    +

    形式が許す最小サイズの有効なファイルは通るでしょうか。

    +

    empty-and-minimal

    +
  • +
  • +

    ファイル名の扱い

    +

    想定外のファイル名を、システムは保存し、表示し、返せるでしょうか。

    +

    filename-handling

    +
  • +
  • +

    サイズの境界

    +

    サイズ制限は、宣言された位置ちょうどで適用されているでしょうか。

    +

    size-boundaries

    +
  • +
  • +

    表の取り込み

    +

    実際のツールが出力する表を、取り込みは正しく処理できるでしょうか。

    +

    tabular-import

    +
  • +
  • +

    文字コード

    +

    読み取り側はファイルの文字コードを知っているのでしょうか。それとも推測でしょうか。

    +

    text-encoding

    +
  • +
  • +

    アップロードの検証

    +

    アップロードフォームは、受け入れるべきものを受け入れ、それ以外を拒否できるでしょうか。

    +

    upload-validation

    +
  • +
+ +
+

プリセットとレシピは何が違いますか。

+

+ 中身は同じです。プリセットは、いくつかの設定からツールが書くレシピです。tfg preset + ejectはそのレシピを出力するので、テストの隣に保管して編集できます。また、自分のレシピはextends: + preset:にIDを続けた1行で、プリセットを土台にできます。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

既定値は信頼できますか。

+

+ ファイルについては信頼できます。アップロードフォームの制限のように、システムだけが知っている数値については、既定値はこちらの仮の値で、ツールは使うたびにそう伝えます。各プリセットのページはそれらの設定に印を付け、tfg + preset showは何かを書き込む前に伝えます。 +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/size-boundaries/index.html b/web/public/ja/presets/size-boundaries/index.html new file mode 100644 index 00000000..fe9c6b55 --- /dev/null +++ b/web/public/ja/presets/size-boundaries/index.html @@ -0,0 +1,278 @@ + + + + + + +アップロードのサイズ制限をテスト - 境界ちょうどのファイル + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

サイズの境界

+

サイズ制限は、宣言された位置ちょうどで適用されているでしょうか。

+

+ size-boundariesプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • 制限値での1つずれのエラー
  • +
  • MBとMiBの取り違え。差は4.8パーセントで、通すべきでないファイルを通すには十分です
  • +
  • サーバーではなくブラウザーだけで適用されている制限
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show size-boundariesが報告するとおりです。

+
+ + + + + + + +
ファイル数7
レシピ内のターゲット数7
合計サイズ73 400 320 B
形式pdf
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。4
rejectシステムはこのファイルを拒否するべきです。3
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
設定値既定値動作
--limit2mbのようなサイズ10mbシステムが宣言するサイズ制限です。他のすべてはこの値を基準に測ります。 この既定値はこちらの仮の値で、あなたのシステムの値ではありません。ご自身の値を指定してください。
--spreadカンマ区切りのサイズ1B,1kb,1mb制限の両側へどこまで広げるかを、サイズの一覧で指定します。
--format形式ページにある形式IDpdfセット内のすべてのファイルの形式です。ツール自体のフラグで、プリセットは既定値を与えるだけです。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

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

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/tabular-import/index.html b/web/public/ja/presets/tabular-import/index.html new file mode 100644 index 00000000..f4a00123 --- /dev/null +++ b/web/public/ja/presets/tabular-import/index.html @@ -0,0 +1,272 @@ + + + + + + +CSVとExcelの取り込みテスト用ファイル - 区切り文字とヘッダー + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

表の取り込み

+

実際のツールが出力する表を、取り込みは正しく処理できるでしょうか。

+

+ tabular-importプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • 区切り文字を探さず決めつけたために、1列として読まれるセミコロン区切りのファイル
  • +
  • 各行の後に空行が入って行分割されるCRLFのファイル
  • +
  • 最初のデータ行が列名として取り込まれてしまうヘッダーなしの表
  • +
  • 表示できる列だけを残し、残りを黙って捨てる取り込み
  • +
  • JSONレコードを1行ずつ読み、最初のインデント付きドキュメントで止まるリーダー
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show tabular-importが報告するとおりです。

+
+ + + + + + + +
ファイル数13
レシピ内のターゲット数13
合計サイズ3 080 060 B
形式csv, json, xlsx
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。8
unspecifiedシステムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。5
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + + + + + + + +
設定値既定値動作
--rows1 - 200000 行1000スプレッドシートの行数です。その行数がちょうど収まるサイズで書き出されるため、上の予算はこの値に応じて動きます。
--columns1 - 32768 列10スプレッドシートの各行の列数です。行数と列数の積には上限があり、超える指定は何かを書き込む前に拒否されます。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/text-encoding/index.html b/web/public/ja/presets/text-encoding/index.html new file mode 100644 index 00000000..90acb556 --- /dev/null +++ b/web/public/ja/presets/text-encoding/index.html @@ -0,0 +1,265 @@ + + + + + + +文字コードのテスト用ファイル - UTF-8、UTF-16、BOM、CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

文字コード

+

読み取り側はファイルの文字コードを知っているのでしょうか。それとも推測でしょうか。

+

+ text-encodingプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • UTF-8だと決めつけて、UTF-16のファイルを3文字に1文字だけ、または四角の列として表示するリーダー
  • +
  • バイトオーダーマークが内容として読まれ、取り込みの最初のフィールドが余分な3文字で始まる問題
  • +
  • 先頭バイトから文字コードを推測し、長いファイルでは違う推測をするインポーター
  • +
  • 各行の後に空行が入って行分割されるCRLFのファイル、または最後のフィールドに残るキャリッジリターン
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show text-encodingが報告するとおりです。

+
+ + + + + + + +
ファイル数20
レシピ内のターゲット数20
合計サイズ81 920 B
形式csv, log, md, txt, xml
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。10
unspecifiedシステムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。10
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + +
設定値既定値動作
--sample2mbのようなサイズ4kbセット内の各ファイルの大きさです。UTF-16は1文字に2バイトを使うため、奇数は拒否されます。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/presets/upload-validation/index.html b/web/public/ja/presets/upload-validation/index.html new file mode 100644 index 00000000..7144a4f8 --- /dev/null +++ b/web/public/ja/presets/upload-validation/index.html @@ -0,0 +1,294 @@ + + + + + + +アップロード検証のテスト用ファイル - 種類、サイズ、名前 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

プリセット

+

アップロードの検証

+

アップロードフォームは、受け入れるべきものを受け入れ、それ以外を拒否できるでしょうか。

+

+ upload-validationプリセットは、この疑問に対する本物のテストファイル一式を1つのコマンドで作り、その隣に、システムが各ファイルにどう反応すべきかを示すmanifest.jsonを置きます。以下はすべて、このバージョンの既定値でプログラムから読み取ったものです。 +

+ + +
+

普通は何を見つけますか。

+
    +
  • サーバーではなくブラウザーだけで適用されている制限
  • +
  • 画像やプレーンテキストと見なされるSVGやHTMLファイル。スクリプトにフォームの検査をすり抜けさせる手口です
  • +
  • 拡張子だけで判定され、開かれないファイル。.jpgという名前のPDFが通ってしまいます
  • +
  • サイズを確認する前に、本文全体をメモリに読み込むフォーム
  • +
  • photo.jpgは受け付けるのにPHOTO.JPGは拒否される、またはその逆になるアップロード
  • +
  • スペースやかっこ、ASCII以外の文字を含む名前が、そのままディスクに書き込まれる問題
  • +
+
+ + +
+

セットには何が入っていますか。

+

既定値で、tfg preset show upload-validationが報告するとおりです。

+
+ + + + + + + +
ファイル数71
レシピ内のターゲット数22
合計サイズ120 639 488 B
形式html, jpg, pdf, png, svg, txt
+
+

そして、そのセットのマニフェストがシステムに期待していること:

+
+ + + + + + + + + +
期待意味ファイル数
acceptシステムはこのファイルを受け入れるべきです。56
rejectシステムはこのファイルを拒否するべきです。10
unspecifiedシステムのルール次第です。あなたが決め、実際に起きることが意図どおりかを確認してください。5
+
+
+ +
+

何を変更できますか。

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
設定値既定値動作
--limit2mbのようなサイズ10mbアップロードフォームが宣言するサイズ制限です。このセットは制限の両側に1段ずつ取ります。あらゆる距離のファイルが必要な場合は、size-boundariesプリセットを実行してください。 この既定値はこちらの仮の値で、あなたのシステムの値ではありません。ご自身の値を指定してください。
--allowカンマ区切りの形式IDjpg,png,pdfフォームが受け入れるべき種類です。それぞれがその種類の本物のファイルになり、セット全体の陽性対照になります。
--denyカンマ区切りの拡張子svg,html,exe,shフォームが拒否すべき拡張子です。このビルドに対応する形式がない拡張子でも、その名前でプレーンテキストを含むファイルが作られます。
--far-over10x, 2x, off2x1つだけの大きなファイルが制限をどれだけ超えるかです。制限の何倍も書き込むのがディスクの無駄になる場合はオフにします。
--bulk0 - 10000 ファイル50一括アップロードに含めるファイル数です。0にすると、そのグループはセットから完全に外れます。
+
+
+ +
+

どう実行しますか。

+

セットのコストを確認し、作成し、または編集用にそのレシピを取り出します。

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

または、テストの隣に置いた自分のレシピで、これを土台にします。

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ja/test-files-in-ci/index.html b/web/public/ja/test-files-in-ci/index.html new file mode 100644 index 00000000..804cac96 --- /dev/null +++ b/web/public/ja/test-files-in-ci/index.html @@ -0,0 +1,359 @@ + + + + + + +CIでのテストファイル - GitHub Actions、GitLab CI、PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

利用例

+

CIパイプラインでテストファイルを生成する方法

+

+ リポジトリ内のバイナリのフィクスチャは履歴に永遠に残り、diffでレビューできず、ファイルが大きくなると成り立たなくなります。代わりに、パイプラインの中でレシピからファイルを生成してください。レシピはテキストで、バイトは毎回同じになり、最後のステップで何も動いていないことを証明できます。 +

+ +
+

短い答え

+

+ tfgをインストールし、テストの前にtfg generate fixtures.yaml --out + ./fixturesを、テストの後にtfg verify + ./fixtures/manifest.jsonを実行します。どちらのステップも自らビルドを失敗させ、理由を示す終了コードを返します。 +

+
+ +
+

コミットしない理由

+

フィクスチャをリポジトリに置くべきでない理由

+
    +
  • + 履歴に残ります。バイナリをあとで削除しても、すべてのバージョンが残っているのでクローンは小さくなりません。 +
  • +
  • + diffでは何が変わったかが分かりません。レビューする人にはPDFが違うことしか見えません。レシピなら変更は1行です。 +
  • +
  • + 大きなファイルは収まりません。GitHubは100 MBを超えるファイルを含むプッシュを拒否するので、500 + MBのアップロード上限のテストにはコミットできるものがありません。 +
  • +
+

+ コミットするのはレシピです。同じレシピと同じシードは、どのマシンでも同じバイトを書き出すので、パイプラインで生成したファイルは、ノートPCで使っていたファイルと同じものです。 +

+
+ +
+

レシピ

+

テストの隣に置くレシピ

+

+ このレシピは、受け入れられるべき請求書を25件と、上限を超えて拒否されるべき画像を2枚書き出し、マニフェストが両方の期待を記録します。 +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yamlは何も書き込まずにレシピを検査し、すべての問題を一度に挙げます。 +

+
+ +
+

GitHub Actions

+

ツールをインストールしてフィクスチャを作るワークフロー

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ チェックサムの行は、アーカイブを同じリリースのverify-SHA256SUMS.txtと照合します。バージョンは固定されているので、新しいリリースが、手を付けていないビルドを変えることはありません。 +

+
+ +
+

GitLab CI

+

同じことをGitLabのジョブで

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

赤くなったとき

+

ステップを失敗させるものとその理由

+

+ 終わり方ごとに専用の終了コードがあるので、ステップは自ら失敗し、ログがどれかを示します。パイプラインが出会うのは次のものです。 +

+
    +
  • 3 - レシピが正しくありません。何も書き込まれず、すべての問題が示されます
  • +
  • 4 - 形式が求められたことをできません。たとえば最小サイズを下回るサイズです
  • +
  • 6 - ディスクの空き容量が足りません
  • +
  • 7 - tfg verifyがマニフェストと一致しないファイルを見つけました
  • +
  • 8 - 実行は終わりましたが、すべてが作られたわけではありません
  • +
+

+ 失敗した実行は標準出力に何も出力しないので、ログパーサーがエラーをデータと取り違えることはありません。表の全体はドキュメントのページにあります。 +

+
+ +
+

PowerShell

+

PowerShellのスクリプトにはもう1行必要です

+

+ PowerShellは、プログラムの終了コードを.ps1ファイルの外に持ち出しません。-Fileで実行すると、中のツールが作業を拒否した場合でもスクリプトは0を返し、赤になるはずのビルドが緑になります。最後の1行が修正のすべてです。 +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ これはPowerShellの挙動であり、このツールの話ではありません。cmd、bash、zshには余分な手当ては要りません。 +

+
+ +
+

複数のジョブ

+

ジョブ間でフィクスチャを共有する

+

+ たいていアップロードは不要です。同じレシピは同じバイトを書き出すので、各ジョブが自分でtfg + generateを実行でき、アップロードしてダウンロードするより速くなります。あるジョブが別のジョブからファイルを受け取る必要があるときは、転送の後にマニフェストに対してtfg + verifyを実行すると、届いたものが書き出されたものと同じかどうかが分かります。 +

+
+ +
+

次へ

+

ここからどこへ

+
    +
  • + 破損したテストファイルは、同じレシピに意図的に壊したファイルを加えます。 +
  • +
  • + ユースケースは、パイプラインでの実行がほかに何を確かめられるかを示します。 +
  • +
  • + ドキュメントには、すべてのコマンド、レシピのキー、終了コードが載っています。 +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/ja/use-cases/index.html b/web/public/ja/use-cases/index.html new file mode 100644 index 00000000..3bb6d39b --- /dev/null +++ b/web/public/ja/use-cases/index.html @@ -0,0 +1,294 @@ + + + + + + +利用例 - アップロード制限、CIのフィクスチャ、大量テスト + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

何に使われているか

+

+ 人からファイルを受け取るほぼすべてのプロジェクトで出てくる5つの作業と、それぞれを実行するコマンド。以下の例はすべて、書かれたとおりに動きます。 +

+ +
+

アップロード制限

+

ファイルサイズ制限が、言っている位置で適用されているかをテストする

+

+ 制限は1つではなく3つのテストケースです。直前、ちょうど、直後。これを手作業で用意するとバイト数を計算することになり、1つずれていないことを祈るしかありません。代わりにセットを要求します。 +

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

+ 1048575、1048576、1048577バイトの本物のPDFが3つ得られ、マニフェストは、最初の2つを受け入れ、3つ目をsize_limitで拒否すべきだと示します。アサーションを3つ手書きする代わりに、テストは期待値を読みます。制限が変わったら、数値を1つ変えて再実行するだけです。 +

+

+ 1つの境界セットをインラインで用意したいときは、プリセットなしでも同じことができます。 +

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

継続的インテグレーション

+

フィクスチャを失わずに、リポジトリの外に置く

+

+ 大きなバイナリのフィクスチャは、リポジトリのクローンを遅くし、レビューを難しくし、1つが置き換えられても何が変わったのか誰にも分かりません。レシピは数百文字のYAMLで、同一のファイルを再構築します。どのマシンでもバイト単位で同じです。すべてのファイルが実行のシードから導かれるためです。 +

+
- 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
+

+ 終わり方ごとに専用の終了コードがあるため、パイプラインは、誤ったレシピ、ディスク満杯、検証の不一致を区別できます。失敗した実行は標準出力に何も出力しないので、ログパーサーがエラーをデータとして読み取ることもありません。 +

+
+ +
+

規模

+

フォルダーが大きいときに何が起きるかを確かめる

+

+ 取り込み処理、夜間ジョブ、ディレクトリ一覧は、10ファイルのときと1万ファイルのときで挙動が変わります。範囲から決めたサイズを使うと、1万個の同一ファイルではなく実際のトラフィックに近いセットになります。抽選はシードから決まるため、セットは明日も同じです。 +

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

+ 合計がギガバイト単位になるときは特に、何かを書き込む前に実行のコストを確認します。 +

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

+ ディスクの空き容量より大きい実行は、最初の1バイトを書く前に拒否されます。ディスクを埋めて途中で失敗することはありません。 +

+
+ +
+

アーカイブ

+

実際にファイルが入ったアーカイブで、展開処理をテストする

+

+ 拡張子だけ正しい空のアーカイブでは、それを開いて中身をたどるコードについて何も証明できません。中身を宣言すれば、アーカイブは実際にそれを含みます。 +

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

+ ネストの深さ、エントリ数、中身のサイズは、どれも取り込み処理が意見を持つ項目で、これが、その意見を知る方法です。 +

+
+ +
+

パーサーとビューアー

+

自分のコードが、実際のソフトウェアと同じように形式を読めているかを確かめる

+

+ ここにあるすべての形式は、出荷前に独立したリーダーで検証されています。PNGは開かれてピクセルが比較され、DOCXは別のライブラリで読み直され、アーカイブは展開されます。つまり、あなたのパーサーが拒否するファイルは、生成ツールではなくあなたのパーサーに関する発見です。 +

+
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
+

+ 形式ページに、各形式が受け付ける設定と、取りうる最小のファイルを載せています。 +

+
+ +
+

ガイド

+

そのうち2つを詳しく

+
    +
  • + 破損したテストファイル - 意図的に壊した、サイズが正確なファイル。そのファイルをどう扱うべきかはマニフェストに書かれます。 +
  • +
  • + CIでのテストファイル - GitHub + Actionsのワークフロー、GitLabのジョブ、そしてビルドを失敗させる終了コード。 +
  • +
+
+ +
+

誰のためのものか

+

+ QAエンジニア、テスト自動化、そしてコードの先にアップロードフォーム、取り込み処理、パーサー、ストレージの割り当てがあるすべての人のためのものです。ネットワークが一切ないマシンで動くため、ブラウザーベースの生成ツールが使えない閉じた社内環境でも役立ちます。 +

+ +

無料のオープンソース、GPL-3.0。登録は不要です。WindowsとmacOS向けのダウンロードは署名済みで、警告なしで起動します。

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/corrupt-test-files/index.html b/web/public/ko/corrupt-test-files/index.html new file mode 100644 index 00000000..b90fa43b --- /dev/null +++ b/web/public/ko/corrupt-test-files/index.html @@ -0,0 +1,363 @@ + + + + + + +손상된 테스트 파일 - 크기가 정확한 망가진 파일 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

활용 사례

+

테스트용 손상 파일을 만드는 방법

+

+ 멀쩡한 파일만 본 검증기는 제대로 테스트된 것이 아닙니다. 일부러 망가뜨렸고, 요청한 크기 그대로 나오며, 시스템이 그 파일을 어떻게 다뤄야 하는지 + 알려 주는 매니페스트가 딸려 오는 파일을 얻는 방법을 설명합니다. +

+ +
+

짧은 답

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out은 정확히 2097152바이트이고 첫 + 바이트들이 0인 PNG를 쓰며, 옆의 매니페스트에는 시스템이 그것을 거부해야 한다고 기록됩니다. +

+
+ +
+

흔한 방법

+

손으로 망가뜨린 파일이 좋지 않은 테스트인 이유

+

+ 흔한 방법은 16진 편집기, 임의의 바이트 몇 개를 뒤집는 스크립트, 또는 head나 truncate로 파일을 잘라 내는 것입니다. + 한 번은 통하지만 나중에 대가를 치릅니다. +

+
    +
  • + 매번 다릅니다. 임의의 바이트는 실행할 때마다 새로운 위치에 떨어지므로, 화요일에 난 실패가 수요일에는 다시 나타나지 않을 수 있습니다. +
  • +
  • + 크기가 바뀝니다. 잘라 낸 파일은 그 아래에 있어야 했던 한도보다 작아지므로, 크기 검사가 내용 검사보다 먼저 답하고 테스트는 잘못된 이유로 + 통과합니다. +
  • +
  • + 눈치채지 못하는 경우가 많습니다. 일반 텍스트는 중간의 바이트 하나가 바뀌어도 읽히고, 관대한 이미지 리더는 그냥 그려 버리므로, 망가져야 할 파일이 + 받아들여집니다. +
  • +
  • + 무엇이 일어나야 하는지 알려 주지 않습니다. 파일은 그저 바이트일 뿐이고, 나중에 테스트를 읽는 사람은 수락이 의도였는지 거부가 의도였는지 짐작해야 + 합니다. +
  • +
+
+ +
+

얻는 것

+

손상된 파일도 요청한 크기를 유지합니다

+

+ 파일은 평소대로 생성된 뒤 디스크로 가는 길에 망가집니다. 요청한 크기는 그대로이고, 같은 명령은 같은 바이트를 다시 씁니다. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 설정은 콜론 뒤에 씁니다. 옵션은 반복할 수 있고, 손상은 쓴 순서대로 적용됩니다. 26개 형식 모두에서 동작합니다. +

+
+ +
+

할 수 있는 것

+

어떤 손상이 있나요?

+

+ 이것은 프로그램이 출력하는 목록이며, 이 페이지를 빌드할 때 프로그램에서 읽어 옵니다. tfg damage는 같은 목록을 출력하고, tfg + damage <id>는 그중 하나가 받는 설정을 알려 줍니다. +

+
+ + + + + + + + + + + + + + + + + +
손상바이트에 하는 일가장 작은 파일설정
zero-head파일의 첫 바이트들을 길이는 그대로 둔 채 0으로 덮어씁니다. 대부분의 리더가 가장 먼저 그곳을 보므로 거의 모든 것이 이 손상을 알아챕니다.8bytes
+
+

+ zero-head는 파일의 시작 부분을 0으로 덮어씁니다. 대부분의 리더는 파일이 무엇인지 알려 주는 시그니처와 헤더가 있는 그곳을 가장 먼저 봅니다. + 그래서 거의 모든 리더가 알아챕니다. 일반 텍스트와 로그에는 시그니처가 없지만 역시 거부됩니다. 0 바이트의 연속은 텍스트가 아니기 때문입니다. 4바이트 미만에서는 어떤 + 리더도 불평하지 않는 손상이 나오는 형식이 있으며, 설정이 4부터 시작하는 이유가 그것입니다. +

+
+ +
+

매니페스트가 말하는 것

+

무엇이 일어나야 하는지 말해 주는 매니페스트

+

+ 손상된 파일마다 시스템이 그것을 거부해야 한다는 항목이 붙고, 손상 내용이 그 옆에 기록됩니다. +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 두 가지 요청은 무엇이든 쓰기 전에 거부됩니다. 둘 다 매니페스트가 잘못 설명하는 파일을 디스크에 남기게 되기 때문입니다. +

+
    +
  • 손상에 필요한 크기보다 작은 파일. 그대로 나오게 됩니다
  • +
  • + 손상 옆의 expected: accept. 어떤 것도 그것을 충족할 수 없기 때문입니다. 시스템이 파일을 복구해야 한다면 + sanitize를, 바로 그것을 확인하려는 것이라면 unspecified를 쓰세요 +
  • +
+
+ +
+

레시피에서

+

한 번의 실행에 멀쩡한 파일과 망가진 파일을

+

+ 둘을 한 레시피에 넣으면 매니페스트가 파일마다 기대 결과를 가지므로, 테스트에 어느 것이 어느 것인지 알려 주는 목록이 필요 없습니다. +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

테스트에서

+

테스트로 만들기

+

+ 테스트는 매니페스트를 읽고 일어난 일이 선언된 것과 같은지 확인합니다. 파일 이름 목록은 필요 없습니다. +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 좋은 거부는 깔끔한 거부입니다. 무엇이 잘못됐는지 알려 주는 메시지가 원하는 답입니다. 서버 오류, 멈춤, 반쯤 저장된 파일은 이 테스트가 찾아내려고 존재하는 결함입니다. +

+
+ +
+

다음

+

여기서 어디로

+
    +
  • + upload-validation 프리셋은 폼에 나머지 두 가지 질문, 즉 크기와 형식을 묻습니다. +
  • +
  • + CI의 테스트 파일은 이와 같은 레시피를 파이프라인에서 실행합니다. +
  • +
  • + 문서에는 tfg generate의 모든 옵션이 있습니다. +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/create-file-exact-size/index.html b/web/public/ko/create-file-exact-size/index.html new file mode 100644 index 00000000..51f4e5cf --- /dev/null +++ b/web/public/ko/create-file-exact-size/index.html @@ -0,0 +1,319 @@ + + + + + + +지정한 크기의 파일 만드는 법 - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

정확한 크기의 파일을 만드는 방법

+

+ 모든 시스템에 이를 위한 명령이 있으며, 세 가지 모두 아래에 있습니다. 정확한 바이트 수의 파일을 만들어 주며, 많은 테스트에서는 그것만으로 충분합니다. 이 + 페이지의 모든 명령은 게시하기 전에 해당 시스템에서 실행해 보았습니다. +

+ +
+

짧은 답

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. 크기는 바이트 단위이며, 파일 관리자가 세는 방식의 10MB는 + 10485760입니다. +

+
+ +
+

Windows

+

fsutil, 그리고 추가 도구가 필요 없는 PowerShell 방식

+

+ fsutil은 Windows에 포함되어 있습니다. 크기를 바이트 단위로 받으므로 먼저 숫자를 계산하세요. 10MB는 + 10485760, 100MB는 104857600, 1GB는 1073741824입니다. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11에서 측정했습니다. 관리자 권한이 아닌 일반 프롬프트에서도 동작하며, 파일은 정확히 10485760바이트가 됩니다. +

+

PowerShell은 다른 프로그램을 호출하지 않고도 같은 일을 할 수 있으며 단위를 이해합니다.

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell의 10MB는 탐색기가 쓰는 것과 같은 1024 기준 계산으로 10485760바이트를 뜻하므로, 위의 두 명령은 같은 크기를 만듭니다. +

+
+ +
+

Linux

+

dd, truncate, fallocate, 그리고 사람들이 걸려 넘어지는 차이

+

dd는 누구나 아는 명령입니다. 바이트를 실제로 씁니다.

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate는 즉시 끝나는데, 그것이 함정입니다. Alpine Linux에서 측정해 보면 파일은 10485760바이트로 보고되지만 차지하는 블록은 + 0개로, 희소 파일입니다. 읽는 쪽은 0으로 채워진 10메가바이트를 받지만, 디스크는 공간을 내준 적이 + 없습니다. +

+
truncate -s 10M test10mb.bin
+

+ 업로드 한도를 테스트하기에는 괜찮지만 디스크 할당량을 테스트할 때는 오해를 부릅니다. 공간이 실제여야 할 때는 fallocate를 쓰세요. +

+
fallocate -l 10M test10mb.bin
+

그리고 압축 프로그램이 다시 줄일 수 없도록 내용이 압축 불가능해야 할 때는:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

희소 파일이 아닌 mkfile, 그리고 이미 아시는 두 가지

+

+ macOS에는 mkfile이 포함되어 있습니다. macOS 26.6.2에서 측정하니 10485760바이트에 20480블록이었으므로, 공간은 약속이 아니라 + 실제로 할당됩니다. +

+
mkfile 10m test10mb.bin
+

dd와 truncate도 있으며 Linux와 같게 동작합니다.

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

이 방법이 통하지 않는 곳

+

크기가 맞는 파일이 종류까지 맞는 파일은 아닙니다

+

+ 위의 방법은 모두 0으로 된 덩어리를 줍니다. 테스트 대상이 크기만 본다면, 예를 들어 업로드 한도, 할당량, 전송이라면 충분합니다. 하지만 무엇이든 그 파일을 + 여는 순간 충분하지 않게 됩니다. +

+

+ 직접 측정했으며, 여러분도 해 볼 만합니다. fsutil로 2MB 파일을 만들고 photo.png라고 이름 붙인 다음 이미지 + 라이브러리에 넘겨 보세요. Pillow는 cannot identify image file이라고 답합니다. 그것은 PNG가 아닙니다. 처음부터 + 아니었고, 이름만 그렇게 말했을 뿐입니다. +

+

+ 이는 들리는 것보다 중요합니다. 테스트가 그다음에 어느 쪽으로 실패하는지가 걸려 있기 때문입니다. 업로드 엔드포인트가 파일을 거부하고, 테스트가 + 초록색이 되며, 크기 한도가 동작한다고 결론짓게 됩니다. 하지만 크기 때문에 거부한 것이 아닙니다. 바이트가 이미지가 아니어서 거부한 것이며, 테스트하려던 규칙에는 닿지도 + 않았습니다. +

+
    +
  • 파서가 크기 규칙을 살펴보기도 전에 거부한다
  • +
  • 썸네일 단계가 실패하고 읽게 되는 오류가 썸네일에 관한 것이다
  • +
  • 백신이나 콘텐츠 검사가 세 번째 이유로 거부한다
  • +
  • 뷰어가 아무것도 보여 주지 않고, 그것이 버그인지 아무도 알 수 없다
  • +
+
+ +
+

다른 방법

+

그 형식의 실제 파일, 요청한 크기 그대로

+

+ 이것이 Testing Files Generator가 하는 일입니다. 파일은 해당 형식의 진짜 파일로, 해당 소프트웨어에서 열리며, 요청한 바이트 수와 정확히 같습니다. +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 형식이 도달할 수 없는 크기를 요청하면 하한과 그 이유를 알려 주는 오류가 나오며, 크기가 틀린 파일은 나오지 않습니다. 형식 + 페이지에 각 형식과 만들 수 있는 가장 작은 파일이 나와 있습니다. +

+

그리고 한도는 하나가 아니라 세 개의 테스트 케이스이므로, 도구가 세 개 모두 만듭니다.

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 10485759, 10485760, 10485761바이트의 파일과, 시스템이 어느 것을 받고 어느 것을 거부해야 하는지 알려 주는 매니페스트를 얻습니다. + 활용 사례 페이지에서 이것과 이 도구가 대상으로 하는 네 가지 다른 작업을 다룹니다. +

+ +

무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.

+
+ +
+

그러면 무엇을 써야 할까요?

+
    +
  • +

    시스템 명령을 쓰세요

    +

    + 아무것도 파일을 열지 않을 때입니다. 크기를 먼저 확인하는 엔드포인트의 크기 한도 테스트, 전송, 할당량, 디스크 가득 참 상황이 그렇습니다. 한 줄이면 되고 이미 설치되어 + 있습니다. +

    +
  • +
  • +

    실제 생성기를 쓰세요

    +

    + 무엇이든 파일을 파싱하거나 렌더링하거나 가져오거나 풀 때, 그리고 내일 다른 컴퓨터에서 같은 픽스처가 바이트 단위로 다시 필요할 때입니다. +

    +
  • +
+

+ 둘 다 이 페이지에 있는 이유는 둘 다 때로는 맞기 때문입니다. 피해야 할 실수는 두 번째가 필요한 곳에서 첫 번째를 쓰고 초록색 테스트를 증거로 읽는 것입니다. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/docs/index.html b/web/public/ko/docs/index.html new file mode 100644 index 00000000..d6e02427 --- /dev/null +++ b/web/public/ko/docs/index.html @@ -0,0 +1,535 @@ + + + + + + +문서 - 명령, 레시피, 매니페스트, 종료 코드 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

문서

+

+ 도구가 하는 모든 일을 사람들이 실제로 가져오는 질문 형태로 정리했습니다. 저장소의 README가 전체 레퍼런스이며, + 내려받은 빌드와 항상 일치합니다. +

+ +
+

어떤 명령이 있나요?

+

각 명령은 한 가지 일만 합니다.

+
tfg generate    레시피나 플래그로 파일을 만든다
+tfg validate    레시피를 검사하고 아무것도 쓰지 않는다
+tfg verify      디렉터리를 매니페스트와 대조해 검사한다
+tfg cleanup     매니페스트에 나열된 파일을 삭제한다
+tfg recipe fmt  레시피를 정돈된 형태로 출력한다
+tfg preset      이름 붙은 테스트 질문으로 파일 세트를 만든다
+tfg formats     이 빌드가 지원하는 형식을 나열한다
+tfg damage      이 빌드가 파일을 일부러 망가뜨릴 수 있는 방법을 나열한다
+tfg tool        이미 가진 파일을 위한 작은 도구
+tfg version     도구 버전을 출력한다
+tfg license     라이선스와 생성된 파일에 대한 의미를 출력한다
+
+ +
+

정확한 크기의 파일 하나는 어떻게 만드나요?

+

+ 형식, 크기, 저장 위치를 지정합니다. 크기는 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>한도 주변의 파일 세 개: 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매니페스트를 표준 출력에 씀
+
+
+ +
+

일부러 망가진 파일은 어떻게 만드나요?

+

+ 이 도구가 쓰는 다른 모든 파일은 구조상 올바르며, 이는 업로드 검증기가 던지는 세 가지 질문 중 두 가지에 답합니다. --damage는 세 번째, 곧 + 파일이 아예 열리는지에 답합니다. 파일은 정상적으로 만들어진 뒤 망가지므로 요청한 크기는 그대로입니다. +

+
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를 받고, 옆에 손상 내용이 기록됩니다. 두 가지는 아무것도 쓰기 전에 거부됩니다. 각각 + 매니페스트가 잘못 설명하는 파일을 디스크에 남기게 되기 때문입니다. +

+
    +
  • 손상에 필요한 크기보다 작은 파일. 바뀌지 않은 채 나오기 때문입니다
  • +
  • + 손상과 함께 쓴 expected: accept. 어떤 파일도 이를 충족할 수 없기 때문입니다. 테스트 대상 시스템이 파일을 복구해야 한다면 + sanitize를, 바로 그것이 묻고 싶은 질문이라면 unspecified를 쓰세요 +
  • +
+

+ 세 번째는 미리 알 수 없습니다. 손상이 실행되었는데 한 바이트도 바뀌지 않았다면 그 파일은 쓰이지 않고 버려집니다. 실행은 계속되고, 어떤 파일이었는지 알려 주며, 일부만 완료된 + 종료 코드로 끝납니다. +

+

+ 단계별로, 매니페스트를 읽는 테스트와 함께 설명합니다. 테스트용 손상 파일을 만드는 방법. +

+
+ +
+

레시피는 어떻게 생겼나요?

+

+ 레시피는 실행 전체를 기술하는 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 중 + 정확히 하나가 필요합니다. 둘은 오류이고 하나도 없는 것도 오류입니다. 올바르지 않은 레시피는 파일을 하나도 쓰지 않으며, 첫 번째 문제만이 + 아니라 모든 문제를 한꺼번에 보고하고 각각 해당 설정의 이름을 알려 줍니다. +

+
+ +
+

시스템이 파일을 어떻게 처리해야 하는지는 어떻게 선언하나요?

+

결과만 있으면 충분할 때는 짧은 형식을, 이유가 중요할 때는 긴 형식을 씁니다.

+
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입니다. +

+
+ +
+

매니페스트에는 무엇이 들어 있나요?

+

+ 중단된 실행을 포함해 모든 실행이 끝날 때 파일 옆에 쓰입니다. 파일마다 항목이 하나씩 있습니다. +

+
{
+  "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가 레시피를 출력하므로 + 거기서부터 편집할 수 있습니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 + 전용 페이지가 있습니다. +

+
    +
  • +

    빈 파일과 최소 파일

    +

    형식이 허용하는 가장 작은 크기의 유효한 파일이 통과할까요?

    +

    empty-and-minimal

    +
  • +
  • +

    파일 이름 처리

    +

    예상하지 못한 파일 이름을 시스템이 저장하고, 보여 주고, 돌려줄 수 있을까요?

    +

    filename-handling

    +
  • +
  • +

    크기 경계

    +

    크기 한도가 선언한 바로 그 지점에서 적용되고 있을까요?

    +

    size-boundaries

    +
  • +
  • +

    표 가져오기

    +

    실제 도구가 내보내는 표를 제 가져오기 기능이 제대로 처리할까요?

    +

    tabular-import

    +
  • +
  • +

    텍스트 인코딩

    +

    제 리더는 파일의 인코딩을 알고 있을까요, 아니면 추측하고 있을까요?

    +

    text-encoding

    +
  • +
  • +

    업로드 검증

    +

    제 업로드 양식은 받아야 할 것을 받고 나머지는 거부할까요?

    +

    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는 세트를 만들기 전에 비용이 얼마나 드는지 알려 주고, 숫자가 여러분의 한도가 아니라 우리 쪽의 임시값일 때는 분명히 말해 줍니다. +

+
+ +
+

종료 코드는 무엇을 뜻하나요?

+

+ 끝나는 방식마다 고유한 코드가 있고, 기계가 읽을 수 있는 출력은 표준 출력으로 나가며, 실패한 실행은 거기에 아무것도 출력하지 않습니다. 이 표는 고정된 약속이며, 코드의 의미를 + 바꾸려면 메이저 버전을 올려야 합니다. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
코드의미
0모두 정상적으로 동작했습니다.
1도구 내부에서 예기치 않은 오류가 발생했습니다.
2명령 또는 플래그가 잘못되었습니다.
3레시피가 올바르지 않습니다.
4해당 형식으로는 요청한 작업을 할 수 없습니다.
5읽기 또는 쓰기에 실패했습니다.
6디스크 공간이 부족합니다.
7verify가 불일치를 발견했습니다.
8실행은 끝났지만 모든 것이 만들어지지는 않았습니다.
130Ctrl+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 파이프라인에서 테스트 파일을 생성하는 + 방법. +

+
+ +
+

데스크톱 창이 있나요?

+

+ 네. 같은 엔진 위에 창을 얹은 것으로, 스크립트로 하지 않는 테스트를 위한 것입니다. 축소판이 아닙니다. 테스트가 두 인터페이스를 기능별로 비교하며, 한쪽만 할 수 있는 것은 + 조용히 벌어지는 대신 선언하고 이유를 밝혀야 합니다. +

+

+ 화면은 단일 배치, 프리셋, 여러 배치 동시 실행, 정보입니다. 무엇이든 쓰기 전에 실행 비용을 보여 주고, 실행 중에는 진행 상황을 알려 주며, 쓰다 만 파일을 남기지 않고 + 도중에 취소할 수 있습니다. 아직 레시피 파일은 열지 못합니다. 지금은 레시피가 명령줄의 몫이고, 창은 양식에서 배치를 구성합니다. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/faq/index.html b/web/public/ko/faq/index.html new file mode 100644 index 00000000..57b01b25 --- /dev/null +++ b/web/public/ko/faq/index.html @@ -0,0 +1,347 @@ + + + + + + +FAQ - 테스트 파일 생성에 관한 질문 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

자주 묻는 질문

+

+ 라이선스, 개인정보, 재현성, 그리고 사람들이 생성기를 빌드 파이프라인에 넣기 전에 확인하는 것들. 질문이 여기에 없다면 이슈 + 트래커가 열려 있습니다. +

+ +
+
+

dd, fsutil, truncate와는 무엇이 다른가요?

+
+

그 명령들은 크기만 맞고 내용이 텅 빈 파일을 줍니다. 그렇게 만든 2MB짜리 photo.png는 PNG가 아니므로, 실제로 파싱하는 것은 모두 엉뚱한 이유로 거부하고, 여러분의 테스트도 엉뚱한 이유로 통과합니다. 이 도구는 정확히 2MB인 실제 PNG를 만듭니다. 이미지 뷰어에서 열리며, 시스템이 이를 어떻게 다루어야 하는지에 대한 선언도 함께 제공됩니다.

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

무료인가요? 업무에서 써도 되나요?

+
+

둘 다 가능합니다. GPL-3.0으로 배포되며 비용이 들지 않습니다. 계정도, 라이선스 키도, 유료 요금제도 없습니다.

+
+
+
+

생성한 파일을 클로즈드 소스 제품에 써도 되나요?

+
+

네. 라이선스는 도구의 코드에 적용되며 도구가 만든 것에는 적용되지 않습니다. 생성된 파일, 레시피, 매니페스트는 파생 저작물이 아니라 출력물이므로, 어떤 의무도 없이 커밋하고 배포할 수 있습니다.

+
+
+
+

생성된 파일에 실제 개인 정보가 들어 있나요?

+
+

아니요. 내부의 모든 내용은 시드에서 합성됩니다. 어떤 데이터 세트도 읽지 않고, 어떤 서비스에도 접속하지 않으며, 제3자 콘텐츠도 포함하지 않습니다. 생성된 이메일 주소는 아직 쓰이지 않은 주소가 아니라 쓸 수 없는 주소로 여기세요. 임의의 문자열이 우연히 실제 주소와 같을 수 있기 때문입니다.

+
+
+
+

다른 컴퓨터에서도 완전히 같은 파일이 나오나요?

+
+

네. 같은 레시피와 같은 시드라면 바이트 단위로 같습니다. 프로젝트는 변경할 때마다 이를 테스트하며, 이를 깨려면 메이저 버전을 올려야 합니다. 그래서 큰 바이너리 픽스처 대신 작은 레시피를 커밋할 수 있습니다.

+
+
+
+

인터넷 연결이 필요한가요?

+
+

전혀 필요 없습니다. 텔레메트리도, 업데이트 확인도, 클라우드 클라이언트도 없으며, 명령줄 바이너리에는 네트워크 스택이 아예 컴파일되어 있지 않습니다. 네트워크가 없는 컴퓨터와 폐쇄된 기업 환경에서도 동작합니다.

+
+
+
+

형식이 도달할 수 없는 크기를 요청하면 어떻게 되나요?

+
+

형식, 가능한 가장 작은 크기, 그 하한의 이유, 대신 해야 할 일을 알려 주는 오류가 나오고 파일은 쓰이지 않습니다. 도구는 크기를 조용히 반올림하지 않습니다. 모든 하한은 형식 페이지에 나와 있습니다.

+
tfg formats png
+
+
+
+

일부러 망가진 파일도 만들 수 있나요?

+
+

네. --damage zero-head를 추가하면 파일은 요청한 크기 그대로, 첫 바이트가 0으로 덮어쓰인 채 나오므로 리더가 그것을 거부하고, 매니페스트에는 시스템이 그것을 거부해야 한다고 적힙니다. 자세한 내용은 손상된 테스트 파일 페이지에 있습니다.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

다음에는 어떤 형식이 추가되나요?

+
+

7z, mp3, mp4입니다. 현재 26가지 형식이 처음부터 끝까지 동작합니다.

+
+
+
+

어떤 시스템에서 실행할 수 있나요?

+
+

명령줄은 Windows와 Linux의 Intel과 ARM, 그리고 Apple Silicon Mac에서 실행됩니다. 데스크톱 창은 Intel의 Windows, Intel의 Linux, Apple Silicon Mac용으로 제공됩니다. Intel Mac은 지원하지 않으며 빌드도 하지 않습니다.

+
+
+
+

설치해야 하는 것이 있나요?

+
+

없습니다. 시스템에 맞는 압축 파일을 내려받아 풀고 바이너리를 실행하면 됩니다. 설치 프로그램도, 추가할 런타임도, 해결할 의존성도 없습니다. Go가 있다면 go install 명령 하나로도 됩니다.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

수천 개의 파일을 처리하는 실행이 Windows에서 더 느린 이유는 무엇인가요?

+
+

Windows는 살펴보는 경로 하나하나에 더 많은 비용을 치르게 하고, 수천 개의 파일을 훑는 명령은 수천 개의 경로를 살펴보기 때문입니다. 1kB 파일 3000개가 있는 한 컴퓨터에서 측정하니 verify는 Windows에서 약 0.9초, 컨테이너 안의 Linux에서 약 0.2초가 걸렸습니다. 출력 경로를 짧게 하면 Windows 수치가 줄어듭니다. 파일 위의 모든 폴더도 살펴보는 대상에 포함되기 때문입니다.

+
+
+
+ + +
+

아직 고민 중이신가요?

+

+ 활용 사례 페이지는 이 도구가 대상으로 하는 작업을, 형식 페이지는 각 형식과 + 만들 수 있는 가장 작은 파일을 보여 줍니다. 저장소의 README가 전체 레퍼런스입니다. +

+ +

무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/formats/index.html b/web/public/ko/formats/index.html new file mode 100644 index 00000000..0d063c60 --- /dev/null +++ b/web/public/ko/formats/index.html @@ -0,0 +1,900 @@ + + + + + + +지원하는 파일 형식 26종 - PDF, DOCX, PNG, ZIP 등 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

파일 형식 26가지, 모두 정확한 크기로 생성됩니다

+

+ 이들은 모두 해당 형식의 실제 파일입니다. 해당 소프트웨어에서 열리며 요청한 바이트 수와 정확히 같습니다. 확장자만 붙인 채운 0은 하나도 없습니다. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
형식이름확장자가장 작은 파일완전성검증 도구
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155full해당 없음
mdMarkdown.md0full해당 없음
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0full해당 없음
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

각 열의 의미

+
    +
  • +

    가장 작은 파일

    +

    + 파일 안에 쓰는 레이블을 포함해, 이 도구가 해당 형식에 대해 받아들이는 최소 바이트 수입니다. 더 작게 요청하면 하한과 그 이유를 알려 주는 오류가 나오며, 크기가 틀린 파일은 + 나오지 않습니다. +

    +
  • +
  • +

    완전성

    +

    + 파일이 얼마나 완전한지입니다. full은 형식을 실제로 파싱하는 리더가 받아들인다는 뜻이며, 단순히 확장자가 맞다는 뜻이 아닙니다. +

    +
  • +
  • +

    검증 도구

    +

    + 형식을 출시하기 전에 생성된 모든 파일을 여는 독립적인 리더입니다. 별도의 구현이며, 우리 코드가 스스로 숙제를 채점하는 것이 아닙니다. +

    +
  • +
+

+ 모든 형식은 바이트 단위로 반복되기도 합니다. 같은 레시피와 같은 시드는 어느 컴퓨터에서나 같은 파일을 만들며, 그래서 픽스처 자체 대신 레시피를 커밋해도 안전합니다. +

+
+ +
+

각 형식이 받는 설정

+

+ 대부분의 형식에는 고유한 설정이 있습니다. 이미지 크기, JPEG 품질, PDF 쪽수, 스프레드시트의 행과 열, 아카이브에 들어가는 항목 수 등입니다. 명령줄에서는 + --set key=value로, 레시피에서는 properties: 아래에서 설정합니다. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
형식설정허용값
avifwidth1 - 16384 픽셀
height1 - 16384 픽셀
quality1 - 100
bmpwidth1 - 20000 픽셀
height1 - 20000 픽셀
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
header참 또는 거짓
quote_styleall, minimal, none
columns2 - 32768 열
docxparagraphs1 - 50000 단락
gifwidth1 - 20000 픽셀
height1 - 20000 픽셀
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 픽셀
height1 - 256 픽셀
embedbmp, png
jpgwidth1 - 20000 픽셀
height1 - 20000 픽셀
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 픽셀
height1 - 16384 픽셀
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 초당 항목 수
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bom참 또는 거짓
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
title임의의 텍스트
author임의의 텍스트
subject임의의 텍스트
keywords임의의 텍스트
creator임의의 텍스트
producer임의의 텍스트
created2024-02-29 또는 2024-02-29T13:45:00+02:00 같은 날짜, 또는 none
modified2024-02-29 또는 2024-02-29T13:45:00+02:00 같은 날짜, 또는 none
pngwidth1 - 20000 픽셀
height1 - 20000 픽셀
pptxslides1 - 500 슬라이드
svgwidth1 - 20000 픽셀
height1 - 20000 픽셀
targzentries0 - 10000
entry_formattfg formats가 나열하는 형식의 id
entry_size2mb와 같은 크기
compressionbest, default, fast, none
depth0 - 50
directory_entries참 또는 거짓
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 픽셀
height1 - 20000 픽셀
txtencodingutf-16be, utf-16le, utf-8
bom참 또는 거짓
wavsample_rate8000 - 192000 헤르츠
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 픽셀
height1 - 16383 픽셀
xlsxrows1 - 200000 행
columns1 - 32768 열
xmlencodingutf-16be, utf-16le, utf-8
bom참 또는 거짓
zipentries0 - 10000
entry_formattfg formats가 나열하는 형식의 id
entry_size2mb와 같은 크기
compressionbest, default, fast, none
depth0 - 50
directory_entries참 또는 거짓
password암호(평문)
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ 설정이 받는 범위를 벗어난 값은 설정, 허용 범위, 대신 쓸 값을 알려 주는 메시지와 함께 거부됩니다. 알 수 없는 설정도 오류이며 조용히 기본값이 되는 일은 없습니다. 조용히 + 받아들여진 오타는 잘못된 설정의 파일과, 통과하면 안 되는 테스트가 왜 통과하는지 고민하는 한 시간을 낳습니다. +

+

+ 가지고 있는 빌드에서 한 형식이 정확히 무엇을 받는지 보려면 tfg formats <id>를 실행하세요. +

+
+ +
+

아카이브에는 실제 파일이 들어 있습니다

+

+ targz와 zip는 빈 + 껍데기로 두지 않고 항목으로 채울 수 있습니다. 생성된 아카이브는 담았다고 하는 문서를 실제로 담고 있으므로, 테스트 중에 이를 푸는 것은 무엇이든 안에서 실제 파일을 + 찾습니다. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/index.html b/web/public/ko/index.html new file mode 100644 index 00000000..94f81748 --- /dev/null +++ b/web/public/ko/index.html @@ -0,0 +1,444 @@ + + + + + + +테스트 파일 생성기 - 정확한 크기, 실제 형식 26종 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

정확한 크기의 실제 테스트 파일을 만드세요

+

+ PDF, PNG, DOCX, ZIP 등 모두 26가지 형식이며, 모두 해당 소프트웨어에서 열리는 실제 파일로 + 요청한 크기와 정확히 같습니다. 매 실행마다 애플리케이션이 각 파일을 어떻게 처리해야 하는지도 함께 기록합니다. 명령줄과 데스크톱 창, 무료 + 오픈 소스이며, 모두 여러분의 컴퓨터에서 동작합니다. +

+ + +

무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.

+
+ +
+ 테스트 파일 배치를 쓸 준비가 된 Testing Files Generator 데스크톱 창 +
파일 배치를 쓸 준비가 된 데스크톱 창. 명령줄 뒤에서도 같은 엔진이 동작합니다.
+
+
+ +
    +
  • + 26 +

    가지 실제 형식, 각각 해당 소프트웨어에서 열립니다

    +
  • +
  • + 1바이트 +

    요청한 모든 크기의 정확도, 조용히 반올림되는 일은 없습니다

    +
  • +
  • + 0 +

    어디로도 연결하지 않습니다. 계정도, 텔레메트리도, 업데이트 확인도 없습니다

    +
  • +
+ +
+

문제

+

테스트 파일 하나를 만드는 것은 쉽습니다. 알맞은 천 개를 만드는 것이 번거로운 부분입니다

+

여러분은 사람들에게서 파일을 받는 소프트웨어를 테스트하고 있습니다. 머지않아 다음이 필요해집니다.

+
    +
  • 업로드 한도가 실제인지 확인할 정확히 10MB인 PDF
  • +
  • 하나 차이 오류를 잡기 위한 그 한도 양쪽의 파일 세 개
  • +
  • 폴더가 클 때 야간 작업이 어떻게 되는지 보기 위한 로그 파일 10,000개
  • +
  • 확장자만 맞춘 빈 껍데기가 아니라 실제로 문서 200개가 들어 있는 ZIP
  • +
  • 저장소에 4GB 파일을 두지 않고도 쓸 수 있는 4GB 파일
  • +
  • 노트북과 빌드 서버에서 바이트 단위로 같은 픽스처
  • +
+

+ 이것이 바로 이 도구가 대체하는 일입니다. QA 엔지니어, 테스트 자동화, 그리고 코드 뒤에 업로드 양식, 가져오기 루틴, 파서, 저장 용량 할당이 있는 모든 분을 위해 + 만들었습니다. +

+
+ +
+

무엇이 다른가

+

다른 생성기는 바이트에서 멈춥니다. 이 도구는 테스트가 실제로 묻는 것에 답합니다

+

+ 파일이 가득한 폴더만으로는 각 파일이 무엇을 증명해야 하는지 여전히 직접 정해야 합니다. 여기서는 실행할 때마다 파일 옆에 manifest.json을 + 씁니다. 만들어진 모든 것의 단순한 목록이며, 항목마다 선언된 기대값이 있습니다. +

+

업로드 엔드포인트가 1MB까지 허용한다고 해 봅시다. 그 경계선 위에 놓인 파일 세 개를 요청합니다.

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
파일바이트시스템의 처리이유
1mb_under_1b.pdf1048575수락한도 안쪽입니다
1mb_at_limit.pdf1048576수락한도 값 자체는 허용됩니다
1mb_over_1b.pdf1048577거부size_limit
+
+ +

파일 세 개, 서로 다른 세 가지 답을 기계가 읽을 수 있는 형태로 줍니다. 어서션을 직접 쓰는 대신 테스트가 매니페스트를 읽습니다.

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

답이 여러분의 정책에 달려 있는 경우, 매니페스트는 그렇다고 말합니다

+

+ 기대값을 지어내지 않고 unspecified를 기록합니다. 추측하는 생성기는 거짓 실패를 만들고, 거짓 경보를 울려 대는 테스트 묶음은 결국 꺼집니다. +

+
+
+ +
+

프리셋

+

질문을 고르면 세트 전체를 얻습니다

+

+ 프리셋은 하나의 테스트 질문을 중심으로 설계한 테스트 파일 세트로, 어떤 파일이 무엇을 증명하는지 직접 따져 볼 필요가 없습니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 + 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 페이지가 있습니다. +

+
    +
  • +

    빈 파일과 최소 파일

    +

    형식이 허용하는 가장 작은 크기의 유효한 파일이 통과할까요?

    +

    empty-and-minimal

    +
  • +
  • +

    파일 이름 처리

    +

    예상하지 못한 파일 이름을 시스템이 저장하고, 보여 주고, 돌려줄 수 있을까요?

    +

    filename-handling

    +
  • +
  • +

    크기 경계

    +

    크기 한도가 선언한 바로 그 지점에서 적용되고 있을까요?

    +

    size-boundaries

    +
  • +
  • +

    표 가져오기

    +

    실제 도구가 내보내는 표를 제 가져오기 기능이 제대로 처리할까요?

    +

    tabular-import

    +
  • +
  • +

    텍스트 인코딩

    +

    제 리더는 파일의 인코딩을 알고 있을까요, 아니면 추측하고 있을까요?

    +

    text-encoding

    +
  • +
  • +

    업로드 검증

    +

    제 업로드 양식은 받아야 할 것을 받고 나머지는 거부할까요?

    +

    upload-validation

    +
  • +
+

모든 프리셋과 레시피와의 관계

+
+ +
+

빠른 시작

+

동작을 확인하는 명령 세 개

+
    +
  1. +

    파일 하나 만들기

    +

    PNG 하나, 정확히 2메가바이트:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    많은 파일 만들기

    +

    + 각각 1KB에서 8KB 사이이고 크기를 시드에서 뽑은 로그 파일 1만 개로, 내일도 같은 세트가 나옵니다. 실행마다 고유한 디렉터리를 쓰세요. + 매니페스트는 실행이 쓴 내용의 유일한 기록이므로, 도구는 그 위에 두 번째 매니페스트를 쓰기를 거부합니다. +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    검사한 뒤 삭제하기

    +

    verify는 아무것도 바뀌지 않았음을 알려 줍니다. cleanup은 쓰인 것만 정확히 삭제하고 다른 것은 건드리지 않습니다.

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 크기는 파일 관리자처럼 1024 단위로 세므로 2mb는 2097152바이트입니다. 바이트 수를 그대로 써도 됩니다. + 문서에서 레시피, 매니페스트, 종료 코드를 다룹니다. +

+
+ +
+

얻는 것

+

무인으로 실행되는 테스트 묶음을 위해 만들었습니다

+
    +
  • +

    정확한 크기, 바이트 단위까지

    +

    10485761바이트를 요청하면 정확히 그 크기가 나옵니다. 형식이 도달할 수 없는 크기는 이유가 붙은 오류가 되며, 크기가 틀린 파일이 되는 일은 없습니다.

    +
  • +
  • +

    실제 형식 26가지

    +

    확장자만 붙인 채운 0이 아닙니다. 생성된 PNG는 이미지 뷰어에서 열리고, DOCX는 Word에서 열리며, ZIP은 풀립니다. 모든 형식은 출시 전에 독립적인 리더로 검증됩니다.

    +
  • +
  • +

    테스트 오라클이 되는 매니페스트

    +

    경로, 크기, SHA-256, 형식, 시드, 도구 버전, 그리고 시스템이 그 파일을 어떻게 처리해야 하는지.

    +
  • +
  • +

    재현 가능

    +

    같은 레시피와 같은 시드라면 어느 컴퓨터에서나 바이트까지 같습니다. 큰 바이너리 픽스처 대신 작은 YAML 레시피를 커밋하세요.

    +
  • +
  • +

    두 가지 인터페이스, 하나의 엔진

    +

    CI를 위해 만든 명령줄과 탐색적 테스트를 위한 데스크톱 창. 어느 쪽도 다른 쪽의 축소판이 아니며, 테스트가 두 인터페이스를 기능별로 비교합니다.

    +
  • +
  • +

    완전한 오프라인

    +

    계정도, 클라우드도, 텔레메트리도, 업데이트 확인도 없습니다. 명령줄 바이너리에는 네트워크 스택이 아예 컴파일되어 있지 않습니다.

    +
  • +
+
+ +
+

다운로드

+

시스템에 맞는 빌드를 고르세요

+

+ 압축 파일을 풀고 실행하세요. tfg는 명령줄이고 tfg-gui는 데스크톱 창입니다. 설치 프로그램은 없으며 컴퓨터에 추가할 것도 + 없습니다. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
시스템명령줄데스크톱 창
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

서명된 것과 그렇지 않은 것

+

+ Windows와 macOS 다운로드는 서명되어 있어 확인되지 않은 개발자 경고 없이 실행됩니다. Linux용은 데스크톱 Linux에 서명할 수 있는 대응 수단이 없어 서명되어 있지 + 않습니다. 모든 압축 파일은 릴리스 페이지의 verify-SHA256SUMS.txt에 나열되어 있으므로 내려받은 것을 확인할 수 있습니다. +

+
+ +

무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.

+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/empty-and-minimal/index.html b/web/public/ko/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..2779a7ad --- /dev/null +++ b/web/public/ko/presets/empty-and-minimal/index.html @@ -0,0 +1,266 @@ + + + + + + +모든 형식의 가장 작은 유효 파일과 빈 파일 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

빈 파일과 최소 파일

+

형식이 허용하는 가장 작은 크기의 유효한 파일이 통과할까요?

+

+ empty-and-minimal 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • 검사가 바이트를 읽지 않고 개수만 세기 때문에 너무 작다며 거부되는 유효한 파일
  • +
  • 보고되지 않고 읽는 쪽을 비정상 종료시키는 빈 파일
  • +
  • 썸네일을 만드는 도중 0으로 나누기가 발생하는 너비 1픽셀의 이미지
  • +
  • 0바이트를 업로드 실패로 보고 계속 재시도하는 스토리지
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show empty-and-minimal가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수28
레시피의 타깃 수28
총 크기32 667 B
형식avif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.26
unspecified시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요.2
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + +
설정값기본값동작
--formats쉼표로 구분한 형식 id 또는 allall세트를 구성하는 형식입니다. 이 빌드의 모든 형식을 쓰려면 all로 두고, 시스템이 받는 형식만 쓰려면 이름을 지정합니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/filename-handling/index.html b/web/public/ko/presets/filename-handling/index.html new file mode 100644 index 00000000..54539c82 --- /dev/null +++ b/web/public/ko/presets/filename-handling/index.html @@ -0,0 +1,265 @@ + + + + + + +테스트용 까다로운 파일 이름 - 유니코드와 길이 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

파일 이름 처리

+

예상하지 못한 파일 이름을 시스템이 저장하고, 보여 주고, 돌려줄 수 있을까요?

+

+ filename-handling 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • 화면이나 로그, 목록에서 다른 이름처럼 보이는 이름
  • +
  • 업로드와 저장 사이에 잘리거나 다듬어지거나 다시 쓰이는 이름
  • +
  • 스토리지는 바이트로 세는데 문자로 세는 길이 제한
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show filename-handling가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수50
레시피의 타깃 수50
총 크기51 200 B
형식txt
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.4
unspecified시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요.46
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + +
설정값기본값동작
--format형식 페이지의 형식 idtxt세트에 포함된 모든 파일의 형식입니다. 도구 자체의 플래그이며, 프리셋은 기본값만 지정합니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/index.html b/web/public/ko/presets/index.html new file mode 100644 index 00000000..a0297545 --- /dev/null +++ b/web/public/ko/presets/index.html @@ -0,0 +1,239 @@ + + + + + + +테스트 파일 프리셋 - QA 질문별 기성 세트 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

테스트 파일 프리셋, 테스트 질문마다 한 세트

+

+ 프리셋은 하나의 질문을 중심으로 설계한 테스트 파일 세트 전체이며, 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 매니페스트가 함께 제공됩니다. 질문을 고르면 도구가 세트를 + 만듭니다. 각 프리셋에는 보통 무엇을 찾아내는지, 세트에 무엇이 들어 있는지, 어떤 설정을 받는지 설명하는 고유한 페이지가 있습니다. +

+ +
    +
  • +

    빈 파일과 최소 파일

    +

    형식이 허용하는 가장 작은 크기의 유효한 파일이 통과할까요?

    +

    empty-and-minimal

    +
  • +
  • +

    파일 이름 처리

    +

    예상하지 못한 파일 이름을 시스템이 저장하고, 보여 주고, 돌려줄 수 있을까요?

    +

    filename-handling

    +
  • +
  • +

    크기 경계

    +

    크기 한도가 선언한 바로 그 지점에서 적용되고 있을까요?

    +

    size-boundaries

    +
  • +
  • +

    표 가져오기

    +

    실제 도구가 내보내는 표를 제 가져오기 기능이 제대로 처리할까요?

    +

    tabular-import

    +
  • +
  • +

    텍스트 인코딩

    +

    제 리더는 파일의 인코딩을 알고 있을까요, 아니면 추측하고 있을까요?

    +

    text-encoding

    +
  • +
  • +

    업로드 검증

    +

    제 업로드 양식은 받아야 할 것을 받고 나머지는 거부할까요?

    +

    upload-validation

    +
  • +
+ +
+

프리셋과 레시피는 어떻게 다른가요?

+

+ 내부적으로는 다르지 않습니다. 프리셋은 몇 가지 설정으로 도구가 대신 써 주는 레시피입니다. tfg preset eject가 그 레시피를 출력하므로 테스트 + 옆에 두고 편집할 수 있으며, 직접 만든 레시피는 extends: preset: 뒤에 id를 붙인 한 줄로 프리셋을 바탕으로 할 수 있습니다. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

기본값을 믿어도 되나요?

+

+ 파일에 대해서는 그렇습니다. 업로드 양식의 한도처럼 여러분의 시스템만 아는 숫자라면 기본값은 우리 쪽의 임시값이며, 도구는 임시값을 쓸 때마다 그렇게 알려 줍니다. 각 프리셋의 + 페이지는 그러한 설정을 표시하고, tfg preset show는 무엇이든 쓰기 전에 그 사실을 알려 줍니다. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/size-boundaries/index.html b/web/public/ko/presets/size-boundaries/index.html new file mode 100644 index 00000000..e9e8205d --- /dev/null +++ b/web/public/ko/presets/size-boundaries/index.html @@ -0,0 +1,279 @@ + + + + + + +업로드 크기 한도 테스트 - 경계 바로 위의 파일 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

크기 경계

+

크기 한도가 선언한 바로 그 지점에서 적용되고 있을까요?

+

+ size-boundaries 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • 한도에서 발생하는 하나 차이 오류
  • +
  • MB와 MiB를 혼동하는 경우로, 4.8퍼센트 차이이며 통과하면 안 되는 파일을 통과시키기에 충분합니다
  • +
  • 서버가 아니라 브라우저에서만 적용되는 한도
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show size-boundaries가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수7
레시피의 타깃 수7
총 크기73 400 320 B
형식pdf
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.4
reject시스템은 이 파일을 거부해야 합니다.3
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
설정값기본값동작
--limit2mb와 같은 크기10mb시스템이 선언한 크기 한도입니다. 다른 모든 값은 이 값을 기준으로 측정됩니다. 이 기본값은 우리 쪽의 임시값이며 여러분 시스템의 값이 아닙니다. 직접 값을 지정하세요.
--spread쉼표로 구분한 크기1B,1kb,1mb한도 양쪽으로 얼마나 멀리 갈지를 크기 목록으로 지정합니다.
--format형식 페이지의 형식 idpdf세트에 포함된 모든 파일의 형식입니다. 도구 자체의 플래그이며, 프리셋은 기본값만 지정합니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

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

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/tabular-import/index.html b/web/public/ko/presets/tabular-import/index.html new file mode 100644 index 00000000..a239e671 --- /dev/null +++ b/web/public/ko/presets/tabular-import/index.html @@ -0,0 +1,273 @@ + + + + + + +CSV와 Excel 가져오기 테스트 파일 - 구분자, 머리글 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

표 가져오기

+

실제 도구가 내보내는 표를 제 가져오기 기능이 제대로 처리할까요?

+

+ tabular-import 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • 구분자를 찾지 않고 가정했기 때문에 한 열로 읽히는 세미콜론 구분 파일
  • +
  • 각 줄 뒤에 빈 줄이 생기며 행으로 나뉘는 CRLF 파일
  • +
  • 첫 데이터 행이 열 이름으로 처리되어 사라지는 머리글 없는 표
  • +
  • 표시할 수 있는 열만 남기고 나머지는 말없이 버리는 가져오기
  • +
  • JSON 레코드를 한 줄씩 읽다가 들여쓰기된 첫 문서에서 멈추는 리더
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show tabular-import가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수13
레시피의 타깃 수13
총 크기3 080 060 B
형식csv, json, xlsx
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.8
unspecified시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요.5
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + + + + + + + +
설정값기본값동작
--rows1 - 200000 행1000스프레드시트에 담길 행 수입니다. 그만큼의 행이 패키징되는 정확한 크기로 파일이 쓰이므로, 위의 예산이 이 값에 따라 움직입니다.
--columns1 - 32768 열10스프레드시트의 각 행에 있는 열 수입니다. 행 수와 열 수의 곱에는 상한이 있으며, 이를 넘는 요청은 아무것도 쓰기 전에 거부됩니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/text-encoding/index.html b/web/public/ko/presets/text-encoding/index.html new file mode 100644 index 00000000..569104f3 --- /dev/null +++ b/web/public/ko/presets/text-encoding/index.html @@ -0,0 +1,266 @@ + + + + + + +텍스트 인코딩 테스트 파일 - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

텍스트 인코딩

+

제 리더는 파일의 인코딩을 알고 있을까요, 아니면 추측하고 있을까요?

+

+ text-encoding 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • UTF-8로 가정하여 UTF-16 파일을 세 글자에 한 글자만, 또는 네모 칸의 행으로 보여 주는 리더
  • +
  • 바이트 순서 표시를 내용으로 읽어서 가져오기의 첫 필드가 낯선 문자 세 개로 시작하는 문제
  • +
  • 앞쪽 바이트로 인코딩을 추측하고 더 긴 파일에서는 다르게 추측하는 임포터
  • +
  • 각 줄 뒤에 빈 줄이 생기며 행으로 나뉘는 CRLF 파일, 또는 마지막 필드에 남는 캐리지 리턴
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show text-encoding가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수20
레시피의 타깃 수20
총 크기81 920 B
형식csv, log, md, txt, xml
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.10
unspecified시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요.10
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + +
설정값기본값동작
--sample2mb와 같은 크기4kb세트에 포함된 각 파일의 크기입니다. UTF-16은 글자당 2바이트를 저장하므로 홀수는 거부됩니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/presets/upload-validation/index.html b/web/public/ko/presets/upload-validation/index.html new file mode 100644 index 00000000..f455c243 --- /dev/null +++ b/web/public/ko/presets/upload-validation/index.html @@ -0,0 +1,295 @@ + + + + + + +업로드 검증 테스트 파일 - 유형, 크기, 이름 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

프리셋

+

업로드 검증

+

제 업로드 양식은 받아야 할 것을 받고 나머지는 거부할까요?

+

+ upload-validation 프리셋은 이 질문에 대한 실제 테스트 파일 세트 전체를 명령 하나로 만들고, 그 옆에 시스템이 각 파일에 어떻게 반응해야 하는지 알려 주는 + manifest.json을 둡니다. 아래의 모든 내용은 이 버전의 기본값으로 프로그램에서 읽어 온 것입니다. +

+ + +
+

보통 무엇을 찾아내나요?

+
    +
  • 서버가 아니라 브라우저에서만 적용되는 한도
  • +
  • 이미지나 일반 텍스트로 오인되는 SVG 또는 HTML 파일로, 스크립트가 양식 검사를 통과하는 방법이 됩니다
  • +
  • 확장자로만 검사하고 열어 보지 않아서 .jpg라는 이름의 PDF가 통과하는 파일
  • +
  • 크기를 확인하기 전에 본문 전체를 메모리로 읽어 들이는 양식
  • +
  • photo.jpg는 받으면서 PHOTO.JPG는 거부하거나 그 반대인 업로드
  • +
  • 공백, 괄호, ASCII 이외의 문자가 든 이름이 그대로 디스크에 쓰이는 문제
  • +
+
+ + +
+

세트에는 무엇이 들어 있나요?

+

기본값에서 tfg preset show upload-validation가 보고하는 대로입니다.

+
+ + + + + + + +
파일 수71
레시피의 타깃 수22
총 크기120 639 488 B
형식html, jpg, pdf, png, svg, txt
+
+

그리고 그 세트의 매니페스트가 시스템에 기대하는 것:

+
+ + + + + + + + + +
기대값의미파일 수
accept시스템은 이 파일을 받아야 합니다.56
reject시스템은 이 파일을 거부해야 합니다.10
unspecified시스템의 규칙에 따라 다릅니다. 직접 결정한 뒤 실제 일어나는 일이 의도한 것인지 확인하세요.5
+
+
+ +
+

무엇을 바꿀 수 있나요?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
설정값기본값동작
--limit2mb와 같은 크기10mb업로드 양식이 선언한 크기 한도입니다. 이 세트는 한도 양쪽으로 한 단계씩 만듭니다. 모든 거리의 파일이 필요하면 size-boundaries 프리셋을 실행하세요. 이 기본값은 우리 쪽의 임시값이며 여러분 시스템의 값이 아닙니다. 직접 값을 지정하세요.
--allow쉼표로 구분한 형식 idjpg,png,pdf양식이 받아야 할 유형입니다. 각 유형이 해당 유형의 실제 파일이 되며, 세트 전체의 양성 대조군이 됩니다.
--deny쉼표로 구분한 확장자svg,html,exe,sh양식이 거부해야 할 확장자입니다. 이 빌드에 형식이 없는 확장자도 그 이름의 파일이 만들어지며, 내용은 일반 텍스트입니다.
--far-over10x, 2x, off2x하나뿐인 큰 파일이 한도를 얼마나 넘는지입니다. 한도의 몇 배를 쓰는 것이 디스크 낭비라면 꺼 두세요.
--bulk0 - 10000 파일50대량 업로드에 포함할 파일 수입니다. 0이면 그 그룹은 세트에서 완전히 빠집니다.
+
+
+ +
+

어떻게 실행하나요?

+

세트의 비용을 확인하고, 만들거나, 편집할 레시피를 꺼냅니다.

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

또는 테스트 옆에 둔 직접 만든 레시피에서 이를 바탕으로 이어 갑니다.

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/ko/test-files-in-ci/index.html b/web/public/ko/test-files-in-ci/index.html new file mode 100644 index 00000000..11f5a509 --- /dev/null +++ b/web/public/ko/test-files-in-ci/index.html @@ -0,0 +1,364 @@ + + + + + + +CI의 테스트 파일 - GitHub Actions, GitLab CI, PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

활용 사례

+

CI 파이프라인에서 테스트 파일을 생성하는 방법

+

+ 저장소의 바이너리 픽스처는 기록에 영원히 남고, diff에서 검토할 수 없으며, 파일이 커지면 아예 불가능해집니다. 대신 파이프라인 안에서 레시피로 파일을 생성하세요. 레시피는 + 텍스트이고, 바이트는 매번 같게 나오며, 마지막 단계가 아무것도 움직이지 않았음을 증명합니다. +

+ +
+

짧은 답

+

+ tfg를 설치하고, 테스트 전에 tfg generate fixtures.yaml --out ./fixtures를, 테스트 후에 + tfg verify ./fixtures/manifest.json을 실행하세요. 두 단계 모두 스스로 빌드를 실패시키며, 이유를 알려 주는 종료 코드를 + 남깁니다. +

+
+ +
+

커밋하지 않는 이유

+

픽스처가 저장소에 있으면 안 되는 이유

+
    +
  • + 기록에 남습니다. 바이너리를 나중에 삭제해도 모든 버전이 그대로 있으므로 클론은 작아지지 않습니다. +
  • +
  • + diff로는 무엇이 바뀌었는지 알 수 없습니다. 검토자는 PDF가 다르다는 것만 볼 뿐 그 이상은 모릅니다. 레시피는 한 줄만 바뀝니다. +
  • +
  • + 큰 파일은 들어가지 않습니다. GitHub는 100 MB를 넘는 파일이 든 푸시를 거부하므로, 500 MB 업로드 한도를 테스트하려면 커밋할 것이 + 없습니다. +
  • +
+

+ 커밋할 것은 레시피입니다. 같은 레시피와 같은 시드는 어느 머신에서나 같은 바이트를 쓰므로, 파이프라인에서 생성한 파일은 노트북에 있던 바로 그 파일입니다. +

+
+ +
+

레시피

+

테스트 옆에 두는 레시피

+

+ 이 레시피는 수락되어야 하는 청구서 25건과 한도를 넘어 거부되어야 하는 이미지 2장을 쓰며, 매니페스트는 두 기대 결과를 모두 기록합니다. +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml은 아무것도 쓰지 않고 레시피를 검사하며 모든 문제를 한 번에 알려 줍니다. +

+
+ +
+

GitHub Actions

+

도구를 설치하고 픽스처를 만드는 워크플로

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 체크섬 줄은 아카이브를 같은 릴리스의 verify-SHA256SUMS.txt와 비교합니다. 버전이 고정되어 있어서 새 릴리스가 손대지 않은 빌드를 바꾸는 + 일은 없습니다. +

+
+ +
+

GitLab CI

+

같은 일을 GitLab 작업으로

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

빨갛게 변했을 때

+

무엇이 단계를 실패시키는지, 그리고 이유

+

+ 끝나는 방식마다 고유한 종료 코드가 있으므로 단계는 스스로 실패하고 로그가 어느 것인지 알려 줍니다. 파이프라인이 만나는 코드는 다음과 같습니다. +

+
    +
  • 3 - 레시피가 유효하지 않습니다. 아무것도 쓰이지 않았고 모든 문제가 지목됩니다
  • +
  • 4 - 형식이 요청받은 일을 할 수 없습니다. 예를 들어 최소보다 작은 크기입니다
  • +
  • 6 - 디스크 공간이 부족합니다
  • +
  • 7 - tfg verify가 매니페스트와 맞지 않는 파일을 찾았습니다
  • +
  • 8 - 실행은 끝났지만 모든 것이 만들어지지는 않았습니다
  • +
+

+ 실패한 실행은 표준 출력에 아무것도 출력하지 않으므로 로그 파서가 오류를 데이터로 착각하는 일이 없습니다. 전체 표는 문서 페이지에 + 있습니다. +

+
+ +
+

PowerShell

+

PowerShell 스크립트에는 한 줄이 더 필요합니다

+

+ PowerShell은 프로그램의 종료 코드를 .ps1 파일 밖으로 전달하지 않습니다. -File로 실행하면 안에 있는 도구가 작업을 + 거부했더라도 스크립트는 0으로 답하므로, 빨갛게 되어야 할 빌드가 초록이 됩니다. 마지막 한 줄이 수정의 전부입니다. +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 이것은 PowerShell의 동작이지 이 도구와는 무관합니다. cmd, bash, zsh에는 따로 필요한 것이 + 없습니다. +

+
+ +
+

여러 작업

+

작업 사이에서 픽스처 공유하기

+

+ 보통은 업로드할 필요가 없습니다. 같은 레시피가 같은 바이트를 쓰므로 각 작업이 자기 tfg generate를 실행할 수 있고, 이것이 업로드 후 + 다운로드보다 빠릅니다. 한 작업이 다른 작업에서 파일을 받아야 한다면 전송 후 매니페스트에 tfg verify를 실행하세요. 도착한 것이 기록된 것과 + 같은지 알려 줍니다. +

+
+ +
+

다음

+

여기서 어디로

+
    +
  • + 손상된 테스트 파일은 같은 레시피에 일부러 망가뜨린 파일을 더합니다. +
  • +
  • + 사용 사례는 파이프라인의 실행이 그 밖에 무엇을 확인할 수 있는지 보여 줍니다. +
  • +
  • + 문서에는 모든 명령, 레시피 키, 종료 코드가 있습니다. +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/ko/use-cases/index.html b/web/public/ko/use-cases/index.html new file mode 100644 index 00000000..d55fb4f5 --- /dev/null +++ b/web/public/ko/use-cases/index.html @@ -0,0 +1,302 @@ + + + + + + +활용 사례 - 업로드 한도, CI 픽스처, 대량 테스트 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

어떤 일에 쓰나요

+

+ 사람들에게서 파일을 받는 거의 모든 프로젝트에 나오는 다섯 가지 작업과, 각각을 처리하는 명령입니다. 아래의 모든 예제는 쓰인 그대로 실행됩니다. +

+ +
+

업로드 한도

+

파일 크기 한도가 말한 위치에서 적용되는지 테스트하기

+

+ 한도는 하나가 아니라 세 개의 테스트 케이스입니다. 바로 아래, 정확히 그 값, 바로 위입니다. 이를 손으로 만들려면 바이트 수를 계산하고 하나 어긋나지 않았기를 바라야 합니다. + 대신 세트를 요청하세요. +

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

+ 1048575, 1048576, 1048577바이트의 실제 PDF 세 개와, 처음 두 개는 수락하고 세 번째는 size_limit으로 거부해야 한다고 알려 + 주는 매니페스트를 얻습니다. 어서션 세 개를 직접 쓰는 대신 테스트가 기대값을 읽으며, 한도가 바뀌면 숫자 하나를 바꾸고 다시 실행하면 됩니다. +

+

+ 경계 세트 하나를 인라인으로 만들고 싶다면 프리셋 없이도 같은 일을 할 수 있습니다. +

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

지속적 통합

+

픽스처를 잃지 않으면서 저장소 밖에 두기

+

+ 큰 바이너리 픽스처는 저장소 복제를 느리게 하고 리뷰를 불편하게 하며, 하나가 교체되어도 무엇이 바뀌었는지 아무도 알 수 없습니다. 레시피는 똑같은 파일을 다시 만드는 몇백 자의 + YAML입니다. 어느 컴퓨터에서나 바이트 단위로 같습니다. 모든 파일이 실행의 시드에서 파생되기 때문입니다. +

+
- 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
+

+ 끝나는 방식마다 고유한 종료 코드가 있으므로 파이프라인은 잘못된 레시피, 디스크 가득 참, 검증 불일치를 구별할 수 있습니다. 실패한 실행은 표준 출력에 아무것도 출력하지 않아 + 로그 파서가 오류를 데이터로 읽지 않습니다. +

+
+ +
+

규모

+

폴더가 클 때 무슨 일이 일어나는지 알아내기

+

+ 가져오기 루틴, 야간 작업, 디렉터리 목록은 파일이 10개일 때와 1만 개일 때 다르게 동작합니다. 범위에서 뽑은 크기는 똑같은 파일 1만 개가 아니라 실제 트래픽처럼 보이는 + 세트를 만들며, 추첨은 시드에서 나오므로 세트는 내일도 같습니다. +

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

+ 합계가 기가바이트 단위일 때는 특히, 무언가를 쓰기 전에 실행 비용을 확인하세요. +

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

+ 디스크 여유 공간보다 큰 실행은 첫 바이트를 쓰기 전에 거부되며, 디스크를 가득 채운 채 중간에 실패하는 일이 없습니다. +

+
+ +
+

아카이브

+

실제로 파일이 들어 있는 아카이브로 압축 해제 기능 테스트하기

+

+ 확장자만 맞는 빈 아카이브는 이를 열어 내용을 순회하는 코드에 대해 아무것도 증명하지 못합니다. 내용을 선언하면 아카이브가 실제로 그것을 담습니다. +

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

+ 중첩 깊이, 항목 수, 내부 내용의 크기는 모두 가져오기 루틴이 나름의 의견을 가진 것들이며, 이것이 그 의견이 무엇인지 알아내는 방법입니다. +

+
+ +
+

파서와 뷰어

+

내 코드가 실제 소프트웨어처럼 형식을 읽는지 확인하기

+

+ 여기 있는 모든 형식은 출시 전에 독립적인 리더로 검증됩니다. PNG는 열어서 픽셀을 비교하고, DOCX는 별도의 라이브러리로 다시 읽고, 아카이브는 풀어 봅니다. 즉 여러분의 + 파서가 거부하는 파일은 생성기가 아니라 여러분의 파서에 대한 발견입니다. +

+
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
+

+ 형식 페이지에 각 형식이 받는 설정과 각각이 될 수 있는 가장 작은 파일이 나와 있습니다. +

+
+ +
+

가이드

+

그중 두 가지를 자세히

+
    +
  • + 손상된 테스트 파일 - 일부러 망가뜨린, 크기가 정확한 파일. 그 파일을 어떻게 다뤄야 하는지는 매니페스트에 + 적힙니다. +
  • +
  • + CI의 테스트 파일 - GitHub Actions 워크플로, GitLab 작업, 그리고 빌드를 실패시키는 종료 + 코드. +
  • +
+
+ +
+

누구를 위한 것인가

+

+ QA 엔지니어, 테스트 자동화, 그리고 코드 뒤에 업로드 양식, 가져오기 루틴, 파서, 저장 용량 할당이 있는 모든 분을 위한 것입니다. 네트워크가 전혀 없는 컴퓨터에서 + 동작하므로, 브라우저 기반 생성기를 쓸 수 없는 폐쇄된 기업 환경에서 특히 중요합니다. +

+ +

무료 오픈 소스, GPL-3.0. 가입이 필요 없습니다. Windows와 macOS 다운로드는 서명되어 있어 경고 없이 실행됩니다.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/beschadigde-testbestanden/index.html b/web/public/nl/beschadigde-testbestanden/index.html new file mode 100644 index 00000000..8346dea8 --- /dev/null +++ b/web/public/nl/beschadigde-testbestanden/index.html @@ -0,0 +1,385 @@ + + + + + + +Beschadigde testbestanden - kapotte bestanden op exacte grootte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Toepassingen

+

Hoe maak je een beschadigd bestand om mee te testen

+

+ Een validator aan wie alleen gezonde bestanden zijn getoond, is niet echt getest. Zo krijg je een + bestand dat met opzet kapot is, precies de grootte heeft die je vraagt en een + manifest meebrengt dat zegt wat je systeem ermee moet doen. +

+ +
+

Het korte antwoord

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out schrijft een PNG + van precies 2097152 bytes waarvan de eerste bytes nullen zijn, en het manifest ernaast legt vast + dat je systeem het moet weigeren. +

+
+ +
+

De gebruikelijke weg

+

Waarom een met de hand beschadigd bestand een slechte test is

+

+ Gebruikelijk zijn een hexeditor, een script dat een paar willekeurige bytes omgooit, of een bestand + dat met head of truncate wordt ingekort. Het werkt één keer, en daarna + kost het je: +

+
    +
  • + Het is elke keer anders. Een willekeurige byte komt bij elke run ergens anders + terecht, dus een fout van dinsdag komt woensdag misschien niet terug. +
  • +
  • + Het verandert de grootte. Een ingekort bestand is kleiner dan de limiet waaronder + het hoorde te blijven, dus de groottecontrole antwoordt vóór de inhoudscontrole en de test + slaagt om de verkeerde reden. +
  • +
  • + Het valt vaak niet op. Platte tekst blijft leesbaar met een gewijzigde byte in het + midden, en een toegeeflijke afbeeldingslezer tekent het gewoon, waardoor het bestand dat kapot + moest zijn wordt geaccepteerd. +
  • +
  • + Het zegt niets over wat er moet gebeuren. Het bestand is alleen bytes, en wie de + test later leest, moet raden of acceptatie of weigering de bedoeling was. +
  • +
+
+ +
+

Wat je krijgt

+

Een beschadigd bestand heeft nog steeds de grootte die je vroeg

+

+ Het bestand wordt normaal gegenereerd en daarna kapotgemaakt, op weg naar de schijf. Het houdt de + grootte die je vroeg, en hetzelfde commando schrijft opnieuw dezelfde bytes. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Instellingen komen achter een dubbele punt. De optie mag herhaald worden, en de beschadigingen + worden toegepast in de volgorde waarin je ze schrijft. Het werkt met elk van de + 26 formaten. +

+
+ +
+

Wat het kan

+

Welke beschadigingen zijn er?

+

+ Dit is de lijst die het programma afdrukt, uit het programma gelezen op het moment dat deze pagina + wordt gebouwd. tfg damage drukt dezelfde af, en tfg damage <id> + zegt wat één ervan aanneemt. +

+
+ + + + + + + + + + + + + + + + + +
BeschadigingWat het met de bytes doetKleinste bestandInstellingen
zero-headOverschrijft de eerste bytes van het bestand met nullen en laat de lengte ongemoeid. De meeste lezers kijken daar eerst, dus bijna alles merkt deze beschadiging.8bytes
+
+

+ zero-head schrijft nullen over het begin van het bestand. De meeste lezers kijken daar + eerst, naar de handtekening en de kop die zeggen wat het bestand is, dus bijna elke lezer merkt + het. Platte tekst en logbestanden hebben geen handtekening en worden ook geweigerd, omdat een + reeks nulbytes geen tekst is. Onder vier bytes komen sommige formaten uit met schade waar geen + lezer over klaagt, en daarom begint de instelling bij vier. +

+
+ +
+

Wat het manifest zegt

+

Een manifest dat zegt wat er moet gebeuren

+

+ Elk beschadigd bestand krijgt een regel die zegt dat je systeem het moet weigeren, met de + beschadiging ernaast vastgelegd: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Twee verzoeken worden geweigerd voordat er iets wordt geschreven, omdat elk een bestand op schijf + zou laten staan dat het manifest verkeerd beschrijft: +

+
    +
  • een bestand dat kleiner is dan de beschadiging nodig heeft en ongewijzigd zou uitkomen
  • +
  • + expected: accept naast een beschadiging, omdat niets daaraan kan voldoen. Schrijf + sanitize als je systeem het bestand moet repareren, of unspecified + als dat juist de vraag is die je stelt +
  • +
+
+ +
+

In een recept

+

Gezonde en kapotte bestanden in één run

+

+ Zet beide in één recept, en het manifest draagt de verwachting van elk bestand, zodat de test geen + lijst nodig heeft van welk bestand welk is: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

In een test

+

Er een test van maken

+

+ De test leest het manifest en controleert dat wat er gebeurde is wat er werd opgegeven. Hij heeft + geen lijst met bestandsnamen nodig: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Een goede weigering is een schone weigering. Een melding die zegt wat er mis was, is het antwoord + dat je wilt. Een serverfout, een vastloper of een half opgeslagen bestand is het gebrek dat deze + test moet vinden. +

+
+ +
+

Verder

+

Waar je vandaar heen kunt

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/bestand-met-exacte-grootte-maken/index.html b/web/public/nl/bestand-met-exacte-grootte-maken/index.html new file mode 100644 index 00000000..0bb53b6e --- /dev/null +++ b/web/public/nl/bestand-met-exacte-grootte-maken/index.html @@ -0,0 +1,335 @@ + + + + + + +Een bestand van een exacte grootte maken - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Hoe maak je een bestand van een exacte grootte

+

+ Elk systeem heeft er een opdracht voor, en alle drie staan hieronder. Ze geven je een bestand met + precies het juiste aantal bytes - en voor veel tests is dat alles wat je nodig hebt. Elke + opdracht op deze pagina is uitgevoerd vóór publicatie, op het systeem waartoe hij + behoort. +

+ +
+

Het korte antwoord

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Groottes zijn in bytes, en 10 MB + geteld zoals je bestandsbeheer telt is 10485760. +

+
+ +
+

Windows

+

fsutil, en een PowerShell-versie die niets extra's nodig heeft

+

+ fsutil wordt met Windows meegeleverd. Het neemt de grootte in bytes, + reken het getal dus eerst uit - 10 MB is 10485760, 100 MB is 104857600, 1 GB is 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Gemeten op Windows 11: het werkt vanaf een gewone prompt en heeft geen verhoogde nodig, en het + bestand komt uit op precies 10485760 bytes. +

+

PowerShell kan hetzelfde zonder een ander programma aan te roepen, en begrijpt eenheden:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB betekent in PowerShell 10485760 bytes, dezelfde telling op basis van 1024 die + Verkenner gebruikt, dus de twee opdrachten hierboven geven dezelfde grootte. +

+
+ +
+

Linux

+

dd, truncate en fallocate, en het verschil dat mensen te pakken neemt

+

dd is degene die iedereen kent. Het schrijft de bytes echt:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate is direct klaar, en dat is de adder onder het gras. Gemeten op Alpine Linux + meldt het bestand 10485760 bytes en neemt het nul blokken in beslag - het is + een sparse bestand. Alles wat het leest krijgt tien megabyte aan nullen, maar + de schijf heeft de ruimte nooit afgestaan: +

+
truncate -s 10M test10mb.bin
+

+ Dat is prima om een uploadlimiet te testen en misleidend om een schijfquotum te testen. + fallocate is degene waar je naar grijpt als de ruimte echt moet zijn: +

+
fallocate -l 10M test10mb.bin
+

En als de inhoud onsamendrukbaar moet zijn, zodat een archiefprogramma hem niet weer kan verkleinen:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, dat niet sparse is, en de twee die je al kent

+

+ macOS levert mkfile mee. Gemeten op macOS 26.6.2: 10485760 bytes en 20480 blokken, dus + de ruimte is echt toegewezen in plaats van beloofd: +

+
mkfile 10m test10mb.bin
+

dd en truncate zijn er ook en gedragen zich zoals op Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Waar dit ophoudt te werken

+

Een bestand van de juiste grootte is geen bestand van het juiste soort

+

+ Alles hierboven geeft je een blok nullen. Dat is genoeg als wat getest wordt alleen naar de grootte + kijkt - een uploadlimiet, een quotum, een overdracht. Het is niet meer genoeg zodra iets het + bestand opent. +

+

+ Gemeten, en het is de moeite waard om het zelf te doen: maak een bestand van 2 MB met + fsutil, noem het photo.png en geef het aan een afbeeldingsbibliotheek. + Pillow antwoordt cannot identify image file. Het is geen PNG. Dat is het ook nooit + geweest - alleen de naam zei het. +

+

+ Dat doet er meer toe dan het klinkt, vanwege de kant waarop de test dan faalt. Je + upload-endpoint weigert het bestand, je test wordt groen en je concludeert dat de groottelimiet + werkt. Het weigerde het niet vanwege de grootte. Het weigerde het omdat de bytes geen afbeelding + waren, en de regel die je wilde testen is nooit bereikt. +

+
    +
  • een parser weigert het voordat een groottegrens wordt bekeken
  • +
  • een miniatuurstap faalt en de fout die je leest gaat over het miniatuur
  • +
  • een virusscanner of inhoudscontrole weigert het om een derde reden
  • +
  • een viewer toont niets, en niemand kan zeggen of dat de bug is
  • +
+
+ +
+

De andere weg

+

Een echt bestand van dat formaat, in precies de grootte die je vroeg

+

+ Dit is wat Testing Files Generator doet. Het bestand is een echt bestand van zijn formaat - het + opent in het programma waartoe het behoort - en het heeft het exacte aantal bytes dat je vroeg, + tot op de byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Vraag een grootte die een formaat niet kan halen en je krijgt een fout die de ondergrens en de reden + noemt, nooit een bestand van de verkeerde grootte. De pagina met + formaten toont elk formaat met het kleinste bestand dat het kan maken. +

+

En een limiet is drie testgevallen in plaats van één, dus de tool bouwt ze alle drie:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Dat geeft je 10485759, 10485760 en 10485761 bytes, en een manifest dat zegt welke je systeem moet + accepteren en welke het moet weigeren. De pagina met + toepassingen loopt dat en vier andere taken door waarvoor het is gebouwd. +

+ +

Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.

+
+ +
+

Dus wat moet je gebruiken?

+
    +
  • +

    Gebruik de systeemopdracht

    +

    + Als niets het bestand opent. Een groottelimiet testen op een endpoint dat eerst de grootte + controleert, een overdracht, een quotum, een volle schijf. Het is één regel en het is al + geïnstalleerd. +

    +
  • +
  • +

    Gebruik een echte generator

    +

    + Als iets het bestand parset, rendert, importeert of uitpakt - en als je morgen op een andere machine + dezelfde fixtures nodig hebt, byte voor byte. +

    +
  • +
+

+ Beide staan op deze pagina omdat beide soms goed zijn. De fout die je moet vermijden is de eerste + gebruiken waar de tweede nodig is en de groene test als bewijs lezen. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/documentatie/index.html b/web/public/nl/documentatie/index.html new file mode 100644 index 00000000..7bded62b --- /dev/null +++ b/web/public/nl/documentatie/index.html @@ -0,0 +1,563 @@ + + + + + + +Documentatie - opdrachten, recepten, manifest, afsluitcodes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentatie

+

+ Alles wat de tool doet, geordend als de vragen waarmee mensen echt komen. De + README in de repository is de volledige referentie en komt altijd + overeen met de build die je hebt gedownload. +

+ +
+

Welke opdrachten zijn er?

+

Elke doet precies één ding:

+
tfg generate    bestanden maken, uit een recept of met opties
+tfg validate    een recept controleren en niets schrijven
+tfg verify      een map controleren tegen een manifest
+tfg cleanup     de bestanden verwijderen die een manifest opsomt
+tfg recipe fmt  een recept in zijn vaste vorm afdrukken
+tfg preset      een set bestanden bouwen uit een benoemde testvraag
+tfg formats     de formaten opsommen die deze build ondersteunt
+tfg damage      de manieren opsommen waarop deze build een bestand met opzet kan beschadigen
+tfg tool        kleine hulpmiddelen voor bestanden die je al hebt
+tfg version     de versie van de tool tonen
+tfg license     de licentie tonen en wat die betekent voor gegenereerde bestanden
+
+ +
+

Hoe genereer ik één bestand van een exacte grootte?

+

+ Noem het formaat, de grootte en waar het naartoe moet. Groottes tellen in 1024-tallen, dus + 2mb is 2097152 bytes. Een gewoon aantal bytes werkt ook, dus --size + 10485761 vraagt precies zoveel. +

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

De nuttige opties van generate:

+
+ + + + + + + + + + + + + + + + + +
OptieWat het doet
--format <id>formaat van de bestanden, bijvoorbeeld txt
--size <size>exacte grootte van elk bestand, zoals 10mb of een gewoon aantal bytes
--size-range <a-b>een grootte die per bestand uit een bereik wordt getrokken, zoals 1kb-8kb. De trekking komt uit de seed
--boundary <size>drie bestanden rond een limiet: één byte eronder, de limiet, één byte erboven
--count <n>hoeveel bestanden te maken. Standaard 1
--name <template>naamsjabloon, bijvoorbeeld invoice_{index:04}.txt
--out <dir>map om naartoe te schrijven
--seed <n>seed van de run. Dezelfde seed geeft dezelfde bytes
--set <k>=<v>een formaatinstelling, herhaalbaar
--damage <name>de bestanden met opzet beschadigen, herhaalbaar en in volgorde toegepast. Draai tfg damage voor de lijst
--expected <outcome>accept, reject, sanitize of unspecified
--dry-runtellen en tonen, helemaal niets schrijven
--jsonhet manifest naar de standaarduitvoer schrijven
+
+
+ +
+

Hoe maak ik een bestand dat met opzet kapot is?

+

+ Elk ander bestand dat deze tool schrijft is correct per constructie, wat twee van de drie vragen + beantwoordt die een uploadvalidator stelt. --damage beantwoordt de derde - gaat het + bestand überhaupt open. Het bestand wordt normaal gemaakt en daarna beschadigd, dus het heeft + nog steeds de grootte die je vroeg. +

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

+ Instellingen komen na een dubbele punt. De optie herhaalt zich, en de volgorde waarin je ze schrijft + is de volgorde waarin ze worden toegepast. tfg damage toont wat deze build kan en + wat elke variant accepteert. +

+

In een recept is de sleutel een lijst, van namen of van instellingen:

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

+ Een beschadigd bestand krijgt expected: reject in het manifest, met de beschadiging + ernaast vastgelegd. Twee dingen worden geweigerd voordat er iets wordt geschreven, omdat elk + anders een bestand op schijf zou zetten dat het manifest verkeerd beschrijft: +

+
    +
  • een bestand dat kleiner is dan de beschadiging nodig heeft, omdat het ongewijzigd zou uitkomen
  • +
  • + expected: accept naast een beschadiging, omdat niets daaraan kan voldoen. Schrijf + sanitize als het geteste systeem het bestand moet repareren, of + unspecified als dat de vraag is die je stelt +
  • +
+

+ Een derde is vooraf niet te weten. Als een beschadiging draait en geen enkele byte verschuift, wordt + dat bestand weggegooid in plaats van geschreven - de run gaat door, zegt om welk bestand het + ging en eindigt met de gedeeltelijke afsluitcode. +

+

+ Stap voor stap, met een test die het manifest leest: hoe + maak je een beschadigd bestand om mee te testen. +

+
+ +
+

Hoe ziet een recept eruit?

+

+ Een recept is een YAML-bestand dat een hele run beschrijft. Commit het naast je tests en de fixtures + zijn geen binaries meer in je repository - iedereen kan ze byte voor byte opnieuw opbouwen uit + een bestand van een paar honderd tekens. +

+
# 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
+

+ Elk target heeft precies één van deze sleutels nodig: size, size-range, + boundary of contains. Twee is een fout en geen ook. Een ongeldig + recept schrijft helemaal geen bestanden en meldt alle problemen tegelijk in + plaats van alleen het eerste, elk met de instelling waar het over gaat. +

+
+ +
+

Hoe leg ik vast wat mijn systeem met een bestand moet doen?

+

Korte vorm als de uitkomst genoeg is, lange vorm als de reden ertoe doet:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ De uitkomsten zijn accept, reject, sanitize en + unspecified. De redenen zijn een gesloten lijst zodat een rapport erop kan + groeperen: 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 en + size_zero. +

+

+ Een reden noemt de regel die in het spel is, niet het oordeel. Daarom kan dezelfde + reden onder beide uitkomsten staan - een bestand één byte onder een limiet is + accept, en de regel waar het om gaat is nog steeds size_limit. +

+
+ +
+

Wat staat er in het manifest?

+

+ Het wordt aan het einde van elke run naast de bestanden geschreven, ook bij een onderbroken run. Eén + item per bestand: +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Er komt een recipe_hash bij als de run uit een recept kwam, en preset met + overrides als hij uit een preset kwam, zodat een manifest altijd te herleiden is + tot wat het maakte. +

+

+ Elk item draagt ook target_id, de id van het target in het recept dat het bestand + maakte, en summary.by_target telt de bestanden waar elk target op uitkwam. Een + recept met meerdere targets kan zo target voor target worden gecontroleerd zonder bestandsnamen + te lezen. +

+
+ +
+

Wat is een preset?

+

+ Een kant-en-klare set bestanden die een veelvoorkomende testvraag beantwoordt, zodat je de set niet + zelf hoeft te ontwerpen. Presets zijn gewone recepten onder de motorkap, en eject + drukt het recept af zodat je het vanaf daar kunt bewerken. Elke preset heeft + een eigen pagina met wat hij meestal vindt, wat er in de set zit en + welke instellingen hij kent. +

+
    +
  • +

    Leeg en minimaal

    +

    Komt een geldig bestand dat zo klein is als het formaat toestaat door de controle?

    +

    empty-and-minimal

    +
  • +
  • +

    Omgaan met bestandsnamen

    +

    Slaat mijn systeem een bestandsnaam op, toont en geeft het die terug, ook als het die niet verwachtte?

    +

    filename-handling

    +
  • +
  • +

    Groottegrenzen

    +

    Wordt een groottelimiet precies afgedwongen waar hij is opgegeven?

    +

    size-boundaries

    +
  • +
  • +

    Tabelimport

    +

    Overleeft mijn tabelimport wat echte tools exporteren?

    +

    tabular-import

    +
  • +
  • +

    Tekencodering

    +

    Weet mijn lezer in welke codering een bestand staat, of gokt hij?

    +

    text-encoding

    +
  • +
  • +

    Uploadvalidatie

    +

    Neemt mijn uploadformulier aan wat het moet en weigert het de rest?

    +

    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 zegt je wat de set zou kosten voordat je hem bouwt, en zegt zonder omwegen wanneer + een getal een tijdelijke waarde van ons is in plaats van een limiet van jou. +

+
+ +
+

Wat betekenen de afsluitcodes?

+

+ Elk einde heeft zijn eigen code, machineleesbare uitvoer gaat naar de standaarduitvoer, en een + mislukte run drukt daar niets af. De tabel is een bevroren contract - de betekenis van een code + wijzigen vereist een major-versie. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeBetekenis
0Alles werkte.
1Een onverwachte fout in de tool.
2Verkeerde opdracht of optie.
3Het recept is niet geldig.
4Het formaat kan niet wat er gevraagd werd.
5Een lees- of schrijfactie is mislukt.
6Niet genoeg schijfruimte.
7verify vond een afwijking.
8De run is klaar, maar niet alles is gemaakt.
130Onderbroken met Ctrl+C.
143Gestopt door een signaal, zo ziet een CI-timeout eruit.
+
+
- 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
+

+ Een run die met Ctrl+C is gestopt laat nog steeds een manifest achter en nooit een half geschreven + bestand, zodat een afgebroken taak door de volgende nog kan worden opgeruimd. +

+

+ Kant-en-klare workflows voor GitHub Actions en GitLab CI: hoe + genereer je testbestanden in een CI-pipeline. +

+
+ +
+

Is er een bureaubladvenster?

+

+ Ja, dezelfde engine met een venster erop, voor het testen dat niet geautomatiseerd is. Het is geen + uitgeklede versie: een test vergelijkt de twee interfaces mogelijkheid voor mogelijkheid, en + alles wat maar één van beide kan moet worden verklaard en gerechtvaardigd in plaats van + ongemerkt uit elkaar te drijven. +

+

+ De schermen zijn één batch, presets, meerdere batches tegelijk en info. Het toont wat een run zou + kosten voordat er iets wordt geschreven, meldt de voortgang terwijl het draait en kan halverwege + worden afgebroken zonder een half geschreven bestand achter te laten. Het opent nog geen + receptbestand - recepten zijn voorlopig iets van de opdrachtregel, en het venster bouwt zijn + batches in het formulier. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/formaten/index.html b/web/public/nl/formaten/index.html new file mode 100644 index 00000000..f081d182 --- /dev/null +++ b/web/public/nl/formaten/index.html @@ -0,0 +1,913 @@ + + + + + + +26 ondersteunde bestandsformaten - PDF, DOCX, PNG, ZIP en meer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 bestandsformaten, elk gegenereerd in een exacte grootte

+

+ Elk daarvan is een echt bestand van dat formaat. Het opent in het programma waartoe + het behoort en is precies het aantal bytes dat je vroeg. Geen enkele is opgevulde nullen met een + extensie eraan geplakt. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormaatNaamExtensieKleinste bestandVolledigheidGecontroleerd met
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullniet van toepassing
mdMarkdown.md0fullniet van toepassing
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullniet van toepassing
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Wat de kolommen betekenen

+
    +
  • +

    Kleinste bestand

    +

    + Het minste aantal bytes dat deze tool voor dat formaat accepteert, inclusief het label dat hij in + het bestand schrijft. Vraag je minder, dan krijg je een fout die de ondergrens en de reden + noemt, nooit een bestand van de verkeerde grootte. +

    +
  • +
  • +

    Volledigheid

    +

    + Hoe volledig het bestand is. full betekent dat een lezer die het formaat echt parset + het accepteert, niet alleen dat de extensie klopt. +

    +
  • +
  • +

    Gecontroleerd met

    +

    + De onafhankelijke lezer die elk gegenereerd bestand opent voordat het formaat wordt uitgebracht - + een aparte implementatie, niet onze eigen code die haar eigen huiswerk nakijkt. +

    +
  • +
+

+ Elk formaat herhaalt zich ook tot op de byte: hetzelfde recept en dezelfde seed geven op elke + machine identieke bestanden, en daardoor is het veilig een recept te committen in plaats van de + fixtures zelf. +

+
+ +
+

Instellingen die elk formaat accepteert

+

+ De meeste formaten hebben eigen instellingen - afbeeldingsafmetingen, JPEG-kwaliteit, aantal + PDF-pagina's, rijen en kolommen in een spreadsheet, hoeveel items er in een archief zitten. Stel + ze in met --set key=value op de opdrachtregel, of onder properties: in + een recept. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormaatInstellingAccepteert
avifwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
bmpwidth1 - 20000 pixels
height1 - 20000 pixels
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerwaar of onwaar
quote_styleall, minimal, none
columns2 - 32768 kolommen
docxparagraphs1 - 50000 alinea's
gifwidth1 - 20000 pixels
height1 - 20000 pixels
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixels
height1 - 256 pixels
embedbmp, png
jpgwidth1 - 20000 pixels
height1 - 20000 pixels
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 items per seconde
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomwaar of onwaar
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlewillekeurige tekst
authorwillekeurige tekst
subjectwillekeurige tekst
keywordswillekeurige tekst
creatorwillekeurige tekst
producerwillekeurige tekst
createdeen datum zoals 2024-02-29 of 2024-02-29T13:45:00+02:00, of none
modifiedeen datum zoals 2024-02-29 of 2024-02-29T13:45:00+02:00, of none
pngwidth1 - 20000 pixels
height1 - 20000 pixels
pptxslides1 - 500 dia's
svgwidth1 - 20000 pixels
height1 - 20000 pixels
targzentries0 - 10000
entry_formatde id van een formaat, zoals tfg formats ze opsomt
entry_sizeeen grootte zoals 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entrieswaar of onwaar
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixels
height1 - 20000 pixels
txtencodingutf-16be, utf-16le, utf-8
bomwaar of onwaar
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixels
height1 - 16383 pixels
xlsxrows1 - 200000 rijen
columns1 - 32768 kolommen
xmlencodingutf-16be, utf-16le, utf-8
bomwaar of onwaar
zipentries0 - 10000
entry_formatde id van een formaat, zoals tfg formats ze opsomt
entry_sizeeen grootte zoals 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entrieswaar of onwaar
passwordhet wachtwoord, als platte tekst
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Een waarde buiten wat een instelling accepteert wordt geweigerd met een melding die de instelling, + het toegestane bereik en het alternatief noemt. Een onbekende instelling is ook een fout, nooit + een stille standaardwaarde - een stilzwijgend geaccepteerde typefout geeft een bestand met de + verkeerde instellingen en een uur zoeken waarom de test slaagt terwijl dat niet zou moeten. +

+

+ Draai tfg formats <id> om precies te zien wat één formaat accepteert in de build + die je hebt. +

+
+ +
+

Archieven bevatten echte bestanden

+

+ targz en zip + kunnen met items worden gevuld in plaats van als lege huls te blijven. Een gegenereerd archief + bevat echt de documenten die het zegt te bevatten, dus alles wat het tijdens een test uitpakt + vindt er echte bestanden in. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/index.html b/web/public/nl/index.html new file mode 100644 index 00000000..d1ea531b --- /dev/null +++ b/web/public/nl/index.html @@ -0,0 +1,453 @@ + + + + + + +Testbestanden genereren - exacte grootte, 26 echte formaten + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Genereer echte testbestanden in elke exacte grootte

+

+ PDF, PNG, DOCX, ZIP - 26 formaten in totaal, en elk is een + echt bestand dat opent in het programma waartoe het behoort, in precies de grootte die + je vroeg. Elke run schrijft ook op wat je applicatie met elk bestand moet doen. + Opdrachtregel en bureaubladvenster, gratis en open source, volledig op je eigen machine. +

+ + +

Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.

+
+ +
+ Het bureaubladvenster van Testing Files Generator, klaargezet om een reeks testbestanden te schrijven +
Het bureaubladvenster, klaargezet om een reeks bestanden te schrijven. Dezelfde engine draait achter de opdrachtregel.
+
+
+ +
    +
  • + 26 +

    echte formaten, elk opent in het programma waartoe het behoort

    +
  • +
  • + 1 byte +

    de nauwkeurigheid van elke grootte die je vraagt, nooit stilzwijgend afgerond

    +
  • +
  • + 0 +

    verbindingen naar wat dan ook - geen account, geen telemetrie, geen updatecontrole

    +
  • +
+ +
+

Het probleem

+

Eén testbestand maken is makkelijk. De juiste duizend maken is het vervelende deel

+

Je test software die bestanden van mensen aanneemt. Vroeg of laat heb je nodig:

+
    +
  • een PDF van precies 10 MB, om uit te zoeken of de uploadlimiet echt is
  • +
  • de drie bestanden aan weerszijden van die limiet, om off-by-one-fouten te vangen
  • +
  • 10.000 logbestanden, om te zien wat de nachtelijke taak doet als de map groot is
  • +
  • een ZIP die echt 200 documenten bevat, geen lege huls met de juiste extensie
  • +
  • een bestand van 4 GB, zonder een bestand van 4 GB in je repository te bewaren
  • +
  • dezelfde fixtures op je laptop en op de buildserver, byte voor byte
  • +
+

+ Dat is wat dit vervangt. Het is gebouwd voor QA-engineers, testautomatisering en iedereen wiens code + een uploadformulier, een importroutine, een parser of een opslagquotum achter zich heeft. +

+
+ +
+

Wat het anders maakt

+

Andere generatoren stoppen bij de bytes. Deze beantwoordt wat je test werkelijk vraagt

+

+ Een map met bestanden laat je nog steeds beslissen wat elk bestand moet bewijzen. Elke run schrijft + hier een manifest.json naast de bestanden - een eenvoudige lijst van alles wat is + gemaakt, en bij elk item een gedeclareerde verwachting. +

+

Stel dat je upload-endpoint 1 MB toestaat. Vraag de drie bestanden die op die lijn zitten:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
BestandBytesJe systeem moetOmdat
1mb_under_1b.pdf1048575accepterenhet valt binnen de limiet
1mb_at_limit.pdf1048576accepterende limiet zelf is toegestaan
1mb_over_1b.pdf1048577weigerensize_limit
+
+ +

Drie bestanden, drie verschillende antwoorden, in machineleesbare vorm. Je test leest het manifest in plaats van dat jij de asserties met de hand schrijft:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Waar het antwoord van je eigen beleid afhangt, zegt het manifest dat

+

+ Het legt unspecified vast in plaats van een verwachting te verzinnen. Een generator die + gokt levert valse fouten op, en een suite die loos alarm slaat wordt uitgezet. +

+
+
+ +
+

Presets

+

Kies de vraag, krijg de hele set

+

+ Een preset is een set testbestanden ontworpen rond één testvraag, zodat je zelf niet hoeft uit te + zoeken welke bestanden wat bewijzen. Elke heeft een pagina die zegt wat hij meestal vindt, wat + er in de set zit en welke instellingen hij kent. +

+
    +
  • +

    Leeg en minimaal

    +

    Komt een geldig bestand dat zo klein is als het formaat toestaat door de controle?

    +

    empty-and-minimal

    +
  • +
  • +

    Omgaan met bestandsnamen

    +

    Slaat mijn systeem een bestandsnaam op, toont en geeft het die terug, ook als het die niet verwachtte?

    +

    filename-handling

    +
  • +
  • +

    Groottegrenzen

    +

    Wordt een groottelimiet precies afgedwongen waar hij is opgegeven?

    +

    size-boundaries

    +
  • +
  • +

    Tabelimport

    +

    Overleeft mijn tabelimport wat echte tools exporteren?

    +

    tabular-import

    +
  • +
  • +

    Tekencodering

    +

    Weet mijn lezer in welke codering een bestand staat, of gokt hij?

    +

    text-encoding

    +
  • +
  • +

    Uploadvalidatie

    +

    Neemt mijn uploadformulier aan wat het moet en weigert het de rest?

    +

    upload-validation

    +
  • +
+

Alle presets, en hoe ze zich tot recepten verhouden

+
+ +
+

Snel starten

+

Drie opdrachten om het te zien werken

+
    +
  1. +

    Maak een bestand

    +

    Eén PNG, precies twee megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Maak veel bestanden

    +

    + Tienduizend logbestanden, elk tussen één en acht kilobyte, met groottes getrokken uit de seed zodat + morgen dezelfde set oplevert. Geef elke run een eigen map - het manifest is + het enige verslag van wat een run schreef, dus de tool weigert er een tweede overheen te + schrijven: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Controleer ze en verwijder ze dan

    +

    verify zegt je dat er niets verschoven is. cleanup verwijdert precies wat is geschreven en niets anders:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Groottes tellen in 1024-tallen, zoals je bestandsbeheer doet, dus 2mb betekent 2097152 + bytes. Een gewoon aantal bytes werkt ook. De documentatie + behandelt recepten, het manifest en de afsluitcodes. +

+
+ +
+

Wat je krijgt

+

Gebouwd voor een suite die onbeheerd draait

+
    +
  • +

    Exacte grootte, tot op de byte

    +

    Vraag 10485761 bytes en krijg precies dat. Een grootte die een formaat niet kan halen is een fout met een reden, nooit een bestand van de verkeerde grootte.

    +
  • +
  • +

    26 echte formaten

    +

    Geen opgevulde nullen met een extensie. Een gegenereerde PNG opent in een afbeeldingsviewer, een DOCX opent in Word, een ZIP pakt uit. Elk wordt vóór levering gecontroleerd met onafhankelijke lezers.

    +
  • +
  • +

    Een manifest dat een testorakel is

    +

    Pad, grootte, SHA-256, formaat, seed, toolversie - en wat je systeem met het bestand moet doen.

    +
  • +
  • +

    Reproduceerbaar

    +

    Hetzelfde recept en dezelfde seed, dezelfde bytes, op elke machine. Commit een klein YAML-recept in plaats van grote binaire fixtures.

    +
  • +
  • +

    Twee interfaces, één engine

    +

    Een opdrachtregel gebouwd voor CI en een bureaubladvenster voor verkennend testen. Geen van beide is een uitgeklede versie van de ander, en een test vergelijkt ze mogelijkheid voor mogelijkheid.

    +
  • +
  • +

    Volledig offline

    +

    Geen account, geen cloud, geen telemetrie, geen updatecontrole. In de opdrachtregel-binary is helemaal geen netwerkstack gecompileerd.

    +
  • +
+
+ +
+

Download

+

Kies de build voor je systeem

+

+ Pak het archief uit en start het. tfg is de opdrachtregel en tfg-gui is + het bureaubladvenster. Er is geen installatieprogramma en niets om aan je machine toe te voegen. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SysteemOpdrachtregelBureaubladvenster
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Wat is ondertekend, en wat niet

+

+ De downloads voor Windows en macOS zijn ondertekend, dus ze starten zonder waarschuwing over een + onbekende ontwikkelaar. Die voor Linux niet, omdat desktop-Linux niets vergelijkbaars heeft om + ze mee te ondertekenen. Elk archief staat in verify-SHA256SUMS.txt op de + releasepagina, zodat je kunt controleren wat je hebt gedownload. +

+
+ +

Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.

+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/empty-and-minimal/index.html b/web/public/nl/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..3bbc18d8 --- /dev/null +++ b/web/public/nl/presets/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +Kleinste geldige en lege testbestanden in elk formaat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Leeg en minimaal

+

Komt een geldig bestand dat zo klein is als het formaat toestaat door de controle?

+

+ De preset empty-and-minimal bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • een geldig bestand dat als te klein wordt geweigerd, omdat de controle bytes telt in plaats van ze te lezen
  • +
  • een leeg bestand dat de lezer laat crashen in plaats van gemeld te worden
  • +
  • een afbeelding van één pixel breed die op weg naar het miniatuur door nul deelt
  • +
  • opslag die nul bytes als een mislukte upload leest en blijft opnieuw proberen
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show empty-and-minimal het meldt:

+
+ + + + + + + +
Bestanden28
Targets in het recept28
Totale grootte32 667 B
Formatenavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.26
unspecifiedHet hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde.2
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--formatsformaat-id's gescheiden door komma's, of allallUit welke formaten de set is opgebouwd. Laat het op all staan voor elk formaat van deze build, of noem de formaten die je systeem accepteert.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/filename-handling/index.html b/web/public/nl/presets/filename-handling/index.html new file mode 100644 index 00000000..8b15b6e1 --- /dev/null +++ b/web/public/nl/presets/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Lastige bestandsnamen om te testen - Unicode en lengte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Omgaan met bestandsnamen

+

Slaat mijn systeem een bestandsnaam op, toont en geeft het die terug, ook als het die niet verwachtte?

+

+ De preset filename-handling bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • een naam die er op het scherm, in een log of in een lijst als een andere uitziet
  • +
  • een naam die tussen upload en opslag wordt afgekapt, ingekort of herschreven
  • +
  • een lengtelimiet die in tekens wordt geteld waar de opslag bytes telt
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show filename-handling het meldt:

+
+ + + + + + + +
Bestanden50
Targets in het recept50
Totale grootte51 200 B
Formatentxt
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.4
unspecifiedHet hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde.46
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--formateen formaat-id van de pagina met formatentxtHet formaat van elk bestand in de set. Het is een optie van de tool zelf, en de preset geeft er alleen een standaardwaarde aan.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/index.html b/web/public/nl/presets/index.html new file mode 100644 index 00000000..c6109eca --- /dev/null +++ b/web/public/nl/presets/index.html @@ -0,0 +1,244 @@ + + + + + + +Presets voor testbestanden - kant-en-klare sets voor QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Presets voor testbestanden, een set voor elke testvraag

+

+ Een preset is een hele set testbestanden ontworpen rond één vraag, met een manifest dat zegt hoe je + systeem op elk bestand moet reageren. Jij kiest de vraag, de tool bouwt de set. Elke preset heeft + een eigen pagina met wat hij meestal vindt, wat er in de set zit en welke instellingen hij kent. +

+ +
    +
  • +

    Leeg en minimaal

    +

    Komt een geldig bestand dat zo klein is als het formaat toestaat door de controle?

    +

    empty-and-minimal

    +
  • +
  • +

    Omgaan met bestandsnamen

    +

    Slaat mijn systeem een bestandsnaam op, toont en geeft het die terug, ook als het die niet verwachtte?

    +

    filename-handling

    +
  • +
  • +

    Groottegrenzen

    +

    Wordt een groottelimiet precies afgedwongen waar hij is opgegeven?

    +

    size-boundaries

    +
  • +
  • +

    Tabelimport

    +

    Overleeft mijn tabelimport wat echte tools exporteren?

    +

    tabular-import

    +
  • +
  • +

    Tekencodering

    +

    Weet mijn lezer in welke codering een bestand staat, of gokt hij?

    +

    text-encoding

    +
  • +
  • +

    Uploadvalidatie

    +

    Neemt mijn uploadformulier aan wat het moet en weigert het de rest?

    +

    upload-validation

    +
  • +
+ +
+

Hoe verschilt een preset van een recept?

+

+ Eronder niet. Een preset is een recept dat de tool voor je schrijft uit een paar instellingen. + tfg preset eject drukt dat recept af zodat je het naast je tests kunt bewaren en + bewerken, en een eigen recept kan met één regel op een preset voortbouwen, extends: + preset: gevolgd door zijn id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Kan ik de standaardwaarden vertrouwen?

+

+ Voor de bestanden wel. Voor een getal dat alleen je systeem kent, zoals de limiet van een + uploadformulier, is een standaardwaarde een tijdelijke waarde van ons, en de tool zegt dat elke + keer dat hij er een gebruikt. De pagina van elke preset markeert die instellingen, en tfg + preset show zegt het voordat er iets wordt geschreven. +

+
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/size-boundaries/index.html b/web/public/nl/presets/size-boundaries/index.html new file mode 100644 index 00000000..e7884e6c --- /dev/null +++ b/web/public/nl/presets/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Een uploadlimiet testen - bestanden precies op de grens + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Groottegrenzen

+

Wordt een groottelimiet precies afgedwongen waar hij is opgegeven?

+

+ De preset size-boundaries bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • off-by-one-fouten bij de limiet
  • +
  • MB verward met MiB, wat 4,8 procent is en genoeg om een bestand door te laten dat niet door zou mogen
  • +
  • een limiet die in de browser wordt afgedwongen en niet op de server
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show size-boundaries het meldt:

+
+ + + + + + + +
Bestanden7
Targets in het recept7
Totale grootte73 400 320 B
Formatenpdf
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.4
rejectJe systeem moet het bestand weigeren.3
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--limiteen grootte zoals 2mb10mbDe groottelimiet die je systeem opgeeft. Al het andere wordt hiervan afgemeten. Deze standaardwaarde is onze tijdelijke waarde, niet de waarde van je systeem. Geef je eigen op.
--spreadgroottes gescheiden door komma's1B,1kb,1mbHoe ver aan beide kanten van de limiet te gaan, als een lijst met groottes.
--formateen formaat-id van de pagina met formatenpdfHet formaat van elk bestand in de set. Het is een optie van de tool zelf, en de preset geeft er alleen een standaardwaarde aan.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

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

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/tabular-import/index.html b/web/public/nl/presets/tabular-import/index.html new file mode 100644 index 00000000..e3698f26 --- /dev/null +++ b/web/public/nl/presets/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +Testbestanden voor CSV- en Excel-import - scheidingstekens + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Tabelimport

+

Overleeft mijn tabelimport wat echte tools exporteren?

+

+ De preset tabular-import bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • een bestand met puntkomma's dat als één kolom wordt gelezen, omdat het scheidingsteken is aangenomen in plaats van gezocht
  • +
  • een CRLF-bestand dat in rijen wordt gesplitst met na elke rij een lege rij
  • +
  • een tabel zonder koprij waarvan de eerste gegevensrij als kolomnamen wordt opgegeten
  • +
  • een import die de kolommen houdt die hij kan tonen en de rest zonder een woord weggooit
  • +
  • een lezer die JSON-records regel voor regel leest en stopt bij het eerste ingesprongen document
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show tabular-import het meldt:

+
+ + + + + + + +
Bestanden13
Targets in het recept13
Totale grootte3 080 060 B
Formatencsv, json, xlsx
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.8
unspecifiedHet hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde.5
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--rows1 - 200000 rijen1000Hoeveel rijen de spreadsheet bevat. Het bestand wordt precies zo groot geschreven als zoveel rijen verpakt worden, dus het budget hierboven verschuift met deze waarde.
--columns1 - 32768 kolommen10Hoeveel kolommen elke rij van de spreadsheet heeft. Rijen maal kolommen heeft een plafond, en erboven vragen wordt geweigerd voordat er iets geschreven wordt.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/text-encoding/index.html b/web/public/nl/presets/text-encoding/index.html new file mode 100644 index 00000000..d8af732a --- /dev/null +++ b/web/public/nl/presets/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +Testbestanden voor tekencodering - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Tekencodering

+

Weet mijn lezer in welke codering een bestand staat, of gokt hij?

+

+ De preset text-encoding bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • een lezer die UTF-8 aanneemt en een UTF-16-bestand toont als één teken op de drie, of als rijen vakjes
  • +
  • een byte order mark die als inhoud wordt gelezen, zodat het eerste veld van een import met drie vreemde tekens begint
  • +
  • een importeur die de codering uit de eerste bytes raadt en bij een langer bestand anders raadt
  • +
  • een CRLF-bestand dat in rijen wordt gesplitst met na elke rij een lege rij, of een regelterugloop die in het laatste veld blijft staan
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show text-encoding het meldt:

+
+ + + + + + + +
Bestanden20
Targets in het recept20
Totale grootte81 920 B
Formatencsv, log, md, txt, xml
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.10
unspecifiedHet hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde.10
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--sampleeen grootte zoals 2mb4kbHoe groot elk bestand van de set is. UTF-16 slaat twee bytes per teken op, dus een oneven getal wordt geweigerd.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/presets/upload-validation/index.html b/web/public/nl/presets/upload-validation/index.html new file mode 100644 index 00000000..b495d395 --- /dev/null +++ b/web/public/nl/presets/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +Testbestanden voor uploadvalidatie - type, grootte en naam + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Uploadvalidatie

+

Neemt mijn uploadformulier aan wat het moet en weigert het de rest?

+

+ De preset upload-validation bouwt met één opdracht een hele set echte testbestanden voor deze + vraag, en een manifest.json ernaast dat zegt hoe je systeem op elk bestand moet + reageren. Alles hieronder wordt uit het programma gelezen, bij de standaardwaarden van deze + versie. +

+ + +
+

Wat vindt hij meestal?

+
    +
  • een limiet die in de browser wordt afgedwongen en niet op de server
  • +
  • een SVG- of HTML-bestand dat voor een afbeelding of platte tekst wordt aangezien, een manier om een script langs een formulier te smokkelen
  • +
  • een bestand dat op extensie wordt gecontroleerd en nooit geopend, zodat een PDF met de naam .jpg erdoor komt
  • +
  • een formulier dat de hele body in het geheugen leest voordat het kijkt hoe groot hij is
  • +
  • een upload met de naam PHOTO.JPG die wordt geweigerd terwijl photo.jpg wordt aangenomen, of andersom
  • +
  • een naam met spaties, haakjes of tekens buiten ASCII die ongewijzigd naar schijf wordt geschreven
  • +
+
+ + +
+

Wat zit er in de set?

+

Bij de standaardwaarden, zoals tfg preset show upload-validation het meldt:

+
+ + + + + + + +
Bestanden71
Targets in het recept22
Totale grootte120 639 488 B
Formatenhtml, jpg, pdf, png, svg, txt
+
+

En wat het manifest van die set van je systeem verwacht:

+
+ + + + + + + + + +
VerwachtBetekenisBestanden
acceptJe systeem moet het bestand aannemen.56
rejectJe systeem moet het bestand weigeren.10
unspecifiedHet hangt af van de regels van je systeem. Jij beslist, en controleert daarna of wat er gebeurt is wat je bedoelde.5
+
+
+ +
+

Wat kun je wijzigen?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InstellingAccepteertStandaardWat het doet
--limiteen grootte zoals 2mb10mbDe groottelimiet die je uploadformulier opgeeft. Deze set zet één stap aan beide kanten - voor een bestand op elke afstand draai je de preset size-boundaries. Deze standaardwaarde is onze tijdelijke waarde, niet de waarde van je systeem. Geef je eigen op.
--allowformaat-id's gescheiden door komma'sjpg,png,pdfWelke typen je formulier moet accepteren. Elk wordt een echt bestand van dat type, en ze vormen de positieve controle van de hele set.
--denyextensies gescheiden door komma'ssvg,html,exe,shWelke extensies je formulier moet weigeren. Een extensie waarvoor deze build geen formaat heeft, krijgt toch een bestand met die naam, met platte tekst erin.
--far-over10x, 2x, off2xHoe ver boven de limiet het ene grote bestand komt. Zet het uit waar het schrijven van een veelvoud van de limiet de schijfruimte niet waard is.
--bulk0 - 10000 bestanden50Hoeveel bestanden de bulkupload bevat. Nul laat die groep helemaal uit de set.
+
+
+ +
+

Hoe draai je hem?

+

Bekijk wat de set zou kosten, bouw hem, of neem zijn recept om te bewerken:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Of bouw erop voort in een eigen recept, naast je tests:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ +
+ + +
+ + diff --git a/web/public/nl/testbestanden-in-ci/index.html b/web/public/nl/testbestanden-in-ci/index.html new file mode 100644 index 00000000..02443cfc --- /dev/null +++ b/web/public/nl/testbestanden-in-ci/index.html @@ -0,0 +1,380 @@ + + + + + + +Testbestanden in CI - GitHub Actions, GitLab CI en PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Toepassingen

+

Hoe genereer je testbestanden in een CI-pipeline

+

+ Een binaire fixture in een repository blijft voorgoed in de geschiedenis, kan niet in een diff + worden beoordeeld en wordt onmogelijk zodra het bestand groot is. Genereer de bestanden in plaats + daarvan in de pipeline uit een recept. Het recept is tekst, de bytes komen elke keer hetzelfde uit + en een laatste stap bewijst dat er niets is veranderd. +

+ +
+

Het korte antwoord

+

+ Installeer tfg, voer vóór de tests tfg generate fixtures.yaml --out + ./fixtures uit en erna tfg verify ./fixtures/manifest.json. Beide stappen + laten de build vanzelf mislukken, met een afsluitcode die zegt waarom. +

+
+ +
+

Waarom niet committen

+

Waarom een fixture niet in de repository hoort

+
    +
  • + Het blijft in de geschiedenis. Een binair bestand later verwijderen maakt een kloon + niet kleiner, want elke versie ervan staat er nog. +
  • +
  • + Een diff laat niet zien wat er veranderde. De reviewer ziet dat een PDF anders is + en verder niets. Een recept verandert met één regel. +
  • +
  • + Grote bestanden passen niet. GitHub weigert een push met een bestand van meer dan + 100 MB, dus voor een test van een uploadlimiet van 500 MB valt er niets te committen. +
  • +
+

+ Het recept is wat je commit. Hetzelfde recept en dezelfde seed schrijven op elke machine dezelfde + bytes, dus het bestand dat in de pipeline wordt gegenereerd is het bestand dat je op je laptop + had. +

+
+ +
+

Het recept

+

Een recept dat naast de tests staat

+

+ Dit schrijft vijfentwintig facturen die geaccepteerd moeten worden en twee afbeeldingen boven een + limiet die geweigerd moeten worden, en het manifest legt beide verwachtingen vast: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml controleert het zonder iets te schrijven en noemt alle + problemen tegelijk. +

+
+ +
+

GitHub Actions

+

Een workflow die de tool installeert en de fixtures bouwt

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ De regel met de controlesom vergelijkt het archief met verify-SHA256SUMS.txt uit + dezelfde release. De versie is vastgezet, dus een nieuwe release verandert nooit een build die + je niet hebt aangeraakt. +

+
+ +
+

GitLab CI

+

Hetzelfde als GitLab-job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Wanneer het rood wordt

+

Wat een stap laat mislukken, en waarom

+

+ Elk einde heeft zijn eigen afsluitcode, dus de stap mislukt vanzelf en het log zegt welke. De codes + die een pipeline tegenkomt: +

+
    +
  • 3 - het recept is niet geldig. Er is niets geschreven en elk probleem wordt genoemd
  • +
  • 4 - het formaat kan niet wat er gevraagd werd, bijvoorbeeld een grootte onder zijn minimum
  • +
  • 6 - er is niet genoeg schijfruimte
  • +
  • 7 - tfg verify vond een bestand dat niet bij zijn manifest past
  • +
  • 8 - de run is klaar, maar niet alles is gemaakt
  • +
+

+ Een mislukte run drukt niets af op de standaarduitvoer, zodat een logparser een fout nooit voor data + aanziet. De hele tabel staat op de documentatiepagina. +

+
+ +
+

PowerShell

+

Een PowerShell-script heeft nog één regel nodig

+

+ PowerShell neemt de afsluitcode van een programma niet mee uit een .ps1-bestand. Start + er een met -File en het script antwoordt 0, ook als de tool erin het + werk weigerde, waardoor een build die rood hoort te zijn groen wordt. De laatste regel is de + hele oplossing: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Zo gedraagt PowerShell zich, het ligt niet aan deze tool. cmd, bash en + zsh hebben niets extra nodig. +

+
+ +
+

Meerdere jobs

+

De fixtures delen tussen jobs

+

+ Uploaden is meestal niet nodig. Omdat hetzelfde recept dezelfde bytes schrijft, kan elke job zijn + eigen tfg generate uitvoeren, wat sneller is dan uploaden en downloaden. Moet een + job bestanden van een andere ontvangen, voer dan na de overdracht tfg verify uit op + het manifest, en het zegt of wat aankwam is wat werd geschreven. +

+
+ +
+

Verder

+

Waar je vandaar heen kunt

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/toepassingen/index.html b/web/public/nl/toepassingen/index.html new file mode 100644 index 00000000..f4f73c9a --- /dev/null +++ b/web/public/nl/toepassingen/index.html @@ -0,0 +1,318 @@ + + + + + + +Toepassingen - uploadlimieten, CI-fixtures, massatests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Waar mensen het voor gebruiken

+

+ Vijf taken die in bijna elk project voorkomen dat bestanden van mensen aanneemt, en de opdracht die + elk doet. Elk voorbeeld hieronder werkt zoals het is geschreven. +

+ +
+

Uploadlimieten

+

Testen of een limiet voor bestandsgrootte wordt afgedwongen waar hij zegt dat hij dat doet

+

+ Een limiet is drie testgevallen, niet één: net eronder, precies erop en net erboven. Die met de hand + maken betekent bytetellingen uitrekenen en hopen dat je er niet één naast zit. Vraag in plaats + daarvan de set: +

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

+ Je krijgt drie echte PDF's van 1048575, 1048576 en 1048577 bytes, en een manifest dat zegt dat de + eerste twee geaccepteerd moeten worden en de derde geweigerd wegens size_limit. Je + test leest de verwachting in plaats van dat jij drie asserties met de hand schrijft - en als de + limiet verandert, wijzig je één getal en draai je opnieuw. +

+

+ Hetzelfde werkt zonder preset als je één set grenzen inline wilt: +

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

Continuous integration

+

Fixtures uit de repository houden zonder ze kwijt te raken

+

+ Grote binaire fixtures maken een repository traag om te klonen en lastig te reviewen, en niemand kan + zien wat er veranderde toen er een werd vervangen. Een recept is een paar honderd tekens YAML + die de identieke bestanden opnieuw opbouwen - byte voor byte, op elke machine - + omdat elk bestand is afgeleid van de seed van de run. +

+
- 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
+

+ Elk einde heeft zijn eigen afsluitcode, dus een pipeline kan een slecht recept onderscheiden van een + volle schijf en van een afwijking bij verificatie. Een mislukte run drukt niets af op de + standaarduitvoer, waardoor een logparser een fout niet als gegevens leest. +

+
+ +
+

Schaal

+

Uitzoeken wat er gebeurt als de map groot is

+

+ Importroutines, nachtelijke taken en maplijsten gedragen zich anders bij tienduizend bestanden dan + bij tien. Groottes getrokken uit een bereik laten de set op echt verkeer lijken in plaats van op + tienduizend identieke bestanden, en de trekking komt uit de seed, dus de set is morgen dezelfde. +

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

+ Bekijk wat een run zou kosten voordat hij iets schrijft, wat telt als het totaal in gigabytes wordt + gemeten: +

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

+ Een run die groter is dan de vrije ruimte op de schijf wordt geweigerd voordat de eerste byte is + geschreven, in plaats van de schijf te vullen en halverwege te falen. +

+
+ +
+

Archieven

+

Een uitpakprogramma testen met een archief dat echt bestanden bevat

+

+ Een leeg archief met de juiste extensie bewijst niets over code die het opent en doorloopt wat erin + zit. Declareer de inhoud en het archief bevat die echt: +

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

+ Nestdiepte, aantal items en de grootte van wat erin zit zijn allemaal dingen waar een importroutine + een mening over heeft, en zo kom je erachter wat die meningen zijn. +

+
+ +
+

Parsers en viewers

+

Controleren dat je eigen code een formaat leest zoals echte software dat doet

+

+ Elk formaat hier wordt vóór levering gecontroleerd met een onafhankelijke lezer - een PNG wordt + geopend en de pixels worden vergeleken, een DOCX wordt teruggelezen door aparte bibliotheken, + een archief wordt uitgepakt. Dat betekent dat een bestand dat je parser weigert een bevinding is + over je parser, niet over de 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
+

+ De pagina met formaten toont de instellingen die elk accepteert en het + kleinste bestand dat elk kan zijn. +

+
+ +
+

Handleidingen

+

Twee hiervan in detail

+
    +
  • + Beschadigde testbestanden - een bestand dat met opzet + kapot is, op exacte grootte, met in het manifest wat ermee moet gebeuren. +
  • +
  • + Testbestanden in CI - een GitHub Actions-workflow, een + GitLab-job en de afsluitcodes die een build laten mislukken. +
  • +
+
+ +
+

Voor wie dit is

+

+ QA-engineers, testautomatisering en iedereen wiens code een uploadformulier, een importroutine, een + parser of een opslagquotum achter zich heeft. Het draait op een machine zonder enig netwerk, wat + telt in een afgesloten bedrijfsomgeving waar een generator in de browser geen optie is. +

+ +

Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/nl/veelgestelde-vragen/index.html b/web/public/nl/veelgestelde-vragen/index.html new file mode 100644 index 00000000..bdf220c0 --- /dev/null +++ b/web/public/nl/veelgestelde-vragen/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - vragen over het genereren van testbestanden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Veelgestelde vragen

+

+ Licentie, privacy, reproduceerbaarheid en de dingen die mensen nagaan voordat ze een generator in + een buildpipeline zetten. Staat je vraag er niet bij, dan staat de + issuetracker open. +

+ +
+
+

Waarin verschilt dit van dd, fsutil of truncate?

+
+

Die geven je een bestand van de juiste grootte vol met niets. Een bestand van 2 MB met de naam photo.png dat zo is gemaakt is geen PNG, dus alles wat het echt parset weigert het om de verkeerde reden, en je test slaagt dan ook om de verkeerde reden. Dit maakt een echte PNG van precies 2 MB die opent in een afbeeldingsviewer, en komt met een verklaring over hoe je systeem ermee om moet gaan.

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

Is het gratis, en mag ik het op het werk gebruiken?

+
+

Ja op beide. Het is uitgebracht onder de GPL-3.0 en kost niets. Er is geen account, geen licentiesleutel en geen betaalde variant.

+
+
+
+

Mag ik de gegenereerde bestanden in een closed source product gebruiken?

+
+

Ja. De licentie geldt voor de code van de tool, niet voor wat de tool produceert. Gegenereerde bestanden, recepten en manifesten zijn uitvoer en geen afgeleide werken, dus je kunt ze committen en verspreiden zonder enige verplichting.

+
+
+
+

Bevatten de gegenereerde bestanden echte persoonsgegevens?

+
+

Nee. Alles erin wordt gesynthetiseerd uit een seed. Er wordt geen dataset gelezen, geen dienst benaderd en geen inhoud van derden ingebed. Behandel een gegenereerd e-mailadres als onbruikbaar in plaats van als ongebruikt, want elke willekeurige tekenreeks kan bij toeval samenvallen met een echte.

+
+
+
+

Krijg ik op een andere machine precies dezelfde bestanden?

+
+

Ja, byte voor byte, bij hetzelfde recept en dezelfde seed. Het project test dat bij elke wijziging, en het breken ervan vereist een major-versie. Daardoor kun je een klein recept committen in plaats van grote binaire fixtures.

+
+
+
+

Heeft het een internetverbinding nodig?

+
+

Nooit. Er is geen telemetrie, geen updatecontrole en geen cloudclient, en in de opdrachtregel-binary is helemaal geen netwerkstack gecompileerd. Het werkt op een machine zonder netwerk en binnen een afgesloten bedrijfsomgeving.

+
+
+
+

Wat gebeurt er als ik een grootte vraag die een formaat niet kan halen?

+
+

Je krijgt een fout die het formaat noemt, de kleinst mogelijke grootte, de reden voor die ondergrens en wat je in plaats daarvan kunt doen, en er wordt geen bestand geschreven. De tool rondt een grootte nooit stilzwijgend af. Elke ondergrens staat op de pagina met formaten.

+
tfg formats png
+
+
+
+

Kan ik een bewust kapot bestand genereren?

+
+

Ja. Voeg --damage zero-head toe en het bestand komt uit op precies de gevraagde grootte, met de eerste bytes overschreven door nullen, zodat een lezer het weigert, en het manifest zegt dat je systeem het moet weigeren. De details staan op de pagina over beschadigde testbestanden.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Welke formaten komen er nog?

+
+

7z, mp3 en mp4. Vandaag werken 26 formaten van begin tot eind.

+
+
+
+

Op welke systemen kan ik het draaien?

+
+

De opdrachtregel draait op Windows en Linux, zowel op Intel als op ARM, en op Macs met Apple Silicon. Het bureaubladvenster wordt geleverd voor Windows op Intel, Linux op Intel en Macs met Apple Silicon. Intel-Macs worden niet ondersteund en daar wordt niets voor gebouwd.

+
+
+
+

Moet ik iets installeren?

+
+

Nee. Download het archief voor je systeem, pak het uit en start de binary. Er is geen installatieprogramma, geen runtime om toe te voegen en geen afhankelijkheid om op te lossen. Als je Go hebt, werkt ook één enkele go install-opdracht.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Waarom is een run over duizenden bestanden trager op Windows?

+
+

Omdat Windows meer rekent voor elk pad dat het bekijkt, en een opdracht die over duizenden bestanden gaat bekijkt duizenden paden. Gemeten op één machine met 3000 bestanden van 1 kB doet verify er ongeveer 0,9 seconde over op Windows en ongeveer 0,2 seconde op Linux in een container. Een korter uitvoerpad maakt het cijfer voor Windows kleiner, omdat elke map boven de bestanden deel uitmaakt van wat wordt bekeken.

+
+
+
+ + +
+

Nog aan het twijfelen?

+

+ De pagina met toepassingen toont de taken waarvoor het is gebouwd, + en de pagina met formaten toont elk formaat met het kleinste bestand + dat het kan maken. De README in de repository is de volledige + referentie. +

+ +

Gratis en open source, GPL-3.0. Geen account nodig. De downloads voor Windows en macOS zijn ondertekend en starten zonder waarschuwing.

+
+ +
+ +
+ + +
+ + diff --git a/web/public/pl/dokumentacja/index.html b/web/public/pl/dokumentacja/index.html index 2dce6de2..81535d27 100644 --- a/web/public/pl/dokumentacja/index.html +++ b/web/public/pl/dokumentacja/index.html @@ -3,15 +3,36 @@ + Dokumentacja - komendy, przepisy, manifest, kody wyjścia + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
@@ -172,6 +239,9 @@

Jak zrobić plik celowo zepsuty?

jednego bajtu, taki plik zostaje odrzucony zamiast zapisany - przebieg idzie dalej, mówi, którego pliku to dotyczyło, i kończy się kodem częściowego wyniku.

+

+ Krok po kroku, z testem czytającym manifest: jak zrobić uszkodzony plik do testów. +

@@ -428,6 +498,9 @@

Co znaczą kody wyjścia?

Przebieg zatrzymany przez Ctrl+C i tak zostawia manifest i nigdy nie zostawia pliku zapisanego w połowie, więc anulowane zadanie da się posprzątać następnym.

+

+ Gotowe workflow dla GitHub Actions i GitLab CI: jak generować pliki testowe w potoku CI. +

diff --git a/web/public/pl/faq/index.html b/web/public/pl/faq/index.html index 81236616..51ee18fe 100644 --- a/web/public/pl/faq/index.html +++ b/web/public/pl/faq/index.html @@ -3,15 +3,36 @@ + FAQ - pytania o generowanie plików testowych + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
@@ -130,7 +197,8 @@

Najczęstsze pytania

Czy mogę wygenerować plik celowo uszkodzony?

-

Jeszcze nie. Pliki uszkodzone i niepoprawne są zaplanowaną funkcją. Dziś każdy plik, który narzędzie zapisuje, jest poprawnym plikiem swojego formatu.

+

Tak. Dodaj --damage zero-head, a plik wyjdzie dokładnie o podanym rozmiarze, z pierwszymi bajtami nadpisanymi zerami, więc czytnik go odrzuci, a manifest powie, że system powinien go odrzucić. Szczegóły są na stronie o uszkodzonych plikach testowych.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
@@ -202,7 +270,7 @@

Najczęstsze pytania

{ "@type": "Question", "name": "Czy mogę wygenerować plik celowo uszkodzony?", - "acceptedAnswer": { "@type": "Answer", "text": "Jeszcze nie. Pliki uszkodzone i niepoprawne są zaplanowaną funkcją. Dziś każdy plik, który narzędzie zapisuje, jest poprawnym plikiem swojego formatu." } + "acceptedAnswer": { "@type": "Answer", "text": "Tak. Dodaj --damage zero-head, a plik wyjdzie dokładnie o podanym rozmiarze, z pierwszymi bajtami nadpisanymi zerami, więc czytnik go odrzuci, a manifest powie, że system powinien go odrzucić. Szczegóły są na stronie o uszkodzonych plikach testowych." } }, { "@type": "Question", diff --git a/web/public/pl/formaty/index.html b/web/public/pl/formaty/index.html index d2599df3..29508445 100644 --- a/web/public/pl/formaty/index.html +++ b/web/public/pl/formaty/index.html @@ -3,15 +3,36 @@ + 26 formatów plików testowych - PDF, DOCX, PNG, ZIP + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/index.html b/web/public/pl/index.html index 11f34f97..53c412c7 100644 --- a/web/public/pl/index.html +++ b/web/public/pl/index.html @@ -3,15 +3,36 @@ + Generator plików testowych o zadanym rozmiarze - 26 formatów + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -77,9 +118,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/plik-o-zadanym-rozmiarze/index.html b/web/public/pl/plik-o-zadanym-rozmiarze/index.html index 35742895..f712b68c 100644 --- a/web/public/pl/plik-o-zadanym-rozmiarze/index.html +++ b/web/public/pl/plik-o-zadanym-rozmiarze/index.html @@ -3,15 +3,36 @@ + Jak stworzyć plik o określonym rozmiarze + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/pliki-testowe-w-ci/index.html b/web/public/pl/pliki-testowe-w-ci/index.html new file mode 100644 index 00000000..e3b6abd3 --- /dev/null +++ b/web/public/pl/pliki-testowe-w-ci/index.html @@ -0,0 +1,376 @@ + + + + + + +Pliki testowe w CI - GitHub Actions, GitLab CI i PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Zastosowania

+

Jak generować pliki testowe w potoku CI

+

+ Binarny plik testowy w repozytorium zostaje w jego historii na zawsze, nie da się go ocenić w + różnicach i przestaje być możliwy, gdy plik jest duży. Zamiast tego generuj pliki w potoku z + przepisu. Przepis jest tekstem, bajty wychodzą za każdym razem takie same, a ostatni krok dowodzi, + że nic się nie ruszyło. +

+ +
+

Krótka odpowiedź

+

+ Zainstaluj tfg, uruchom tfg generate fixtures.yaml --out ./fixtures przed + testami, a tfg verify ./fixtures/manifest.json po nich. Oba kroki same przerywają + build, z kodem wyjścia mówiącym dlaczego. +

+
+ +
+

Dlaczego nie commitować

+

Dlaczego pliku testowego nie powinno być w repozytorium

+
    +
  • + Zostaje w historii. Usunięcie pliku binarnego później nie zmniejsza klonu, bo każda + jego wersja nadal tam jest. +
  • +
  • + Różnice nie pokażą, co się zmieniło. Recenzent widzi, że PDF jest inny, i nic + więcej. Przepis zmienia się o jedną linię. +
  • +
  • + Duże pliki się nie mieszczą. GitHub odrzuca push z plikiem większym niż 100 MB, + więc test limitu uploadu 500 MB nie ma czego commitować. +
  • +
+

+ Commitować trzeba przepis. Ten sam przepis i ziarno zapisują te same bajty na każdej maszynie, więc + plik wygenerowany w potoku jest tym plikiem, który miałeś na laptopie. +

+
+ +
+

Przepis

+

Przepis, który leży obok testów

+

+ Ten zapisuje dwadzieścia pięć faktur, które powinny zostać przyjęte, i dwa obrazy ponad limitem, + które powinny zostać odrzucone, a manifest zapisuje oba oczekiwania: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml sprawdza go, nic nie zapisując, i od razu wymienia każdy + problem. +

+
+ +
+

GitHub Actions

+

Workflow, który instaluje narzędzie i buduje pliki testowe

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Wiersz z sumą kontrolną porównuje archiwum z verify-SHA256SUMS.txt z tego samego + wydania. Wersja jest przypięta, więc nowe wydanie nigdy nie zmieni buildu, którego nie ruszałeś. +

+
+ +
+

GitLab CI

+

To samo jako zadanie GitLaba

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Gdy robi się czerwono

+

Co przerywa krok i dlaczego

+

+ Każde zakończenie ma własny kod wyjścia, więc krok sam się przerywa, a log mówi, który to był. Te, + które spotyka potok: +

+
    +
  • 3 - przepis jest niepoprawny. Nic nie zapisano, a każdy problem jest nazwany
  • +
  • 4 - format nie potrafi tego, o co poproszono, na przykład rozmiaru poniżej swojego najmniejszego
  • +
  • 6 - brakuje miejsca na dysku
  • +
  • 7 - tfg verify znalazł plik, który nie zgadza się z manifestem
  • +
  • 8 - przebieg się skończył, ale nie wszystko powstało
  • +
+

+ Nieudany przebieg nie wypisuje niczego na standardowe wyjście, więc parser logów nigdy nie weźmie + błędu za dane. Cała tabela jest na stronie dokumentacji. +

+
+ +
+

PowerShell

+

Skrypt PowerShella potrzebuje jeszcze jednej linii

+

+ PowerShell nie wynosi kodu wyjścia programu poza plik .ps1. Uruchom go z + -File, a skrypt odpowie 0, nawet gdy narzędzie w środku odmówiło + pracy, więc build, który powinien być czerwony, robi się zielony. Ostatnia linia to cała + poprawka: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Tak zachowuje się PowerShell, a nie to narzędzie. cmd, bash i + zsh nie potrzebują niczego więcej. +

+
+ +
+

Kilka zadań

+

Przekazywanie plików testowych między zadaniami

+

+ Zwykle nie trzeba ich wysyłać. Skoro ten sam przepis zapisuje te same bajty, każde zadanie może + uruchomić własne tfg generate, co jest szybsze niż wysyłanie i pobieranie. Gdy + zadanie musi dostać pliki z innego, uruchom tfg verify na manifeście po przesłaniu, + a powie, czy to, co dotarło, jest tym, co zapisano. +

+
+ +
+

Dalej

+

Dokąd pójść stąd

+
    +
  • + Uszkodzone pliki testowe dokładają do tego samego + przepisu pliki zepsute celowo. +
  • +
  • + Zastosowania pokazują, co jeszcze może sprawdzić przebieg w potoku. +
  • +
  • + Dokumentacja ma każde polecenie, klucz przepisu i kod wyjścia. +
  • +
+
+ +
+ +
+ + +
+ + diff --git a/web/public/pl/presety/empty-and-minimal/index.html b/web/public/pl/presety/empty-and-minimal/index.html index c453ee5a..8f084db6 100644 --- a/web/public/pl/presety/empty-and-minimal/index.html +++ b/web/public/pl/presety/empty-and-minimal/index.html @@ -3,15 +3,36 @@ + Najmniejsze poprawne i puste pliki w każdym formacie + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/filename-handling/index.html b/web/public/pl/presety/filename-handling/index.html index 15b48de3..acb26d14 100644 --- a/web/public/pl/presety/filename-handling/index.html +++ b/web/public/pl/presety/filename-handling/index.html @@ -3,15 +3,36 @@ + Problematyczne nazwy plików do testów - Unicode i długość + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/index.html b/web/public/pl/presety/index.html index 433609a5..b181ead0 100644 --- a/web/public/pl/presety/index.html +++ b/web/public/pl/presety/index.html @@ -3,15 +3,36 @@ + Presety plików testowych - gotowe zestawy do testów QA + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/size-boundaries/index.html b/web/public/pl/presety/size-boundaries/index.html index cbfeeb76..237684f5 100644 --- a/web/public/pl/presety/size-boundaries/index.html +++ b/web/public/pl/presety/size-boundaries/index.html @@ -3,15 +3,36 @@ + Test limitu rozmiaru pliku - pliki dokładnie na granicy + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/tabular-import/index.html b/web/public/pl/presety/tabular-import/index.html index ee06e9a4..bc4a5af9 100644 --- a/web/public/pl/presety/tabular-import/index.html +++ b/web/public/pl/presety/tabular-import/index.html @@ -3,15 +3,36 @@ + Pliki testowe do importu CSV i Excel - separatory, nagłówki + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/text-encoding/index.html b/web/public/pl/presety/text-encoding/index.html index 93d6063c..b7deb332 100644 --- a/web/public/pl/presety/text-encoding/index.html +++ b/web/public/pl/presety/text-encoding/index.html @@ -3,15 +3,36 @@ + Pliki testowe kodowania - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/presety/upload-validation/index.html b/web/public/pl/presety/upload-validation/index.html index 3496d7d5..f7a322f8 100644 --- a/web/public/pl/presety/upload-validation/index.html +++ b/web/public/pl/presety/upload-validation/index.html @@ -3,15 +3,36 @@ + Pliki do testu walidacji uploadu - typ, rozmiar, nazwa + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
diff --git a/web/public/pl/uszkodzone-pliki-testowe/index.html b/web/public/pl/uszkodzone-pliki-testowe/index.html new file mode 100644 index 00000000..a3254844 --- /dev/null +++ b/web/public/pl/uszkodzone-pliki-testowe/index.html @@ -0,0 +1,381 @@ + + + + + + +Uszkodzone pliki testowe - zepsute pliki o dokładnym rozmiarze + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Zastosowania

+

Jak zrobić uszkodzony plik do testów

+

+ Walidator, któremu pokazywano tylko zdrowe pliki, nie został naprawdę przetestowany. Oto jak dostać + plik zepsuty celowo, o dokładnie takim rozmiarze, jaki podasz, z manifestem + mówiącym, co system ma z nim zrobić. +

+ +
+

Krótka odpowiedź

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out zapisuje PNG o + dokładnie 2097152 bajtach, którego pierwsze bajty są zerami, a manifest obok zapisuje, że system + powinien go odrzucić. +

+
+ +
+

Zwykła droga

+

Dlaczego plik uszkodzony ręcznie to kiepski test

+

+ Zwykle używa się edytora szesnastkowego, skryptu zmieniającego kilka losowych bajtów albo ucięcia + pliku przez head lub truncate. Za pierwszym razem działa, a potem + kosztuje: +

+
    +
  • + Za każdym razem jest inaczej. Losowy bajt trafia w nowe miejsce przy każdym + przebiegu, więc błąd z wtorku może nie wrócić w środę. +
  • +
  • + Zmienia rozmiar. Plik ucięty jest mniejszy niż limit, pod którym miał się mieścić, + więc kontrola rozmiaru odpowiada przed kontrolą zawartości, a test przechodzi z niewłaściwego + powodu. +
  • +
  • + Często nikt tego nie zauważa. Zwykły tekst da się czytać mimo zmienionego bajtu w + środku, a pobłażliwy czytnik obrazów po prostu go narysuje, więc plik, który miał być zepsuty, + zostaje przyjęty. +
  • +
  • + Nic nie mówi o tym, co ma się stać. Plik to same bajty, a ten, kto później czyta + test, musi zgadywać, czy chodziło o przyjęcie, czy o odrzucenie. +
  • +
+
+ +
+

Co dostajesz

+

Uszkodzony plik ma nadal rozmiar, o który prosiłeś

+

+ Plik jest generowany normalnie, a psuty dopiero w drodze na dysk. Zachowuje rozmiar, który podałeś, + a to samo polecenie zapisuje znowu te same bajty. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Ustawienia podaje się po dwukropku. Flagę można powtarzać, a uszkodzenia są stosowane w kolejności, + w jakiej je zapiszesz. Działa z każdym z 26 formatów. +

+
+ +
+

Co potrafi

+

Jakie są uszkodzenia?

+

+ To lista, którą wypisuje program, odczytana z niego w chwili budowania tej strony. tfg + damage wypisuje to samo, a tfg damage <id> mówi, co przyjmuje jedno z + nich. +

+
+ + + + + + + + + + + + + + + + + +
UszkodzenieCo robi z bajtamiNajmniejszy plikUstawienia
zero-headNadpisuje pierwsze bajty pliku zerami, nie zmieniając jego długości. Większość czytników zagląda tam najpierw, więc to uszkodzenie zauważy prawie wszystko.8bytes
+
+

+ zero-head zapisuje zera na początku pliku. Większość czytników zagląda tam najpierw, w + sygnaturę i nagłówek mówiące, czym jest plik, więc zauważy to prawie każdy czytnik. Zwykły tekst + i logi nie mają sygnatury i też są odrzucane, bo ciąg zerowych bajtów nie jest tekstem. Poniżej + czterech bajtów niektóre formaty wychodzą z uszkodzeniem, na które nie skarży się żaden czytnik, + dlatego ustawienie zaczyna się od czterech. +

+
+ +
+

Co mówi manifest

+

Manifest, który mówi, co ma się stać

+

+ Każdy uszkodzony plik dostaje wpis mówiący, że system powinien go odrzucić, a obok zapisane jest + uszkodzenie: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dwie prośby są odrzucane, zanim cokolwiek powstanie, bo każda zostawiłaby na dysku plik, który + manifest opisuje błędnie: +

+
    +
  • plik mniejszy, niż potrzebuje uszkodzenie, bo wyszedłby nietknięty
  • +
  • + expected: accept obok uszkodzenia, bo nic nie mogłoby tego spełnić. Napisz + sanitize, jeśli system ma plik naprawić, albo unspecified, jeśli + właśnie o to pytasz +
  • +
+
+ +
+

W przepisie

+

Zdrowe i zepsute pliki w jednym przebiegu

+

+ Włóż jedno i drugie do jednego przepisu, a manifest niesie oczekiwanie każdego pliku, więc test nie + potrzebuje listy, który jest który: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

W teście

+

Zamiana tego w test

+

+ Test czyta manifest i sprawdza, czy to, co się stało, jest tym, co zadeklarowano. Nie potrzebuje + listy nazw plików: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Dobre odrzucenie jest czyste. Komunikat mówiący, co było nie tak, to odpowiedź, o którą chodzi. Błąd + serwera, zawieszenie albo plik zapisany do połowy to wada, którą ten test ma znaleźć. +

+
+ +
+

Dalej

+

Dokąd pójść stąd

+ +
+ +
+ +
+ + +
+ + diff --git a/web/public/pl/zastosowania/index.html b/web/public/pl/zastosowania/index.html index 5db8fe78..686f7c09 100644 --- a/web/public/pl/zastosowania/index.html +++ b/web/public/pl/zastosowania/index.html @@ -3,15 +3,36 @@ + Zastosowania - limity uploadu, dane do CI, testy masowe + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Rozmiar pliku FAQ -
- English -
+
+ + + Polski + + +
@@ -181,6 +248,19 @@

Sprawdzenie, czy Twój kod czyta format tak jak prawdziwe oprogramowanie

+
+

Poradniki

+

Dwa z tych zastosowań dokładniej

+ +
+

Dla kogo to jest

diff --git a/web/public/presets/empty-and-minimal/index.html b/web/public/presets/empty-and-minimal/index.html index b8c1e161..aa91bd66 100644 --- a/web/public/presets/empty-and-minimal/index.html +++ b/web/public/presets/empty-and-minimal/index.html @@ -3,15 +3,36 @@ + Smallest Valid and Empty Test Files in Every Format + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -

- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/filename-handling/index.html b/web/public/presets/filename-handling/index.html index 9c8aa6c9..3561b311 100644 --- a/web/public/presets/filename-handling/index.html +++ b/web/public/presets/filename-handling/index.html @@ -3,15 +3,36 @@ + Problematic File Names for Testing - Unicode and Length + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/index.html b/web/public/presets/index.html index e81fc407..1513d0a7 100644 --- a/web/public/presets/index.html +++ b/web/public/presets/index.html @@ -3,15 +3,36 @@ + Test File Presets - Ready-Made Sets for QA Questions + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/size-boundaries/index.html b/web/public/presets/size-boundaries/index.html index 5e547f87..4d867dd7 100644 --- a/web/public/presets/size-boundaries/index.html +++ b/web/public/presets/size-boundaries/index.html @@ -3,15 +3,36 @@ + Test an Upload Size Limit - Files at the Exact Boundary + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/tabular-import/index.html b/web/public/presets/tabular-import/index.html index 97cb5df5..30ccd7f0 100644 --- a/web/public/presets/tabular-import/index.html +++ b/web/public/presets/tabular-import/index.html @@ -3,15 +3,36 @@ + CSV and Excel Import Test Files - Delimiters, Headers + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/text-encoding/index.html b/web/public/presets/text-encoding/index.html index c45614db..0fe10eb9 100644 --- a/web/public/presets/text-encoding/index.html +++ b/web/public/presets/text-encoding/index.html @@ -3,15 +3,36 @@ + Text Encoding Test Files - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/presets/upload-validation/index.html b/web/public/presets/upload-validation/index.html index b9ff7bd3..7b6e2e86 100644 --- a/web/public/presets/upload-validation/index.html +++ b/web/public/presets/upload-validation/index.html @@ -3,15 +3,36 @@ + Upload Validation Test Files - Type, Size and Name + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -74,9 +115,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
diff --git a/web/public/pt-br/arquivos-de-teste-corrompidos/index.html b/web/public/pt-br/arquivos-de-teste-corrompidos/index.html new file mode 100644 index 00000000..26906ac5 --- /dev/null +++ b/web/public/pt-br/arquivos-de-teste-corrompidos/index.html @@ -0,0 +1,382 @@ + + + + + + +Arquivos de teste corrompidos - arquivos quebrados, tamanho exato + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casos de uso

+

Como criar um arquivo corrompido para testes

+

+ Um validador que só viu arquivos saudáveis não foi realmente testado. Veja como obter um arquivo + quebrado de propósito, que sai com exatamente o tamanho que você pede e traz um + manifesto dizendo o que o seu sistema deve fazer com ele. +

+ +
+

A resposta curta

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out grava um PNG de + exatamente 2097152 bytes cujos primeiros bytes são zeros, e o manifesto ao lado registra que o + seu sistema deve rejeitá-lo. +

+
+ +
+

O jeito de sempre

+

Por que um arquivo corrompido à mão é um teste ruim

+

+ O jeito de sempre é um editor hexadecimal, um script que troca alguns bytes aleatórios ou cortar um + arquivo com head ou truncate. Funciona uma vez, e depois sai caro: +

+
    +
  • + É diferente a cada vez. Um byte aleatório cai num lugar novo a cada execução, então + uma falha de terça pode não voltar na quarta. +
  • +
  • + Muda o tamanho. Um arquivo cortado fica menor que o limite abaixo do qual deveria + ficar, então a checagem de tamanho responde antes da checagem de conteúdo e o teste passa pelo + motivo errado. +
  • +
  • + Muitas vezes passa despercebido. Texto simples continua legível com um byte + alterado no meio, e um leitor de imagens tolerante simplesmente o desenha, então o arquivo que + deveria estar quebrado é aceito. +
  • +
  • + Não diz nada sobre o que deve acontecer. O arquivo é só bytes, e quem ler o teste + depois precisa adivinhar se a intenção era aceitação ou rejeição. +
  • +
+
+ +
+

O que você recebe

+

Um arquivo danificado continua com o tamanho que você pediu

+

+ O arquivo é gerado normalmente e quebrado depois, a caminho do disco. Ele mantém o tamanho pedido, e + o mesmo comando grava os mesmos bytes outra vez. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ As configurações vão depois de dois-pontos. A opção pode ser repetida, e os danos são aplicados na + ordem em que você os escreve. Funciona com cada um dos 26 formatos. +

+
+ +
+

O que ele sabe fazer

+

Quais danos existem?

+

+ Esta é a lista que o programa imprime, lida dele quando esta página é construída. tfg + damage imprime a mesma, e tfg damage <id> diz o que cada um aceita. +

+
+ + + + + + + + + + + + + + + + + +
DanoO que faz com os bytesMenor arquivoConfigurações
zero-headSobrescreve os primeiros bytes do arquivo com zeros, sem mexer no comprimento. A maioria dos leitores olha ali primeiro, então quase tudo percebe este dano.8bytes
+
+

+ zero-head grava zeros sobre o início do arquivo. A maioria dos leitores olha ali + primeiro, para a assinatura e o cabeçalho que dizem o que o arquivo é, então quase todo leitor + percebe. Texto simples e logs não têm assinatura e também são recusados, porque uma sequência de + bytes zero não é texto. Abaixo de quatro bytes, alguns formatos saem com um dano de que nenhum + leitor reclama, e por isso a configuração começa em quatro. +

+
+ +
+

O que o manifesto diz

+

Um manifesto que diz o que deve acontecer

+

+ Cada arquivo danificado recebe uma entrada dizendo que o seu sistema deve rejeitá-lo, com o dano + registrado ao lado: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Dois pedidos são recusados antes de qualquer coisa ser gravada, porque cada um deixaria no disco um + arquivo que o manifesto descreve errado: +

+
    +
  • um arquivo menor do que o dano precisa, que sairia intacto
  • +
  • + expected: accept ao lado de um dano, porque nada poderia cumprir isso. Escreva + sanitize se o seu sistema deve consertar o arquivo, ou unspecified + se essa é justamente a pergunta que você faz +
  • +
+
+ +
+

Em uma receita

+

Arquivos saudáveis e quebrados em uma execução

+

+ Ponha os dois em uma receita, e o manifesto leva a expectativa de cada arquivo, então o teste não + precisa de uma lista de qual é qual: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Em um teste

+

Transformando em um teste

+

+ O teste lê o manifesto e confere se o que aconteceu é o que foi declarado. Não precisa de uma lista + de nomes de arquivo: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Uma boa recusa é uma recusa limpa. Uma mensagem que diz o que estava errado é a resposta que você + quer. Um erro de servidor, uma trava ou um arquivo salvo pela metade é o defeito que este teste + existe para achar. +

+
+ +
+

A seguir

+

Para onde ir daqui

+ +
+ +
+ + + + diff --git a/web/public/pt-br/arquivos-de-teste-no-ci/index.html b/web/public/pt-br/arquivos-de-teste-no-ci/index.html new file mode 100644 index 00000000..b1af7638 --- /dev/null +++ b/web/public/pt-br/arquivos-de-teste-no-ci/index.html @@ -0,0 +1,379 @@ + + + + + + +Arquivos de teste no CI - GitHub Actions, GitLab CI e PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Casos de uso

+

Como gerar arquivos de teste em um pipeline de CI

+

+ Uma fixture binária em um repositório fica para sempre no histórico, não pode ser revisada em um + diff e deixa de ser viável quando o arquivo é grande. Gere os arquivos dentro do pipeline a partir + de uma receita. A receita é texto, os bytes saem iguais a cada vez e um último passo prova que + nada mudou. +

+ +
+

A resposta curta

+

+ Instale o tfg, rode tfg generate fixtures.yaml --out ./fixtures antes dos + testes e tfg verify ./fixtures/manifest.json depois. Os dois passos fazem o build + falhar sozinhos, com um código de saída que diz o motivo. +

+
+ +
+

Por que não commitar

+

Por que uma fixture não deve morar no repositório

+
    +
  • + Ela fica no histórico. Apagar um binário depois não deixa um clone menor, porque + todas as versões dele continuam lá. +
  • +
  • + Um diff não mostra o que mudou. O revisor vê que um PDF é diferente e nada mais. + Uma receita muda em uma linha. +
  • +
  • + Arquivos grandes não cabem. O GitHub recusa um push que contenha um arquivo acima + de 100 MB, então um teste de limite de upload de 500 MB não tem o que commitar. +
  • +
+

+ O que se commita é a receita. A mesma receita e a mesma semente gravam os mesmos bytes em qualquer + máquina, então o arquivo gerado no pipeline é o arquivo que você tinha no notebook. +

+
+ +
+

A receita

+

Uma receita que mora junto dos testes

+

+ Esta grava vinte e cinco faturas que devem ser aceitas e duas imagens acima de um limite que devem + ser recusadas, e o manifesto registra as duas expectativas: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml verifica a receita sem gravar nada e nomeia todos os + problemas de uma vez. +

+
+ +
+

GitHub Actions

+

Um workflow que instala a ferramenta e constrói as fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ A linha da soma de verificação compara o arquivo com verify-SHA256SUMS.txt da mesma + versão. A versão está fixada, então uma versão nova nunca altera um build que você não mexeu. +

+
+ +
+

GitLab CI

+

A mesma coisa como job do GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Quando fica vermelho

+

O que faz um passo falhar, e por quê

+

+ Cada final tem o seu próprio código de saída, então o passo falha sozinho e o log diz qual foi. Os + que um pipeline encontra: +

+
    +
  • 3 - a receita não é válida. Nada foi gravado, e cada problema é nomeado
  • +
  • 4 - o formato não consegue fazer o que foi pedido, por exemplo um tamanho abaixo do seu mínimo
  • +
  • 6 - não há espaço em disco suficiente
  • +
  • 7 - tfg verify achou um arquivo que não bate com o manifesto
  • +
  • 8 - a execução terminou, mas nem tudo foi produzido
  • +
+

+ Uma execução que falhou não imprime nada na saída padrão, então um analisador de logs nunca toma um + erro por dado. A tabela completa está na página de + documentação. +

+
+ +
+

PowerShell

+

Um script PowerShell precisa de mais uma linha

+

+ O PowerShell não leva o código de saída de um programa para fora de um arquivo .ps1. + Rode um com -File e o script responde 0 mesmo quando a ferramenta lá + dentro recusou o trabalho, então um build que deveria ficar vermelho fica verde. A última linha + é a correção inteira: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ É assim que o PowerShell se comporta, não algo desta ferramenta. cmd, bash + e zsh não precisam de mais nada. +

+
+ +
+

Vários jobs

+

Compartilhando as fixtures entre jobs

+

+ Em geral não é preciso enviá-las. Como a mesma receita grava os mesmos bytes, cada job pode rodar o + seu próprio tfg generate, que é mais rápido que um upload e um download. Quando um + job precisa receber arquivos de outro, rode tfg verify no manifesto depois da + transferência, e ele diz se o que chegou é o que foi gravado. +

+
+ +
+

A seguir

+

Para onde ir daqui

+ +
+ +
+ + + + diff --git a/web/public/pt-br/casos-de-uso/index.html b/web/public/pt-br/casos-de-uso/index.html new file mode 100644 index 00000000..98a9aead --- /dev/null +++ b/web/public/pt-br/casos-de-uso/index.html @@ -0,0 +1,321 @@ + + + + + + +Casos de uso - limites de upload, fixtures de CI, testes em massa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Para que as pessoas usam

+

+ Cinco tarefas que aparecem em quase todo projeto que aceita arquivos de pessoas, e o comando que faz + cada uma. Todo exemplo abaixo roda como está escrito. +

+ +
+

Limites de upload

+

Testar se um limite de tamanho de arquivo é aplicado onde diz que é

+

+ Um limite são três casos de teste, não um: logo abaixo, exatamente nele e logo acima. Conseguir + esses à mão significa calcular contagens de bytes e torcer para não ter errado por um. Peça o + conjunto no lugar: +

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

+ Você recebe três PDFs reais com 1048575, 1048576 e 1048577 bytes, e um manifesto dizendo que os dois + primeiros devem ser aceitos e o terceiro rejeitado por size_limit. Seu teste lê a + expectativa em vez de você escrever três asserções à mão - e quando o limite muda, você muda um + número e roda de novo. +

+

+ O mesmo funciona sem preset quando você quer um único conjunto de limites embutido: +

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

Integração contínua

+

Manter fixtures fora do repositório sem perdê-las

+

+ Fixtures binárias grandes deixam um repositório lento de clonar e chato de revisar, e ninguém sabe + dizer o que mudou quando uma é substituída. Uma receita são algumas centenas de caracteres de + YAML que reconstroem os arquivos idênticos - byte a byte, em qualquer máquina - + porque cada arquivo é derivado do seed da execução. +

+
- 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
+

+ Cada término tem seu próprio código de saída, então um pipeline consegue distinguir uma receita ruim + de um disco cheio e de uma divergência de verificação. Uma execução com falha não imprime nada + na saída padrão, o que impede um parser de logs de ler um erro como dado. +

+
+ +
+

Escala

+

Descobrir o que acontece quando a pasta é grande

+

+ Rotinas de importação, jobs noturnos e listagens de diretório se comportam diferente com dez mil + arquivos do que com dez. Tamanhos sorteados de um intervalo fazem o conjunto parecer tráfego + real em vez de dez mil arquivos idênticos, e o sorteio vem do seed, então o conjunto é o mesmo + amanhã. +

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

+ Confira quanto uma execução custaria antes de ela escrever qualquer coisa, o que importa quando o + total é medido em gigabytes: +

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

+ Uma execução maior que o espaço livre no disco é recusada antes de o primeiro byte ser escrito, em + vez de encher o disco e falhar no meio. +

+
+ +
+

Arquivos compactados

+

Testar um descompactador com um arquivo compactado que realmente contém arquivos

+

+ Um arquivo compactado vazio com a extensão certa não prova nada sobre o código que o abre e percorre + o que há dentro. Declare o conteúdo e o arquivo compactado realmente o contém: +

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

+ Profundidade de aninhamento, contagem de entradas e tamanho do que há dentro são coisas sobre as + quais uma rotina de importação tem opinião, e é assim que você descobre quais são. +

+
+ +
+

Parsers e visualizadores

+

Conferir se o seu próprio código lê um formato como o software real

+

+ Todo formato aqui é verificado com um leitor independente antes de ser liberado - um PNG é aberto e + seus pixels comparados, um DOCX é relido por bibliotecas separadas, um arquivo compactado é + extraído. Isso significa que um arquivo que o seu parser recusa é uma descoberta sobre o seu + parser, não sobre o gerador. +

+
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
+

+ A página de formatos lista as configurações que cada um aceita e o + menor arquivo que cada um pode ser. +

+
+ +
+

Guias

+

Dois deles em detalhe

+
    +
  • + Arquivos de teste corrompidos - um arquivo + quebrado de propósito, com o tamanho exato e com o que deve acontecer com ele escrito no + manifesto. +
  • +
  • + Arquivos de teste no CI - um workflow do GitHub + Actions, um job do GitLab e os códigos de saída que fazem um build falhar. +
  • +
+
+ +
+

Para quem é

+

+ Engenheiros de QA, automação de testes e qualquer pessoa cujo código tenha atrás um formulário de + upload, uma rotina de importação, um parser ou uma cota de armazenamento. Roda em uma máquina + sem rede nenhuma, o que importa em um ambiente corporativo fechado onde um gerador baseado em + navegador não é opção. +

+ +

Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.

+
+ +
+ + + + diff --git a/web/public/pt-br/criar-arquivo-de-tamanho-exato/index.html b/web/public/pt-br/criar-arquivo-de-tamanho-exato/index.html new file mode 100644 index 00000000..5b0acfe3 --- /dev/null +++ b/web/public/pt-br/criar-arquivo-de-tamanho-exato/index.html @@ -0,0 +1,331 @@ + + + + + + +Criar um arquivo de tamanho exato - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Como criar um arquivo de tamanho exato

+

+ Todo sistema tem um comando para isso, e os três estão abaixo. Eles dão um arquivo com exatamente o + número certo de bytes - e para muito teste isso é tudo de que você precisa. Todo comando + desta página foi executado antes de ser publicado, no sistema a que pertence. +

+ +
+

A resposta curta

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Os tamanhos são em bytes, e 10 MB + contados como o seu gerenciador de arquivos conta são 10485760. +

+
+ +
+

Windows

+

fsutil, e uma versão em PowerShell que não precisa de nada extra

+

+ O fsutil vem com o Windows. Ele recebe o tamanho em bytes, então + calcule o número antes - 10 MB são 10485760, 100 MB são 104857600, 1 GB é 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Medido no Windows 11: funciona em um prompt comum, sem precisar de um elevado, e o arquivo sai com + exatamente 10485760 bytes. +

+

O PowerShell faz o mesmo sem chamar outro programa, e entende unidades:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB no PowerShell significa 10485760 bytes, a mesma contagem em base 1024 que o + Explorer usa, então os dois comandos acima produzem o mesmo tamanho. +

+
+ +
+

Linux

+

dd, truncate e fallocate, e a diferença que pega as pessoas

+

O dd é o que todo mundo conhece. Ele escreve os bytes de verdade:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ O truncate é instantâneo, e essa é a pegadinha. Medido no Alpine Linux, o arquivo + informa 10485760 bytes e ocupa zero blocos - é um arquivo + esparso. Qualquer coisa que o leia recebe dez megabytes de zeros, mas o disco nunca + cedeu o espaço: +

+
truncate -s 10M test10mb.bin
+

+ Isso serve para testar um limite de upload e engana para testar uma cota de disco. O + fallocate é o que se deve usar quando o espaço precisa ser real: +

+
fallocate -l 10M test10mb.bin
+

E quando o conteúdo precisa ser incompressível, para que um compactador não consiga comprimi-lo de volta:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, que não é esparso, e os dois que você já conhece

+

+ O macOS traz o mkfile. Medido no macOS 26.6.2: 10485760 bytes e 20480 blocos, então o + espaço é realmente alocado em vez de prometido: +

+
mkfile 10m test10mb.bin
+

dd e truncate também estão lá e se comportam como no Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Onde isso deixa de funcionar

+

Um arquivo do tamanho certo não é um arquivo do tipo certo

+

+ Tudo acima dá um bloco de zeros. Isso basta quando o que está sob teste olha só o tamanho - um + limite de upload, uma cota, uma transferência. Deixa de bastar no momento em que qualquer coisa + abre o arquivo. +

+

+ Medido, e vale a pena fazer você mesmo: crie um arquivo de 2 MB com fsutil, chame-o de + photo.png e entregue a uma biblioteca de imagens. O Pillow responde cannot + identify image file. Não é um PNG. Nunca foi - só o nome dizia que era. +

+

+ Isso importa mais do que parece, por causa de o jeito como o teste então falha. Seu + endpoint de upload recusa o arquivo, seu teste fica verde e você conclui que o limite de tamanho + funciona. Ele não recusou pelo tamanho. Recusou porque os bytes não eram uma imagem, e a regra + que você queria testar nunca foi alcançada. +

+
    +
  • um parser o recusa antes de qualquer regra de tamanho ser olhada
  • +
  • uma etapa de miniatura falha e o erro que você lê é sobre a miniatura
  • +
  • um antivírus ou uma verificação de conteúdo o recusa por um terceiro motivo
  • +
  • um visualizador não mostra nada, e ninguém sabe dizer se esse é o bug
  • +
+
+ +
+

O outro caminho

+

Um arquivo real desse formato, exatamente no tamanho que você pediu

+

+ É isso que o Testing Files Generator faz. O arquivo é um genuíno do seu formato - abre no programa a + que pertence - e tem o número exato de bytes que você pediu, ao byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Peça um tamanho que um formato não alcança e você recebe um erro que nomeia o piso e o motivo, nunca + um arquivo de tamanho errado. A página de formatos lista cada + formato com o menor arquivo que ele pode produzir. +

+

E um limite são três casos de teste em vez de um, então a ferramenta monta os três:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Isso dá 10485759, 10485760 e 10485761 bytes, e um manifesto dizendo quais deles seu sistema deve + aceitar e quais deve rejeitar. A página de casos de uso + percorre isso e outras quatro tarefas para as quais foi feito. +

+ +

Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.

+
+ +
+

Então qual usar?

+
    +
  • +

    Use o comando do sistema

    +

    + Quando nada abre o arquivo. Testar um limite de tamanho em um endpoint que checa o tamanho primeiro, + uma transferência, uma cota, um disco cheio. É uma linha e já está instalado. +

    +
  • +
  • +

    Use um gerador de verdade

    +

    + Quando qualquer coisa interpreta, renderiza, importa ou extrai o arquivo - e quando você precisa das + mesmas fixtures amanhã, em outra máquina, byte a byte. +

    +
  • +
+

+ Os dois estão nesta página porque os dois estão certos parte do tempo. O erro a evitar é usar o + primeiro onde o segundo é necessário e ler o teste verde como prova. +

+
+ +
+ + + + diff --git a/web/public/pt-br/documentacao/index.html b/web/public/pt-br/documentacao/index.html new file mode 100644 index 00000000..0a63bafe --- /dev/null +++ b/web/public/pt-br/documentacao/index.html @@ -0,0 +1,558 @@ + + + + + + +Documentação - comandos, receitas, manifesto, códigos de saída + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentação

+

+ Tudo o que a ferramenta faz, organizado como as perguntas com que as pessoas realmente chegam. O + README do repositório é a referência completa e sempre corresponde + à versão que você baixou. +

+ +
+

Quais comandos existem?

+

Cada um faz uma única coisa:

+
tfg generate    produzir arquivos, a partir de uma receita ou de opções
+tfg validate    verificar uma receita sem escrever nada
+tfg verify      verificar um diretório contra um manifesto
+tfg cleanup     remover os arquivos que um manifesto lista
+tfg recipe fmt  imprimir uma receita na sua forma normalizada
+tfg preset      montar um conjunto de arquivos a partir de uma pergunta de teste nomeada
+tfg formats     listar os formatos que esta versão suporta
+tfg damage      listar as formas como esta versão pode quebrar um arquivo de propósito
+tfg tool        pequenas utilidades para arquivos que você já tem
+tfg version     imprimir a versão da ferramenta
+tfg license     imprimir a licença e o que ela significa para os arquivos gerados
+
+ +
+

Como gero um único arquivo de tamanho exato?

+

+ Informe o formato, o tamanho e o destino. Os tamanhos contam de 1024 em 1024, então 2mb + são 2097152 bytes. Uma contagem simples de bytes também funciona, então --size + 10485761 pede exatamente essa quantidade. +

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

As opções úteis de generate:

+
+ + + + + + + + + + + + + + + + + +
OpçãoO que faz
--format <id>formato dos arquivos, por exemplo txt
--size <size>tamanho exato de cada arquivo, como 10mb ou uma contagem simples de bytes
--size-range <a-b>um tamanho sorteado por arquivo dentro de um intervalo, como 1kb-8kb. O sorteio vem do seed
--boundary <size>três arquivos ao redor de um limite: um byte abaixo, o limite, um byte acima
--count <n>quantos arquivos produzir. Padrão 1
--name <template>modelo de nome, por exemplo invoice_{index:04}.txt
--out <dir>diretório onde escrever
--seed <n>seed da execução. O mesmo seed dá os mesmos bytes
--set <k>=<v>uma configuração de formato, repetível
--damage <name>quebrar os arquivos de propósito, repetível e aplicado em ordem. Rode tfg damage para ver a lista
--expected <outcome>accept, reject, sanitize ou unspecified
--dry-runcontar e mostrar, sem escrever absolutamente nada
--jsonescrever o manifesto na saída padrão
+
+
+ +
+

Como faço um arquivo quebrado de propósito?

+

+ Todo outro arquivo que esta ferramenta escreve é correto por construção, o que responde a duas das + três perguntas que um validador de upload faz. --damage responde à terceira - se o + arquivo abre, afinal. O arquivo é produzido normalmente e depois quebrado, então continua com o + tamanho que você pediu. +

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

+ As configurações vão depois de dois-pontos. A opção se repete, e a ordem em que você as escreve é a + ordem em que são aplicadas. tfg damage lista o que esta versão pode fazer e o que + cada uma aceita. +

+

Em uma receita a chave é uma lista, de nomes ou de configurações:

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

+ Um arquivo danificado recebe expected: reject no manifesto, com o dano registrado ao + lado. Duas coisas são recusadas antes de escrever qualquer coisa, porque cada uma deixaria no + disco um arquivo que o manifesto descreve errado: +

+
    +
  • um arquivo menor do que o dano precisa, porque sairia sem alteração
  • +
  • + expected: accept ao lado de um dano, porque nada poderia cumpri-lo. Escreva + sanitize se o sistema sob teste deve reparar o arquivo, ou + unspecified se essa é a pergunta que você está fazendo +
  • +
+

+ Uma terceira não pode ser conhecida de antemão. Se um dano roda e não move nenhum byte, esse arquivo + é descartado em vez de escrito - a execução continua, diz qual arquivo foi e termina com o + código de saída parcial. +

+

+ Passo a passo, com um teste que lê o manifesto: como + criar um arquivo corrompido para testes. +

+
+ +
+

Como é uma receita?

+

+ Uma receita é um arquivo YAML que descreve uma execução inteira. Versione-a ao lado dos seus testes + e as fixtures deixam de ser binários no seu repositório - qualquer pessoa pode reconstruí-las, + byte a byte, a partir de um arquivo de algumas centenas de caracteres. +

+
# 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
+

+ Cada target precisa de exatamente uma destas chaves: size, size-range, + boundary ou contains. Duas é um erro e nenhuma também. Uma receita + inválida escreve nenhum arquivo e relata todos os problemas de uma vez em vez + de só o primeiro, cada um nomeando a configuração a que se refere. +

+
+ +
+

Como declaro o que meu sistema deve fazer com um arquivo?

+

Forma curta quando o resultado basta, forma longa quando o motivo importa:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Os resultados são accept, reject, sanitize e + unspecified. Os motivos são uma lista fechada para que um relatório possa agrupar + por eles: 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 e size_zero. +

+

+ Um motivo nomeia a regra em jogo, não o veredito. Por isso o mesmo motivo pode + ficar sob qualquer um dos resultados - um arquivo um byte abaixo de um limite é + accept, e a regra de que se trata continua sendo size_limit. +

+
+ +
+

O que há no manifesto?

+

+ Ele é escrito ao lado dos arquivos no fim de cada execução, inclusive de uma execução interrompida. + Uma entrada por arquivo: +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Um recipe_hash é adicionado quando a execução veio de uma receita, e + preset com overrides quando veio de um preset, de modo que um + manifesto sempre pode ser rastreado até o que o produziu. +

+

+ Cada entrada também traz target_id, o id do target da receita que produziu o arquivo, e + summary.by_target conta os arquivos a que cada target chegou. Uma receita com + vários targets pode assim ser verificada target por target sem ler nomes de arquivo. +

+
+ +
+

O que é um preset?

+

+ Um conjunto de arquivos pronto que responde a uma pergunta de teste comum, para que você não precise + desenhar o conjunto. Presets são receitas comuns por baixo, e eject imprime a + receita para você editá-la a partir dali. Cada preset tem uma página + própria com o que costuma encontrar, o que há no conjunto e cada configuração que aceita. +

+
    +
  • +

    Vazio e mínimo

    +

    Um arquivo válido e tão pequeno quanto o formato permite passa?

    +

    empty-and-minimal

    +
  • +
  • +

    Tratamento de nomes de arquivo

    +

    Meu sistema vai guardar, mostrar e devolver um nome de arquivo que ele não esperava?

    +

    filename-handling

    +
  • +
  • +

    Limites de tamanho

    +

    Um limite de tamanho é aplicado exatamente onde foi declarado?

    +

    size-boundaries

    +
  • +
  • +

    Importação de tabelas

    +

    A minha importação de tabelas sobrevive ao que ferramentas reais exportam?

    +

    tabular-import

    +
  • +
  • +

    Codificação de texto

    +

    Meu leitor sabe em que codificação um arquivo está, ou está adivinhando?

    +

    text-encoding

    +
  • +
  • +

    Validação de upload

    +

    Meu formulário de upload aceita o que deve e recusa o resto?

    +

    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 diz quanto o conjunto custaria antes de você montá-lo, e diz abertamente quando um + número é um valor provisório nosso, e não um limite seu. +

+
+ +
+

O que significam os códigos de saída?

+

+ Cada término tem seu próprio código, a saída legível por máquina vai para a saída padrão, e uma + execução com falha não imprime nada lá. A tabela é um contrato congelado - mudar o que um código + significa exige uma versão maior. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CódigoSignificado
0Tudo funcionou.
1Um erro inesperado dentro da ferramenta.
2Comando ou opção incorretos.
3A receita não é válida.
4O formato não consegue fazer o que foi pedido.
5Uma leitura ou escrita falhou.
6Espaço em disco insuficiente.
7verify encontrou uma divergência.
8A execução terminou, mas nem tudo foi produzido.
130Interrompido com Ctrl+C.
143Encerrado por um sinal, que é a cara de um timeout de 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
+

+ Uma execução parada com Ctrl+C ainda deixa um manifesto e nunca deixa um arquivo pela metade, então + um job cancelado ainda pode ser limpo pelo seguinte. +

+

+ Workflows prontos para GitHub Actions e GitLab CI: como + gerar arquivos de teste em um pipeline de CI. +

+
+ +
+

Existe uma janela de desktop?

+

+ Sim, o mesmo motor com uma janela por cima, para o teste que não é automatizado. Não é uma versão + reduzida: um teste compara as duas interfaces capacidade por capacidade, e tudo que só uma delas + pode fazer precisa ser declarado e justificado em vez de divergir em silêncio. +

+

+ As telas são um lote, presets, vários lotes de uma vez e Sobre. Ela mostra quanto uma execução + custaria antes de escrever qualquer coisa, informa o progresso enquanto roda e pode ser + cancelada no meio sem deixar um arquivo pela metade. Ainda não abre um arquivo de receita - por + enquanto receitas são coisa de linha de comando, e a janela monta seus lotes no formulário. +

+
+ +
+ + + + diff --git a/web/public/pt-br/formatos/index.html b/web/public/pt-br/formatos/index.html new file mode 100644 index 00000000..314f43bc --- /dev/null +++ b/web/public/pt-br/formatos/index.html @@ -0,0 +1,912 @@ + + + + + + +26 formatos de arquivo - PDF, DOCX, PNG, ZIP e mais + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formatos de arquivo, cada um gerado em um tamanho exato

+

+ Cada um é um arquivo real daquele formato. Abre no programa a que pertence e tem + exatamente o número de bytes que você pediu. Nenhum é preenchimento de zeros com uma extensão + colada. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoNomeExtensãoMenor arquivoFidelidadeVerificado com
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullnão se aplica
mdMarkdown.md0fullnão se aplica
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullnão se aplica
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

O que as colunas significam

+
    +
  • +

    Menor arquivo

    +

    + O menor número de bytes que esta ferramenta aceita para aquele formato, incluindo o rótulo que ela + escreve dentro do arquivo. Peça menos e você recebe um erro que nomeia o piso e o motivo, + nunca um arquivo de tamanho errado. +

    +
  • +
  • +

    Fidelidade

    +

    + Quão completo é o arquivo. full significa que um leitor que realmente interpreta o + formato o aceita, e não apenas que a extensão combina. +

    +
  • +
  • +

    Verificado com

    +

    + O leitor independente que abre todo arquivo gerado antes de o formato ser liberado - uma + implementação separada, não o nosso próprio código corrigindo o próprio dever de casa. +

    +
  • +
+

+ Todo formato também se repete ao byte: a mesma receita e o mesmo seed produzem arquivos idênticos em + qualquer máquina, o que torna seguro versionar uma receita no lugar das próprias fixtures. +

+
+ +
+

Configurações que cada formato aceita

+

+ A maioria dos formatos tem configurações próprias - dimensões de imagem, qualidade JPEG, número de + páginas do PDF, linhas e colunas de uma planilha, quantas entradas vão dentro de um arquivo + compactado. Defina-as com --set key=value na linha de comando, ou em + properties: numa receita. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatoConfiguraçãoAceita
avifwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
bmpwidth1 - 20000 pixels
height1 - 20000 pixels
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerverdadeiro ou falso
quote_styleall, minimal, none
columns2 - 32768 colunas
docxparagraphs1 - 50000 parágrafos
gifwidth1 - 20000 pixels
height1 - 20000 pixels
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixels
height1 - 256 pixels
embedbmp, png
jpgwidth1 - 20000 pixels
height1 - 20000 pixels
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixels
height1 - 16384 pixels
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 entradas por segundo
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomverdadeiro ou falso
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlequalquer texto
authorqualquer texto
subjectqualquer texto
keywordsqualquer texto
creatorqualquer texto
producerqualquer texto
createduma data como 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none
modifieduma data como 2024-02-29 ou 2024-02-29T13:45:00+02:00, ou none
pngwidth1 - 20000 pixels
height1 - 20000 pixels
pptxslides1 - 500 slides
svgwidth1 - 20000 pixels
height1 - 20000 pixels
targzentries0 - 10000
entry_formato id de um formato, como o tfg formats lista
entry_sizeum tamanho como 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesverdadeiro ou falso
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixels
height1 - 20000 pixels
txtencodingutf-16be, utf-16le, utf-8
bomverdadeiro ou falso
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixels
height1 - 16383 pixels
xlsxrows1 - 200000 linhas
columns1 - 32768 colunas
xmlencodingutf-16be, utf-16le, utf-8
bomverdadeiro ou falso
zipentries0 - 10000
entry_formato id de um formato, como o tfg formats lista
entry_sizeum tamanho como 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesverdadeiro ou falso
passworda senha, em texto simples
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Um valor fora do que uma configuração aceita é recusado com uma mensagem que nomeia a configuração, + o intervalo permitido e o que usar no lugar. Uma configuração desconhecida também é um erro, + nunca um padrão silencioso - um erro de digitação aceito em silêncio dá um arquivo com as + configurações erradas e uma hora se perguntando por que o teste passa quando não deveria. +

+

+ Rode tfg formats <id> para ver exatamente o que um formato aceita na versão que + você tem. +

+
+ +
+

Arquivos compactados contêm arquivos reais

+

+ targz e zip + podem ser preenchidos com entradas em vez de ficarem como uma casca vazia. Um arquivo compactado + gerado realmente contém os documentos que diz conter, então qualquer coisa que o descompacte + durante um teste encontra arquivos reais dentro. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/pt-br/index.html b/web/public/pt-br/index.html new file mode 100644 index 00000000..3e3cd751 --- /dev/null +++ b/web/public/pt-br/index.html @@ -0,0 +1,456 @@ + + + + + + +Gerador de arquivos de teste - tamanho exato, 26 formatos reais + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Gere arquivos de teste reais no tamanho exato

+

+ PDF, PNG, DOCX, ZIP - 26 formatos no total, e cada um é um + arquivo real que abre no programa a que pertence, com exatamente o tamanho que você + pediu. Cada execução também registra o que sua aplicação deve fazer com cada arquivo. + Linha de comando e janela de desktop, gratuito e de código aberto, funcionando inteiramente na + sua máquina. +

+ + +

Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.

+
+ +
+ A janela de desktop do Testing Files Generator, pronta para escrever um lote de arquivos de teste +
A janela de desktop, pronta para escrever um lote de arquivos. O mesmo motor roda por trás da linha de comando.
+
+
+ + + +
+

O problema

+

Fazer um arquivo de teste é fácil. Fazer os mil certos é a parte tediosa

+

Você está testando um software que aceita arquivos de pessoas. Mais cedo ou mais tarde, você precisa de:

+
    +
  • um PDF de exatamente 10 MB, para descobrir se o limite de upload é real
  • +
  • os três arquivos dos dois lados desse limite, para pegar erros de um a mais ou a menos
  • +
  • 10.000 arquivos de log, para ver o que o job noturno faz quando a pasta é grande
  • +
  • um ZIP que realmente contém 200 documentos, não uma casca com a extensão certa
  • +
  • um arquivo de 4 GB, sem guardar um arquivo de 4 GB no seu repositório
  • +
  • as mesmas fixtures no seu notebook e no servidor de build, byte a byte
  • +
+

+ É isso que isto substitui. Foi feito para engenheiros de QA, automação de testes e qualquer pessoa + cujo código tenha atrás um formulário de upload, uma rotina de importação, um parser ou uma cota + de armazenamento. +

+
+ +
+

O que o torna diferente

+

Outros geradores param nos bytes. Este responde ao que o seu teste realmente pergunta

+

+ Uma pasta de arquivos ainda deixa você decidindo o que cada um deve provar. Cada execução aqui + escreve um manifest.json ao lado dos arquivos - uma lista simples de tudo que foi + produzido e, para cada entrada, uma expectativa declarada. +

+

Digamos que seu endpoint de upload permita 1 MB. Peça os três arquivos que ficam nessa linha:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ArquivoBytesSeu sistema devePorque
1mb_under_1b.pdf1048575aceitarestá dentro do limite
1mb_at_limit.pdf1048576aceitaro próprio limite é permitido
1mb_over_1b.pdf1048577rejeitarsize_limit
+
+ +

Três arquivos, três respostas diferentes, em forma legível por máquina. Seu teste lê o manifesto em vez de você escrever as asserções à mão:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Onde a resposta depende da sua própria política, o manifesto diz isso

+

+ Ele registra unspecified em vez de inventar uma expectativa. Um gerador que adivinha + produz falhas falsas, e uma suíte que dá alarme falso acaba desligada. +

+
+
+ +
+

Presets

+

Escolha a pergunta, receba o conjunto inteiro

+

+ Um preset é um conjunto de arquivos de teste desenhado em torno de uma pergunta de teste, para que + você não precise descobrir quais arquivos provam o quê. Cada um tem uma página dizendo o que + costuma encontrar, o que há no conjunto e cada configuração que aceita. +

+
    +
  • +

    Vazio e mínimo

    +

    Um arquivo válido e tão pequeno quanto o formato permite passa?

    +

    empty-and-minimal

    +
  • +
  • +

    Tratamento de nomes de arquivo

    +

    Meu sistema vai guardar, mostrar e devolver um nome de arquivo que ele não esperava?

    +

    filename-handling

    +
  • +
  • +

    Limites de tamanho

    +

    Um limite de tamanho é aplicado exatamente onde foi declarado?

    +

    size-boundaries

    +
  • +
  • +

    Importação de tabelas

    +

    A minha importação de tabelas sobrevive ao que ferramentas reais exportam?

    +

    tabular-import

    +
  • +
  • +

    Codificação de texto

    +

    Meu leitor sabe em que codificação um arquivo está, ou está adivinhando?

    +

    text-encoding

    +
  • +
  • +

    Validação de upload

    +

    Meu formulário de upload aceita o que deve e recusa o resto?

    +

    upload-validation

    +
  • +
+

Todos os presets, e como eles se relacionam com receitas

+
+ +
+

Início rápido

+

Três comandos para ver funcionando

+
    +
  1. +

    Faça um arquivo

    +

    Um PNG, exatamente dois megabytes:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Faça muitos arquivos

    +

    + Dez mil arquivos de log, cada um entre um e oito kilobytes, com os tamanhos sorteados a partir do + seed para que amanhã dê o mesmo conjunto. Dê a cada execução o seu próprio + diretório - o manifesto é o único registro do que uma execução escreveu, então a + ferramenta se recusa a escrever um segundo por cima: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Verifique e depois remova

    +

    verify diz que nada mudou. cleanup remove exatamente o que foi escrito e mais nada:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Os tamanhos contam de 1024 em 1024, como o seu gerenciador de arquivos faz, então 2mb + significa 2097152 bytes. Uma contagem simples de bytes também funciona. A + documentação cobre receitas, o manifesto e os códigos de + saída. +

+
+ +
+

O que você recebe

+

Feito para uma suíte que roda sem supervisão

+
    +
  • +

    Tamanho exato, ao byte

    +

    Peça 10485761 bytes e receba exatamente isso. Um tamanho que um formato não alcança é um erro com um motivo, nunca um arquivo de tamanho errado.

    +
  • +
  • +

    26 formatos reais

    +

    Não são zeros de preenchimento com uma extensão. Um PNG gerado abre em um visualizador de imagens, um DOCX abre no Word, um ZIP extrai. Cada um é verificado com leitores independentes antes de ser liberado.

    +
  • +
  • +

    Um manifesto que é um oráculo de teste

    +

    Caminho, tamanho, SHA-256, formato, seed, versão da ferramenta - e o que seu sistema deve fazer com o arquivo.

    +
  • +
  • +

    Reproduzível

    +

    Mesma receita e mesmo seed, mesmos bytes, em qualquer máquina. Versione uma pequena receita YAML em vez de fixtures binárias grandes.

    +
  • +
  • +

    Duas interfaces, um motor

    +

    Uma linha de comando feita para CI e uma janela de desktop para testes exploratórios. Nenhuma é uma versão reduzida da outra, e um teste compara as duas capacidade por capacidade.

    +
  • +
  • +

    Totalmente offline

    +

    Sem conta, sem nuvem, sem telemetria, sem verificação de atualizações. O binário da linha de comando não tem nenhuma pilha de rede compilada nele.

    +
  • +
+
+ +
+

Download

+

Escolha a versão para o seu sistema

+

+ Descompacte o arquivo e execute. tfg é a linha de comando e tfg-gui é a + janela de desktop. Não há instalador e nada para adicionar à sua máquina. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemaLinha de comandoJanela de desktop
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

O que é assinado e o que não é

+

+ Os downloads de Windows e macOS são assinados, então iniciam sem aviso de desenvolvedor + desconhecido. Os de Linux não são, porque o Linux de desktop não tem equivalente para + assiná-los. Cada arquivo está listado em verify-SHA256SUMS.txt na página de + releases, para que você possa conferir o que baixou. +

+
+ +

Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.

+
+ + +
+ + + + diff --git a/web/public/pt-br/perguntas-frequentes/index.html b/web/public/pt-br/perguntas-frequentes/index.html new file mode 100644 index 00000000..97ea06a9 --- /dev/null +++ b/web/public/pt-br/perguntas-frequentes/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - perguntas sobre gerar arquivos de teste + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Perguntas frequentes

+

+ Licença, privacidade, reprodutibilidade e o que as pessoas conferem antes de colocar um gerador em + um pipeline de build. Se a sua pergunta não está aqui, o rastreador + de issues está aberto. +

+ +
+
+

Como isso é diferente de dd, fsutil ou truncate?

+
+

Esses comandos dão um arquivo do tamanho certo cheio de nada. Um arquivo de 2 MB chamado photo.png feito assim não é um PNG, então qualquer coisa que realmente o interprete o recusa pelo motivo errado, e o seu teste também passa pelo motivo errado. Isto produz um PNG real de exatamente 2 MB que abre em um visualizador de imagens e vem com uma declaração de como o seu sistema deve tratá-lo.

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

É gratuito, e posso usar no trabalho?

+
+

Sim para os dois. É distribuído sob a GPL-3.0 e não custa nada. Não há conta, chave de licença nem plano pago.

+
+
+
+

Posso usar os arquivos gerados em um produto de código fechado?

+
+

Sim. A licença cobre o código da ferramenta, não o que ela produz. Arquivos, receitas e manifestos gerados são saída e não obras derivadas, então você pode versioná-los e distribuí-los sem nenhuma obrigação.

+
+
+
+

Os arquivos gerados contêm dados pessoais reais?

+
+

Não. Tudo dentro deles é sintetizado a partir de um seed. Nenhum conjunto de dados é lido, nenhum serviço é contatado e nenhum conteúdo de terceiros é embutido. Trate um endereço de e-mail gerado como inutilizável em vez de não usado, porque qualquer texto aleatório pode coincidir por acaso com um real.

+
+
+
+

Vou obter exatamente os mesmos arquivos em outra máquina?

+
+

Sim, byte a byte, com a mesma receita e o mesmo seed. O projeto testa isso a cada mudança, e quebrá-lo exige uma versão maior. É isso que permite versionar uma receita pequena em vez de fixtures binárias grandes.

+
+
+
+

Precisa de conexão com a internet?

+
+

Nunca. Não há telemetria, verificação de atualizações nem cliente de nuvem, e o binário da linha de comando não tem pilha de rede compilada nele. Funciona em uma máquina sem rede e dentro de um ambiente corporativo fechado.

+
+
+
+

O que acontece se eu pedir um tamanho que um formato não consegue alcançar?

+
+

Você recebe um erro que nomeia o formato, o menor tamanho possível, o motivo desse piso e o que fazer em vez disso, e nenhum arquivo é escrito. A ferramenta nunca arredonda um tamanho em silêncio. Cada piso está listado na página de formatos.

+
tfg formats png
+
+
+
+

Posso gerar um arquivo deliberadamente quebrado?

+
+

Sim. Adicione --damage zero-head e o arquivo sai com exatamente o tamanho pedido, com os primeiros bytes sobrescritos por zeros, de modo que um leitor o recusa, e o manifesto diz que o seu sistema deve rejeitá-lo. A página sobre arquivos de teste corrompidos traz os detalhes.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Quais formatos vêm a seguir?

+
+

7z, mp3 e mp4. Hoje 26 formatos funcionam de ponta a ponta.

+
+
+
+

Em quais sistemas posso rodar?

+
+

A linha de comando roda em Windows e Linux, tanto em Intel quanto em ARM, e em Macs com Apple Silicon. A janela de desktop é distribuída para Windows em Intel, Linux em Intel e Macs com Apple Silicon. Macs Intel não são suportados e nada é compilado para eles.

+
+
+
+

Preciso instalar alguma coisa?

+
+

Não. Baixe o arquivo do seu sistema, descompacte e execute o binário. Não há instalador, runtime para adicionar nem dependência para resolver. Se você tem Go, um único comando go install também funciona.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Por que uma execução sobre milhares de arquivos é mais lenta no Windows?

+
+

Porque o Windows cobra mais por cada caminho que examina, e um comando que percorre milhares de arquivos examina milhares de caminhos. Medido em uma máquina com 3000 arquivos de 1 kB, o verify leva cerca de 0,9 segundo no Windows e cerca de 0,2 segundo no Linux em um contêiner. Um caminho de saída mais curto reduz o valor do Windows, porque cada pasta acima dos arquivos faz parte do que é examinado.

+
+
+
+ + +
+

Ainda decidindo?

+

+ A página de casos de uso mostra as tarefas para as quais foi + feito, e a página de formatos lista cada formato com o menor + arquivo que ele pode produzir. O README do repositório é a + referência completa. +

+ +

Gratuito e de código aberto, GPL-3.0. Sem cadastro. Os downloads de Windows e macOS são assinados e iniciam sem aviso.

+
+ +
+ + + + diff --git a/web/public/pt-br/presets/empty-and-minimal/index.html b/web/public/pt-br/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..a42cba05 --- /dev/null +++ b/web/public/pt-br/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Menores arquivos de teste válidos e vazios em cada formato + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Vazio e mínimo

+

Um arquivo válido e tão pequeno quanto o formato permite passa?

+

+ O preset empty-and-minimal monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • um arquivo válido recusado por ser pequeno demais, porque a verificação conta bytes em vez de lê-los
  • +
  • um arquivo vazio que derruba o leitor em vez de ser reportado
  • +
  • uma imagem de um pixel de largura que divide por zero a caminho da miniatura
  • +
  • um armazenamento que lê zero byte como upload com falha e fica tentando de novo
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show empty-and-minimal informa:

+
+ + + + + + + +
Arquivos28
Targets na sua receita28
Tamanho total32 667 B
Formatosavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.26
unspecifiedDepende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria.2
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--formatsids de formato separados por vírgulas, ou allallDe quais formatos o conjunto é feito. Deixe em all para todos os formatos desta versão, ou nomeie os que o seu sistema aceita.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/pt-br/presets/filename-handling/index.html b/web/public/pt-br/presets/filename-handling/index.html new file mode 100644 index 00000000..b172a105 --- /dev/null +++ b/web/public/pt-br/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Nomes de arquivo problemáticos para testar - Unicode e tamanho + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Tratamento de nomes de arquivo

+

Meu sistema vai guardar, mostrar e devolver um nome de arquivo que ele não esperava?

+

+ O preset filename-handling monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • um nome que parece outro na tela, em um log ou em uma lista
  • +
  • um nome cortado, aparado ou reescrito entre o upload e o armazenamento
  • +
  • um limite de tamanho contado em caracteres onde o armazenamento conta bytes
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show filename-handling informa:

+
+ + + + + + + +
Arquivos50
Targets na sua receita50
Tamanho total51 200 B
Formatostxt
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.4
unspecifiedDepende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria.46
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--formatum id de formato da página de formatostxtO formato de cada arquivo do conjunto. É uma opção da própria ferramenta, e o preset apenas dá a ela um valor padrão.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/pt-br/presets/index.html b/web/public/pt-br/presets/index.html new file mode 100644 index 00000000..80a00eb7 --- /dev/null +++ b/web/public/pt-br/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +Presets de arquivos de teste - conjuntos prontos para QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Presets de arquivos de teste, um conjunto para cada pergunta de teste

+

+ Um preset é um conjunto inteiro de arquivos de teste desenhado em torno de uma pergunta, com um + manifesto dizendo como seu sistema deve reagir a cada arquivo. Você escolhe a pergunta, a + ferramenta monta o conjunto. Cada preset tem sua própria página com o que costuma encontrar, o que + há no conjunto e cada configuração que aceita. +

+ + + +
+

Como um preset é diferente de uma receita?

+

+ Por baixo, não é. Um preset é uma receita que a ferramenta escreve para você a partir de algumas + configurações. tfg preset eject imprime essa receita para você guardá-la ao lado + dos seus testes e editá-la, e uma receita sua pode se basear em um preset com uma linha, + extends: preset: seguido do id dele. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Posso confiar nos valores padrão?

+

+ Para os arquivos, sim. Para um número que só o seu sistema conhece, como o limite de um formulário + de upload, um valor padrão é um provisório nosso, e a ferramenta diz isso toda vez que usa um. A + página de cada preset marca essas configurações, e tfg preset show diz isso antes + de qualquer coisa ser escrita. +

+
+ +
+ + + + diff --git a/web/public/pt-br/presets/size-boundaries/index.html b/web/public/pt-br/presets/size-boundaries/index.html new file mode 100644 index 00000000..0236a80f --- /dev/null +++ b/web/public/pt-br/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Testar um limite de tamanho de upload - arquivos no limite exato + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Limites de tamanho

+

Um limite de tamanho é aplicado exatamente onde foi declarado?

+

+ O preset size-boundaries monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • erros de um a mais ou a menos no limite
  • +
  • MB confundido com MiB, que dá 4,8 por cento e basta para deixar passar um arquivo que não deveria passar
  • +
  • um limite aplicado no navegador e não no servidor
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show size-boundaries informa:

+
+ + + + + + + +
Arquivos7
Targets na sua receita7
Tamanho total73 400 320 B
Formatospdf
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.4
rejectSeu sistema deve recusar o arquivo.3
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--limitum tamanho como 2mb10mbO limite de tamanho que seu sistema declara. Todo o resto é medido a partir dele. Este valor padrão é o nosso provisório, não o valor do seu sistema. Passe o seu.
--spreadtamanhos separados por vírgulas1B,1kb,1mbAté onde ir de cada lado do limite, como uma lista de tamanhos.
--formatum id de formato da página de formatospdfO formato de cada arquivo do conjunto. É uma opção da própria ferramenta, e o preset apenas dá a ela um valor padrão.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

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

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/pt-br/presets/tabular-import/index.html b/web/public/pt-br/presets/tabular-import/index.html new file mode 100644 index 00000000..7721c922 --- /dev/null +++ b/web/public/pt-br/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Arquivos de teste para importar CSV e Excel - delimitadores + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Importação de tabelas

+

A minha importação de tabelas sobrevive ao que ferramentas reais exportam?

+

+ O preset tabular-import monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • um arquivo com ponto e vírgula lido como uma coluna só, porque o delimitador foi presumido em vez de procurado
  • +
  • um arquivo CRLF dividido em linhas com uma linha vazia depois de cada uma
  • +
  • uma tabela sem cabeçalho cuja primeira linha de dados é engolida como nomes de coluna
  • +
  • uma importação que mantém as colunas que consegue mostrar e descarta o resto sem dizer nada
  • +
  • um leitor que lê registros JSON uma linha por vez e para no primeiro documento indentado
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show tabular-import informa:

+
+ + + + + + + +
Arquivos13
Targets na sua receita13
Tamanho total3 080 060 B
Formatoscsv, json, xlsx
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.8
unspecifiedDepende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria.5
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--rows1 - 200000 linhas1000Quantas linhas a planilha tem. Ela é escrita exatamente no tamanho que essas linhas ocupam, então o orçamento acima muda com este valor.
--columns1 - 32768 colunas10Quantas colunas cada linha da planilha tem. Linhas vezes colunas tem um teto, e pedir além disso é recusado antes de escrever qualquer coisa.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/pt-br/presets/text-encoding/index.html b/web/public/pt-br/presets/text-encoding/index.html new file mode 100644 index 00000000..d96b7103 --- /dev/null +++ b/web/public/pt-br/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Arquivos de teste de codificação - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Codificação de texto

+

Meu leitor sabe em que codificação um arquivo está, ou está adivinhando?

+

+ O preset text-encoding monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • um leitor que presume UTF-8 e mostra um arquivo UTF-16 com um caractere a cada três, ou como fileiras de quadradinhos
  • +
  • uma marca de ordem de bytes lida como conteúdo, de modo que o primeiro campo de uma importação começa com três caracteres estranhos
  • +
  • um importador que adivinha a codificação pelos primeiros bytes e adivinha diferente num arquivo mais longo
  • +
  • um arquivo CRLF dividido em linhas com uma linha vazia depois de cada uma, ou um retorno de carro que sobra dentro do último campo
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show text-encoding informa:

+
+ + + + + + + +
Arquivos20
Targets na sua receita20
Tamanho total81 920 B
Formatoscsv, log, md, txt, xml
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.10
unspecifiedDepende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria.10
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--sampleum tamanho como 2mb4kbO tamanho de cada arquivo do conjunto. UTF-16 guarda dois bytes por caractere, então um número ímpar é recusado.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/pt-br/presets/upload-validation/index.html b/web/public/pt-br/presets/upload-validation/index.html new file mode 100644 index 00000000..03b0600a --- /dev/null +++ b/web/public/pt-br/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Arquivos de teste de validação de upload - tipo, tamanho e nome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presets

+

Validação de upload

+

Meu formulário de upload aceita o que deve e recusa o resto?

+

+ O preset upload-validation monta com um único comando um conjunto inteiro de arquivos de teste + reais para esta pergunta, e um manifest.json ao lado dizendo como seu sistema deve + reagir a cada arquivo. Tudo abaixo é lido do programa, com os valores padrão desta versão. +

+ + +
+

O que ele costuma encontrar?

+
    +
  • um limite aplicado no navegador e não no servidor
  • +
  • um SVG ou HTML tomado por imagem ou por texto simples, que é um jeito de passar um script por um formulário
  • +
  • um arquivo verificado pela extensão e nunca aberto, de modo que um PDF chamado .jpg passa
  • +
  • um formulário que lê o corpo inteiro na memória antes de olhar o tamanho
  • +
  • um upload chamado PHOTO.JPG recusado onde photo.jpg é aceito, ou o contrário
  • +
  • um nome com espaços, parênteses ou caracteres fora do ASCII gravado em disco sem alteração
  • +
+
+ + +
+

O que há no conjunto?

+

Com os valores padrão, como o tfg preset show upload-validation informa:

+
+ + + + + + + +
Arquivos71
Targets na sua receita22
Tamanho total120 639 488 B
Formatoshtml, jpg, pdf, png, svg, txt
+
+

E o que o manifesto desse conjunto espera do seu sistema:

+
+ + + + + + + + + +
EsperadoSignificadoArquivos
acceptSeu sistema deve aceitar o arquivo.56
rejectSeu sistema deve recusar o arquivo.10
unspecifiedDepende das regras do seu sistema. Você decide e depois confere se o que acontece é o que você queria.5
+
+
+ +
+

O que você pode mudar?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfiguraçãoAceitaPadrãoO que faz
--limitum tamanho como 2mb10mbO limite de tamanho que seu formulário de upload declara. Este conjunto dá um passo para cada lado - para um arquivo em cada distância, rode o preset size-boundaries. Este valor padrão é o nosso provisório, não o valor do seu sistema. Passe o seu.
--allowids de formato separados por vírgulasjpg,png,pdfQuais tipos seu formulário deve aceitar. Cada um vira um arquivo real desse tipo, e eles são o controle positivo do conjunto todo.
--denyextensões separadas por vírgulassvg,html,exe,shQuais extensões seu formulário deve recusar. Uma extensão para a qual esta versão não tem formato ainda recebe um arquivo com esse nome, com texto simples.
--far-over10x, 2x, off2xO quanto acima do limite vai o único arquivo grande. Desligue onde escrever várias vezes o limite não vale o disco.
--bulk0 - 10000 arquivos50Quantos arquivos o upload em massa contém. Zero deixa esse grupo totalmente fora do conjunto.
+
+
+ +
+

Como executar?

+

Veja quanto o conjunto custaria, monte-o ou pegue a receita dele para editar:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Ou construa sobre ele em uma receita sua, ao lado dos seus testes:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ro/cazuri-de-utilizare/index.html b/web/public/ro/cazuri-de-utilizare/index.html new file mode 100644 index 00000000..3fadfbca --- /dev/null +++ b/web/public/ro/cazuri-de-utilizare/index.html @@ -0,0 +1,319 @@ + + + + + + +Cazuri de utilizare - limite de încărcare, fixture-uri, teste + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Pentru ce îl folosesc oamenii

+

+ Cinci sarcini care apar în aproape orice proiect care primește fișiere de la oameni și comanda care + face fiecare. Fiecare exemplu de mai jos rulează așa cum e scris. +

+ +
+

Limite de încărcare

+

Testarea dacă o limită de dimensiune a fișierelor este aplicată acolo unde spune că este

+

+ O limită înseamnă trei cazuri de test, nu unul: puțin sub, exact pe ea și puțin peste. Să le faci de + mână înseamnă să calculezi numere de octeți și să speri că n-ai greșit cu unu. Cere în schimb + setul: +

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

+ Primești trei PDF-uri reale de 1048575, 1048576 și 1048577 de octeți și un manifest care spune că + primele două trebuie acceptate, iar al treilea respins pentru size_limit. Testul + tău citește așteptarea în loc să scrii tu trei asertări de mână - iar când limita se schimbă, + schimbi un număr și rulezi din nou. +

+

+ La fel merge fără presetare când vrei un singur set de limite inline: +

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

Integrare continuă

+

Ținerea fixture-urilor în afara repository-ului fără a le pierde

+

+ Fixture-urile binare mari fac un repository lent la clonare și incomod la revizuire, și nimeni nu + poate spune ce s-a schimbat când una e înlocuită. O rețetă este câteva sute de caractere de YAML + care reconstruiesc fișierele identice - octet cu octet, pe orice mașină - + pentru că fiecare fișier derivă din seed-ul rulării. +

+
- 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
+

+ Fiecare final are propriul cod de ieșire, așa că un pipeline poate deosebi o rețetă proastă de un + disc plin și de o nepotrivire la verificare. O rulare eșuată nu tipărește nimic la ieșirea + standard, ceea ce împiedică un parser de jurnale să citească o eroare drept date. +

+
+ +
+

Scară

+

Aflarea a ce se întâmplă când folderul e mare

+

+ Rutinele de import, joburile de noapte și listările de directoare se comportă altfel la zece mii de + fișiere decât la zece. Dimensiunile extrase dintr-un interval fac setul să semene cu trafic + real, nu cu zece mii de fișiere identice, iar extragerea vine din seed, deci setul e același + mâine. +

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

+ Verifică cât ar costa o rulare înainte să scrie ceva, ceea ce contează când totalul se măsoară în + gigaocteți: +

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

+ O rulare mai mare decât spațiul liber de pe disc este refuzată înainte de a se scrie primul octet, + în loc să umple discul și să eșueze pe la jumătate. +

+
+ +
+

Arhive

+

Testarea unui dezarhivator cu o arhivă care conține cu adevărat fișiere

+

+ O arhivă goală cu extensia potrivită nu dovedește nimic despre codul care o deschide și parcurge ce + e înăuntru. Declară conținutul și arhiva îl conține cu adevărat: +

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

+ Adâncimea de imbricare, numărul de intrări și dimensiunea a ce e înăuntru sunt toate lucruri despre + care o rutină de import are păreri, iar așa afli care sunt acele păreri. +

+
+ +
+

Parsere și vizualizatoare

+

Verificarea că propriul tău cod citește un format cum o face software-ul real

+

+ Fiecare format de aici este verificat cu un cititor independent înainte de livrare - un PNG este + deschis și pixelii lui comparați, un DOCX este recitit de biblioteci separate, o arhivă este + extrasă. Asta înseamnă că un fișier pe care parserul tău îl respinge este o constatare despre + parserul tău, nu despre 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
+

+ Pagina de formate listează setările pe care le acceptă fiecare format și + cel mai mic fișier posibil pentru fiecare. +

+
+ +
+

Ghiduri

+

Două dintre ele mai în detaliu

+
    +
  • + Fișiere de test corupte - un fișier stricat intenționat, + de mărime exactă, cu ce trebuie să se întâmple cu el scris în manifest. +
  • +
  • + Fișiere de test în CI - un workflow GitHub Actions, un job + GitLab și codurile de ieșire care fac un build să eșueze. +
  • +
+
+ +
+

Pentru cine este

+

+ Ingineri QA, automatizarea testelor și oricine are în spatele codului un formular de încărcare, o + rutină de import, un parser sau o cotă de stocare. Rulează pe o mașină fără nicio rețea, ceea ce + contează într-un mediu corporativ închis unde un generator din browser nu e o opțiune. +

+ +

Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.

+
+ +
+ + + + diff --git a/web/public/ro/creare-fisier-de-dimensiune-exacta/index.html b/web/public/ro/creare-fisier-de-dimensiune-exacta/index.html new file mode 100644 index 00000000..2788b906 --- /dev/null +++ b/web/public/ro/creare-fisier-de-dimensiune-exacta/index.html @@ -0,0 +1,331 @@ + + + + + + +Cum creezi un fișier de dimensiune exactă - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cum creezi un fișier de dimensiune exactă

+

+ Fiecare sistem are o comandă pentru asta, iar toate trei sunt mai jos. Îți dau un fișier cu exact + numărul potrivit de octeți - și pentru multe teste atât îți trebuie. Fiecare comandă de pe + această pagină a fost rulată înainte de publicare, pe sistemul căruia îi aparține. +

+ +
+

Răspunsul scurt

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Dimensiunile sunt în octeți, iar 10 + MB numărați cum numără managerul tău de fișiere sunt 10485760. +

+
+ +
+

Windows

+

fsutil și o variantă PowerShell care nu are nevoie de nimic în plus

+

+ fsutil vine cu Windows. Primește dimensiunea în octeți, așa că + calculează mai întâi numărul - 10 MB sunt 10485760, 100 MB sunt 104857600, 1 GB este 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Măsurat pe Windows 11: merge dintr-un prompt obișnuit, fără să ceară unul cu privilegii ridicate, + iar fișierul iese de exact 10485760 de octeți. +

+

PowerShell poate face același lucru fără să cheme alt program și înțelege unitățile:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB în PowerShell înseamnă 10485760 de octeți, aceeași numărare în baza 1024 pe care o + folosește Explorer, deci cele două comenzi de mai sus produc aceeași dimensiune. +

+
+ +
+

Linux

+

dd, truncate și fallocate, și diferența care îi prinde pe oameni

+

dd este cel pe care îl știe toată lumea. Scrie într-adevăr octeții:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate e instantaneu și asta e capcana. Măsurat pe Alpine Linux, fișierul raportează + 10485760 de octeți și ocupă zero blocuri - este un fișier rar + (sparse). Tot ce îl citește primește zece megaocteți de zerouri, dar discul nu a cedat niciodată + spațiul: +

+
truncate -s 10M test10mb.bin
+

+ E bine pentru a testa o limită de încărcare și înșelător pentru a testa o cotă de disc. + fallocate este cel de folosit când spațiul trebuie să fie real: +

+
fallocate -l 10M test10mb.bin
+

Și când conținutul trebuie să fie incompresibil, ca un arhivator să nu-l poată strânge la loc:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, care nu e rar, și cele două pe care le știi deja

+

+ macOS vine cu mkfile. Măsurat pe macOS 26.6.2: 10485760 de octeți și 20480 de blocuri, + deci spațiul este alocat cu adevărat, nu doar promis: +

+
mkfile 10m test10mb.bin
+

dd și truncate sunt și ele acolo și se comportă ca pe Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Unde nu mai merge asta

+

Un fișier de dimensiunea potrivită nu este un fișier de tipul potrivit

+

+ Tot ce e mai sus îți dă un bloc de zerouri. Asta ajunge când ce se testează se uită doar la + dimensiune - o limită de încărcare, o cotă, un transfer. Nu mai ajunge din clipa în care ceva + deschide fișierul. +

+

+ Măsurat, și merită să încerci singur: fă un fișier de 2 MB cu fsutil, numește-l + photo.png și dă-l unei biblioteci de imagini. Pillow răspunde cannot identify + image file. Nu e un PNG. N-a fost niciodată - doar numele o spunea. +

+

+ Contează mai mult decât pare, din cauza direcției în care eșuează testul. + Endpointul tău de încărcare respinge fișierul, testul tău devine verde și tragi concluzia că + limita de dimensiune funcționează. Nu l-a respins pentru dimensiune. L-a respins pentru că + octeții nu erau o imagine, iar regula pe care voiai s-o testezi n-a fost niciodată atinsă. +

+
    +
  • un parser îl respinge înainte să se uite vreo regulă de dimensiune
  • +
  • un pas de miniatură eșuează și eroarea pe care o citești e despre miniatură
  • +
  • un antivirus sau o verificare de conținut îl refuză dintr-un al treilea motiv
  • +
  • un vizualizator nu arată nimic și nimeni nu poate spune dacă asta e bug-ul
  • +
+
+ +
+

Cealaltă cale

+

Un fișier real de acel format, la exact dimensiunea cerută

+

+ Asta face Testing Files Generator. Fișierul este unul autentic al formatului său - se deschide în + programul căruia îi aparține - și are numărul exact de octeți pe care l-ai cerut, la octet: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Cere o dimensiune pe care un format nu o poate atinge și primești o eroare care numește pragul și + motivul lui, niciodată un fișier de dimensiune greșită. Pagina de + formate listează fiecare format cu cel mai mic fișier pe care îl poate produce. +

+

Iar o limită înseamnă trei cazuri de test, nu unul, așa că instrumentul le construiește pe toate trei:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Asta îți dă 10485759, 10485760 și 10485761 de octeți și un manifest care spune pe care sistemul tău + trebuie să le accepte și pe care să le respingă. Pagina de + cazuri de utilizare parcurge asta și alte patru sarcini pentru care a fost făcut. +

+ +

Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.

+
+ +
+

Deci pe care să-l folosești?

+
    +
  • +

    Folosește comanda sistemului

    +

    + Când nimic nu deschide fișierul. Testarea unei limite de dimensiune pe un endpoint care verifică + întâi dimensiunea, un transfer, o cotă, un disc plin. E o singură linie și e deja instalat. +

    +
  • +
  • +

    Folosește un generator adevărat

    +

    + Când ceva analizează, randează, importă sau extrage fișierul - și când ai nevoie de aceleași + fixture-uri mâine, pe altă mașină, octet cu octet. +

    +
  • +
+

+ Ambele sunt pe această pagină pentru că ambele au dreptate o parte din timp. Greșeala de evitat este + să-l folosești pe primul unde îl trebuie pe al doilea și să citești testul verde drept dovadă. +

+
+ +
+ + + + diff --git a/web/public/ro/documentatie/index.html b/web/public/ro/documentatie/index.html new file mode 100644 index 00000000..fb869966 --- /dev/null +++ b/web/public/ro/documentatie/index.html @@ -0,0 +1,559 @@ + + + + + + +Documentație - comenzi, rețete, manifest, coduri de ieșire + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

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țiuneCe 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-runnumără și arată, nu scrie absolut nimic
--jsonscrie 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: accept alături de o deteriorare, pentru că nimic nu l-ar putea îndeplini. + Scrie sanitize dacă sistemul testat trebuie să repare fișierul sau + unspecified dacă 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ă. +

+
    +
  • +

    Gol și minimal

    +

    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

    +
  • +
  • +

    Limite de dimensiune

    +

    Este o limită de dimensiune aplicată exact acolo unde este declarată?

    +

    size-boundaries

    +
  • +
  • +

    Import de tabele

    +

    Supraviețuiește importul meu de tabele la ce exportă instrumentele reale?

    +

    tabular-import

    +
  • +
  • +

    Codarea textului

    +

    Știe cititorul meu în ce codare este un fișier sau doar ghicește?

    +

    text-encoding

    +
  • +
  • +

    Validarea încărcării

    +

    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ă. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodSemnificație
0Totul a mers.
1O eroare neașteptată în interiorul instrumentului.
2Comandă sau opțiune greșită.
3Rețeta nu este validă.
4Formatul nu poate face ce s-a cerut.
5O citire sau o scriere a eșuat.
6Nu este destul spațiu pe disc.
7verify a găsit o nepotrivire.
8Rularea s-a terminat, dar nu s-a produs totul.
130Întreruptă cu Ctrl+C.
143Oprită 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. +

+
+ +
+ + + + diff --git a/web/public/ro/fisiere-de-test-corupte/index.html b/web/public/ro/fisiere-de-test-corupte/index.html new file mode 100644 index 00000000..15e337a4 --- /dev/null +++ b/web/public/ro/fisiere-de-test-corupte/index.html @@ -0,0 +1,384 @@ + + + + + + +Fișiere de test corupte - fișiere stricate de mărime exactă + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cazuri de utilizare

+

Cum faci un fișier corupt pentru teste

+

+ Un validator căruia i s-au arătat doar fișiere sănătoase nu a fost cu adevărat testat. Iată cum + obții un fișier stricat intenționat, care iese cu exact mărimea pe care o ceri și + vine cu un manifest care spune ce trebuie să facă sistemul tău cu el. +

+ +
+

Răspunsul scurt

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out scrie un PNG de + exact 2097152 de octeți ai cărui primi octeți sunt zerouri, iar manifestul de lângă el notează + că sistemul tău trebuie să îl respingă. +

+
+ +
+

Calea obișnuită

+

De ce un fișier corupt de mână face un test prost

+

+ Căile obișnuite sunt un editor hexazecimal, un script care schimbă câțiva octeți la întâmplare sau + un fișier scurtat cu head ori truncate. Merg o dată, apoi te costă: +

+
    +
  • + Este altfel de fiecare dată. Un octet ales la întâmplare cade în alt loc la fiecare + rulare, deci o eroare de marți poate să nu se mai întoarcă miercuri. +
  • +
  • + Schimbă mărimea. Un fișier tăiat este mai mic decât limita sub care trebuia să + stea, deci verificarea mărimii răspunde înaintea celei a conținutului, iar testul trece din + motivul greșit. +
  • +
  • + Adesea trece neobservat. Textul simplu se citește în continuare cu un octet + schimbat la mijloc, iar un cititor de imagini îngăduitor îl desenează pur și simplu, așa că + fișierul care trebuia să fie stricat este acceptat. +
  • +
  • + Nu spune nimic despre ce trebuie să se întâmple. Fișierul este doar octeți, iar + cine citește testul mai târziu trebuie să ghicească dacă s-a urmărit acceptarea sau + respingerea. +
  • +
+
+ +
+

Ce primești

+

Un fișier deteriorat are în continuare mărimea cerută

+

+ Fișierul este generat normal și stricat după aceea, pe drumul spre disc. Păstrează mărimea cerută, + iar aceeași comandă scrie din nou aceiași octeți. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Setările se scriu după două puncte. Opțiunea poate fi repetată, iar deteriorările se aplică în + ordinea în care le scrii. Funcționează cu fiecare dintre cele 26 formate. +

+
+ +
+

Ce poate face

+

Ce deteriorări există?

+

+ Aceasta este lista pe care o afișează programul, citită din el când se construiește pagina. + tfg damage o afișează pe aceeași, iar tfg damage <id> spune ce + primește una dintre ele. +

+
+ + + + + + + + + + + + + + + + + +
DeteriorareCe face cu octețiiCel mai mic fișierSetări
zero-headSuprascrie cu zerouri primii octeți ai fișierului, fără să îi schimbe lungimea. Majoritatea cititorilor se uită întâi acolo, deci aproape orice observă această deteriorare.8bytes
+
+

+ zero-head scrie zerouri peste începutul fișierului. Majoritatea cititorilor se uită + întâi acolo, la semnătura și antetul care spun ce este fișierul, așa că aproape orice cititor + observă. Textul simplu și jurnalele nu au semnătură și sunt respinse și ele, pentru că un șir de + octeți nuli nu este text. Sub patru octeți, unele formate ies cu o deteriorare de care nu se + plânge niciun cititor, de aceea setarea începe de la patru. +

+
+ +
+

Ce spune manifestul

+

Un manifest care spune ce trebuie să se întâmple

+

+ Fiecare fișier deteriorat primește o intrare care spune că sistemul tău trebuie să îl respingă, cu + deteriorarea notată alături: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Două cereri sunt refuzate înainte să se scrie ceva, pentru că fiecare ar lăsa pe disc un fișier pe + care manifestul îl descrie greșit: +

+
    +
  • un fișier mai mic decât are nevoie deteriorarea, care ar ieși neschimbat
  • +
  • + expected: accept lângă o deteriorare, pentru că nimic nu ar putea îndeplini asta. Scrie + sanitize dacă sistemul tău trebuie să repare fișierul sau + unspecified dacă tocmai asta este întrebarea pe care o pui +
  • +
+
+ +
+

Într-o rețetă

+

Fișiere sănătoase și stricate într-o singură rulare

+

+ Pune-le pe amândouă într-o rețetă, iar manifestul poartă așteptarea fiecărui fișier, deci testul nu + are nevoie de o listă cu care este care: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Într-un test

+

Transformarea într-un test

+

+ Testul citește manifestul și verifică dacă ce s-a întâmplat este ce s-a declarat. Nu are nevoie de o + listă de nume de fișiere: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ O respingere bună este una curată. Un mesaj care spune ce a fost greșit este răspunsul pe care îl + vrei. O eroare de server, o blocare sau un fișier salvat pe jumătate este defectul pe care acest + test există ca să îl găsească. +

+
+ +
+

Mai departe

+

Unde să mergi de aici

+ +
+ +
+ + + + diff --git a/web/public/ro/fisiere-de-test-in-ci/index.html b/web/public/ro/fisiere-de-test-in-ci/index.html new file mode 100644 index 00000000..c6d937f5 --- /dev/null +++ b/web/public/ro/fisiere-de-test-in-ci/index.html @@ -0,0 +1,380 @@ + + + + + + +Fișiere de test în CI - GitHub Actions, GitLab CI și PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cazuri de utilizare

+

Cum generezi fișiere de test într-un pipeline CI

+

+ Un fixture binar într-un repository rămâne pentru totdeauna în istoricul lui, nu poate fi revizuit + într-un diff și devine imposibil când fișierul este mare. Generează în schimb fișierele în + pipeline, dintr-o rețetă. Rețeta este text, octeții ies la fel de fiecare dată, iar un ultim pas + dovedește că nimic nu s-a mișcat. +

+ +
+

Răspunsul scurt

+

+ Instalează tfg, rulează tfg generate fixtures.yaml --out ./fixtures + înaintea testelor și tfg verify ./fixtures/manifest.json după ele. Ambii pași fac + singuri build-ul să eșueze, cu un cod de ieșire care spune de ce. +

+
+ +
+

De ce să nu le comiți

+

De ce un fixture nu trebuie să stea în repository

+
    +
  • + Rămâne în istoric. Ștergerea ulterioară a unui binar nu face un clon mai mic, + pentru că fiecare versiune a lui este încă acolo. +
  • +
  • + Un diff nu arată ce s-a schimbat. Cel care revizuiește vede că un PDF este diferit + și nimic altceva. O rețetă se schimbă cu o linie. +
  • +
  • + Fișierele mari nu încap. GitHub refuză un push care conține un fișier de peste 100 + MB, așa că un test al unei limite de încărcare de 500 MB nu are ce comite. +
  • +
+

+ Ce trebuie comis este rețeta. Aceeași rețetă și același seed scriu aceiași octeți pe orice mașină, + deci fișierul generat în pipeline este fișierul pe care l-ai avut pe laptop. +

+
+ +
+

Rețeta

+

O rețetă care stă lângă teste

+

+ Aceasta scrie douăzeci și cinci de facturi care trebuie acceptate și două imagini peste o limită + care trebuie respinse, iar manifestul notează ambele așteptări: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml o verifică fără să scrie nimic și numește toate problemele + deodată. +

+
+ +
+

GitHub Actions

+

Un workflow care instalează instrumentul și construiește fixture-urile

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Linia cu suma de control compară arhiva cu verify-SHA256SUMS.txt din aceeași versiune. + Versiunea este fixată, așa că o versiune nouă nu schimbă niciodată un build pe care nu l-ai + atins. +

+
+ +
+

GitLab CI

+

Același lucru ca job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Când se face roșu

+

Ce face un pas să eșueze, și de ce

+

+ Fiecare final are propriul cod de ieșire, deci pasul eșuează singur, iar jurnalul spune care a fost. + Cele pe care le întâlnește un pipeline: +

+
    +
  • 3 - rețeta nu este validă. Nu s-a scris nimic, iar fiecare problemă este numită
  • +
  • 4 - formatul nu poate face ce s-a cerut, de exemplu o mărime sub minimul lui
  • +
  • 6 - nu este destul spațiu pe disc
  • +
  • 7 - tfg verify a găsit un fișier care nu se potrivește cu manifestul lui
  • +
  • 8 - rularea s-a încheiat, dar nu s-a produs totul
  • +
+

+ O rulare eșuată nu afișează nimic la ieșirea standard, așa că un parser de jurnale nu ia niciodată o + eroare drept date. Tabelul complet este pe pagina de + documentație. +

+
+ +
+

PowerShell

+

Un script PowerShell mai are nevoie de o linie

+

+ PowerShell nu scoate codul de ieșire al unui program dintr-un fișier .ps1. Rulează unul + cu -File și scriptul răspunde 0 chiar și când instrumentul dinăuntru a + refuzat lucrul, așa că un build care ar trebui să fie roșu devine verde. Ultima linie este toată + soluția: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Așa se comportă PowerShell, nu este ceva legat de acest instrument. cmd, + bash și zsh nu au nevoie de nimic în plus. +

+
+ +
+

Mai multe joburi

+

Împărțirea fixture-urilor între joburi

+

+ De obicei nu e nevoie să le încarci. Fiindcă aceeași rețetă scrie aceiași octeți, fiecare job își + poate rula propriul tfg generate, ceea ce e mai rapid decât o încărcare și o + descărcare. Când un job trebuie să primească fișiere de la altul, rulează tfg + verify pe manifest după transfer, și îți spune dacă ce a ajuns este ce s-a scris. +

+
+ +
+

Mai departe

+

Unde să mergi de aici

+ +
+ +
+ + + + diff --git a/web/public/ro/formate/index.html b/web/public/ro/formate/index.html new file mode 100644 index 00000000..6a6c99ec --- /dev/null +++ b/web/public/ro/formate/index.html @@ -0,0 +1,912 @@ + + + + + + +26 formate de fișiere - PDF, DOCX, PNG, ZIP și altele + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 formate de fișiere, fiecare generat la o dimensiune exactă

+

+ Fiecare este un fișier real al acelui format. Se deschide în programul căruia îi + aparține și are exact numărul de octeți pe care l-ai cerut. Niciunul nu e umplutură de zerouri cu + o extensie lipită. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatNumeExtensieCel mai mic fișierFidelitateVerificat cu
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullnu se aplică
mdMarkdown.md0fullnu se aplică
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullnu se aplică
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Ce înseamnă coloanele

+
    +
  • +

    Cel mai mic fișier

    +

    + Cel mai mic număr de octeți pe care instrumentul îl acceptă pentru acel format, inclusiv eticheta pe + care o scrie în fișier. Cere mai puțin și primești o eroare care numește pragul și motivul + lui, niciodată un fișier de dimensiune greșită. +

    +
  • +
  • +

    Fidelitate

    +

    + Cât de complet este fișierul. full înseamnă că un cititor care analizează cu adevărat + formatul îl acceptă, nu doar că extensia se potrivește. +

    +
  • +
  • +

    Verificat cu

    +

    + Cititorul independent care deschide fiecare fișier generat înainte ca formatul să fie livrat - o + implementare separată, nu propriul nostru cod care își corectează singur temele. +

    +
  • +
+

+ Fiecare format se și repetă la octet: aceeași rețetă și același seed produc fișiere identice pe + orice mașină, ceea ce face sigur să comiți o rețetă în locul fixture-urilor înseși. +

+
+ +
+

Setările pe care le acceptă fiecare format

+

+ Majoritatea formatelor au setări proprii - dimensiunile imaginii, calitatea JPEG, numărul de pagini + PDF, rândurile și coloanele dintr-o foaie de calcul, câte intrări intră într-o arhivă. + Setează-le cu --set key=value în linia de comandă sau sub properties: + într-o rețetă. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatSetareAcceptă
avifwidth1 - 16384 pixeli
height1 - 16384 pixeli
quality1 - 100
bmpwidth1 - 20000 pixeli
height1 - 20000 pixeli
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headeradevărat sau fals
quote_styleall, minimal, none
columns2 - 32768 coloane
docxparagraphs1 - 50000 paragrafe
gifwidth1 - 20000 pixeli
height1 - 20000 pixeli
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixeli
height1 - 256 pixeli
embedbmp, png
jpgwidth1 - 20000 pixeli
height1 - 20000 pixeli
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixeli
height1 - 16384 pixeli
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 intrări pe secundă
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomadevărat sau fals
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleorice text
authororice text
subjectorice text
keywordsorice text
creatororice text
producerorice text
createdo dată precum 2024-02-29 sau 2024-02-29T13:45:00+02:00, sau none
modifiedo dată precum 2024-02-29 sau 2024-02-29T13:45:00+02:00, sau none
pngwidth1 - 20000 pixeli
height1 - 20000 pixeli
pptxslides1 - 500 diapozitive
svgwidth1 - 20000 pixeli
height1 - 20000 pixeli
targzentries0 - 10000
entry_formatid-ul unui format, așa cum îl listează tfg formats
entry_sizeo dimensiune precum 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesadevărat sau fals
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixeli
height1 - 20000 pixeli
txtencodingutf-16be, utf-16le, utf-8
bomadevărat sau fals
wavsample_rate8000 - 192000 herți
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixeli
height1 - 16383 pixeli
xlsxrows1 - 200000 rânduri
columns1 - 32768 coloane
xmlencodingutf-16be, utf-16le, utf-8
bomadevărat sau fals
zipentries0 - 10000
entry_formatid-ul unui format, așa cum îl listează tfg formats
entry_sizeo dimensiune precum 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesadevărat sau fals
passwordparola, în text simplu
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ O valoare în afara a ce acceptă o setare este refuzată cu un mesaj care numește setarea, intervalul + permis și ce să folosești în loc. O setare necunoscută este și ea o eroare, niciodată o valoare + implicită tăcută - o greșeală de scriere acceptată pe tăcute dă un fișier cu setările greșite și + o oră de întrebări de ce trece testul când n-ar trebui. +

+

+ Rulează tfg formats <id> ca să vezi exact ce acceptă un format în versiunea pe + care o ai. +

+
+ +
+

Arhivele conțin fișiere reale

+

+ targz și zip pot + fi umplute cu intrări, nu lăsate ca o carcasă goală. O arhivă generată conține cu adevărat + documentele pe care spune că le conține, așa că tot ce o dezarhivează în timpul unui test + găsește înăuntru fișiere reale. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/ro/index.html b/web/public/ro/index.html new file mode 100644 index 00000000..86c6d51a --- /dev/null +++ b/web/public/ro/index.html @@ -0,0 +1,454 @@ + + + + + + +Generator de fișiere de test - dimensiune exactă, 26 formate reale + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Generează fișiere de test reale la dimensiunea exactă

+

+ PDF, PNG, DOCX, ZIP - 26 formate în total, și fiecare este un + fișier real care se deschide în programul căruia îi aparține, la exact dimensiunea pe + care ai cerut-o. Fiecare rulare notează și ce trebuie să facă aplicația ta cu fiecare + fișier. Linie de comandă și fereastră desktop, gratuit și open source, funcționând în întregime + pe mașina ta. +

+ + +

Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.

+
+ +
+ Fereastra desktop Testing Files Generator, pregătită să scrie un lot de fișiere de test +
Fereastra desktop, pregătită să scrie un lot de fișiere. Același motor rulează în spatele liniei de comandă.
+
+
+ + + +
+

Problema

+

Să faci un fișier de test e ușor. Să faci cele o mie potrivite e partea plictisitoare

+

Testezi software care primește fișiere de la oameni. Mai devreme sau mai târziu ai nevoie de:

+
    +
  • un PDF de exact 10 MB, ca să afli dacă limita de încărcare e reală
  • +
  • cele trei fișiere de o parte și de alta a acelei limite, ca să prinzi erorile de unu
  • +
  • 10.000 de fișiere de jurnal, ca să vezi ce face jobul de noapte când folderul e mare
  • +
  • un ZIP care chiar conține 200 de documente, nu o carcasă goală cu extensia potrivită
  • +
  • un fișier de 4 GB, fără să ții un fișier de 4 GB în repository
  • +
  • aceleași fixture-uri pe laptopul tău și pe serverul de build, octet cu octet
  • +
+

+ Asta înlocuiește acesta. Este construit pentru ingineri QA, automatizarea testelor și oricine are în + spatele codului un formular de încărcare, o rutină de import, un parser sau o cotă de stocare. +

+
+ +
+

Ce îl face diferit

+

Alte generatoare se opresc la octeți. Acesta răspunde la ce întreabă de fapt testul tău

+

+ Un folder de fișiere te lasă tot pe tine să hotărăști ce trebuie să demonstreze fiecare. Fiecare + rulare scrie aici un manifest.json lângă fișiere - o listă simplă a tot ce s-a + produs și, pentru fiecare intrare, o așteptare declarată. +

+

Să zicem că endpointul tău de încărcare permite 1 MB. Cere cele trei fișiere de pe acea linie:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
FișierOctețiSistemul tău trebuie săPentru că
1mb_under_1b.pdf1048575acceptee în interiorul limitei
1mb_at_limit.pdf1048576acceptelimita însăși este permisă
1mb_over_1b.pdf1048577respingăsize_limit
+
+ +

Trei fișiere, trei răspunsuri diferite, în formă citibilă de mașină. Testul tău citește manifestul în loc să scrii tu asertările de mână:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Acolo unde răspunsul depinde de propria ta politică, manifestul spune asta

+

+ Înregistrează unspecified în loc să inventeze o așteptare. Un generator care ghicește + produce eșecuri false, iar o suită care dă alarme false ajunge oprită. +

+
+
+ +
+

Presetări

+

Alege întrebarea, primești setul întreg

+

+ O presetare este un set de fișiere de test conceput în jurul unei întrebări de test, ca să nu fie + nevoie să afli tu ce fișiere dovedesc ce. Fiecare are o pagină care spune ce găsește de obicei, + ce este în set și fiecare setare pe care o acceptă. +

+
    +
  • +

    Gol și minimal

    +

    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

    +
  • +
  • +

    Limite de dimensiune

    +

    Este o limită de dimensiune aplicată exact acolo unde este declarată?

    +

    size-boundaries

    +
  • +
  • +

    Import de tabele

    +

    Supraviețuiește importul meu de tabele la ce exportă instrumentele reale?

    +

    tabular-import

    +
  • +
  • +

    Codarea textului

    +

    Știe cititorul meu în ce codare este un fișier sau doar ghicește?

    +

    text-encoding

    +
  • +
  • +

    Validarea încărcării

    +

    Acceptă formularul meu de încărcare ce trebuie și respinge restul?

    +

    upload-validation

    +
  • +
+

Toate presetările și cum se leagă de rețete

+
+ +
+

Pornire rapidă

+

Trei comenzi ca să-l vezi funcționând

+
    +
  1. +

    Fă un fișier

    +

    Un PNG, exact doi megaocteți:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Fă multe fișiere

    +

    + Zece mii de fișiere de jurnal, fiecare între unu și opt kiloocteți, cu dimensiunile extrase din seed + ca mâine să dea același set. Dă fiecărei rulări propriul director - + manifestul este singura evidență a ce a scris o rulare, așa că instrumentul refuză să scrie + un al doilea peste el: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Verifică-le, apoi șterge-le

    +

    verify îți spune că nimic nu s-a mișcat. cleanup șterge exact ce s-a scris și nimic altceva:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Dimensiunile se numără din 1024 în 1024, cum o face managerul tău de fișiere, deci 2mb + înseamnă 2097152 octeți. Merge și un simplu număr de octeți. + Documentația acoperă rețetele, manifestul și codurile de ieșire. +

+
+ +
+

Ce primești

+

Construit pentru o suită care rulează nesupravegheată

+
    +
  • +

    Dimensiune exactă, la octet

    +

    Cere 10485761 de octeți și primești exact atât. O dimensiune pe care un format nu o poate atinge este o eroare cu un motiv, niciodată un fișier de dimensiune greșită.

    +
  • +
  • +

    26 formate reale

    +

    Nu zerouri de umplutură cu o extensie. Un PNG generat se deschide într-un vizualizator de imagini, un DOCX se deschide în Word, un ZIP se extrage. Fiecare este verificat cu cititori independenți înainte de livrare.

    +
  • +
  • +

    Un manifest care este un oracol de test

    +

    Cale, dimensiune, SHA-256, format, seed, versiunea instrumentului - și ce trebuie să facă sistemul tău cu fișierul.

    +
  • +
  • +

    Reproductibil

    +

    Aceeași rețetă și același seed, aceiași octeți, pe orice mașină. Comite o rețetă YAML mică în loc de fixture-uri binare mari.

    +
  • +
  • +

    Două interfețe, un singur motor

    +

    O linie de comandă făcută pentru CI și o fereastră desktop pentru testarea exploratorie. Niciuna nu e o versiune redusă a celeilalte, iar un test le compară capacitate cu capacitate.

    +
  • +
  • +

    Complet offline

    +

    Fără cont, fără cloud, fără telemetrie, fără verificare de actualizări. Binarul liniei de comandă nu are compilat în el niciun stack de rețea.

    +
  • +
+
+ +
+

Descărcare

+

Alege versiunea pentru sistemul tău

+

+ Dezarhivează arhiva și rulează-o. tfg este linia de comandă și tfg-gui + este fereastra desktop. Nu există instalator și nimic de adăugat pe mașina ta. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemLinie de comandăFereastră desktop
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Ce este semnat și ce nu

+

+ Descărcările pentru Windows și macOS sunt semnate, așa că pornesc fără avertisment despre un + dezvoltator necunoscut. Cele pentru Linux nu sunt, pentru că Linux pe desktop nu are un + echivalent cu care să le semnezi. Fiecare arhivă este listată în + verify-SHA256SUMS.txt pe pagina de versiuni, ca să poți verifica ce ai descărcat. +

+
+ +

Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.

+
+ + +
+ + + + diff --git a/web/public/ro/intrebari-frecvente/index.html b/web/public/ro/intrebari-frecvente/index.html new file mode 100644 index 00000000..4dd86bdb --- /dev/null +++ b/web/public/ro/intrebari-frecvente/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - întrebări despre generarea fișierelor de test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Întrebări frecvente

+

+ Licență, confidențialitate, reproductibilitate și lucrurile pe care oamenii le verifică înainte să + pună un generator într-un pipeline de build. Dacă întrebarea ta nu e aici, + sistemul de issue-uri este deschis. +

+ +
+
+

Prin ce diferă de dd, fsutil sau truncate?

+
+

Acelea îți dau un fișier de dimensiunea potrivită, plin de nimic. Un fișier de 2 MB numit photo.png făcut așa nu este un PNG, deci tot ce îl analizează cu adevărat îl respinge din motivul greșit, iar testul tău trece apoi tot din motivul greșit. Acesta produce un PNG real de exact 2 MB care se deschide într-un vizualizator de imagini și vine cu o declarație despre cum trebuie să îl trateze sistemul tău.

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

Este gratuit și îl pot folosi la serviciu?

+
+

Da la amândouă. Este publicat sub GPL-3.0 și nu costă nimic. Nu există cont, cheie de licență sau nivel plătit.

+
+
+
+

Pot folosi fișierele generate într-un produs cu cod închis?

+
+

Da. Licența acoperă codul instrumentului, nu ce produce el. Fișierele, rețetele și manifestele generate sunt rezultat și nu lucrări derivate, deci le poți comite și distribui fără nicio obligație.

+
+
+
+

Conțin fișierele generate date personale reale?

+
+

Nu. Tot ce se află în ele este sintetizat dintr-un seed. Nu se citește niciun set de date, nu se contactează niciun serviciu și nu se încorporează conținut de la terți. Tratează o adresă de e-mail generată ca inutilizabilă, nu ca neutilizată, pentru că orice șir aleatoriu poate coincide din întâmplare cu una reală.

+
+
+
+

Voi obține exact aceleași fișiere pe altă mașină?

+
+

Da, octet cu octet, cu aceeași rețetă și același seed. Proiectul testează asta la fiecare modificare, iar încălcarea ei cere o versiune majoră. Asta îți permite să comiți o rețetă mică în loc de fixture-uri binare mari.

+
+
+
+

Are nevoie de conexiune la internet?

+
+

Niciodată. Nu există telemetrie, verificare de actualizări sau client cloud, iar binarul liniei de comandă nu are compilat în el niciun stack de rețea. Funcționează pe o mașină fără rețea și într-un mediu corporativ închis.

+
+
+
+

Ce se întâmplă dacă cer o dimensiune pe care un format nu o poate atinge?

+
+

Primești o eroare care numește formatul, cea mai mică dimensiune posibilă, motivul acelui prag și ce să faci în loc, și nu se scrie niciun fișier. Instrumentul nu rotunjește niciodată o dimensiune pe tăcute. Fiecare prag este listat în pagina de formate.

+
tfg formats png
+
+
+
+

Pot genera un fișier stricat în mod deliberat?

+
+

Da. Adaugă --damage zero-head și fișierul iese cu exact mărimea cerută, cu primii octeți suprascriși cu zerouri, așa că un cititor îl respinge, iar manifestul spune că sistemul tău trebuie să îl respingă. Detaliile sunt pe pagina despre fișierele de test corupte.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Ce formate urmează?

+
+

7z, mp3 și mp4. Azi funcționează de la un capăt la altul 26 formate.

+
+
+
+

Pe ce sisteme îl pot rula?

+
+

Linia de comandă rulează pe Windows și Linux, atât pe Intel, cât și pe ARM, și pe Mac-uri cu Apple Silicon. Fereastra desktop este livrată pentru Windows pe Intel, Linux pe Intel și Mac-uri cu Apple Silicon. Mac-urile Intel nu sunt acceptate și nu se construiește nimic pentru ele.

+
+
+
+

Trebuie să instalez ceva?

+
+

Nu. Descarcă arhiva pentru sistemul tău, dezarhiveaz-o și rulează binarul. Nu există instalator, mediu de execuție de adăugat sau dependență de rezolvat. Dacă ai Go, funcționează și o singură comandă go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

De ce o rulare peste mii de fișiere este mai lentă pe Windows?

+
+

Pentru că Windows cere mai mult pentru fiecare cale pe care o examinează, iar o comandă care parcurge mii de fișiere examinează mii de căi. Măsurat pe o mașină cu 3000 de fișiere de 1 kB, verify durează aproximativ 0,9 secunde pe Windows și aproximativ 0,2 secunde pe Linux într-un container. O cale de ieșire mai scurtă micșorează cifra de pe Windows, pentru că fiecare folder de deasupra fișierelor face parte din ce se examinează.

+
+
+
+ + +
+

Încă te decizi?

+

+ Pagina de cazuri de utilizare arată sarcinile pentru care a + fost făcut, iar pagina de formate listează fiecare format cu cel mai + mic fișier pe care îl poate produce. README-ul din repository + este referința completă. +

+ +

Gratuit și open source, GPL-3.0. Fără cont. Descărcările pentru Windows și macOS sunt semnate și pornesc fără avertisment.

+
+ +
+ + + + diff --git a/web/public/ro/presetari/empty-and-minimal/index.html b/web/public/ro/presetari/empty-and-minimal/index.html new file mode 100644 index 00000000..88d55bd6 --- /dev/null +++ b/web/public/ro/presetari/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +Cele mai mici fișiere de test valide și goale, în fiecare format + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

Gol și minimal

+

Trece un fișier valid, cât de mic permite formatul?

+

+ Presetarea empty-and-minimal construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • un fișier valid respins pentru că e prea mic, când verificarea numără octeți în loc să îi citească
  • +
  • un fișier gol care prăbușește cititorul în loc să fie raportat
  • +
  • o imagine lată de un pixel care împarte la zero pe drumul spre miniatură
  • +
  • un depozit care citește zero octeți ca pe o încărcare eșuată și tot reîncearcă
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show empty-and-minimal:

+
+ + + + + + + +
Fișiere28
Targeturi în rețeta lui28
Dimensiune totală32 667 B
Formateavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.26
unspecifiedDepinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut.2
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--formatsid-uri de format separate prin virgule, sau allallDin ce formate este alcătuit setul. Lasă all pentru toate formatele acestei versiuni sau numește-le pe cele pe care le acceptă sistemul tău.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/ro/presetari/filename-handling/index.html b/web/public/ro/presetari/filename-handling/index.html new file mode 100644 index 00000000..5f75d84e --- /dev/null +++ b/web/public/ro/presetari/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Nume de fișiere problematice pentru teste - Unicode și lungime + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

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?

+

+ Presetarea filename-handling construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • un nume care arată ca altul pe ecran, într-un jurnal sau într-o listă
  • +
  • un nume tăiat, scurtat sau rescris între încărcare și stocare
  • +
  • o limită de lungime numărată în caractere acolo unde depozitul numără octeți
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show filename-handling:

+
+ + + + + + + +
Fișiere50
Targeturi în rețeta lui50
Dimensiune totală51 200 B
Formatetxt
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.4
unspecifiedDepinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut.46
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--formatun id de format din pagina de formatetxtFormatul fiecărui fișier din set. Este o opțiune a instrumentului însuși, iar presetarea îi dă doar o valoare implicită.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/ro/presetari/index.html b/web/public/ro/presetari/index.html new file mode 100644 index 00000000..7b052b16 --- /dev/null +++ b/web/public/ro/presetari/index.html @@ -0,0 +1,245 @@ + + + + + + +Presetări de fișiere de test - seturi gata făcute pentru QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Presetări de fișiere de test, câte un set pentru fiecare întrebare de test

+

+ O presetare este un set întreg de fișiere de test conceput în jurul unei întrebări, cu un manifest + care spune cum trebuie să reacționeze sistemul tău la fiecare fișier. Tu alegi întrebarea, + instrumentul construiește setul. Fiecare presetare are propria pagină cu ce găsește de obicei, ce + este în set și fiecare setare pe care o acceptă. +

+ + + +
+

Prin ce diferă o presetare de o rețetă?

+

+ Pe dedesubt, prin nimic. O presetare este o rețetă pe care instrumentul o scrie pentru tine din + câteva setări. tfg preset eject afișează acea rețetă ca s-o poți păstra lângă + testele tale și s-o editezi, iar o rețetă proprie se poate sprijini pe o presetare cu o singură + linie, extends: preset: urmat de id-ul ei. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Pot avea încredere în valorile implicite?

+

+ Pentru fișiere, da. Pentru un număr pe care îl știe doar sistemul tău, precum limita unui formular + de încărcare, o valoare implicită este o valoare provizorie de-a noastră, iar instrumentul o + spune de fiecare dată când folosește una. Pagina fiecărei presetări marchează acele setări, iar + tfg preset show o spune înainte să se scrie ceva. +

+
+ +
+ + + + diff --git a/web/public/ro/presetari/size-boundaries/index.html b/web/public/ro/presetari/size-boundaries/index.html new file mode 100644 index 00000000..160f9047 --- /dev/null +++ b/web/public/ro/presetari/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Testarea unei limite de încărcare - fișiere exact la limită + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

Limite de dimensiune

+

Este o limită de dimensiune aplicată exact acolo unde este declarată?

+

+ Presetarea size-boundaries construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • erori de unu în plus sau în minus la limită
  • +
  • MB confundat cu MiB, adică 4,8 la sută, suficient cât să treacă un fișier care n-ar trebui să treacă
  • +
  • o limită aplicată în browser și nu pe server
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show size-boundaries:

+
+ + + + + + + +
Fișiere7
Targeturi în rețeta lui7
Dimensiune totală73 400 320 B
Formatepdf
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.4
rejectSistemul tău trebuie să respingă fișierul.3
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--limito dimensiune precum 2mb10mbLimita de dimensiune declarată de sistemul tău. Tot restul se măsoară pornind de la ea. Această valoare implicită este valoarea noastră provizorie, nu valoarea sistemului tău. Dă-o pe a ta.
--spreaddimensiuni separate prin virgule1B,1kb,1mbCât de departe să se meargă de ambele părți ale limitei, ca listă de dimensiuni.
--formatun id de format din pagina de formatepdfFormatul fiecărui fișier din set. Este o opțiune a instrumentului însuși, iar presetarea îi dă doar o valoare implicită.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

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

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ro/presetari/tabular-import/index.html b/web/public/ro/presetari/tabular-import/index.html new file mode 100644 index 00000000..9ed6090a --- /dev/null +++ b/web/public/ro/presetari/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +Fișiere de test pentru import CSV și Excel - delimitatori + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

Import de tabele

+

Supraviețuiește importul meu de tabele la ce exportă instrumentele reale?

+

+ Presetarea tabular-import construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • un fișier cu punct și virgulă citit ca o singură coloană, pentru că delimitatorul a fost presupus în loc să fie căutat
  • +
  • un fișier CRLF împărțit în rânduri cu un rând gol după fiecare
  • +
  • un tabel fără antet al cărui prim rând de date este înghițit drept nume de coloane
  • +
  • un import care păstrează coloanele pe care le poate arăta și aruncă restul fără o vorbă
  • +
  • un cititor care ia înregistrările JSON câte o linie și se oprește la primul document indentat
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show tabular-import:

+
+ + + + + + + +
Fișiere13
Targeturi în rețeta lui13
Dimensiune totală3 080 060 B
Formatecsv, json, xlsx
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.8
unspecifiedDepinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut.5
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--rows1 - 200000 rânduri1000Câte rânduri are foaia de calcul. Se scrie exact la dimensiunea pe care o ocupă atâtea rânduri, așa că bugetul de mai sus se mută odată cu această valoare.
--columns1 - 32768 coloane10Câte coloane are fiecare rând al foii de calcul. Rânduri înmulțit cu coloane are un plafon, iar cererea peste el este refuzată înainte de a se scrie ceva.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/ro/presetari/text-encoding/index.html b/web/public/ro/presetari/text-encoding/index.html new file mode 100644 index 00000000..5d917e0c --- /dev/null +++ b/web/public/ro/presetari/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +Fișiere de test pentru codarea textului - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

Codarea textului

+

Știe cititorul meu în ce codare este un fișier sau doar ghicește?

+

+ Presetarea text-encoding construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • un cititor care presupune UTF-8 și arată un fișier UTF-16 cu un caracter din trei sau ca rânduri de pătrățele
  • +
  • o marcă de ordine a octeților citită ca și conținut, astfel încât primul câmp al unui import începe cu trei caractere străine
  • +
  • un importator care ghicește codarea din primii octeți și ghicește altfel pentru un fișier mai lung
  • +
  • un fișier CRLF împărțit în rânduri cu un rând gol după fiecare sau un retur de car rămas în ultimul câmp
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show text-encoding:

+
+ + + + + + + +
Fișiere20
Targeturi în rețeta lui20
Dimensiune totală81 920 B
Formatecsv, log, md, txt, xml
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.10
unspecifiedDepinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut.10
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--sampleo dimensiune precum 2mb4kbCât de mare este fiecare fișier din set. UTF-16 stochează doi octeți pentru fiecare caracter, așa că un număr impar este refuzat.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/ro/presetari/upload-validation/index.html b/web/public/ro/presetari/upload-validation/index.html new file mode 100644 index 00000000..1c3fdb4c --- /dev/null +++ b/web/public/ro/presetari/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +Fișiere de test pentru validarea încărcării - tip și nume + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Presetări

+

Validarea încărcării

+

Acceptă formularul meu de încărcare ce trebuie și respinge restul?

+

+ Presetarea upload-validation construiește cu o singură comandă un set întreg de fișiere de test + reale pentru această întrebare, și un manifest.json alături care spune cum trebuie să + reacționeze sistemul tău la fiecare fișier. Tot ce urmează este citit din program, la valorile + implicite ale acestei versiuni. +

+ + +
+

Ce găsește de obicei?

+
    +
  • o limită aplicată în browser și nu pe server
  • +
  • un SVG sau un HTML luat drept imagine sau text simplu, o cale de a strecura un script printr-un formular
  • +
  • un fișier verificat după extensie și niciodată deschis, așa că un PDF numit .jpg trece
  • +
  • un formular care citește tot corpul în memorie înainte să vadă cât de mare e
  • +
  • o încărcare numită PHOTO.JPG respinsă acolo unde photo.jpg e acceptată, sau invers
  • +
  • un nume cu spații, paranteze sau caractere în afara ASCII scris pe disc neschimbat
  • +
+
+ + +
+

Ce este în set?

+

La valorile implicite, așa cum le raportează tfg preset show upload-validation:

+
+ + + + + + + +
Fișiere71
Targeturi în rețeta lui22
Dimensiune totală120 639 488 B
Formatehtml, jpg, pdf, png, svg, txt
+
+

Și ce așteaptă manifestul acelui set de la sistemul tău:

+
+ + + + + + + + + +
AșteptatSemnificațieFișiere
acceptSistemul tău trebuie să accepte fișierul.56
rejectSistemul tău trebuie să respingă fișierul.10
unspecifiedDepinde de regulile sistemului tău. Tu decizi, apoi verifici că ce se întâmplă este ce ai vrut.5
+
+
+ +
+

Ce poți schimba?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SetarePrimeșteImplicitCe face
--limito dimensiune precum 2mb10mbLimita de dimensiune declarată de formularul tău de încărcare. Acest set face câte un pas de fiecare parte - pentru un fișier la orice distanță rulează presetarea size-boundaries. Această valoare implicită este valoarea noastră provizorie, nu valoarea sistemului tău. Dă-o pe a ta.
--allowid-uri de format separate prin virgulejpg,png,pdfCe tipuri trebuie să accepte formularul tău. Fiecare devine un fișier real de acel tip și ele formează controlul pozitiv al întregului set.
--denyextensii separate prin virgulesvg,html,exe,shCe extensii trebuie să respingă formularul tău. O extensie pentru care această versiune nu are format primește totuși un fișier cu acel nume, conținând text simplu.
--far-over10x, 2x, off2xCât de mult peste limită ajunge singurul fișier mare. Oprește-l unde scrierea de mai multe ori limita nu merită discul.
--bulk0 - 10000 fișiere50Câte fișiere conține încărcarea în masă. Zero scoate acel grup complet din set.
+
+
+ +
+

Cum o rulezi?

+

Vezi cât ar costa setul, construiește-l sau ia-i rețeta ca s-o editezi:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Sau construiește peste ea într-o rețetă proprie, lângă testele tale:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ru/corrupt-test-files/index.html b/web/public/ru/corrupt-test-files/index.html new file mode 100644 index 00000000..820982e6 --- /dev/null +++ b/web/public/ru/corrupt-test-files/index.html @@ -0,0 +1,383 @@ + + + + + + +Повреждённые тестовые файлы - сломанные файлы точного размера + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Сценарии

+

Как сделать повреждённый файл для тестов

+

+ Валидатор, которому показывали только здоровые файлы, на самом деле не проверен. Вот как получить + файл, намеренно испорченный, выходящий точно того размера, который вы просите, и + несущий манифест с указанием, что ваша система должна с ним сделать. +

+ +
+

Короткий ответ

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out записывает PNG + ровно в 2097152 байта, первые байты которого нули, а манифест рядом фиксирует, что ваша система + должна его отклонить. +

+
+ +
+

Обычный путь

+

Почему файл, испорченный вручную, - плохой тест

+

+ Обычно берут шестнадцатеричный редактор, скрипт, переворачивающий несколько случайных байтов, или + укорачивают файл через head либо truncate. Один раз это работает, а + потом обходится дорого: +

+
    +
  • + Каждый раз по-разному. Случайный байт при каждом запуске попадает в новое место, + поэтому сбой во вторник в среду может не повториться. +
  • +
  • + Меняется размер. Обрезанный файл меньше лимита, под которым он должен был + оставаться, поэтому проверка размера отвечает раньше проверки содержимого, и тест проходит по + неверной причине. +
  • +
  • + Это часто остаётся незамеченным. Простой текст читается и с изменённым байтом + посередине, а снисходительная программа чтения изображений просто рисует его, так что файл, + который должен быть испорчен, принимается. +
  • +
  • + Не сказано, что должно произойти. Файл - это просто байты, и тому, кто будет читать + тест позже, придётся гадать, имелось в виду принятие или отклонение. +
  • +
+
+ +
+

Что вы получаете

+

Повреждённый файл остаётся нужного размера

+

+ Файл создаётся как обычно и портится потом, по пути на диск. Он сохраняет заданный размер, а та же + команда снова записывает те же байты. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Настройки пишутся после двоеточия. Параметр можно повторять, а повреждения применяются в том + порядке, в каком вы их записали. Это работает с каждым из 26 форматов. +

+
+ +
+

Что он умеет

+

Какие бывают повреждения?

+

+ Это список, который печатает программа, прочитанный из неё при сборке этой страницы. tfg + damage печатает тот же список, а tfg damage <id> говорит, что + принимает одно из них. +

+
+ + + + + + + + + + + + + + + + + +
ПовреждениеЧто оно делает с байтамиНаименьший файлНастройки
zero-headПерезаписывает первые байты файла нулями, не меняя его длину. Большинство программ чтения смотрят сначала туда, поэтому это повреждение замечает почти всё.8bytes
+
+

+ zero-head записывает нули поверх начала файла. Большинство программ чтения смотрят + сначала туда, на сигнатуру и заголовок, которые говорят, что это за файл, поэтому замечает почти + любая. У простого текста и журналов сигнатуры нет, и их тоже отклоняют, потому что + последовательность нулевых байтов не является текстом. Меньше четырёх байтов у некоторых + форматов получается повреждение, на которое не жалуется ни одна программа чтения, поэтому + настройка начинается с четырёх. +

+
+ +
+

Что говорит манифест

+

Манифест, который говорит, что должно произойти

+

+ Каждый повреждённый файл получает запись о том, что ваша система должна его отклонить, а рядом + записано повреждение: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Два запроса отклоняются до того, как что-либо записано, потому что каждый оставил бы на диске файл, + который манифест описывает неверно: +

+
    +
  • файл меньше, чем нужно повреждению, который вышел бы нетронутым
  • +
  • + expected: accept рядом с повреждением, потому что ничто не могло бы этого выполнить. + Напишите sanitize, если ваша система должна починить файл, или + unspecified, если именно это вы и проверяете +
  • +
+
+ +
+

В рецепте

+

Здоровые и сломанные файлы за один запуск

+

+ Положите оба вида в один рецепт, и манифест несёт ожидание для каждого файла, так что тесту не нужен + список, какой файл какой: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

В тесте

+

Превращаем это в тест

+

+ Тест читает манифест и проверяет, что произошедшее совпадает с заявленным. Список имён файлов ему не + нужен: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Хороший отказ - это чистый отказ. Сообщение, говорящее, что было не так, - тот ответ, который вам + нужен. Ошибка сервера, зависание или наполовину сохранённый файл - тот дефект, ради которого + этот тест и существует. +

+
+ +
+

Дальше

+

Куда идти отсюда

+ +
+ +
+ + + + diff --git a/web/public/ru/create-file-exact-size/index.html b/web/public/ru/create-file-exact-size/index.html new file mode 100644 index 00000000..9187b768 --- /dev/null +++ b/web/public/ru/create-file-exact-size/index.html @@ -0,0 +1,331 @@ + + + + + + +Как создать файл точного размера - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Как создать файл точного размера

+

+ В каждой системе для этого есть команда, и все три приведены ниже. Они дают файл с точным числом + байт, а для многих тестов этого достаточно. Каждая команда на этой странице была выполнена + до публикации в той системе, к которой она относится. +

+ +
+

Короткий ответ

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Размеры указываются в байтах, а 10 + МБ, посчитанные так, как считает ваш файловый менеджер, - это 10485760. +

+
+ +
+

Windows

+

fsutil и вариант на PowerShell, которому ничего дополнительного не нужно

+

+ fsutil входит в Windows. Он принимает размер в байтах, поэтому сначала + посчитайте число: 10 МБ - это 10485760, 100 МБ - 104857600, 1 ГБ - 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Измерено в Windows 11: работает из обычной командной строки без повышенных прав, и файл получается + ровно в 10485760 байт. +

+

PowerShell может сделать то же самое, не вызывая другую программу, и понимает единицы:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB в PowerShell означает 10485760 байт, тот же счёт по основанию 1024, что использует + Проводник, поэтому две команды выше дают один и тот же размер. +

+
+ +
+

Linux

+

dd, truncate и fallocate, и разница, которая ловит людей

+

dd знают все. Он действительно записывает байты:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate срабатывает мгновенно, и в этом подвох. Измерено в Alpine Linux: файл сообщает + 10485760 байт и занимает ноль блоков - это разреженный файл. + Всё, что его читает, получает десять мегабайт нулей, но диск место так и не отдал: +

+
truncate -s 10M test10mb.bin
+

+ Для проверки лимита загрузки это нормально, а для проверки дисковой квоты вводит в заблуждение. + fallocate - то, к чему стоит обратиться, когда место должно быть настоящим: +

+
fallocate -l 10M test10mb.bin
+

А когда содержимое должно быть несжимаемым, чтобы архиватор не мог снова его ужать:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, который не разреженный, и две команды, которые вы уже знаете

+

+ В macOS есть mkfile. Измерено в macOS 26.6.2: 10485760 байт и 20480 блоков, то есть + место действительно выделено, а не обещано: +

+
mkfile 10m test10mb.bin
+

dd и truncate тоже есть и ведут себя как в Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Где это перестаёт работать

+

Файл правильного размера - не файл правильного вида

+

+ Всё сказанное выше даёт блок нулей. Этого достаточно, когда тестируемое смотрит только на размер: + лимит загрузки, квота, передача. Этого перестаёт хватать, как только что-либо + открывает файл. +

+

+ Измерено, и стоит проверить самому: сделайте файл на 2 МБ командой fsutil, назовите его + photo.png и передайте библиотеке работы с изображениями. Pillow ответит + cannot identify image file. Это не PNG. Он им никогда и не был, так говорило лишь + имя. +

+

+ Это важнее, чем кажется, из-за того, в какую сторону тест тогда проваливается. Ваша + точка загрузки отклоняет файл, ваш тест зеленеет, и вы заключаете, что лимит размера работает. + Она отклонила его не из-за размера. Она отклонила его потому, что байты не были изображением, и + правило, которое вы хотели проверить, так и не было достигнуто. +

+
    +
  • парсер отклоняет его, не дойдя до каких-либо правил размера
  • +
  • шаг создания миниатюры падает, и ошибка, которую вы читаете, относится к миниатюре
  • +
  • антивирус или проверка содержимого отклоняет его по третьей причине
  • +
  • просмотрщик ничего не показывает, и никто не может сказать, в этом ли ошибка
  • +
+
+ +
+

Другой путь

+

Настоящий файл этого формата точно того размера, который вы запросили

+

+ Именно это делает Testing Files Generator. Файл - настоящий файл своего формата, он открывается в + своей программе, и в нём ровно то число байт, которое вы запросили, с точностью до байта: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Запросите размер, которого формат не может достичь, и вы получите ошибку с названием минимума и + причиной, а не файл неверного размера. Страница форматов перечисляет + каждый формат с наименьшим файлом, который он может создать. +

+

А лимит - это три тестовых случая, а не один, поэтому инструмент собирает все три:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Вы получите 10485759, 10485760 и 10485761 байт и манифест, который говорит, какие из них ваша + система должна принять, а какие отклонить. Страница сценариев + разбирает это и ещё четыре задачи, для которых инструмент создан. +

+ +

Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.

+
+ +
+

Так что же использовать?

+
    +
  • +

    Используйте системную команду

    +

    + Когда ничто не открывает файл. Проверка лимита размера на точке, которая сначала смотрит размер, + передача, квота, переполнение диска. Это одна строка, и она уже установлена. +

    +
  • +
  • +

    Используйте настоящий генератор

    +

    + Когда что-либо разбирает, отображает, импортирует или распаковывает файл - и когда завтра на другой + машине нужны те же фикстуры, байт в байт. +

    +
  • +
+

+ Обе есть на этой странице, потому что обе бывают правы. Ошибка, которой стоит избегать, - + использовать первую там, где нужна вторая, и принимать зелёный тест за доказательство. +

+
+ +
+ + + + diff --git a/web/public/ru/docs/index.html b/web/public/ru/docs/index.html new file mode 100644 index 00000000..906b10d0 --- /dev/null +++ b/web/public/ru/docs/index.html @@ -0,0 +1,559 @@ + + + + + + +Документация - команды, рецепты, манифест, коды завершения + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Документация

+

+ Всё, что делает инструмент, разложено по вопросам, с которыми люди действительно приходят. + README в репозитории - полный справочник, и он всегда + соответствует скачанной вами сборке. +

+ +
+

Какие есть команды?

+

Каждая делает одно дело:

+
tfg generate    создать файлы по рецепту или по флагам
+tfg validate    проверить рецепт, ничего не записывая
+tfg verify      сверить каталог с манифестом
+tfg cleanup     удалить файлы, перечисленные в манифесте
+tfg recipe fmt  вывести рецепт в устоявшемся виде
+tfg preset      собрать набор файлов по именованному тестовому вопросу
+tfg formats     перечислить форматы этой сборки
+tfg damage      перечислить способы, которыми эта сборка может намеренно испортить файл
+tfg tool        небольшие инструменты для уже имеющихся файлов
+tfg version     вывести версию инструмента
+tfg license     вывести лицензию и что она означает для созданных файлов
+
+ +
+

Как создать один файл точного размера?

+

+ Укажите формат, размер и место назначения. Размеры считаются по 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. Выбор идёт от seed
--boundary <size>три файла вокруг лимита: на байт меньше, сам лимит, на байт больше
--count <n>сколько файлов создать. По умолчанию 1
--name <template>шаблон имени, например invoice_{index:04}.txt
--out <dir>каталог, в который записывать
--seed <n>seed запуска. Один и тот же seed даёт те же байты
--set <k>=<v>настройка формата, можно повторять
--damage <name>намеренно испортить файлы, можно повторять, применяется по порядку. Список выводит tfg damage
--expected <outcome>accept, reject, sanitize или unspecified
--dry-runпосчитать и показать, ничего не записывая
--jsonзаписать манифест в стандартный вывод
+
+
+ +
+

Как сделать намеренно сломанный файл?

+

+ Любой другой файл, который записывает этот инструмент, корректен по построению, и это отвечает на + два из трёх вопросов, которые задаёт проверка загрузки. --damage отвечает на третий + - открывается ли файл вообще. Файл создаётся как обычно, а затем портится, поэтому у него + остаётся запрошенный размер. +

+
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 с записанным рядом + повреждением. Две вещи отклоняются до записи чего-либо, потому что каждая оставила бы на диске + файл, неверно описанный манифестом: +

+
    +
  • файл меньше, чем нужно повреждению, потому что он вышел бы без изменений
  • +
  • + expected: accept рядом с повреждением, потому что этому не мог бы соответствовать ни + один файл. Пишите sanitize, если тестируемая система должна починить файл, или + unspecified, если именно этот вопрос вы и задаёте +
  • +
+

+ Третье заранее узнать нельзя. Если повреждение выполняется и не меняет ни одного байта, такой файл + отбрасывается, а не записывается - запуск продолжается, сообщает, что это был за файл, и + завершается кодом частичного завершения. +

+

+ Шаг за шагом, с тестом, который читает манифест: как сделать + повреждённый файл для тестов. +

+
+ +
+

Как выглядит рецепт?

+

+ Рецепт - это файл 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. Два - это ошибка, и ни одного - тоже. + Недопустимый рецепт записывает ни одного файла и сообщает обо всех проблемах + сразу, а не только о первой, называя каждый раз настройку, к которой она относится. +

+
+ +
+

Как объявить, что моя система должна делать с файлом?

+

Краткая форма, когда достаточно исхода, и длинная, когда важна причина:

+
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. +

+

+ Причина называет действующее правило, а не вердикт. Поэтому одна и та же причина + может стоять под любым исходом - файл на байт меньше лимита получает accept, а + правило, о котором речь, всё равно size_limit. +

+
+ +
+

Что в манифесте?

+

+ Он записывается рядом с файлами в конце каждого запуска, в том числе прерванного. Одна запись на + файл: +

+
{
+  "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 - если по пресету, так что манифест всегда можно отследить до того, что + его создало. +

+

+ Каждая запись также содержит target_id - id цели рецепта, которая создала файл, а + summary.by_target считает файлы каждой цели. Рецепт с несколькими целями можно + поэтому проверить цель за целью, не читая имена файлов. +

+
+ +
+

Что такое пресет?

+

+ Готовый набор файлов, отвечающий на распространённый тестовый вопрос, чтобы вам не приходилось + проектировать набор самостоятельно. Пресеты - обычные рецепты внутри, а eject + выводит рецепт, чтобы вы могли отредактировать его. У каждого пресета есть + отдельная страница о том, что он обычно находит, что входит в набор и + какие настройки принимает. +

+
    +
  • +

    Пустые и минимальные

    +

    Пройдёт ли корректный файл, настолько маленький, насколько позволяет формат?

    +

    empty-and-minimal

    +
  • +
  • +

    Обработка имён файлов

    +

    Сохранит, покажет и вернёт ли моя система имя файла, которого не ожидала?

    +

    filename-handling

    +
  • +
  • +

    Границы размера

    +

    Применяется ли лимит размера ровно там, где он объявлен?

    +

    size-boundaries

    +
  • +
  • +

    Импорт таблиц

    +

    Переживёт ли мой импорт таблиц то, что экспортируют настоящие инструменты?

    +

    tabular-import

    +
  • +
  • +

    Кодировка текста

    +

    Знает ли мой читатель, в какой кодировке файл, или угадывает?

    +

    text-encoding

    +
  • +
  • +

    Проверка загрузки

    +

    Принимает ли моя форма загрузки то, что должна, и отклоняет ли остальное?

    +

    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 сообщает, чего стоил бы набор, прежде чем вы его соберёте, и прямо говорит, когда + число - наша временная подстановка, а не ваш лимит. +

+
+ +
+

Что означают коды завершения?

+

+ У каждого исхода свой код, машиночитаемый вывод идёт в стандартный вывод, а неудачный запуск ничего + туда не печатает. Таблица - замороженный контракт: смена значения кода требует повышения + мажорной версии. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КодЗначение
0Всё сработало.
1Непредвиденная ошибка внутри инструмента.
2Неверная команда или флаг.
3Рецепт недопустим.
4Формат не может сделать то, что запрошено.
5Не удалось прочитать или записать.
6Недостаточно места на диске.
7verify обнаружил расхождение.
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, всё равно оставляет манифест и никогда не оставляет + наполовину записанный файл, поэтому отменённое задание может быть убрано следующим. +

+

+ Готовые workflow для GitHub Actions и GitLab CI: как генерировать + тестовые файлы в конвейере CI. +

+
+ +
+

Есть ли десктопное окно?

+

+ Да, тот же движок с окном сверху, для тестирования, которое не автоматизируется. Это не урезанная + версия: тест сравнивает два интерфейса возможность за возможностью, и всё, что умеет только один + из них, должно быть объявлено и обосновано, а не тихо расходиться. +

+

+ Экраны: одна партия, пресеты, несколько партий одновременно и о программе. Окно показывает, чего + стоил бы запуск, прежде чем что-либо записать, отображает ход работы и может быть отменено на + полпути без наполовину записанного файла. Файл рецепта оно пока не открывает - рецепты пока дело + командной строки, а окно собирает свои партии в форме. +

+
+ +
+ + + + diff --git a/web/public/ru/faq/index.html b/web/public/ru/faq/index.html new file mode 100644 index 00000000..9aea1ee6 --- /dev/null +++ b/web/public/ru/faq/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - вопросы о создании тестовых файлов + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Часто задаваемые вопросы

+

+ Лицензия, приватность, воспроизводимость и то, что люди проверяют, прежде чем включать генератор в + конвейер сборки. Если вашего вопроса здесь нет, трекер задач + открыт. +

+ +
+
+

Чем это отличается от dd, fsutil или truncate?

+
+

Они дают файл нужного размера, набитый пустотой. Файл photo.png на 2 МБ, сделанный так, не является PNG, поэтому всё, что действительно его разбирает, отклоняет его по неверной причине, и ваш тест тоже проходит по неверной причине. Этот инструмент создаёт настоящий PNG ровно на 2 МБ, который открывается в просмотрщике изображений, и сопровождает его заявлением о том, как ваша система должна с ним поступать.

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

Это бесплатно, и можно ли использовать на работе?

+
+

Да в обоих случаях. Инструмент выпущен под GPL-3.0 и ничего не стоит. Нет ни учётной записи, ни лицензионного ключа, ни платного тарифа.

+
+
+
+

Можно ли использовать созданные файлы в продукте с закрытым кодом?

+
+

Да. Лицензия охватывает код инструмента, а не то, что он создаёт. Созданные файлы, рецепты и манифесты являются результатом, а не производными произведениями, поэтому их можно коммитить и поставлять без каких-либо обязательств.

+
+
+
+

Содержат ли созданные файлы настоящие персональные данные?

+
+

Нет. Всё внутри синтезируется из seed. Никакой набор данных не читается, ни к какому сервису не обращаются и никакое стороннее содержимое не встраивается. Считайте созданный адрес электронной почты непригодным, а не неиспользованным, потому что любая случайная строка может случайно совпасть с настоящим адресом.

+
+
+
+

Получу ли я точно такие же файлы на другой машине?

+
+

Да, байт в байт, при том же рецепте и том же seed. Проект проверяет это при каждом изменении, а нарушить это можно только повышением мажорной версии. Именно поэтому вы можете коммитить небольшой рецепт вместо больших бинарных фикстур.

+
+
+
+

Нужно ли подключение к интернету?

+
+

Никогда. Нет ни телеметрии, ни проверки обновлений, ни облачного клиента, а в бинарный файл командной строки вообще не скомпилирован сетевой стек. Он работает на машине без сети и в закрытой корпоративной среде.

+
+
+
+

Что будет, если запросить размер, которого формат не может достичь?

+
+

Вы получите ошибку с названием формата, наименьшим возможным размером, причиной этого минимума и тем, что делать вместо этого, а файл записан не будет. Инструмент никогда не округляет размер молча. Каждый минимум указан на странице форматов.

+
tfg formats png
+
+
+
+

Можно ли создать намеренно сломанный файл?

+
+

Да. Добавьте --damage zero-head, и файл выйдет точно заданного размера, с первыми байтами, перезаписанными нулями, так что программа чтения его отклонит, а манифест скажет, что ваша система должна его отклонить. Подробности на странице о повреждённых тестовых файлах.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Какие форматы появятся дальше?

+
+

7z, mp3 и mp4. Сегодня полностью работают 26 форматов.

+
+
+
+

На каких системах это можно запускать?

+
+

Командная строка работает в Windows и Linux на Intel и ARM, а также на Mac с Apple Silicon. Десктопное окно поставляется для Windows на Intel, Linux на Intel и Mac с Apple Silicon. Mac на Intel не поддерживаются, и для них ничего не собирается.

+
+
+
+

Нужно ли что-нибудь устанавливать?

+
+

Нет. Скачайте архив для своей системы, распакуйте и запустите бинарный файл. Нет установщика, среды выполнения, которую нужно добавлять, и зависимостей, которые нужно разрешать. Если у вас есть Go, подойдёт и одна команда go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Почему запуск на тысячах файлов в Windows медленнее?

+
+

Потому что Windows берёт больше за каждый просматриваемый путь, а команда, обходящая тысячи файлов, просматривает тысячи путей. Измерено на одной машине с 3000 файлов по 1 КБ: verify занимает около 0,9 секунды в Windows и около 0,2 секунды в Linux в контейнере. Более короткий путь вывода уменьшает цифру для Windows, потому что каждая папка над файлами входит в то, что просматривается.

+
+
+
+ + +
+

Всё ещё выбираете?

+

+ Страница сценариев показывает задачи, для которых инструмент создан, а + страница форматов перечисляет каждый формат с наименьшим файлом, + который он может создать. README в репозитории - полный + справочник. +

+ +

Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.

+
+ +
+ + + + diff --git a/web/public/ru/formats/index.html b/web/public/ru/formats/index.html new file mode 100644 index 00000000..8cfdc091 --- /dev/null +++ b/web/public/ru/formats/index.html @@ -0,0 +1,911 @@ + + + + + + +26 форматов файлов - PDF, DOCX, PNG, ZIP и другие + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 форматов файлов, каждый создаётся точного размера

+

+ Каждый из них - настоящий файл этого формата. Он открывается в своей программе и + имеет ровно то число байт, которое вы запросили. Ни один не является нулями-заполнителями с + приклеенным расширением. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ФорматНазваниеРасширениеНаименьший файлПолнотаПроверяется с помощью
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullне применимо
mdMarkdown.md0fullне применимо
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullне применимо
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Что означают столбцы

+
    +
  • +

    Наименьший файл

    +

    + Наименьшее число байт, которое этот инструмент принимает для формата, включая метку, которую он + пишет внутри файла. Запросите меньше, и вы получите ошибку с названием минимума и причиной, + а не файл неверного размера. +

    +
  • +
  • +

    Полнота

    +

    + Насколько полон файл. full означает, что его принимает читатель, который по-настоящему + разбирает формат, а не просто совпадает расширение. +

    +
  • +
  • +

    Проверяется с помощью

    +

    + Независимый читатель, который открывает каждый созданный файл до выпуска формата, - отдельная + реализация, а не наш собственный код, проверяющий собственные домашние задания. +

    +
  • +
+

+ Каждый формат к тому же повторяется до байта: тот же рецепт и тот же seed дают одинаковые файлы на + любой машине, и именно это делает безопасным коммит рецепта вместо самих фикстур. +

+
+ +
+

Настройки, которые принимает каждый формат

+

+ У большинства форматов есть свои настройки - размеры изображения, качество JPEG, число страниц PDF, + строки и столбцы в таблице, сколько записей входит в архив. Задайте их через --set + key=value в командной строке или в разделе properties: рецепта. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ФорматНастройкаДопускает
avifwidth1 - 16384 пикселей
height1 - 16384 пикселей
quality1 - 100
bmpwidth1 - 20000 пикселей
height1 - 20000 пикселей
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerистина или ложь
quote_styleall, minimal, none
columns2 - 32768 столбцов
docxparagraphs1 - 50000 абзацев
gifwidth1 - 20000 пикселей
height1 - 20000 пикселей
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 пикселей
height1 - 256 пикселей
embedbmp, png
jpgwidth1 - 20000 пикселей
height1 - 20000 пикселей
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 пикселей
height1 - 16384 пикселей
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 записей в секунду
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomистина или ложь
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleлюбой текст
authorлюбой текст
subjectлюбой текст
keywordsлюбой текст
creatorлюбой текст
producerлюбой текст
createdдата вида 2024-02-29 или 2024-02-29T13:45:00+02:00, либо none
modifiedдата вида 2024-02-29 или 2024-02-29T13:45:00+02:00, либо none
pngwidth1 - 20000 пикселей
height1 - 20000 пикселей
pptxslides1 - 500 слайдов
svgwidth1 - 20000 пикселей
height1 - 20000 пикселей
targzentries0 - 10000
entry_formatid формата в том виде, как его выводит tfg formats
entry_sizeразмер, например 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesистина или ложь
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 пикселей
height1 - 20000 пикселей
txtencodingutf-16be, utf-16le, utf-8
bomистина или ложь
wavsample_rate8000 - 192000 герц
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 пикселей
height1 - 16383 пикселей
xlsxrows1 - 200000 строк
columns1 - 32768 столбцов
xmlencodingutf-16be, utf-16le, utf-8
bomистина или ложь
zipentries0 - 10000
entry_formatid формата в том виде, как его выводит tfg formats
entry_sizeразмер, например 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesистина или ложь
passwordпароль открытым текстом
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Значение вне допустимого для настройки отклоняется сообщением с названием настройки, допустимым + диапазоном и тем, что использовать вместо этого. Неизвестная настройка тоже ошибка, а не + молчаливое значение по умолчанию - опечатка, принятая молча, даёт файл с неверными настройками и + час раздумий, почему тест проходит, хотя не должен. +

+

+ Выполните tfg formats <id>, чтобы увидеть, что именно принимает один формат в + вашей сборке. +

+
+ +
+

Архивы содержат настоящие файлы

+

+ targz и zip + можно наполнить записями, а не оставлять пустой оболочкой. Созданный архив действительно + содержит документы, которые заявляет, поэтому всё, что распаковывает его во время теста, находит + внутри настоящие файлы. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/ru/index.html b/web/public/ru/index.html new file mode 100644 index 00000000..f037974c --- /dev/null +++ b/web/public/ru/index.html @@ -0,0 +1,454 @@ + + + + + + +Генератор тестовых файлов для QA - точный размер, 26 форматов + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Создавайте настоящие тестовые файлы точного размера

+

+ PDF, PNG, DOCX, ZIP - всего 26 форматов, и каждый из них + настоящий файл, который открывается в своей программе, точно того размера, который вы + запросили. Каждый запуск ещё и записывает, что ваше приложение должно делать с каждым + файлом. Командная строка и десктопное окно, бесплатно и с открытым кодом, всё работает на вашей + машине. +

+ + +

Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.

+
+ +
+ Десктопное окно Testing Files Generator, подготовленное к записи партии тестовых файлов +
Десктопное окно, подготовленное к записи партии файлов. За командной строкой работает тот же движок.
+
+
+ + + +
+

Проблема

+

Сделать один тестовый файл легко. Сделать нужную тысячу - вот утомительная часть

+

Вы тестируете программу, принимающую файлы от людей. Рано или поздно вам понадобятся:

+
    +
  • PDF ровно на 10 МБ, чтобы выяснить, реален ли лимит загрузки
  • +
  • три файла по обе стороны этого лимита, чтобы поймать ошибки на единицу
  • +
  • 10 000 файлов журнала, чтобы увидеть, что делает ночное задание, когда папка велика
  • +
  • ZIP, который действительно содержит 200 документов, а не пустышку с правильным расширением
  • +
  • файл на 4 ГБ без хранения файла на 4 ГБ в вашем репозитории
  • +
  • одинаковые фикстуры на ноутбуке и на сервере сборки, байт в байт
  • +
+

+ Именно это он заменяет. Он создан для QA-инженеров, автоматизации тестирования и всех, за чьим кодом + стоит форма загрузки, процедура импорта, парсер или квота хранилища. +

+
+ +
+

Чем он отличается

+

Другие генераторы останавливаются на байтах. Этот отвечает на то, о чём на самом деле спрашивает ваш тест

+

+ Папка с файлами всё равно оставляет вам решать, что должен доказывать каждый из них. Каждый запуск + здесь записывает рядом с файлами manifest.json - простой список всего созданного и + для каждой записи заявленное ожидание. +

+

Допустим, ваша точка загрузки допускает 1 МБ. Запросите три файла, лежащие на этой границе:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ФайлБайтВаша система должнаПотому что
1mb_under_1b.pdf1048575принятьон в пределах лимита
1mb_at_limit.pdf1048576принятьсам лимит допустим
1mb_over_1b.pdf1048577отклонитьsize_limit
+
+ +

Три файла, три разных ответа, в машиночитаемом виде. Ваш тест читает манифест, вместо того чтобы вы писали проверки вручную:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Там, где ответ зависит от вашей собственной политики, манифест так и говорит

+

+ Он записывает unspecified, а не придумывает ожидание. Генератор, который гадает, даёт + ложные сбои, а набор тестов, который кричит «волки», в итоге отключают. +

+
+
+ +
+

Пресеты

+

Выберите вопрос, получите весь набор

+

+ Пресет - это набор тестовых файлов, продуманный вокруг одного тестового вопроса, чтобы вам не + пришлось выяснять, какие файлы что доказывают. У каждого есть страница о том, что он обычно + находит, что входит в набор и какие настройки принимает. +

+
    +
  • +

    Пустые и минимальные

    +

    Пройдёт ли корректный файл, настолько маленький, насколько позволяет формат?

    +

    empty-and-minimal

    +
  • +
  • +

    Обработка имён файлов

    +

    Сохранит, покажет и вернёт ли моя система имя файла, которого не ожидала?

    +

    filename-handling

    +
  • +
  • +

    Границы размера

    +

    Применяется ли лимит размера ровно там, где он объявлен?

    +

    size-boundaries

    +
  • +
  • +

    Импорт таблиц

    +

    Переживёт ли мой импорт таблиц то, что экспортируют настоящие инструменты?

    +

    tabular-import

    +
  • +
  • +

    Кодировка текста

    +

    Знает ли мой читатель, в какой кодировке файл, или угадывает?

    +

    text-encoding

    +
  • +
  • +

    Проверка загрузки

    +

    Принимает ли моя форма загрузки то, что должна, и отклоняет ли остальное?

    +

    upload-validation

    +
  • +
+

Все пресеты и как они связаны с рецептами

+
+ +
+

Быстрый старт

+

Три команды, чтобы увидеть работу

+
    +
  1. +

    Создайте файл

    +

    Один PNG, ровно два мегабайта:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Создайте много файлов

    +

    + Десять тысяч файлов журнала, каждый от одного до восьми килобайт, с размерами из seed, чтобы завтра + получился тот же набор. Давайте каждому запуску свой каталог - манифест + остаётся единственной записью о том, что записал запуск, поэтому инструмент отказывается + записывать второй поверх него: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Проверьте их, затем удалите

    +

    verify сообщает, что ничего не сдвинулось. cleanup удаляет ровно то, что было записано, и ничего больше:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Размеры считаются по 1024, как в вашем файловом менеджере, поэтому 2mb означает 2097152 + байта. Подойдёт и простое число байт. Документация охватывает рецепты, + манифест и коды завершения. +

+
+ +
+

Что вы получаете

+

Создан для набора тестов, работающего без присмотра

+
    +
  • +

    Точный размер, до байта

    +

    Запросите 10485761 байт и получите ровно столько. Размер, которого формат не может достичь, - это ошибка с причиной, а не файл неверного размера.

    +
  • +
  • +

    26 настоящих форматов

    +

    Не нули-заполнители с расширением. Созданный PNG открывается в просмотрщике изображений, DOCX - в Word, ZIP распаковывается. Каждый формат проверяется независимыми читателями до выпуска.

    +
  • +
  • +

    Манифест, который служит тестовым оракулом

    +

    Путь, размер, SHA-256, формат, seed, версия инструмента - и то, что ваша система должна сделать с файлом.

    +
  • +
  • +

    Воспроизводимость

    +

    Тот же рецепт и тот же seed, те же байты на любой машине. Коммитьте небольшой рецепт YAML вместо больших бинарных фикстур.

    +
  • +
  • +

    Два интерфейса, один движок

    +

    Командная строка, созданная для CI, и десктопное окно для исследовательского тестирования. Ни один не урезанная версия другого, и тест сравнивает их возможность за возможностью.

    +
  • +
  • +

    Полностью офлайн

    +

    Нет учётной записи, облака, телеметрии и проверки обновлений. В бинарный файл командной строки вообще не скомпилирован сетевой стек.

    +
  • +
+
+ +
+

Скачать

+

Выберите сборку для вашей системы

+

+ Распакуйте архив и запустите. tfg - это командная строка, а tfg-gui - + десктопное окно. Нет установщика и ничего, что нужно добавлять на вашу машину. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
СистемаКомандная строкаДесктопное окно
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Что подписано, а что нет

+

+ Сборки для Windows и macOS подписаны, поэтому запускаются без предупреждения о неизвестном + разработчике. Сборки для Linux не подписаны, потому что у десктопного Linux нет эквивалента, + которым их можно подписать. Каждый архив указан в verify-SHA256SUMS.txt на + странице релиза, так что вы можете проверить, что скачали. +

+
+ +

Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.

+
+ + +
+ + + + diff --git a/web/public/ru/presets/empty-and-minimal/index.html b/web/public/ru/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..c10ffd02 --- /dev/null +++ b/web/public/ru/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Минимальные корректные и пустые тестовые файлы в каждом формате + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Пустые и минимальные

+

Пройдёт ли корректный файл, настолько маленький, насколько позволяет формат?

+

+ Пресет empty-and-minimal одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • корректный файл, отклонённый как слишком маленький, потому что проверка считает байты, а не читает их
  • +
  • пустой файл, который роняет читающий код вместо того, чтобы быть замеченным
  • +
  • картинка шириной в один пиксель, которая делит на ноль на пути к миниатюре
  • +
  • хранилище, которое воспринимает ноль байт как неудачную загрузку и бесконечно повторяет попытки
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show empty-and-minimal:

+
+ + + + + + + +
Файлов28
Целей в его рецепте28
Общий размер32 667 B
Форматыavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.26
unspecifiedЗависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду.2
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--formatsid форматов через запятую или allallИз каких форматов состоит набор. Оставьте all для всех форматов этой сборки или перечислите те, которые принимает ваша система.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/ru/presets/filename-handling/index.html b/web/public/ru/presets/filename-handling/index.html new file mode 100644 index 00000000..8b1ab5cd --- /dev/null +++ b/web/public/ru/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Проблемные имена файлов для тестов - Unicode и длина + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Обработка имён файлов

+

Сохранит, покажет и вернёт ли моя система имя файла, которого не ожидала?

+

+ Пресет filename-handling одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • имя, которое на экране, в журнале или в списке выглядит как другое
  • +
  • имя, обрезанное, укороченное или переписанное между загрузкой и хранением
  • +
  • лимит длины, который считается в символах там, где хранилище считает байты
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show filename-handling:

+
+ + + + + + + +
Файлов50
Целей в его рецепте50
Общий размер51 200 B
Форматыtxt
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.4
unspecifiedЗависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду.46
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--formatid формата со страницы форматовtxtФормат каждого файла набора. Это флаг самого инструмента, а пресет лишь задаёт ему значение по умолчанию.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/ru/presets/index.html b/web/public/ru/presets/index.html new file mode 100644 index 00000000..6eedbc33 --- /dev/null +++ b/web/public/ru/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +Пресеты тестовых файлов - готовые наборы для QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Пресеты тестовых файлов, по набору на каждый тестовый вопрос

+

+ Пресет - это целый набор тестовых файлов, продуманный вокруг одного вопроса, с манифестом об + ожидаемой реакции вашей системы на каждый файл. Вы выбираете вопрос, инструмент собирает набор. У + каждого пресета своя страница о том, что он обычно находит, что входит в набор и какие настройки + принимает. +

+ + + +
+

Чем пресет отличается от рецепта?

+

+ По сути ничем. Пресет - это рецепт, который инструмент пишет для вас из нескольких настроек. + tfg preset eject выводит этот рецепт, чтобы вы могли хранить его рядом с тестами и + править, а ваш собственный рецепт может опираться на пресет одной строкой: extends: + preset: и его id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Можно ли доверять значениям по умолчанию?

+

+ Для файлов - да. Для числа, которое знает только ваша система, например лимита формы загрузки, + значение по умолчанию - наша временная подстановка, и инструмент говорит об этом каждый раз, + когда её использует. Страница каждого пресета отмечает такие настройки, а tfg preset + show сообщает об этом до записи чего-либо. +

+
+ +
+ + + + diff --git a/web/public/ru/presets/size-boundaries/index.html b/web/public/ru/presets/size-boundaries/index.html new file mode 100644 index 00000000..0092ac57 --- /dev/null +++ b/web/public/ru/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Проверка лимита размера загрузки - файлы на самой границе + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Границы размера

+

Применяется ли лимит размера ровно там, где он объявлен?

+

+ Пресет size-boundaries одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • ошибки на единицу на границе лимита
  • +
  • МБ, перепутанные с МиБ, то есть 4,8 процента, чего достаточно, чтобы пропустить файл, который не должен проходить
  • +
  • лимит, который применяется в браузере, а не на сервере
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show size-boundaries:

+
+ + + + + + + +
Файлов7
Целей в его рецепте7
Общий размер73 400 320 B
Форматыpdf
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.4
rejectВаша система должна отклонить файл.3
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--limitразмер, например 2mb10mbЛимит размера, который объявляет ваша система. Всё остальное отмеряется от него. Это значение по умолчанию - наша временная подстановка, а не значение вашей системы. Передайте своё.
--spreadразмеры через запятую1B,1kb,1mbКак далеко отходить от лимита в обе стороны, списком размеров.
--formatid формата со страницы форматовpdfФормат каждого файла набора. Это флаг самого инструмента, а пресет лишь задаёт ему значение по умолчанию.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

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

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ru/presets/tabular-import/index.html b/web/public/ru/presets/tabular-import/index.html new file mode 100644 index 00000000..18e42a10 --- /dev/null +++ b/web/public/ru/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Тестовые файлы для импорта CSV и Excel - разделители и заголовки + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Импорт таблиц

+

Переживёт ли мой импорт таблиц то, что экспортируют настоящие инструменты?

+

+ Пресет tabular-import одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • файл с точкой с запятой, прочитанный как один столбец, потому что разделитель предположили, а не искали
  • +
  • файл CRLF, разбитый на строки с пустой строкой после каждой
  • +
  • таблица без заголовка, первая строка данных которой съедается как имена столбцов
  • +
  • импорт, который оставляет столбцы, что может показать, и молча отбрасывает остальные
  • +
  • читатель, который берёт записи JSON по одной строке и останавливается на первом документе с отступами
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show tabular-import:

+
+ + + + + + + +
Файлов13
Целей в его рецепте13
Общий размер3 080 060 B
Форматыcsv, json, xlsx
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.8
unspecifiedЗависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду.5
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--rows1 - 200000 строк1000Сколько строк в таблице. Файл записывается ровно того размера, в который упаковывается столько строк, поэтому бюджет выше меняется вместе с этим значением.
--columns1 - 32768 столбцов10Сколько столбцов в каждой строке таблицы. У произведения строк на столбцы есть потолок, и запрос сверх него отклоняется до записи чего-либо.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/ru/presets/text-encoding/index.html b/web/public/ru/presets/text-encoding/index.html new file mode 100644 index 00000000..97185a99 --- /dev/null +++ b/web/public/ru/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Тестовые файлы кодировки текста - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Кодировка текста

+

Знает ли мой читатель, в какой кодировке файл, или угадывает?

+

+ Пресет text-encoding одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • читатель, который предполагает UTF-8 и показывает файл UTF-16 с одним символом из трёх или рядами квадратиков
  • +
  • метка порядка байтов, прочитанная как содержимое, из-за чего первое поле импорта начинается с трёх лишних символов
  • +
  • импортёр, который угадывает кодировку по первым байтам и угадывает иначе для более длинного файла
  • +
  • файл CRLF, разбитый на строки с пустой строкой после каждой, или возврат каретки, оставшийся в последнем поле
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show text-encoding:

+
+ + + + + + + +
Файлов20
Целей в его рецепте20
Общий размер81 920 B
Форматыcsv, log, md, txt, xml
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.10
unspecifiedЗависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду.10
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--sampleразмер, например 2mb4kbРазмер каждого файла набора. UTF-16 хранит по два байта на символ, поэтому нечётное число отклоняется.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/ru/presets/upload-validation/index.html b/web/public/ru/presets/upload-validation/index.html new file mode 100644 index 00000000..d6884568 --- /dev/null +++ b/web/public/ru/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Тестовые файлы проверки загрузки - тип, размер и имя + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресеты

+

Проверка загрузки

+

Принимает ли моя форма загрузки то, что должна, и отклоняет ли остальное?

+

+ Пресет upload-validation одной командой собирает целый набор настоящих тестовых файлов для + этого вопроса и рядом manifest.json с ожидаемой реакцией вашей системы на каждый + файл. Всё ниже прочитано из программы со значениями по умолчанию этой версии. +

+ + +
+

Что он обычно находит?

+
    +
  • лимит, который применяется в браузере, а не на сервере
  • +
  • SVG или HTML, принятый за картинку или простой текст, что позволяет провести скрипт через форму
  • +
  • файл, проверенный по расширению и ни разу не открытый, так что PDF с именем .jpg проходит
  • +
  • форма, которая читает всё тело в память, прежде чем посмотреть, насколько оно велико
  • +
  • загрузка с именем PHOTO.JPG отклонена там, где photo.jpg принимается, или наоборот
  • +
  • имя с пробелами, скобками или символами вне ASCII, записанное на диск без изменений
  • +
+
+ + +
+

Что входит в набор?

+

Со значениями по умолчанию, как сообщает tfg preset show upload-validation:

+
+ + + + + + + +
Файлов71
Целей в его рецепте22
Общий размер120 639 488 B
Форматыhtml, jpg, pdf, png, svg, txt
+
+

И чего манифест этого набора ожидает от вашей системы:

+
+ + + + + + + + + +
ОжидаетсяЗначениеФайлов
acceptВаша система должна принять файл.56
rejectВаша система должна отклонить файл.10
unspecifiedЗависит от правил вашей системы. Вы решаете, а затем проверяете, что происходит именно то, что вы имели в виду.5
+
+
+ +
+

Что можно изменить?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
НастройкаПринимаетПо умолчаниюЧто делает
--limitразмер, например 2mb10mbЛимит размера, который объявляет ваша форма загрузки. Этот набор делает по одному шагу в обе стороны - для файла на любом расстоянии запустите пресет size-boundaries. Это значение по умолчанию - наша временная подстановка, а не значение вашей системы. Передайте своё.
--allowid форматов через запятуюjpg,png,pdfКакие типы должна принимать ваша форма. Каждый становится настоящим файлом этого типа, и вместе они служат положительным контролем всего набора.
--denyрасширения через запятуюsvg,html,exe,shКакие расширения должна отклонять ваша форма. Расширение, для которого в этой сборке нет формата, всё равно получает файл с таким именем и простым текстом внутри.
--far-over10x, 2x, off2xНасколько далеко за лимит заходит единственный большой файл. Отключите, если запись нескольких лимитов не стоит места на диске.
--bulk0 - 10000 файлов50Сколько файлов в массовой загрузке. Ноль полностью убирает эту группу из набора.
+
+
+ +
+

Как его запустить?

+

Посмотрите, чего стоил бы набор, соберите его или возьмите его рецепт для правки:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Или стройте на нём в собственном рецепте рядом с тестами:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/ru/test-files-in-ci/index.html b/web/public/ru/test-files-in-ci/index.html new file mode 100644 index 00000000..521805ea --- /dev/null +++ b/web/public/ru/test-files-in-ci/index.html @@ -0,0 +1,378 @@ + + + + + + +Тестовые файлы в CI - GitHub Actions, GitLab CI и PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Сценарии

+

Как генерировать тестовые файлы в конвейере CI

+

+ Двоичная фикстура в репозитории остаётся в его истории навсегда, её нельзя проверить в диффе, и она + перестаёт быть возможной, когда файл велик. Генерируйте файлы внутри конвейера из рецепта. Рецепт + - это текст, байты каждый раз выходят одинаковыми, а последний шаг доказывает, что ничего не + сдвинулось. +

+ +
+

Короткий ответ

+

+ Установите tfg, запустите tfg generate fixtures.yaml --out ./fixtures + перед тестами и tfg verify ./fixtures/manifest.json после них. Оба шага сами роняют + сборку, с кодом завершения, который говорит почему. +

+
+ +
+

Почему не коммитить

+

Почему фикстуре не место в репозитории

+
    +
  • + Она остаётся в истории. Удаление двоичного файла позже не делает клон меньше, + потому что каждая его версия всё ещё там. +
  • +
  • + Дифф не показывает, что изменилось. Рецензент видит, что PDF другой, и ничего + больше. Рецепт меняется на одну строку. +
  • +
  • + Большие файлы не помещаются. GitHub отклоняет push, в котором есть файл больше 100 + МБ, поэтому тесту лимита загрузки в 500 МБ нечего коммитить. +
  • +
+

+ Коммитить нужно рецепт. Один и тот же рецепт с тем же зерном записывает одни и те же байты на любой + машине, поэтому файл, созданный в конвейере, - это файл, который был у вас на ноутбуке. +

+
+ +
+

Рецепт

+

Рецепт, который лежит рядом с тестами

+

+ Этот записывает двадцать пять счетов, которые должны быть приняты, и два изображения сверх лимита, + которые должны быть отклонены, а манифест фиксирует оба ожидания: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml проверяет его, ничего не записывая, и называет сразу все + проблемы. +

+
+ +
+

GitHub Actions

+

Workflow, который устанавливает инструмент и собирает фикстуры

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Строка с контрольной суммой сверяет архив с verify-SHA256SUMS.txt из того же выпуска. + Версия зафиксирована, так что новый выпуск никогда не изменит сборку, которой вы не касались. +

+
+ +
+

GitLab CI

+

То же самое как задание GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Когда становится красно

+

Что роняет шаг и почему

+

+ У каждого завершения свой код, так что шаг падает сам, а журнал говорит, какой именно. Те, что + встречает конвейер: +

+
    +
  • 3 - рецепт недопустим. Ничего не записано, и названа каждая проблема
  • +
  • 4 - формат не умеет того, что попросили, например размера меньше своего минимума
  • +
  • 6 - не хватает места на диске
  • +
  • 7 - tfg verify нашёл файл, не совпадающий со своим манифестом
  • +
  • 8 - запуск закончился, но создано не всё
  • +
+

+ Неудачный запуск ничего не печатает в стандартный вывод, поэтому разборщик журналов никогда не + примет ошибку за данные. Вся таблица на странице документации. +

+
+ +
+

PowerShell

+

Скрипту PowerShell нужна ещё одна строка

+

+ PowerShell не выносит код завершения программы из файла .ps1. Запустите такой файл с + -File, и скрипт ответит 0, даже когда инструмент внутри отказался + работать, так что сборка, которая должна быть красной, становится зелёной. Последняя строка - + это всё исправление: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Так ведёт себя PowerShell, а не этот инструмент. cmd, bash и + zsh ничего лишнего не требуют. +

+
+ +
+

Несколько заданий

+

Как делиться фикстурами между заданиями

+

+ Обычно загружать их не нужно. Поскольку один и тот же рецепт записывает одни и те же байты, каждое + задание может запустить собственный tfg generate, что быстрее загрузки и + скачивания. Когда задание должно получить файлы от другого, запустите после передачи tfg + verify на манифесте, и он скажет, совпадает ли полученное с записанным. +

+
+ +
+

Дальше

+

Куда идти отсюда

+ +
+ +
+ + + + diff --git a/web/public/ru/use-cases/index.html b/web/public/ru/use-cases/index.html new file mode 100644 index 00000000..080a85f3 --- /dev/null +++ b/web/public/ru/use-cases/index.html @@ -0,0 +1,317 @@ + + + + + + +Сценарии - лимиты загрузки, фикстуры для CI, массовые тесты + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Для чего это используют

+

+ Пять задач, которые возникают почти в каждом проекте, принимающем файлы от людей, и команда, + решающая каждую. Каждый пример ниже запускается как написано. +

+ +
+

Лимиты загрузки

+

Проверка того, что лимит размера файла применяется там, где заявлено

+

+ Лимит - это три тестовых случая, а не один: чуть ниже, ровно по лимиту и чуть выше. Получить их + вручную значит считать числа байт и надеяться, что вы не ошиблись на единицу. Запросите вместо + этого набор: +

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

+ Вы получите три настоящих PDF по 1048575, 1048576 и 1048577 байт и манифест, который говорит, что + первые два нужно принять, а третий отклонить по size_limit. Ваш тест читает + ожидание, вместо того чтобы вы писали три проверки вручную, а когда лимит меняется, вы меняете + одно число и запускаете заново. +

+

+ То же работает и без пресета, когда нужен один набор границ прямо в команде: +

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

Непрерывная интеграция

+

Держать фикстуры вне репозитория, не теряя их

+

+ Большие бинарные фикстуры замедляют клонирование репозитория и мешают ревью, а при замене никто не + может сказать, что изменилось. Рецепт - это несколько сотен символов YAML, которые пересоздают + те же файлы - байт в байт, на любой машине - потому что каждый файл выводится + из 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
+

+ У каждого исхода свой код завершения, поэтому конвейер отличает плохой рецепт от полного диска и от + расхождения при проверке. Неудачный запуск ничего не печатает в стандартный вывод, и разборщик + журналов не принимает ошибку за данные. +

+
+ +
+

Масштаб

+

Выяснить, что происходит, когда папка велика

+

+ Процедуры импорта, ночные задания и списки каталогов ведут себя иначе при десяти тысячах файлов, чем + при десяти. Размеры, выбранные из диапазона, делают набор похожим на настоящий трафик, а не на + десять тысяч одинаковых файлов, и выбор идёт от seed, так что завтра набор будет тем же. +

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

+ Проверьте, чего стоил бы запуск, до того как он что-либо запишет, это важно, когда итог измеряется + гигабайтами: +

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

+ Запуск больше свободного места на диске отклоняется до записи первого байта, а не заполняет диск и + не падает на полпути. +

+
+ +
+

Архивы

+

Проверка распаковщика на архиве, который действительно содержит файлы

+

+ Пустой архив с правильным расширением ничего не доказывает о коде, который его открывает и обходит + содержимое. Объявите содержимое, и архив действительно его содержит: +

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

+ Глубина вложенности, число записей и размер содержимого - это то, о чём у процедуры импорта есть + своё мнение, и так вы узнаёте, каково оно. +

+
+ +
+

Парсеры и просмотрщики

+

Проверка того, что ваш собственный код читает формат так же, как настоящее ПО

+

+ Каждый формат здесь проверяется независимым читателем до выпуска: PNG открывается и сравниваются его + пиксели, DOCX перечитывается отдельными библиотеками, архив распаковывается. Это значит, что + файл, который отклоняет ваш парсер, - находка о вашем парсере, а не о генераторе. +

+
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
+

+ Страница форматов перечисляет настройки каждого формата и наименьший + файл, каким он может быть. +

+
+ +
+

Руководства

+

Два из них подробнее

+
    +
  • + Повреждённые тестовые файлы - файл, намеренно испорченный, + точного размера, с записанным в манифесте тем, что с ним должно произойти. +
  • +
  • + Тестовые файлы в CI - workflow для GitHub Actions, задание + GitLab и коды завершения, которые роняют сборку. +
  • +
+
+ +
+

Для кого это

+

+ QA-инженеры, автоматизация тестирования и все, за чьим кодом стоит форма загрузки, процедура + импорта, парсер или квота хранилища. Работает на машине вообще без сети, что важно в закрытой + корпоративной среде, где генератор в браузере - не вариант. +

+ +

Бесплатно, открытый код, GPL-3.0. Без регистрации. Сборки для Windows и macOS подписаны и запускаются без предупреждений.

+
+ +
+ + + + diff --git a/web/public/sitemap.xml b/web/public/sitemap.xml index 9c51580a..4e3ed29f 100644 --- a/web/public/sitemap.xml +++ b/web/public/sitemap.xml @@ -21,6 +21,12 @@ https://testingfilesgenerator.donislawdev.com/faq/ + + https://testingfilesgenerator.donislawdev.com/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/test-files-in-ci/ + https://testingfilesgenerator.donislawdev.com/presets/empty-and-minimal/ @@ -40,42 +46,948 @@ https://testingfilesgenerator.donislawdev.com/presets/upload-validation/ - https://testingfilesgenerator.donislawdev.com/pl/ + https://testingfilesgenerator.donislawdev.com/ar/ - https://testingfilesgenerator.donislawdev.com/pl/formaty/ + https://testingfilesgenerator.donislawdev.com/ar/formats/ - https://testingfilesgenerator.donislawdev.com/pl/presety/ + https://testingfilesgenerator.donislawdev.com/ar/presets/ - https://testingfilesgenerator.donislawdev.com/pl/dokumentacja/ + https://testingfilesgenerator.donislawdev.com/ar/docs/ - https://testingfilesgenerator.donislawdev.com/pl/zastosowania/ + https://testingfilesgenerator.donislawdev.com/ar/use-cases/ - https://testingfilesgenerator.donislawdev.com/pl/plik-o-zadanym-rozmiarze/ + https://testingfilesgenerator.donislawdev.com/ar/create-file-exact-size/ - https://testingfilesgenerator.donislawdev.com/pl/faq/ + https://testingfilesgenerator.donislawdev.com/ar/faq/ - https://testingfilesgenerator.donislawdev.com/pl/presety/empty-and-minimal/ + https://testingfilesgenerator.donislawdev.com/ar/corrupt-test-files/ - https://testingfilesgenerator.donislawdev.com/pl/presety/filename-handling/ + https://testingfilesgenerator.donislawdev.com/ar/test-files-in-ci/ - https://testingfilesgenerator.donislawdev.com/pl/presety/size-boundaries/ + https://testingfilesgenerator.donislawdev.com/ar/presets/empty-and-minimal/ - https://testingfilesgenerator.donislawdev.com/pl/presety/tabular-import/ + https://testingfilesgenerator.donislawdev.com/ar/presets/filename-handling/ - https://testingfilesgenerator.donislawdev.com/pl/presety/text-encoding/ + https://testingfilesgenerator.donislawdev.com/ar/presets/size-boundaries/ - https://testingfilesgenerator.donislawdev.com/pl/presety/upload-validation/ + https://testingfilesgenerator.donislawdev.com/ar/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/ar/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/ar/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/cs/ + + + https://testingfilesgenerator.donislawdev.com/cs/formaty/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/ + + + https://testingfilesgenerator.donislawdev.com/cs/dokumentace/ + + + https://testingfilesgenerator.donislawdev.com/cs/pripady-pouziti/ + + + https://testingfilesgenerator.donislawdev.com/cs/vytvoreni-souboru-presne-velikosti/ + + + https://testingfilesgenerator.donislawdev.com/cs/faq/ + + + https://testingfilesgenerator.donislawdev.com/cs/poskozene-testovaci-soubory/ + + + https://testingfilesgenerator.donislawdev.com/cs/testovaci-soubory-v-ci/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/cs/predvolby/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/de/ + + + https://testingfilesgenerator.donislawdev.com/de/formate/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/ + + + https://testingfilesgenerator.donislawdev.com/de/dokumentation/ + + + https://testingfilesgenerator.donislawdev.com/de/anwendungsfaelle/ + + + https://testingfilesgenerator.donislawdev.com/de/datei-bestimmter-groesse-erstellen/ + + + https://testingfilesgenerator.donislawdev.com/de/faq/ + + + https://testingfilesgenerator.donislawdev.com/de/beschaedigte-testdateien/ + + + https://testingfilesgenerator.donislawdev.com/de/testdateien-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/de/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/es/ + + + https://testingfilesgenerator.donislawdev.com/es/formatos/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/ + + + https://testingfilesgenerator.donislawdev.com/es/documentacion/ + + + https://testingfilesgenerator.donislawdev.com/es/casos-de-uso/ + + + https://testingfilesgenerator.donislawdev.com/es/crear-archivo-de-tamano-exacto/ + + + https://testingfilesgenerator.donislawdev.com/es/preguntas-frecuentes/ + + + https://testingfilesgenerator.donislawdev.com/es/archivos-de-prueba-corruptos/ + + + https://testingfilesgenerator.donislawdev.com/es/archivos-de-prueba-en-ci/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/es/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/fr/ + + + https://testingfilesgenerator.donislawdev.com/fr/formats/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/ + + + https://testingfilesgenerator.donislawdev.com/fr/documentation/ + + + https://testingfilesgenerator.donislawdev.com/fr/cas-d-usage/ + + + https://testingfilesgenerator.donislawdev.com/fr/creer-fichier-taille-exacte/ + + + https://testingfilesgenerator.donislawdev.com/fr/faq/ + + + https://testingfilesgenerator.donislawdev.com/fr/fichiers-de-test-corrompus/ + + + https://testingfilesgenerator.donislawdev.com/fr/fichiers-de-test-en-ci/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/fr/prereglages/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/hi/ + + + https://testingfilesgenerator.donislawdev.com/hi/formats/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/ + + + https://testingfilesgenerator.donislawdev.com/hi/docs/ + + + https://testingfilesgenerator.donislawdev.com/hi/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/hi/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/hi/faq/ + + + https://testingfilesgenerator.donislawdev.com/hi/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/hi/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/hi/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/id/ + + + https://testingfilesgenerator.donislawdev.com/id/format/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/ + + + https://testingfilesgenerator.donislawdev.com/id/dokumentasi/ + + + https://testingfilesgenerator.donislawdev.com/id/kasus-penggunaan/ + + + https://testingfilesgenerator.donislawdev.com/id/membuat-file-ukuran-tepat/ + + + https://testingfilesgenerator.donislawdev.com/id/faq/ + + + https://testingfilesgenerator.donislawdev.com/id/file-uji-rusak/ + + + https://testingfilesgenerator.donislawdev.com/id/file-uji-di-ci/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/id/preset/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/it/ + + + https://testingfilesgenerator.donislawdev.com/it/formati/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/ + + + https://testingfilesgenerator.donislawdev.com/it/documentazione/ + + + https://testingfilesgenerator.donislawdev.com/it/casi-d-uso/ + + + https://testingfilesgenerator.donislawdev.com/it/creare-file-di-dimensione-esatta/ + + + https://testingfilesgenerator.donislawdev.com/it/domande-frequenti/ + + + https://testingfilesgenerator.donislawdev.com/it/file-di-test-corrotti/ + + + https://testingfilesgenerator.donislawdev.com/it/file-di-test-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/it/preset/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/ja/ + + + https://testingfilesgenerator.donislawdev.com/ja/formats/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/ + + + https://testingfilesgenerator.donislawdev.com/ja/docs/ + + + https://testingfilesgenerator.donislawdev.com/ja/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/ja/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/ja/faq/ + + + https://testingfilesgenerator.donislawdev.com/ja/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/ja/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/ja/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/ko/ + + + https://testingfilesgenerator.donislawdev.com/ko/formats/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/ + + + https://testingfilesgenerator.donislawdev.com/ko/docs/ + + + https://testingfilesgenerator.donislawdev.com/ko/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/ko/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/ko/faq/ + + + https://testingfilesgenerator.donislawdev.com/ko/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/ko/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/ko/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/nl/ + + + https://testingfilesgenerator.donislawdev.com/nl/formaten/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/ + + + https://testingfilesgenerator.donislawdev.com/nl/documentatie/ + + + https://testingfilesgenerator.donislawdev.com/nl/toepassingen/ + + + https://testingfilesgenerator.donislawdev.com/nl/bestand-met-exacte-grootte-maken/ + + + https://testingfilesgenerator.donislawdev.com/nl/veelgestelde-vragen/ + + + https://testingfilesgenerator.donislawdev.com/nl/beschadigde-testbestanden/ + + + https://testingfilesgenerator.donislawdev.com/nl/testbestanden-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/nl/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/pl/ + + + https://testingfilesgenerator.donislawdev.com/pl/formaty/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/ + + + https://testingfilesgenerator.donislawdev.com/pl/dokumentacja/ + + + https://testingfilesgenerator.donislawdev.com/pl/zastosowania/ + + + https://testingfilesgenerator.donislawdev.com/pl/plik-o-zadanym-rozmiarze/ + + + https://testingfilesgenerator.donislawdev.com/pl/faq/ + + + https://testingfilesgenerator.donislawdev.com/pl/uszkodzone-pliki-testowe/ + + + https://testingfilesgenerator.donislawdev.com/pl/pliki-testowe-w-ci/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/pl/presety/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/formatos/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/documentacao/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/casos-de-uso/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/criar-arquivo-de-tamanho-exato/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/perguntas-frequentes/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/arquivos-de-teste-corrompidos/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/arquivos-de-teste-no-ci/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/pt-br/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/ro/ + + + https://testingfilesgenerator.donislawdev.com/ro/formate/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/ + + + https://testingfilesgenerator.donislawdev.com/ro/documentatie/ + + + https://testingfilesgenerator.donislawdev.com/ro/cazuri-de-utilizare/ + + + https://testingfilesgenerator.donislawdev.com/ro/creare-fisier-de-dimensiune-exacta/ + + + https://testingfilesgenerator.donislawdev.com/ro/intrebari-frecvente/ + + + https://testingfilesgenerator.donislawdev.com/ro/fisiere-de-test-corupte/ + + + https://testingfilesgenerator.donislawdev.com/ro/fisiere-de-test-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/ro/presetari/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/ru/ + + + https://testingfilesgenerator.donislawdev.com/ru/formats/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/ + + + https://testingfilesgenerator.donislawdev.com/ru/docs/ + + + https://testingfilesgenerator.donislawdev.com/ru/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/ru/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/ru/faq/ + + + https://testingfilesgenerator.donislawdev.com/ru/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/ru/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/ru/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/th/ + + + https://testingfilesgenerator.donislawdev.com/th/formats/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/ + + + https://testingfilesgenerator.donislawdev.com/th/docs/ + + + https://testingfilesgenerator.donislawdev.com/th/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/th/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/th/faq/ + + + https://testingfilesgenerator.donislawdev.com/th/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/th/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/th/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/tr/ + + + https://testingfilesgenerator.donislawdev.com/tr/bicimler/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/ + + + https://testingfilesgenerator.donislawdev.com/tr/dokumantasyon/ + + + https://testingfilesgenerator.donislawdev.com/tr/kullanim-senaryolari/ + + + https://testingfilesgenerator.donislawdev.com/tr/tam-boyutta-dosya-olusturma/ + + + https://testingfilesgenerator.donislawdev.com/tr/sss/ + + + https://testingfilesgenerator.donislawdev.com/tr/bozuk-test-dosyalari/ + + + https://testingfilesgenerator.donislawdev.com/tr/ci-icinde-test-dosyalari/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/tr/hazir-ayarlar/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/uk/ + + + https://testingfilesgenerator.donislawdev.com/uk/formats/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/ + + + https://testingfilesgenerator.donislawdev.com/uk/docs/ + + + https://testingfilesgenerator.donislawdev.com/uk/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/uk/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/uk/faq/ + + + https://testingfilesgenerator.donislawdev.com/uk/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/uk/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/uk/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/vi/ + + + https://testingfilesgenerator.donislawdev.com/vi/dinh-dang/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/ + + + https://testingfilesgenerator.donislawdev.com/vi/tai-lieu/ + + + https://testingfilesgenerator.donislawdev.com/vi/truong-hop-su-dung/ + + + https://testingfilesgenerator.donislawdev.com/vi/tao-tep-kich-thuoc-chinh-xac/ + + + https://testingfilesgenerator.donislawdev.com/vi/faq/ + + + https://testingfilesgenerator.donislawdev.com/vi/tep-kiem-thu-bi-hong/ + + + https://testingfilesgenerator.donislawdev.com/vi/tep-kiem-thu-trong-ci/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/vi/preset/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/formats/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/docs/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/faq/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/zh-hans/presets/upload-validation/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/formats/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/docs/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/use-cases/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/create-file-exact-size/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/faq/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/corrupt-test-files/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/test-files-in-ci/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/empty-and-minimal/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/filename-handling/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/size-boundaries/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/tabular-import/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/text-encoding/ + + + https://testingfilesgenerator.donislawdev.com/zh-hant/presets/upload-validation/ diff --git a/web/public/test-files-in-ci/index.html b/web/public/test-files-in-ci/index.html new file mode 100644 index 00000000..50b0b41f --- /dev/null +++ b/web/public/test-files-in-ci/index.html @@ -0,0 +1,375 @@ + + + + + + +Test Files in CI - GitHub Actions, GitLab CI and PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Use cases

+

How to generate test files in a CI pipeline

+

+ A binary fixture in a repository stays in its history for good, cannot be reviewed in a diff, and + stops being possible once the file is large. Generate the files inside the pipeline from a recipe + instead. The recipe is text, the bytes come out the same every time, and a last step proves that + nothing moved. +

+ +
+

The short answer

+

+ Install tfg, run tfg generate fixtures.yaml --out ./fixtures before the + tests, and tfg verify ./fixtures/manifest.json after them. Both steps fail the build + by themselves, with an exit code that says why. +

+
+ +
+

Why not commit them

+

Why a fixture should not live in the repository

+
    +
  • + It stays in the history. Deleting a binary later does not make a clone smaller, + because every version of it is still there. +
  • +
  • + A diff cannot show what changed. A reviewer sees that a PDF is different and + nothing else. A recipe changes by a line. +
  • +
  • + Large files do not fit. GitHub refuses a push that holds a file over 100 MB, so + a test of a 500 MB upload limit has nothing to commit. +
  • +
+

+ The recipe is the thing to commit. The same recipe and seed write the same bytes on every machine, + so the file generated in the pipeline is the file you had on your laptop. +

+
+ +
+

The recipe

+

A recipe that lives beside the tests

+

+ This one writes twenty five invoices that should be accepted and two images over a limit that + should be turned away, and the manifest records both expectations: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml checks it without writing anything, and names every + problem at once. +

+
+ +
+

GitHub Actions

+

A workflow that installs the tool and builds the fixtures

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ The checksum line compares the archive with verify-SHA256SUMS.txt from the same + release. The version is pinned, so a new release never changes a build you did not touch. +

+
+ +
+

GitLab CI

+

The same thing as a GitLab job

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

When it goes red

+

What makes a step fail, and why

+

+ Every ending has its own exit code, so the step fails on its own and the log says which one. The + ones a pipeline meets: +

+
    +
  • 3 - the recipe is not valid. Nothing was written, and every problem is named
  • +
  • 4 - the format cannot do what was asked, for example a size below its smallest
  • +
  • 6 - there is not enough disk space
  • +
  • 7 - tfg verify found a file that does not match its manifest
  • +
  • 8 - the run finished, but not everything was produced
  • +
+

+ A failed run prints nothing on standard output, so a log parser never reads an error as data. The + whole table is on the documentation page. +

+
+ +
+

PowerShell

+

A PowerShell script needs one more line

+

+ PowerShell does not carry the exit code of a program out of a .ps1 file. Run one with + -File and the script answers 0 even when the tool inside refused the + work, so a build that should be red goes green. The last line is the whole fix: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ That is how PowerShell behaves, not something about this tool. cmd, + bash and zsh need nothing extra. +

+
+ +
+

Several jobs

+

Sharing the fixtures between jobs

+

+ There is usually no need to upload them. Because the same recipe writes the same bytes, each job + can run its own tfg generate, which is quicker than an upload and a download. When a + job has to receive files from another, run tfg verify on the manifest after the + transfer, and it tells you whether what arrived is what was written. +

+
+ +
+

Next

+

Where to go from here

+ +
+ +
+ + + + diff --git a/web/public/th/corrupt-test-files/index.html b/web/public/th/corrupt-test-files/index.html new file mode 100644 index 00000000..1dab896f --- /dev/null +++ b/web/public/th/corrupt-test-files/index.html @@ -0,0 +1,375 @@ + + + + + + +ไฟล์ทดสอบที่เสียหาย - ไฟล์เสียขนาดตรงเป๊ะ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

กรณีการใช้งาน

+

วิธีทำไฟล์เสียหายสำหรับการทดสอบ

+

+ ตัวตรวจสอบที่เคยเห็นแต่ไฟล์ปกติยังไม่ถือว่าผ่านการทดสอบจริง นี่คือวิธีได้ไฟล์ที่ตั้งใจทำให้เสีย + ออกมาขนาดตรงตามที่ขอเป๊ะ + และมาพร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรทำอะไรกับไฟล์นั้น +

+ +
+

คำตอบสั้นๆ

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out เขียน PNG ขนาด + 2097152 ไบต์พอดี โดยไบต์แรกๆ เป็นศูนย์ และแมนิเฟสต์ที่อยู่ข้างๆ + บันทึกว่าระบบของคุณควรปฏิเสธไฟล์นี้ +

+
+ +
+

วิธีที่ทำกันทั่วไป

+

ทำไมไฟล์ที่ทำให้เสียด้วยมือจึงเป็นการทดสอบที่แย่

+

+ วิธีทั่วไปคือใช้โปรแกรมแก้ไขเลขฐานสิบหก สคริปต์ที่สลับไบต์สุ่มไม่กี่ตัว หรือตัดไฟล์ให้สั้นลงด้วย + head หรือ truncate ใช้ได้ครั้งเดียว แล้วจะเสียเวลาในภายหลัง: +

+
    +
  • + ได้ผลต่างกันทุกครั้ง ไบต์สุ่มตกที่ใหม่ทุกครั้งที่รัน + ความล้มเหลวของวันอังคารจึงอาจไม่กลับมาในวันพุธ +
  • +
  • + มันเปลี่ยนขนาด ไฟล์ที่ถูกตัดจะเล็กกว่าขีดจำกัดที่มันควรอยู่ต่ำกว่า + การตรวจขนาดจึงตอบก่อนการตรวจเนื้อหา และการทดสอบผ่านด้วยเหตุผลที่ผิด +
  • +
  • + มักไม่มีใครสังเกต ข้อความธรรมดายังอ่านได้แม้เปลี่ยนไบต์กลางไฟล์ + และตัวอ่านภาพที่ใจกว้างก็แค่วาดมันออกมา ไฟล์ที่ควรจะเสียจึงถูกรับไป +
  • +
  • + มันไม่บอกว่าควรเกิดอะไรขึ้น ไฟล์เป็นแค่ไบต์ + และคนที่มาอ่านการทดสอบทีหลังต้องเดาเองว่าตั้งใจให้รับหรือปฏิเสธ +
  • +
+
+ +
+

สิ่งที่คุณได้

+

ไฟล์ที่เสียหายยังมีขนาดตามที่คุณขอ

+

+ ไฟล์ถูกสร้างตามปกติแล้วค่อยทำให้เสียระหว่างทางไปยังดิสก์ ขนาดยังเป็นไปตามที่ขอ + และคำสั่งเดิมเขียนไบต์เดิมซ้ำอีกครั้ง +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ การตั้งค่าเขียนหลังเครื่องหมายทวิภาค ตัวเลือกนี้ใส่ซ้ำได้ + และความเสียหายจะถูกนำมาใช้ตามลำดับที่คุณเขียน ใช้ได้กับทั้ง 26 รูปแบบ +

+
+ +
+

มันทำอะไรได้

+

มีความเสียหายแบบไหนบ้าง

+

+ นี่คือรายการที่โปรแกรมพิมพ์ออกมา อ่านจากตัวโปรแกรมเองตอนสร้างหน้านี้ tfg damage + พิมพ์รายการเดียวกัน และ tfg damage <id> บอกว่าแบบหนึ่งรับอะไรบ้าง +

+
+ + + + + + + + + + + + + + + + + +
ความเสียหายสิ่งที่ทำกับไบต์ไฟล์เล็กที่สุดการตั้งค่า
zero-headเขียนทับไบต์แรกๆ ของไฟล์ด้วยศูนย์ โดยไม่แตะความยาว ตัวอ่านส่วนใหญ่มองตรงนั้นก่อน เกือบทุกอย่างจึงสังเกตเห็นความเสียหายนี้8bytes
+
+

+ zero-head เขียนศูนย์ทับส่วนต้นของไฟล์ ตัวอ่านส่วนใหญ่มองตรงนั้นก่อน + คือลายเซ็นและส่วนหัวที่บอกว่าไฟล์คืออะไร ตัวอ่านเกือบทุกตัวจึงสังเกตเห็น + ข้อความธรรมดาและล็อกไม่มีลายเซ็นและก็ถูกปฏิเสธเช่นกัน เพราะไบต์ศูนย์ต่อกันไม่ใช่ข้อความ + ต่ำกว่าสี่ไบต์ บางรูปแบบออกมาพร้อมความเสียหายที่ไม่มีตัวอ่านใดบ่น + นั่นคือเหตุผลที่การตั้งค่าเริ่มที่สี่ +

+
+ +
+

แมนิเฟสต์บอกอะไร

+

แมนิเฟสต์ที่บอกว่าควรเกิดอะไรขึ้น

+

+ ไฟล์ที่เสียหายทุกไฟล์ได้รายการที่บอกว่าระบบของคุณควรปฏิเสธ โดยบันทึกความเสียหายไว้ข้างๆ: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ คำขอสองแบบถูกปฏิเสธก่อนที่จะมีอะไรถูกเขียน เพราะแต่ละแบบจะทิ้งไฟล์ไว้บนดิสก์ที่แมนิเฟสต์อธิบายผิด: +

+
    +
  • ไฟล์ที่เล็กกว่าที่ความเสียหายต้องการ ซึ่งจะออกมาโดยไม่เปลี่ยนแปลง
  • +
  • + expected: accept คู่กับความเสียหาย เพราะไม่มีอะไรทำให้เป็นจริงได้ เขียน + sanitize ถ้าระบบของคุณควรซ่อมไฟล์ หรือ unspecified + ถ้านั่นคือคำถามที่คุณกำลังถาม +
  • +
+
+ +
+

ในสูตร

+

ไฟล์ปกติและไฟล์เสียในการรันเดียว

+

+ ใส่ทั้งสองอย่างในสูตรเดียว แล้วแมนิเฟสต์จะมีสิ่งที่คาดหวังของแต่ละไฟล์ + การทดสอบจึงไม่ต้องมีรายการบอกว่าไฟล์ไหนเป็นไฟล์ไหน: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

ในการทดสอบ

+

เปลี่ยนให้เป็นการทดสอบ

+

+ การทดสอบอ่านแมนิเฟสต์แล้วตรวจว่าสิ่งที่เกิดขึ้นตรงกับที่ประกาศไว้ ไม่ต้องมีรายชื่อไฟล์: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ การปฏิเสธที่ดีคือการปฏิเสธที่สะอาด ข้อความที่บอกว่าผิดตรงไหนคือคำตอบที่คุณต้องการ + ส่วนข้อผิดพลาดของเซิร์ฟเวอร์ การค้าง + หรือไฟล์ที่บันทึกไว้ครึ่งเดียวคือข้อบกพร่องที่การทดสอบนี้มีไว้หา +

+
+ +
+

ถัดไป

+

จากตรงนี้ไปไหนต่อ

+ +
+ +
+ + + + diff --git a/web/public/th/create-file-exact-size/index.html b/web/public/th/create-file-exact-size/index.html new file mode 100644 index 00000000..fc995997 --- /dev/null +++ b/web/public/th/create-file-exact-size/index.html @@ -0,0 +1,328 @@ + + + + + + +วิธีสร้างไฟล์ขนาดที่กำหนด - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

วิธีสร้างไฟล์ขนาดแม่นยำ

+

+ ทุกระบบมีคำสั่งสำหรับเรื่องนี้ และทั้งสามอยู่ด้านล่าง คำสั่งเหล่านี้ให้ไฟล์ที่มีจำนวนไบต์ถูกต้องพอดี + - และสำหรับการทดสอบจำนวนมากนั่นคือทั้งหมดที่ต้องการ + ทุกคำสั่งในหน้านี้ถูกรันก่อนเผยแพร่ บนระบบที่มันเป็นของ +

+ +
+

คำตอบสั้นๆ

+

+ Windows: fsutil file createnew name 10485760 Linux: dd if=/dev/zero of=name bs=1M + count=10 macOS: mkfile 10m name ขนาดเป็นไบต์ และ 10 MB + ตามวิธีนับของตัวจัดการไฟล์คือ 10485760 +

+
+ +
+

Windows

+

fsutil และเวอร์ชัน PowerShell ที่ไม่ต้องใช้อะไรเพิ่ม

+

+ fsutil มาพร้อม Windows รับขนาดเป็นไบต์ จึงคำนวณตัวเลขก่อน - 10 MB คือ + 10485760, 100 MB คือ 104857600, 1 GB คือ 1073741824 +

+
fsutil file createnew test10mb.bin 10485760
+

+ วัดบน Windows 11: ทำงานจากพรอมต์ธรรมดาโดยไม่ต้องใช้พรอมต์ที่ยกระดับสิทธิ์ และไฟล์ออกมาที่ 10485760 + ไบต์พอดี +

+

PowerShell ทำสิ่งเดียวกันได้โดยไม่ต้องเรียกโปรแกรมอื่น และเข้าใจหน่วย:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB ใน PowerShell หมายถึง 10485760 ไบต์ ซึ่งเป็นการนับฐาน 1024 เดียวกับที่ Explorer + ใช้ ดังนั้นสองคำสั่งข้างต้นให้ขนาดเดียวกัน +

+
+ +
+

Linux

+

dd, truncate และ fallocate และความต่างที่ทำให้คนพลาด

+

dd คือคำสั่งที่ทุกคนรู้จัก มันเขียนไบต์จริงๆ:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate เสร็จทันที และนั่นคือกับดัก วัดบน Alpine Linux ไฟล์รายงาน 10485760 + ไบต์และกินที่ ศูนย์บล็อก - เป็นไฟล์แบบกระจาย + สิ่งที่อ่านไฟล์ได้ศูนย์สิบเมกะไบต์ แต่ดิสก์ไม่เคยสละพื้นที่: +

+
truncate -s 10M test10mb.bin
+

+ ใช้ทดสอบขีดจำกัดการอัปโหลดได้ แต่ทำให้เข้าใจผิดเมื่อทดสอบโควตาดิสก์ fallocate + คือสิ่งที่ควรใช้เมื่อพื้นที่ต้องเป็นของจริง: +

+
fallocate -l 10M test10mb.bin
+

และเมื่อเนื้อหาต้องบีบอัดไม่ได้ เพื่อไม่ให้ตัวเก็บถาวรบีบกลับลงไปอีก:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile ซึ่งไม่ใช่ไฟล์แบบกระจาย และอีกสองคำสั่งที่คุณรู้จักอยู่แล้ว

+

+ macOS มี mkfile มาให้ วัดบน macOS 26.6.2: 10485760 ไบต์ และ 20480 บล็อก + ดังนั้นพื้นที่ถูกจัดสรรจริง ไม่ใช่แค่สัญญา: +

+
mkfile 10m test10mb.bin
+

dd และ truncate ก็มีเช่นกันและทำงานเหมือนบน Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

ตรงที่วิธีนี้เลิกได้ผล

+

ไฟล์ขนาดถูกต้องไม่ใช่ไฟล์ชนิดที่ถูกต้อง

+

+ ทุกวิธีข้างต้นให้บล็อกของศูนย์ นั่นเพียงพอเมื่อสิ่งที่ทดสอบดูแค่ขนาด เช่น ขีดจำกัดอัปโหลด โควตา + หรือการถ่ายโอน และเลิกเพียงพอทันทีที่มีอะไรเปิดไฟล์ +

+

+ วัดแล้ว และควรลองด้วยตัวเอง: สร้างไฟล์ 2 MB ด้วย fsutil ตั้งชื่อว่า + photo.png แล้วส่งให้ไลบรารีรูปภาพ Pillow ตอบว่า cannot identify image + file มันไม่ใช่ PNG และไม่เคยเป็น - มีแต่ชื่อที่บอกเช่นนั้น +

+

+ เรื่องนี้สำคัญกว่าที่ฟังดู เพราะการทดสอบล้มเหลวไปทางไหนต่อจากนั้น + เอนด์พอยต์อัปโหลดของคุณปฏิเสธไฟล์ การทดสอบเป็นสีเขียว และคุณสรุปว่าขีดจำกัดขนาดใช้ได้ + แต่มันไม่ได้ปฏิเสธเพราะขนาด มันปฏิเสธเพราะไบต์ไม่ใช่รูปภาพ + และกฎที่คุณตั้งใจทดสอบไม่เคยถูกแตะต้องเลย +

+
    +
  • ตัวแยกวิเคราะห์ปฏิเสธก่อนจะดูกฎขนาดใดๆ
  • +
  • ขั้นตอนภาพขนาดย่อล้มเหลว และข้อผิดพลาดที่คุณอ่านเป็นเรื่องของภาพขนาดย่อ
  • +
  • โปรแกรมป้องกันไวรัสหรือการตรวจเนื้อหาปฏิเสธด้วยเหตุผลที่สาม
  • +
  • โปรแกรมดูไม่แสดงอะไร และไม่มีใครบอกได้ว่านั่นคือบั๊กหรือไม่
  • +
+
+ +
+

อีกทางหนึ่ง

+

ไฟล์จริงของรูปแบบนั้น ขนาดตรงตามที่คุณขอพอดี

+

+ นี่คือสิ่งที่ Testing Files Generator ทำ ไฟล์เป็นของแท้ของรูปแบบนั้น - เปิดได้ในซอฟต์แวร์ของมัน - + และมีจำนวนไบต์ตรงตามที่คุณขอ ถึงระดับไบต์: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ ขอขนาดที่รูปแบบไปไม่ถึง แล้วคุณจะได้ข้อผิดพลาดที่ระบุขีดล่างและเหตุผล ไม่ใช่ไฟล์ขนาดผิด + หน้ารูปแบบไฟล์แสดงทุกรูปแบบพร้อมไฟล์เล็กที่สุดที่ทำได้ +

+

และขีดจำกัดหนึ่งค่าคือกรณีทดสอบสามกรณี ไม่ใช่หนึ่ง เครื่องมือจึงสร้างทั้งสาม:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ ได้ไฟล์ 10485759, 10485760 และ 10485761 ไบต์ + พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรยอมรับไฟล์ไหนและปฏิเสธไฟล์ไหน + หน้ากรณีการใช้งานอธิบายเรื่องนี้และงานอื่นอีกสี่อย่างที่เครื่องมือนี้สร้างมาเพื่อ +

+ +

ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน

+
+ +
+

แล้วควรใช้อะไร

+
    +
  • +

    ใช้คำสั่งของระบบ

    +

    + เมื่อไม่มีอะไรเปิดไฟล์ ทดสอบขีดจำกัดขนาดบนเอนด์พอยต์ที่ตรวจขนาดก่อน การถ่ายโอน โควตา หรือดิสก์เต็ม + เป็นบรรทัดเดียวและติดตั้งไว้แล้ว +

    +
  • +
  • +

    ใช้ตัวสร้างจริง

    +

    + เมื่อมีอะไรแยกวิเคราะห์ เรนเดอร์ นำเข้า หรือแตกไฟล์ - + และเมื่อคุณต้องการฟิกซ์เจอร์ชุดเดิมอีกครั้งพรุ่งนี้บนเครื่องอื่น ไบต์ต่อไบต์ +

    +
  • +
+

+ ทั้งสองอยู่ในหน้านี้เพราะทั้งสองถูกต้องในบางครั้ง + ข้อผิดพลาดที่ควรเลี่ยงคือการใช้อันแรกในที่ที่ต้องใช้อันที่สอง แล้วอ่านการทดสอบสีเขียวเป็นหลักฐาน +

+
+ +
+ + + + diff --git a/web/public/th/docs/index.html b/web/public/th/docs/index.html new file mode 100644 index 00000000..3dfbeeda --- /dev/null +++ b/web/public/th/docs/index.html @@ -0,0 +1,550 @@ + + + + + + +เอกสาร - คำสั่ง สูตร แมนิเฟสต์ รหัสออก + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

เอกสาร

+

+ ทุกอย่างที่เครื่องมือทำได้ จัดเรียงตามคำถามที่ผู้คนมาถามจริงๆ README + ในรีโพซิทอรีเป็นข้อมูลอ้างอิงฉบับสมบูรณ์และตรงกับบิลด์ที่คุณดาวน์โหลดเสมอ +

+ +
+

มีคำสั่งอะไรบ้าง

+

แต่ละคำสั่งทำสิ่งเดียว:

+
tfg generate    สร้างไฟล์จากสูตรหรือจากแฟลก
+tfg validate    ตรวจสอบสูตรโดยไม่เขียนอะไร
+tfg verify      ตรวจสอบไดเรกทอรีเทียบกับแมนิเฟสต์
+tfg cleanup     ลบไฟล์ที่แมนิเฟสต์ระบุไว้
+tfg recipe fmt  พิมพ์สูตรในรูปแบบมาตรฐาน
+tfg preset      สร้างชุดไฟล์จากคำถามทดสอบที่มีชื่อ
+tfg formats     แสดงรายการรูปแบบที่บิลด์นี้รองรับ
+tfg damage      แสดงรายการวิธีที่บิลด์นี้ทำให้ไฟล์เสียหายโดยตั้งใจ
+tfg tool        เครื่องมือเล็กๆ สำหรับไฟล์ที่คุณมีอยู่แล้ว
+tfg version     พิมพ์เวอร์ชันของเครื่องมือ
+tfg license     พิมพ์ใบอนุญาตและความหมายสำหรับไฟล์ที่สร้างขึ้น
+
+ +
+

สร้างไฟล์เดียวที่ขนาดแม่นยำได้อย่างไร

+

+ ระบุรูปแบบ ขนาด และปลายทาง ขนาดนับเป็นทีละ 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>สามไฟล์รอบขีดจำกัด: น้อยกว่าหนึ่งไบต์ เท่ากับขีดจำกัด และมากกว่าหนึ่งไบต์
--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เขียนแมนิเฟสต์ไปยังเอาต์พุตมาตรฐาน
+
+
+ +
+

ทำไฟล์ที่เสียโดยตั้งใจได้อย่างไร

+

+ ไฟล์อื่นทุกไฟล์ที่เครื่องมือนี้เขียนถูกต้องโดยโครงสร้าง + ซึ่งตอบสองในสามคำถามที่ตัวตรวจสอบการอัปโหลดถาม --damage ตอบข้อที่สาม - + ไฟล์เปิดได้หรือไม่ ไฟล์ถูกสร้างตามปกติแล้วจึงถูกทำให้เสีย จึงยังคงมีขนาดที่คุณขอ +

+
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 ในแมนิเฟสต์ พร้อมบันทึกความเสียหายไว้ข้างๆ + สองอย่างถูกปฏิเสธก่อนจะเขียนอะไร เพราะแต่ละอย่างจะวางไฟล์ที่แมนิเฟสต์อธิบายผิดไว้บนดิสก์: +

+
    +
  • ไฟล์ที่เล็กกว่าที่ความเสียหายต้องการ เพราะจะออกมาโดยไม่เปลี่ยนแปลง
  • +
  • + expected: accept ข้างความเสียหาย เพราะไม่มีสิ่งใดทำให้เป็นจริงได้ เขียน + sanitize ถ้าระบบที่ทดสอบควรซ่อมไฟล์ หรือ unspecified + ถ้านั่นคือคำถามที่คุณกำลังถาม +
  • +
+

+ ข้อที่สามรู้ล่วงหน้าไม่ได้ ถ้าความเสียหายทำงานแล้วไม่ขยับไบต์ใดเลย ไฟล์นั้นจะถูกทิ้งแทนที่จะถูกเขียน + - การรันดำเนินต่อ บอกว่าเป็นไฟล์ไหน และจบด้วยรหัสออกแบบบางส่วน +

+

+ ทีละขั้น พร้อมการทดสอบที่อ่านแมนิเฟสต์: + วิธีทำไฟล์เสียหายสำหรับการทดสอบ +

+
+ +
+

สูตรหน้าตาเป็นอย่างไร

+

+ สูตรคือไฟล์ 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
+

+ แต่ละ target ต้องมี size, size-range, boundary หรือ + contains อย่างใดอย่างหนึ่งพอดี มีสองอย่างคือข้อผิดพลาด ไม่มีเลยก็เป็นข้อผิดพลาด + สูตรที่ไม่ถูกต้องไม่เขียนไฟล์ใดเลย + และรายงานปัญหาทั้งหมดพร้อมกันแทนที่จะรายงานแค่ข้อแรก โดยแต่ละข้อระบุการตั้งค่าที่เกี่ยวข้อง +

+
+ +
+

ประกาศอย่างไรว่าระบบของฉันควรทำอะไรกับไฟล์

+

ใช้รูปแบบสั้นเมื่อผลลัพธ์เพียงพอ ใช้รูปแบบยาวเมื่อเหตุผลสำคัญ:

+
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 +

+

+ เหตุผลระบุกฎที่เกี่ยวข้อง ไม่ใช่คำตัดสิน + ด้วยเหตุนี้เหตุผลเดียวกันจึงอยู่ใต้ผลลัพธ์ใดก็ได้ - ไฟล์ที่น้อยกว่าขีดจำกัดหนึ่งไบต์คือ + accept และกฎที่เกี่ยวข้องก็ยังเป็น size_limit +

+
+ +
+

แมนิเฟสต์มีอะไรบ้าง

+

+ ถูกเขียนไว้ข้างไฟล์เมื่อจบทุกการรัน รวมถึงการรันที่ถูกขัดจังหวะ หนึ่งรายการต่อไฟล์: +

+
{
+  "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 เมื่อมาจากพรีเซ็ต แมนิเฟสต์จึงสืบย้อนไปถึงสิ่งที่สร้างมันได้เสมอ +

+

+ ทุกรายการยังมี target_id ซึ่งเป็นรหัสของ target ในสูตรที่สร้างไฟล์ และ + summary.by_target นับจำนวนไฟล์ที่แต่ละ target สร้างได้ สูตรที่มีหลาย target + จึงตรวจทีละ target ได้โดยไม่ต้องอ่านชื่อไฟล์ +

+
+ +
+

พรีเซ็ตคืออะไร

+

+ ชุดไฟล์สำเร็จรูปที่ตอบคำถามการทดสอบที่พบบ่อย คุณจึงไม่ต้องออกแบบชุดเอง + พรีเซ็ตเป็นสูตรธรรมดาอยู่ข้างใน และ eject + พิมพ์สูตรออกมาเพื่อให้คุณแก้ไขต่อจากตรงนั้น + แต่ละพรีเซ็ตมีหน้าของตัวเองที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร + และรับการตั้งค่าใดบ้าง +

+
    +
  • +

    ไฟล์ว่างและขั้นต่ำ

    +

    ไฟล์ที่ถูกต้องและเล็กเท่าที่รูปแบบอนุญาตจะผ่านไหม

    +

    empty-and-minimal

    +
  • +
  • +

    การจัดการชื่อไฟล์

    +

    ระบบของฉันจะเก็บ แสดง และส่งคืนชื่อไฟล์ที่ไม่ได้คาดไว้ได้ไหม

    +

    filename-handling

    +
  • +
  • +

    ขอบเขตขนาด

    +

    ขีดจำกัดขนาดถูกบังคับใช้ตรงจุดที่ประกาศไว้พอดีหรือไม่

    +

    size-boundaries

    +
  • +
  • +

    การนำเข้าตาราง

    +

    การนำเข้าตารางของฉันรับมือกับสิ่งที่เครื่องมือจริงส่งออกได้ไหม

    +

    tabular-import

    +
  • +
  • +

    การเข้ารหัสข้อความ

    +

    ตัวอ่านของฉันรู้ไหมว่าไฟล์ใช้การเข้ารหัสอะไร หรือกำลังเดาอยู่

    +

    text-encoding

    +
  • +
  • +

    การตรวจสอบการอัปโหลด

    +

    ฟอร์มอัปโหลดของฉันรับสิ่งที่ควรรับและปฏิเสธที่เหลือหรือไม่

    +

    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 บอกว่าชุดจะมีต้นทุนเท่าไรก่อนที่คุณจะสร้าง และบอกตรงๆ + เมื่อตัวเลขใดเป็นค่าชั่วคราวของเรา ไม่ใช่ขีดจำกัดของคุณ +

+
+ +
+

รหัสออกมีความหมายอย่างไร

+

+ ทุกการจบมีรหัสของตัวเอง เอาต์พุตที่เครื่องอ่านได้ไปที่เอาต์พุตมาตรฐาน + และการรันที่ล้มเหลวไม่พิมพ์อะไรที่นั่น ตารางนี้เป็นสัญญาที่ตรึงไว้ - + การเปลี่ยนความหมายของรหัสต้องเลื่อนเวอร์ชันหลัก +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสความหมาย
0ทุกอย่างทำงานได้
1เกิดข้อผิดพลาดที่ไม่คาดคิดภายในเครื่องมือ
2คำสั่งหรือแฟลกไม่ถูกต้อง
3สูตรไม่ถูกต้อง
4รูปแบบนี้ทำสิ่งที่ขอไม่ได้
5การอ่านหรือเขียนล้มเหลว
6พื้นที่ดิสก์ไม่พอ
7verify พบความไม่ตรงกัน
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 +

+
+ +
+

มีหน้าต่างเดสก์ท็อปไหม

+

+ มี เป็นเอนจินเดียวกันที่มีหน้าต่างครอบอยู่ สำหรับการทดสอบที่ไม่ได้เขียนสคริปต์ ไม่ใช่ฉบับตัดทอน: + มีการทดสอบเปรียบเทียบสองอินเทอร์เฟซทีละความสามารถ + และสิ่งที่ทำได้เพียงฝั่งเดียวต้องถูกประกาศและให้เหตุผล แทนที่จะแยกจากกันไปอย่างเงียบๆ +

+

+ หน้าจอมีชุดเดียว พรีเซ็ต หลายชุดพร้อมกัน และเกี่ยวกับ แสดงต้นทุนของการรันก่อนเขียนอะไร + รายงานความคืบหน้าขณะรัน และยกเลิกกลางคันได้โดยไม่ทิ้งไฟล์ที่เขียนค้างครึ่งหนึ่ง + ยังเปิดไฟล์สูตรไม่ได้ - ตอนนี้สูตรเป็นเรื่องของบรรทัดคำสั่ง และหน้าต่างสร้างชุดในฟอร์ม +

+
+ +
+ + + + diff --git a/web/public/th/faq/index.html b/web/public/th/faq/index.html new file mode 100644 index 00000000..bf9ba920 --- /dev/null +++ b/web/public/th/faq/index.html @@ -0,0 +1,348 @@ + + + + + + +คำถามที่พบบ่อย - เรื่องการสร้างไฟล์ทดสอบ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

คำถามที่พบบ่อย

+

+ ใบอนุญาต ความเป็นส่วนตัว การทำซ้ำได้ และสิ่งที่ผู้คนตรวจสอบก่อนนำตัวสร้างไปไว้ในไปป์ไลน์บิลด์ + ถ้าคำถามของคุณไม่อยู่ที่นี่ ตัวติดตามปัญหาเปิดอยู่ +

+ +
+
+

ต่างจาก dd, fsutil หรือ truncate อย่างไร

+
+

คำสั่งเหล่านั้นให้ไฟล์ที่ขนาดถูกต้องแต่เต็มไปด้วยความว่างเปล่า ไฟล์ photo.png ขนาด 2 MB ที่ทำแบบนั้นไม่ใช่ PNG ดังนั้นสิ่งใดที่แยกวิเคราะห์ไฟล์จริงๆ ก็จะปฏิเสธด้วยเหตุผลที่ผิด และการทดสอบของคุณก็ผ่านด้วยเหตุผลที่ผิดเช่นกัน เครื่องมือนี้สร้าง PNG จริงขนาด 2 MB พอดีที่เปิดได้ในโปรแกรมดูภาพ และมาพร้อมคำประกาศว่าระบบของคุณควรปฏิบัติต่อไฟล์นั้นอย่างไร

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

ฟรีไหม และใช้ที่ทำงานได้หรือไม่

+
+

ได้ทั้งสองอย่าง เผยแพร่ภายใต้ GPL-3.0 และไม่มีค่าใช้จ่าย ไม่มีบัญชี ไม่มีคีย์ใบอนุญาต และไม่มีแพ็กเกจเสียเงิน

+
+
+
+

ใช้ไฟล์ที่สร้างในผลิตภัณฑ์ซอร์สปิดได้ไหม

+
+

ได้ ใบอนุญาตครอบคลุมโค้ดของเครื่องมือ ไม่ใช่สิ่งที่เครื่องมือสร้างขึ้น ไฟล์ สูตร และแมนิเฟสต์ที่สร้างขึ้นเป็นผลลัพธ์ ไม่ใช่งานดัดแปลง คุณจึงคอมมิตและแจกจ่ายได้โดยไม่มีข้อผูกมัดใดๆ

+
+
+
+

ไฟล์ที่สร้างมีข้อมูลส่วนบุคคลจริงหรือไม่

+
+

ไม่มี ทุกอย่างข้างในถูกสังเคราะห์จากซีด ไม่มีการอ่านชุดข้อมูล ไม่มีการติดต่อบริการใด และไม่มีการฝังเนื้อหาของบุคคลที่สาม ให้ถือว่าอีเมลที่สร้างขึ้นเป็นที่ใช้ไม่ได้ ไม่ใช่ที่ยังไม่ได้ใช้ เพราะสตริงสุ่มใดๆ อาจบังเอิญตรงกับของจริงได้

+
+
+
+

ได้ไฟล์เหมือนกันทุกประการบนเครื่องอื่นไหม

+
+

ได้ ไบต์ต่อไบต์ เมื่อใช้สูตรและซีดเดียวกัน โครงการทดสอบเรื่องนี้ในทุกการเปลี่ยนแปลง และการทำลายต้องเลื่อนเวอร์ชันหลัก นี่คือสิ่งที่ทำให้คุณคอมมิตสูตรเล็กๆ แทนฟิกซ์เจอร์ไบนารีขนาดใหญ่ได้

+
+
+
+

ต้องใช้อินเทอร์เน็ตไหม

+
+

ไม่เลย ไม่มีเทเลเมทรี ไม่มีการตรวจสอบอัปเดต ไม่มีไคลเอนต์คลาวด์ และไบนารีบรรทัดคำสั่งไม่ได้คอมไพล์สแตกเครือข่ายไว้เลย ทำงานได้บนเครื่องที่ไม่มีเครือข่ายและในสภาพแวดล้อมองค์กรที่ปิด

+
+
+
+

จะเกิดอะไรขึ้นถ้าขอขนาดที่รูปแบบนั้นไปไม่ถึง

+
+

คุณจะได้ข้อผิดพลาดที่ระบุรูปแบบ ขนาดเล็กที่สุดที่เป็นไปได้ เหตุผลของขีดล่างนั้น และสิ่งที่ควรทำแทน และจะไม่มีไฟล์ถูกเขียน เครื่องมือไม่เคยปัดเศษขนาดอย่างเงียบๆ ขีดล่างทุกค่าแสดงไว้ในหน้ารูปแบบไฟล์

+
tfg formats png
+
+
+
+

สร้างไฟล์ที่เสียหายโดยตั้งใจได้ไหม

+
+

ได้ เพิ่ม --damage zero-head แล้วไฟล์จะออกมาขนาดตรงตามที่ขอ โดยไบต์แรกๆ ถูกเขียนทับด้วยศูนย์ ตัวอ่านจึงปฏิเสธ และแมนิเฟสต์บอกว่าระบบของคุณควรปฏิเสธ รายละเอียดอยู่ในหน้าเกี่ยวกับไฟล์ทดสอบที่เสียหาย

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

รูปแบบใดจะมาต่อไป

+
+

7z, mp3 และ mp4 ตอนนี้ 26 รูปแบบทำงานได้ครบตั้งแต่ต้นจนจบ

+
+
+
+

รันบนระบบใดได้บ้าง

+
+

บรรทัดคำสั่งทำงานบน Windows และ Linux ทั้ง Intel และ ARM และบน Mac ที่ใช้ Apple Silicon หน้าต่างเดสก์ท็อปมีให้สำหรับ Windows บน Intel, Linux บน Intel และ Mac ที่ใช้ Apple Silicon ไม่รองรับ Mac แบบ Intel และไม่มีการสร้างบิลด์สำหรับเครื่องเหล่านั้น

+
+
+
+

ต้องติดตั้งอะไรไหม

+
+

ไม่ ดาวน์โหลดไฟล์บีบอัดสำหรับระบบของคุณ แตกไฟล์ แล้วรันไบนารี ไม่มีตัวติดตั้ง ไม่มีรันไทม์ที่ต้องเพิ่ม และไม่มีไลบรารีที่ต้องแก้ ถ้าคุณมี Go คำสั่ง go install เพียงคำสั่งเดียวก็ใช้ได้เช่นกัน

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

ทำไมการรันกับไฟล์นับพันจึงช้ากว่าบน Windows

+
+

เพราะ Windows คิดค่าใช้จ่ายมากกว่าสำหรับทุกพาธที่มันดู และคำสั่งที่วนผ่านไฟล์นับพันก็ดูพาธนับพัน วัดบนเครื่องหนึ่งที่มีไฟล์ขนาด 1 kB จำนวน 3000 ไฟล์ verify ใช้เวลาประมาณ 0.9 วินาทีบน Windows และประมาณ 0.2 วินาทีบน Linux ในคอนเทนเนอร์ พาธเอาต์พุตที่สั้นลงทำให้ตัวเลขบน Windows น้อยลง เพราะทุกโฟลเดอร์เหนือไฟล์เป็นส่วนหนึ่งของสิ่งที่ถูกดู

+
+
+
+ + +
+

ยังตัดสินใจอยู่หรือ

+

+ หน้ากรณีการใช้งานแสดงงานที่เครื่องมือนี้สร้างมาเพื่อ + และหน้ารูปแบบไฟล์แสดงทุกรูปแบบพร้อมไฟล์เล็กที่สุดที่ทำได้ + README ในรีโพซิทอรีเป็นข้อมูลอ้างอิงฉบับสมบูรณ์ +

+ +

ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน

+
+ +
+ + + + diff --git a/web/public/th/formats/index.html b/web/public/th/formats/index.html new file mode 100644 index 00000000..df3fc774 --- /dev/null +++ b/web/public/th/formats/index.html @@ -0,0 +1,907 @@ + + + + + + +26 รูปแบบไฟล์ที่รองรับ - PDF, DOCX, PNG, ZIP และอื่นๆ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 รูปแบบไฟล์ แต่ละรูปแบบสร้างที่ขนาดแม่นยำ

+

+ ทุกรูปแบบเป็นไฟล์จริงของรูปแบบนั้น เปิดได้ในซอฟต์แวร์ของมัน + และมีจำนวนไบต์ตรงตามที่คุณขอพอดี ไม่มีรูปแบบใดเป็นศูนย์เติมเต็มที่แปะนามสกุลเข้าไป +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รูปแบบชื่อนามสกุลไฟล์เล็กที่สุดความสมบูรณ์ตรวจสอบด้วย
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullไม่เกี่ยวข้อง
mdMarkdown.md0fullไม่เกี่ยวข้อง
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullไม่เกี่ยวข้อง
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

ความหมายของคอลัมน์

+
    +
  • +

    ไฟล์เล็กที่สุด

    +

    + จำนวนไบต์น้อยที่สุดที่เครื่องมือนี้ยอมรับสำหรับรูปแบบนั้น รวมป้ายกำกับที่มันเขียนไว้ในไฟล์ + ขอน้อยกว่านี้แล้วคุณจะได้ข้อผิดพลาดที่ระบุขีดล่างและเหตุผล ไม่ใช่ไฟล์ขนาดผิด +

    +
  • +
  • +

    ความสมบูรณ์

    +

    + ไฟล์สมบูรณ์แค่ไหน full หมายความว่าตัวอ่านที่แยกวิเคราะห์รูปแบบจริงๆ ยอมรับมัน + ไม่ใช่แค่นามสกุลตรงกัน +

    +
  • +
  • +

    ตรวจสอบด้วย

    +

    + ตัวอ่านอิสระที่เปิดทุกไฟล์ที่สร้างก่อนปล่อยรูปแบบ - เป็นการพัฒนาแยกต่างหาก + ไม่ใช่โค้ดของเราเองที่ตรวจการบ้านตัวเอง +

    +
  • +
+

+ ทุกรูปแบบยังทำซ้ำได้ถึงระดับไบต์ด้วย: สูตรและซีดเดียวกันสร้างไฟล์เหมือนกันทุกประการบนเครื่องใดก็ตาม + และนี่คือสิ่งที่ทำให้การคอมมิตสูตรแทนตัวฟิกซ์เจอร์ปลอดภัย +

+
+ +
+

การตั้งค่าที่แต่ละรูปแบบรับ

+

+ ส่วนใหญ่ของรูปแบบมีการตั้งค่าของตัวเอง - ขนาดภาพ คุณภาพ JPEG จำนวนหน้า PDF + จำนวนแถวและคอลัมน์ในสเปรดชีต จำนวนรายการในไฟล์บีบอัด ตั้งค่าด้วย --set key=value + ในบรรทัดคำสั่ง หรือใต้ properties: ในสูตร +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รูปแบบการตั้งค่าค่าที่รับ
avifwidth1 - 16384 พิกเซล
height1 - 16384 พิกเซล
quality1 - 100
bmpwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerจริงหรือเท็จ
quote_styleall, minimal, none
columns2 - 32768 คอลัมน์
docxparagraphs1 - 50000 ย่อหน้า
gifwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 พิกเซล
height1 - 256 พิกเซล
embedbmp, png
jpgwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 พิกเซล
height1 - 16384 พิกเซล
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 รายการต่อวินาที
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomจริงหรือเท็จ
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleข้อความใดก็ได้
authorข้อความใดก็ได้
subjectข้อความใดก็ได้
keywordsข้อความใดก็ได้
creatorข้อความใดก็ได้
producerข้อความใดก็ได้
createdวันที่ เช่น 2024-02-29 หรือ 2024-02-29T13:45:00+02:00 หรือ none
modifiedวันที่ เช่น 2024-02-29 หรือ 2024-02-29T13:45:00+02:00 หรือ none
pngwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
pptxslides1 - 500 สไลด์
svgwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
targzentries0 - 10000
entry_formatรหัสของรูปแบบ ตามที่ tfg formats แสดง
entry_sizeขนาด เช่น 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesจริงหรือเท็จ
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 พิกเซล
height1 - 20000 พิกเซล
txtencodingutf-16be, utf-16le, utf-8
bomจริงหรือเท็จ
wavsample_rate8000 - 192000 เฮิรตซ์
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 พิกเซล
height1 - 16383 พิกเซล
xlsxrows1 - 200000 แถว
columns1 - 32768 คอลัมน์
xmlencodingutf-16be, utf-16le, utf-8
bomจริงหรือเท็จ
zipentries0 - 10000
entry_formatรหัสของรูปแบบ ตามที่ tfg formats แสดง
entry_sizeขนาด เช่น 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesจริงหรือเท็จ
passwordรหัสผ่านในรูปข้อความธรรมดา
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ ค่านอกขอบเขตที่การตั้งค่ารับถูกปฏิเสธด้วยข้อความที่ระบุการตั้งค่า ช่วงที่อนุญาต และสิ่งที่ควรใช้แทน + การตั้งค่าที่ไม่รู้จักก็เป็นข้อผิดพลาดเช่นกัน ไม่ใช่ค่าเริ่มต้นเงียบๆ - + ตัวพิมพ์ผิดที่ถูกยอมรับเงียบๆ + ให้ไฟล์ที่ตั้งค่าผิดและหนึ่งชั่วโมงของการสงสัยว่าทำไมการทดสอบจึงผ่านทั้งที่ไม่ควร +

+

+ รัน tfg formats <id> เพื่อดูว่ารูปแบบหนึ่งรับอะไรบ้างในบิลด์ที่คุณมี +

+
+ +
+

ไฟล์บีบอัดมีไฟล์จริงอยู่ข้างใน

+

+ targz และ zip + ใส่รายการลงไปได้ แทนที่จะปล่อยเป็นเปลือกว่าง ไฟล์บีบอัดที่สร้างขึ้นมีเอกสารที่อ้างว่ามีจริงๆ + ดังนั้นสิ่งใดที่แตกไฟล์นั้นระหว่างการทดสอบจะพบไฟล์จริงอยู่ข้างใน +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/th/index.html b/web/public/th/index.html new file mode 100644 index 00000000..5f502a4a --- /dev/null +++ b/web/public/th/index.html @@ -0,0 +1,452 @@ + + + + + + +ตัวสร้างไฟล์ทดสอบสำหรับ QA - ขนาดแม่นยำ 26 รูปแบบจริง + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

สร้างไฟล์ทดสอบจริงที่ขนาดแม่นยำ

+

+ PDF, PNG, DOCX, ZIP - รวม 26 รูปแบบ + และทุกไฟล์เป็นไฟล์จริงที่เปิดได้ในซอฟต์แวร์ของมัน ด้วยขนาดตรงตามที่คุณขอพอดี + ทุกครั้งที่รันยังจดด้วยว่าแอปพลิเคชันของคุณควรทำอย่างไรกับแต่ละไฟล์ + มีทั้งบรรทัดคำสั่งและหน้าต่างเดสก์ท็อป ฟรีและโอเพนซอร์ส ทำงานทั้งหมดบนเครื่องของคุณ +

+ + +

ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน

+
+ +
+ หน้าต่างเดสก์ท็อปของ Testing Files Generator ที่ตั้งค่าพร้อมเขียนไฟล์ทดสอบเป็นชุด +
หน้าต่างเดสก์ท็อปที่ตั้งค่าพร้อมเขียนไฟล์เป็นชุด เอนจินเดียวกันทำงานอยู่เบื้องหลังบรรทัดคำสั่ง
+
+
+ + + +
+

ปัญหา

+

การทำไฟล์ทดสอบหนึ่งไฟล์เป็นเรื่องง่าย การทำหนึ่งพันไฟล์ที่ถูกต้องคือส่วนที่น่าเบื่อ

+

คุณกำลังทดสอบซอฟต์แวร์ที่รับไฟล์จากผู้คน ไม่ช้าก็เร็วคุณจะต้องการ:

+
    +
  • PDF ขนาด 10 MB พอดี เพื่อดูว่าขีดจำกัดการอัปโหลดเป็นของจริงหรือไม่
  • +
  • ไฟล์สามไฟล์ที่อยู่สองข้างของขีดจำกัดนั้น เพื่อจับข้อผิดพลาดคลาดเคลื่อนหนึ่ง
  • +
  • ไฟล์บันทึก 10,000 ไฟล์ เพื่อดูว่างานกลางคืนทำอะไรเมื่อโฟลเดอร์ใหญ่
  • +
  • ZIP ที่มีเอกสาร 200 ฉบับจริงๆ ไม่ใช่เปลือกว่างที่มีนามสกุลถูกต้อง
  • +
  • ไฟล์ขนาด 4 GB โดยไม่ต้องเก็บไฟล์ 4 GB ไว้ในรีโพซิทอรีของคุณ
  • +
  • ฟิกซ์เจอร์ที่ เหมือนกัน บนแล็ปท็อปและบนเซิร์ฟเวอร์บิลด์ ไบต์ต่อไบต์
  • +
+

+ นี่คือสิ่งที่เครื่องมือนี้เข้ามาแทนที่ สร้างขึ้นสำหรับวิศวกร QA งานทดสอบอัตโนมัติ + และทุกคนที่โค้ดมีฟอร์มอัปโหลด ขั้นตอนนำเข้า ตัวแยกวิเคราะห์ + หรือโควตาพื้นที่จัดเก็บอยู่เบื้องหลัง +

+
+ +
+

อะไรที่ทำให้ต่างออกไป

+

ตัวสร้างอื่นหยุดที่ไบต์ ตัวนี้ตอบสิ่งที่การทดสอบของคุณถามจริงๆ

+

+ โฟลเดอร์ที่เต็มไปด้วยไฟล์ยังปล่อยให้คุณตัดสินเองว่าแต่ละไฟล์ควรพิสูจน์อะไร + ที่นี่ทุกครั้งที่รันจะเขียน manifest.json ไว้ข้างไฟล์ + เป็นรายการธรรมดาของทุกอย่างที่สร้างขึ้น และแต่ละรายการมีความคาดหวังที่ประกาศไว้ +

+

สมมติว่าเอนด์พอยต์อัปโหลดของคุณอนุญาต 1 MB ขอไฟล์สามไฟล์ที่อยู่บนเส้นนั้น:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ไฟล์ไบต์ระบบของคุณควรเพราะ
1mb_under_1b.pdf1048575ยอมรับอยู่ภายในขีดจำกัด
1mb_at_limit.pdf1048576ยอมรับตัวขีดจำกัดเองได้รับอนุญาต
1mb_over_1b.pdf1048577ปฏิเสธsize_limit
+
+ +

ไฟล์สามไฟล์ คำตอบสามแบบที่ต่างกัน ในรูปแบบที่เครื่องอ่านได้ การทดสอบของคุณอ่านแมนิเฟสต์แทนที่คุณจะเขียนการยืนยันด้วยมือ:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

เมื่อคำตอบขึ้นอยู่กับนโยบายของคุณเอง แมนิเฟสต์จะบอกอย่างนั้น

+

+ มันบันทึก unspecified แทนที่จะแต่งความคาดหวังขึ้นมา + ตัวสร้างที่เดาทำให้เกิดความล้มเหลวเท็จ และชุดทดสอบที่ร้องหมาป่ามาจะถูกปิดไป +

+
+
+ +
+

พรีเซ็ต

+

เลือกคำถาม แล้วรับทั้งชุด

+

+ พรีเซ็ตคือชุดไฟล์ทดสอบที่ออกแบบรอบคำถามการทดสอบข้อเดียว คุณจึงไม่ต้องหาเองว่าไฟล์ไหนพิสูจน์อะไร + แต่ละชุดมีหน้าที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร และรับการตั้งค่าใดบ้าง +

+
    +
  • +

    ไฟล์ว่างและขั้นต่ำ

    +

    ไฟล์ที่ถูกต้องและเล็กเท่าที่รูปแบบอนุญาตจะผ่านไหม

    +

    empty-and-minimal

    +
  • +
  • +

    การจัดการชื่อไฟล์

    +

    ระบบของฉันจะเก็บ แสดง และส่งคืนชื่อไฟล์ที่ไม่ได้คาดไว้ได้ไหม

    +

    filename-handling

    +
  • +
  • +

    ขอบเขตขนาด

    +

    ขีดจำกัดขนาดถูกบังคับใช้ตรงจุดที่ประกาศไว้พอดีหรือไม่

    +

    size-boundaries

    +
  • +
  • +

    การนำเข้าตาราง

    +

    การนำเข้าตารางของฉันรับมือกับสิ่งที่เครื่องมือจริงส่งออกได้ไหม

    +

    tabular-import

    +
  • +
  • +

    การเข้ารหัสข้อความ

    +

    ตัวอ่านของฉันรู้ไหมว่าไฟล์ใช้การเข้ารหัสอะไร หรือกำลังเดาอยู่

    +

    text-encoding

    +
  • +
  • +

    การตรวจสอบการอัปโหลด

    +

    ฟอร์มอัปโหลดของฉันรับสิ่งที่ควรรับและปฏิเสธที่เหลือหรือไม่

    +

    upload-validation

    +
  • +
+

พรีเซ็ตทั้งหมด และความสัมพันธ์กับสูตร

+
+ +
+

เริ่มต้นอย่างรวดเร็ว

+

สามคำสั่งเพื่อดูว่ามันทำงานอย่างไร

+
    +
  1. +

    สร้างไฟล์หนึ่งไฟล์

    +

    PNG หนึ่งไฟล์ สองเมกะไบต์พอดี:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    สร้างไฟล์จำนวนมาก

    +

    + ไฟล์บันทึกหนึ่งหมื่นไฟล์ แต่ละไฟล์ขนาดระหว่าง 1 ถึง 8 กิโลไบต์ + โดยสุ่มขนาดจากซีดเพื่อให้พรุ่งนี้ได้ชุดเดิม + ให้แต่ละการรันมีไดเรกทอรีของตัวเอง - + แมนิเฟสต์เป็นบันทึกเดียวของสิ่งที่การรันเขียนไว้ เครื่องมือจึงไม่ยอมเขียนฉบับที่สองทับ: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    ตรวจสอบ แล้วลบ

    +

    verify บอกว่าไม่มีอะไรขยับ cleanup ลบเฉพาะสิ่งที่ถูกเขียนไว้และไม่ลบอย่างอื่น:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ ขนาดนับเป็นทีละ 1024 เหมือนตัวจัดการไฟล์ของคุณ ดังนั้น 2mb หมายถึง 2097152 ไบต์ + ใช้จำนวนไบต์ธรรมดาก็ได้ เอกสารครอบคลุมสูตร แมนิเฟสต์ และรหัสออก +

+
+ +
+

สิ่งที่คุณได้รับ

+

สร้างมาสำหรับชุดทดสอบที่รันโดยไม่มีคนเฝ้า

+
    +
  • +

    ขนาดแม่นยำ ถึงระดับไบต์

    +

    ขอ 10485761 ไบต์ แล้วได้ตามนั้นพอดี ขนาดที่รูปแบบไปไม่ถึงคือข้อผิดพลาดที่มีเหตุผล ไม่ใช่ไฟล์ขนาดผิด

    +
  • +
  • +

    26 รูปแบบจริง

    +

    ไม่ใช่ศูนย์ที่เติมเต็มพร้อมนามสกุล PNG ที่สร้างเปิดได้ในโปรแกรมดูภาพ DOCX เปิดได้ใน Word และ ZIP แตกไฟล์ได้ ทุกรูปแบบถูกตรวจด้วยตัวอ่านอิสระก่อนปล่อย

    +
  • +
  • +

    แมนิเฟสต์ที่เป็นเสมือนต้นแบบการทดสอบ

    +

    พาธ ขนาด SHA-256 รูปแบบ ซีด เวอร์ชันเครื่องมือ - และสิ่งที่ระบบของคุณควรทำกับไฟล์

    +
  • +
  • +

    ทำซ้ำได้

    +

    สูตรและซีดเดียวกัน ได้ไบต์เดียวกัน บนเครื่องใดก็ตาม คอมมิตสูตร YAML เล็กๆ แทนฟิกซ์เจอร์ไบนารีขนาดใหญ่

    +
  • +
  • +

    สองอินเทอร์เฟซ หนึ่งเอนจิน

    +

    บรรทัดคำสั่งที่สร้างมาสำหรับ CI และหน้าต่างเดสก์ท็อปสำหรับการทดสอบเชิงสำรวจ ไม่มีอันใดเป็นฉบับตัดทอนของอีกอัน และมีการทดสอบเปรียบเทียบทั้งสองทีละความสามารถ

    +
  • +
  • +

    ออฟไลน์ทั้งหมด

    +

    ไม่มีบัญชี ไม่มีคลาวด์ ไม่มีเทเลเมทรี ไม่มีการตรวจสอบอัปเดต ไบนารีบรรทัดคำสั่งไม่ได้คอมไพล์สแตกเครือข่ายไว้เลย

    +
  • +
+
+ +
+

ดาวน์โหลด

+

เลือกบิลด์สำหรับระบบของคุณ

+

+ แตกไฟล์บีบอัดแล้วรัน tfg คือบรรทัดคำสั่ง และ tfg-gui คือหน้าต่างเดสก์ท็อป + ไม่มีตัวติดตั้ง และไม่มีอะไรต้องเพิ่มลงในเครื่องของคุณ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ระบบบรรทัดคำสั่งหน้าต่างเดสก์ท็อป
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

อะไรลงนามแล้ว และอะไรยังไม่ได้ลงนาม

+

+ ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้ว จึงเริ่มทำงานโดยไม่มีคำเตือนเรื่องผู้พัฒนาที่ไม่รู้จัก + ส่วนของ Linux ไม่ได้ลงนาม เพราะ Linux เดสก์ท็อปไม่มีสิ่งเทียบเท่าที่ใช้ลงนามได้ + ทุกไฟล์บีบอัดอยู่ใน verify-SHA256SUMS.txt บนหน้าเผยแพร่ + เพื่อให้คุณตรวจสอบสิ่งที่ดาวน์โหลดได้ +

+
+ +

ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน

+
+ + +
+ + + + diff --git a/web/public/th/presets/empty-and-minimal/index.html b/web/public/th/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..7540e685 --- /dev/null +++ b/web/public/th/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +ไฟล์ทดสอบที่ถูกต้องเล็กที่สุดและไฟล์ว่างในทุกรูปแบบ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

ไฟล์ว่างและขั้นต่ำ

+

ไฟล์ที่ถูกต้องและเล็กเท่าที่รูปแบบอนุญาตจะผ่านไหม

+

+ พรีเซ็ต empty-and-minimal สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ไฟล์ที่ถูกต้องแต่ถูกปฏิเสธว่าเล็กเกินไป เพราะการตรวจนับไบต์แทนที่จะอ่านไฟล์
  • +
  • ไฟล์ว่างที่ทำให้ตัวอ่านล่มแทนที่จะถูกรายงาน
  • +
  • ภาพกว้างหนึ่งพิกเซลที่หารด้วยศูนย์ระหว่างทางไปสร้างภาพขนาดย่อ
  • +
  • ที่เก็บข้อมูลที่ถือว่าศูนย์ไบต์คืออัปโหลดล้มเหลวแล้วลองซ้ำไม่หยุด
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show empty-and-minimal รายงาน:

+
+ + + + + + + +
ไฟล์28
target ในสูตรของมัน28
ขนาดรวม32 667 B
รูปแบบavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้26
unspecifiedขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ2
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--formatsรหัสรูปแบบที่คั่นด้วยจุลภาค หรือ allallชุดนี้สร้างจากรูปแบบใดบ้าง ปล่อยเป็น all เพื่อใช้ทุกรูปแบบของบิลด์นี้ หรือระบุเฉพาะรูปแบบที่ระบบของคุณรับ
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/th/presets/filename-handling/index.html b/web/public/th/presets/filename-handling/index.html new file mode 100644 index 00000000..a2eae89b --- /dev/null +++ b/web/public/th/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +ชื่อไฟล์ที่เป็นปัญหาสำหรับการทดสอบ - Unicode และความยาว + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

การจัดการชื่อไฟล์

+

ระบบของฉันจะเก็บ แสดง และส่งคืนชื่อไฟล์ที่ไม่ได้คาดไว้ได้ไหม

+

+ พรีเซ็ต filename-handling สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ชื่อที่บนหน้าจอ ในบันทึก หรือในรายการ ดูเหมือนเป็นอีกชื่อหนึ่ง
  • +
  • ชื่อที่ถูกตัด ถูกเล็ม หรือถูกเขียนใหม่ระหว่างอัปโหลดกับจัดเก็บ
  • +
  • ขีดจำกัดความยาวที่นับเป็นอักขระ ทั้งที่ที่เก็บข้อมูลนับเป็นไบต์
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show filename-handling รายงาน:

+
+ + + + + + + +
ไฟล์50
target ในสูตรของมัน50
ขนาดรวม51 200 B
รูปแบบtxt
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้4
unspecifiedขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ46
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--formatรหัสรูปแบบจากหน้ารูปแบบไฟล์txtรูปแบบของทุกไฟล์ในชุด เป็นแฟลกของตัวเครื่องมือเอง และพรีเซ็ตเพียงกำหนดค่าเริ่มต้นให้
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/th/presets/index.html b/web/public/th/presets/index.html new file mode 100644 index 00000000..ee7df7d1 --- /dev/null +++ b/web/public/th/presets/index.html @@ -0,0 +1,244 @@ + + + + + + +พรีเซ็ตไฟล์ทดสอบ - ชุดสำเร็จรูปสำหรับคำถามของ QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

พรีเซ็ตไฟล์ทดสอบ หนึ่งชุดสำหรับทุกคำถามการทดสอบ

+

+ พรีเซ็ตคือชุดไฟล์ทดสอบทั้งชุดที่ออกแบบรอบคำถามข้อเดียว + พร้อมแมนิเฟสต์ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร คุณเลือกคำถาม เครื่องมือสร้างชุด + แต่ละพรีเซ็ตมีหน้าของตัวเองที่บอกว่าโดยทั่วไปมันพบอะไร ในชุดมีอะไร และรับการตั้งค่าใดบ้าง +

+ + + +
+

พรีเซ็ตต่างจากสูตรอย่างไร

+

+ ข้างใต้แล้วไม่ต่าง พรีเซ็ตคือสูตรที่เครื่องมือเขียนให้คุณจากการตั้งค่าไม่กี่อย่าง tfg preset + eject พิมพ์สูตรนั้นออกมาเพื่อให้คุณเก็บไว้ข้างการทดสอบและแก้ไขได้ + และสูตรของคุณเองสร้างต่อยอดจากพรีเซ็ตได้ด้วยบรรทัดเดียว คือ extends: preset: + ตามด้วยรหัสของมัน +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

เชื่อค่าเริ่มต้นได้ไหม

+

+ สำหรับไฟล์ ได้ สำหรับตัวเลขที่มีแต่ระบบของคุณที่รู้ เช่น ขีดจำกัดของฟอร์มอัปโหลด + ค่าเริ่มต้นเป็นค่าชั่วคราวของเรา และเครื่องมือบอกเช่นนั้นทุกครั้งที่ใช้ค่าดังกล่าว + หน้าของแต่ละพรีเซ็ตทำเครื่องหมายการตั้งค่าเหล่านั้น และ tfg preset show + บอกก่อนจะเขียนอะไร +

+
+ +
+ + + + diff --git a/web/public/th/presets/size-boundaries/index.html b/web/public/th/presets/size-boundaries/index.html new file mode 100644 index 00000000..bc065647 --- /dev/null +++ b/web/public/th/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +ทดสอบขีดจำกัดขนาดอัปโหลด - ไฟล์ที่ขอบเขตพอดี + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

ขอบเขตขนาด

+

ขีดจำกัดขนาดถูกบังคับใช้ตรงจุดที่ประกาศไว้พอดีหรือไม่

+

+ พรีเซ็ต size-boundaries สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ข้อผิดพลาดคลาดเคลื่อนหนึ่งที่ขีดจำกัด
  • +
  • สับสนระหว่าง MB กับ MiB ซึ่งต่างกัน 4.8 เปอร์เซ็นต์ และมากพอที่จะปล่อยไฟล์ที่ไม่ควรผ่านให้ผ่านไป
  • +
  • ขีดจำกัดที่บังคับใช้ในเบราว์เซอร์แต่ไม่ได้บังคับที่เซิร์ฟเวอร์
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show size-boundaries รายงาน:

+
+ + + + + + + +
ไฟล์7
target ในสูตรของมัน7
ขนาดรวม73 400 320 B
รูปแบบpdf
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้4
rejectระบบของคุณควรปฏิเสธไฟล์นี้3
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--limitขนาด เช่น 2mb10mbขีดจำกัดขนาดที่ระบบของคุณประกาศ ทุกอย่างที่เหลือวัดจากค่านี้ ค่าเริ่มต้นนี้เป็นค่าชั่วคราวของเรา ไม่ใช่ค่าของระบบคุณ ให้ใส่ค่าของคุณเอง
--spreadขนาดที่คั่นด้วยจุลภาค1B,1kb,1mbจะขยายออกไปไกลแค่ไหนทั้งสองข้างของขีดจำกัด เป็นรายการขนาด
--formatรหัสรูปแบบจากหน้ารูปแบบไฟล์pdfรูปแบบของทุกไฟล์ในชุด เป็นแฟลกของตัวเครื่องมือเอง และพรีเซ็ตเพียงกำหนดค่าเริ่มต้นให้
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

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

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/th/presets/tabular-import/index.html b/web/public/th/presets/tabular-import/index.html new file mode 100644 index 00000000..643550e7 --- /dev/null +++ b/web/public/th/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +ไฟล์ทดสอบนำเข้า CSV และ Excel - ตัวคั่น และส่วนหัว + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

การนำเข้าตาราง

+

การนำเข้าตารางของฉันรับมือกับสิ่งที่เครื่องมือจริงส่งออกได้ไหม

+

+ พรีเซ็ต tabular-import สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ไฟล์ที่ใช้อัฒภาคถูกอ่านเป็นคอลัมน์เดียว เพราะสันนิษฐานตัวคั่นแทนที่จะค้นหา
  • +
  • ไฟล์ CRLF ที่ถูกแบ่งเป็นแถวพร้อมแถวว่างหลังทุกแถว
  • +
  • ตารางที่ไม่มีส่วนหัวซึ่งแถวข้อมูลแรกถูกกลืนไปเป็นชื่อคอลัมน์
  • +
  • การนำเข้าที่เก็บคอลัมน์เท่าที่แสดงได้แล้วทิ้งส่วนที่เหลือโดยไม่บอกสักคำ
  • +
  • ตัวอ่านที่รับระเบียน JSON ทีละบรรทัดและหยุดที่เอกสารแรกที่มีการเยื้อง
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show tabular-import รายงาน:

+
+ + + + + + + +
ไฟล์13
target ในสูตรของมัน13
ขนาดรวม3 080 060 B
รูปแบบcsv, json, xlsx
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้8
unspecifiedขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ5
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--rows1 - 200000 แถว1000สเปรดชีตมีกี่แถว ไฟล์ถูกเขียนที่ขนาดพอดีกับจำนวนแถวนั้น ดังนั้นงบประมาณด้านบนจึงเลื่อนไปตามค่านี้
--columns1 - 32768 คอลัมน์10แต่ละแถวของสเปรดชีตมีกี่คอลัมน์ จำนวนแถวคูณคอลัมน์มีเพดาน และการขอเกินจะถูกปฏิเสธก่อนที่จะเขียนอะไรลงไป
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/th/presets/text-encoding/index.html b/web/public/th/presets/text-encoding/index.html new file mode 100644 index 00000000..2257dfa9 --- /dev/null +++ b/web/public/th/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +ไฟล์ทดสอบการเข้ารหัสข้อความ - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

การเข้ารหัสข้อความ

+

ตัวอ่านของฉันรู้ไหมว่าไฟล์ใช้การเข้ารหัสอะไร หรือกำลังเดาอยู่

+

+ พรีเซ็ต text-encoding สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ตัวอ่านที่สมมติว่าเป็น UTF-8 แล้วแสดงไฟล์ UTF-16 เป็นหนึ่งอักขระในทุกสามอักขระ หรือเป็นแถวของกล่องสี่เหลี่ยม
  • +
  • เครื่องหมายลำดับไบต์ที่ถูกอ่านเป็นเนื้อหา ทำให้ช่องแรกของการนำเข้าขึ้นต้นด้วยอักขระแปลกปลอมสามตัว
  • +
  • ตัวนำเข้าที่เดาการเข้ารหัสจากไบต์แรกๆ และเดาต่างออกไปกับไฟล์ที่ยาวกว่า
  • +
  • ไฟล์ CRLF ที่ถูกแบ่งเป็นแถวพร้อมแถวว่างหลังทุกแถว หรือตัวอักขระขึ้นต้นบรรทัดที่ค้างอยู่ในช่องสุดท้าย
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show text-encoding รายงาน:

+
+ + + + + + + +
ไฟล์20
target ในสูตรของมัน20
ขนาดรวม81 920 B
รูปแบบcsv, log, md, txt, xml
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้10
unspecifiedขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ10
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--sampleขนาด เช่น 2mb4kbแต่ละไฟล์ในชุดมีขนาดเท่าไร UTF-16 เก็บสองไบต์ต่ออักขระ ดังนั้นเลขคี่จะถูกปฏิเสธ
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/th/presets/upload-validation/index.html b/web/public/th/presets/upload-validation/index.html new file mode 100644 index 00000000..a7f649dc --- /dev/null +++ b/web/public/th/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +ไฟล์ทดสอบการตรวจสอบอัปโหลด - ประเภท ขนาด และชื่อ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

พรีเซ็ต

+

การตรวจสอบการอัปโหลด

+

ฟอร์มอัปโหลดของฉันรับสิ่งที่ควรรับและปฏิเสธที่เหลือหรือไม่

+

+ พรีเซ็ต upload-validation สร้างชุดไฟล์ทดสอบจริงทั้งชุดสำหรับคำถามนี้ด้วยคำสั่งเดียว และมี + manifest.json อยู่ข้างๆ ที่บอกว่าระบบของคุณควรตอบสนองต่อแต่ละไฟล์อย่างไร + ทุกอย่างด้านล่างอ่านจากโปรแกรม ที่ค่าเริ่มต้นของเวอร์ชันนี้ +

+ + +
+

โดยทั่วไปมันพบอะไร

+
    +
  • ขีดจำกัดที่บังคับใช้ในเบราว์เซอร์แต่ไม่ได้บังคับที่เซิร์ฟเวอร์
  • +
  • ไฟล์ SVG หรือ HTML ที่ถูกเข้าใจว่าเป็นรูปภาพหรือข้อความธรรมดา ซึ่งเป็นวิธีหนึ่งในการลอบส่งสคริปต์ผ่านฟอร์ม
  • +
  • ไฟล์ที่ตรวจจากนามสกุลโดยไม่เคยเปิดดู ทำให้ PDF ที่ตั้งชื่อ .jpg ผ่านไปได้
  • +
  • ฟอร์มที่อ่านเนื้อหาทั้งหมดเข้าหน่วยความจำก่อนจะดูว่าใหญ่แค่ไหน
  • +
  • การอัปโหลดชื่อ PHOTO.JPG ที่ถูกปฏิเสธขณะที่ photo.jpg ถูกรับ หรือกลับกัน
  • +
  • ชื่อที่มีช่องว่าง วงเล็บ หรืออักขระนอก ASCII ที่ถูกเขียนลงดิสก์โดยไม่เปลี่ยนแปลง
  • +
+
+ + +
+

ในชุดมีอะไร

+

ที่ค่าเริ่มต้น ตามที่ tfg preset show upload-validation รายงาน:

+
+ + + + + + + +
ไฟล์71
target ในสูตรของมัน22
ขนาดรวม120 639 488 B
รูปแบบhtml, jpg, pdf, png, svg, txt
+
+

และสิ่งที่แมนิเฟสต์ของชุดนั้นคาดหวังจากระบบของคุณ:

+
+ + + + + + + + + +
ที่คาดหวังความหมายไฟล์
acceptระบบของคุณควรยอมรับไฟล์นี้56
rejectระบบของคุณควรปฏิเสธไฟล์นี้10
unspecifiedขึ้นอยู่กับกฎของระบบของคุณ คุณเป็นผู้ตัดสิน แล้วตรวจสอบว่าสิ่งที่เกิดขึ้นตรงกับที่ตั้งใจ5
+
+
+ +
+

คุณเปลี่ยนอะไรได้บ้าง

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
การตั้งค่ารับค่าเริ่มต้นทำอะไร
--limitขนาด เช่น 2mb10mbขีดจำกัดขนาดที่ฟอร์มอัปโหลดของคุณประกาศ ชุดนี้ก้าวไปข้างละหนึ่งขั้น - หากต้องการไฟล์ที่ทุกระยะ ให้รันพรีเซ็ต size-boundaries ค่าเริ่มต้นนี้เป็นค่าชั่วคราวของเรา ไม่ใช่ค่าของระบบคุณ ให้ใส่ค่าของคุณเอง
--allowรหัสรูปแบบที่คั่นด้วยจุลภาคjpg,png,pdfประเภทที่ฟอร์มของคุณควรรับ แต่ละประเภทจะกลายเป็นไฟล์จริงของประเภทนั้น และเป็นตัวควบคุมเชิงบวกของทั้งชุด
--denyนามสกุลที่คั่นด้วยจุลภาคsvg,html,exe,shนามสกุลที่ฟอร์มของคุณควรปฏิเสธ นามสกุลที่บิลด์นี้ไม่มีรูปแบบรองรับก็ยังได้ไฟล์ชื่อนั้นที่มีข้อความธรรมดา
--far-over10x, 2x, off2xไฟล์ใหญ่ไฟล์เดียวเกินขีดจำกัดไปไกลแค่ไหน ปิดไว้หากการเขียนหลายเท่าของขีดจำกัดไม่คุ้มกับพื้นที่ดิสก์
--bulk0 - 10000 ไฟล์50การอัปโหลดเป็นกลุ่มมีกี่ไฟล์ ศูนย์จะตัดกลุ่มนั้นออกจากชุดทั้งหมด
+
+
+ +
+

รันอย่างไร

+

ดูว่าชุดจะมีต้นทุนเท่าไร สร้างมัน หรือเอาสูตรของมันไปแก้ไข:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

หรือสร้างต่อยอดจากมันในสูตรของคุณเอง ไว้ข้างการทดสอบของคุณ:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/th/test-files-in-ci/index.html b/web/public/th/test-files-in-ci/index.html new file mode 100644 index 00000000..a6b6b62e --- /dev/null +++ b/web/public/th/test-files-in-ci/index.html @@ -0,0 +1,373 @@ + + + + + + +ไฟล์ทดสอบใน CI - GitHub Actions, GitLab CI และ PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

กรณีการใช้งาน

+

วิธีสร้างไฟล์ทดสอบในไปป์ไลน์ CI

+

+ ฟิกซ์เจอร์ไบนารีในรีโพซิทอรีจะค้างอยู่ในประวัติตลอดไป รีวิวใน diff ไม่ได้ + และเป็นไปไม่ได้เลยเมื่อไฟล์ใหญ่ ให้สร้างไฟล์ในไปป์ไลน์จากสูตรแทน สูตรเป็นข้อความ + ไบต์ออกมาเหมือนกันทุกครั้ง และขั้นสุดท้ายพิสูจน์ว่าไม่มีอะไรขยับ +

+ +
+

คำตอบสั้นๆ

+

+ ติดตั้ง tfg รัน tfg generate fixtures.yaml --out ./fixtures ก่อนการทดสอบ + และ tfg verify ./fixtures/manifest.json หลังการทดสอบ + ทั้งสองขั้นทำให้บิลด์ล้มเหลวได้เอง พร้อมรหัสออกที่บอกเหตุผล +

+
+ +
+

ทำไมไม่คอมมิต

+

ทำไมฟิกซ์เจอร์ไม่ควรอยู่ในรีโพซิทอรี

+
    +
  • + มันค้างอยู่ในประวัติ การลบไฟล์ไบนารีทีหลังไม่ได้ทำให้โคลนเล็กลง + เพราะทุกเวอร์ชันของมันยังอยู่ตรงนั้น +
  • +
  • + diff ไม่แสดงว่าอะไรเปลี่ยน ผู้รีวิวเห็นแค่ว่า PDF ต่างไป ไม่มีอะไรมากกว่านั้น + ส่วนสูตรเปลี่ยนแค่บรรทัดเดียว +
  • +
  • + ไฟล์ใหญ่ไม่พอดี GitHub ปฏิเสธการพุชที่มีไฟล์ใหญ่กว่า 100 MB การทดสอบขีดจำกัดอัปโหลด + 500 MB จึงไม่มีอะไรให้คอมมิต +
  • +
+

+ สิ่งที่ควรคอมมิตคือสูตร สูตรเดียวกันกับซีดเดียวกันเขียนไบต์เดียวกันบนทุกเครื่อง + ไฟล์ที่สร้างในไปป์ไลน์จึงเป็นไฟล์เดียวกับที่คุณมีบนแล็ปท็อป +

+
+ +
+

สูตร

+

สูตรที่อยู่ข้างๆ การทดสอบ

+

+ สูตรนี้เขียนใบแจ้งหนี้ยี่สิบห้าใบที่ควรถูกรับ และรูปสองรูปที่เกินขีดจำกัดซึ่งควรถูกปฏิเสธ + และแมนิเฟสต์บันทึกสิ่งที่คาดหวังทั้งสองอย่าง: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml ตรวจสูตรโดยไม่เขียนอะไร และบอกทุกปัญหาในครั้งเดียว +

+
+ +
+

GitHub Actions

+

เวิร์กโฟลว์ที่ติดตั้งเครื่องมือและสร้างฟิกซ์เจอร์

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ บรรทัดผลรวมตรวจสอบเทียบไฟล์เก็บถาวรกับ verify-SHA256SUMS.txt จากรุ่นเดียวกัน + เวอร์ชันถูกตรึงไว้ รุ่นใหม่จึงไม่มีวันเปลี่ยนบิลด์ที่คุณไม่ได้แตะ +

+
+ +
+

GitLab CI

+

เรื่องเดียวกันในรูปแบบงานของ GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

เมื่อกลายเป็นสีแดง

+

อะไรทำให้ขั้นหนึ่งล้มเหลว และเพราะอะไร

+

+ ทุกการจบมีรหัสออกของตัวเอง ขั้นจึงล้มเหลวได้เอง และล็อกบอกว่าเป็นรหัสไหน รหัสที่ไปป์ไลน์พบ: +

+
    +
  • 3 - สูตรไม่ถูกต้อง ไม่มีอะไรถูกเขียน และทุกปัญหามีชื่อบอก
  • +
  • 4 - รูปแบบทำสิ่งที่ขอไม่ได้ เช่น ขนาดต่ำกว่าขนาดเล็กสุดของมัน
  • +
  • 6 - พื้นที่ดิสก์ไม่พอ
  • +
  • 7 - tfg verify พบไฟล์ที่ไม่ตรงกับแมนิเฟสต์ของมัน
  • +
  • 8 - การรันจบแล้ว แต่ไม่ได้สร้างครบทุกอย่าง
  • +
+

+ การรันที่ล้มเหลวไม่พิมพ์อะไรออกทางเอาต์พุตมาตรฐาน + ตัวแยกวิเคราะห์ล็อกจึงไม่มีวันเข้าใจผิดว่าข้อผิดพลาดเป็นข้อมูล + ตารางทั้งหมดอยู่ในหน้าเอกสาร +

+
+ +
+

PowerShell

+

สคริปต์ PowerShell ต้องการอีกหนึ่งบรรทัด

+

+ PowerShell ไม่นำรหัสออกของโปรแกรมออกมานอกไฟล์ .ps1 รันสคริปต์ด้วย -File + แล้วสคริปต์จะตอบ 0 แม้เครื่องมือข้างในปฏิเสธงาน + ทำให้บิลด์ที่ควรเป็นสีแดงกลายเป็นสีเขียว บรรทัดสุดท้ายคือวิธีแก้ทั้งหมด: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ นี่คือวิธีที่ PowerShell ทำงาน ไม่ใช่เรื่องของเครื่องมือนี้ cmd bash และ + zsh ไม่ต้องการอะไรเพิ่ม +

+
+ +
+

หลายงาน

+

แบ่งปันฟิกซ์เจอร์ระหว่างงาน

+

+ โดยปกติไม่จำเป็นต้องอัปโหลด เพราะสูตรเดียวกันเขียนไบต์เดียวกัน แต่ละงานจึงรัน tfg + generate ของตัวเองได้ ซึ่งเร็วกว่าการอัปโหลดแล้วดาวน์โหลด + เมื่องานหนึ่งต้องรับไฟล์จากอีกงานหนึ่ง ให้รัน tfg verify กับแมนิเฟสต์หลังการถ่ายโอน + แล้วมันจะบอกว่าสิ่งที่มาถึงตรงกับที่เขียนไว้หรือไม่ +

+
+ +
+

ถัดไป

+

จากตรงนี้ไปไหนต่อ

+ +
+ +
+ + + + diff --git a/web/public/th/use-cases/index.html b/web/public/th/use-cases/index.html new file mode 100644 index 00000000..f6948265 --- /dev/null +++ b/web/public/th/use-cases/index.html @@ -0,0 +1,316 @@ + + + + + + +กรณีการใช้งาน - ขีดจำกัดอัปโหลด ฟิกซ์เจอร์ CI ทดสอบจำนวนมาก + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

คนใช้มันทำอะไร

+

+ ห้างานที่เกิดขึ้นในเกือบทุกโครงการที่รับไฟล์จากผู้คน และคำสั่งที่ทำแต่ละงาน + ทุกตัวอย่างด้านล่างรันได้ตามที่เขียน +

+ +
+

ขีดจำกัดการอัปโหลด

+

ทดสอบว่าขีดจำกัดขนาดไฟล์ถูกบังคับใช้ตรงที่บอกไว้หรือไม่

+

+ ขีดจำกัดหนึ่งค่าคือกรณีทดสอบสามกรณี ไม่ใช่หนึ่ง: ต่ำกว่าเล็กน้อย ตรงพอดี และสูงกว่าเล็กน้อย + การทำด้วยมือหมายถึงคำนวณจำนวนไบต์และหวังว่าจะไม่พลาดไปหนึ่ง ขอเป็นชุดแทน: +

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

+ คุณได้ PDF จริงสามไฟล์ขนาด 1048575, 1048576 และ 1048577 ไบต์ + พร้อมแมนิเฟสต์ที่บอกว่าสองไฟล์แรกควรถูกยอมรับและไฟล์ที่สามถูกปฏิเสธด้วย size_limit + การทดสอบของคุณอ่านความคาดหวังแทนที่คุณจะเขียนการยืนยันสามอันด้วยมือ - และเมื่อขีดจำกัดเปลี่ยน + คุณเปลี่ยนตัวเลขเดียวแล้วรันใหม่ +

+

+ ทำแบบเดียวกันได้โดยไม่ใช้พรีเซ็ตเมื่อต้องการชุดขอบเขตเดียวในบรรทัด: +

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

การรวมระบบต่อเนื่อง

+

เก็บฟิกซ์เจอร์ไว้นอกรีโพซิทอรีโดยไม่ทำหาย

+

+ ฟิกซ์เจอร์ไบนารีขนาดใหญ่ทำให้รีโพซิทอรีโคลนช้าและตรวจทานยาก + และไม่มีใครบอกได้ว่าอะไรเปลี่ยนเมื่อมีการเปลี่ยนไฟล์หนึ่ง สูตรคือ YAML + ไม่กี่ร้อยอักขระที่สร้างไฟล์เหมือนเดิมขึ้นใหม่ - ไบต์ต่อไบต์ บนเครื่องใดก็ตาม - + เพราะทุกไฟล์ได้มาจากซีดของการรัน +

+
- 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
+

+ ทุกการจบมีรหัสออกของตัวเอง + ไปป์ไลน์จึงแยกสูตรที่ไม่ดีออกจากดิสก์เต็มและจากความไม่ตรงกันในการตรวจสอบได้ + การรันที่ล้มเหลวไม่พิมพ์อะไรบนเอาต์พุตมาตรฐาน + ทำให้ตัวแยกวิเคราะห์บันทึกไม่อ่านข้อผิดพลาดเป็นข้อมูล +

+
+ +
+

ขนาดใหญ่

+

ค้นหาว่าเกิดอะไรขึ้นเมื่อโฟลเดอร์ใหญ่

+

+ ขั้นตอนนำเข้า งานกลางคืน และรายการไดเรกทอรีทำงานต่างกันเมื่อมีหนึ่งหมื่นไฟล์เทียบกับสิบไฟล์ + ขนาดที่สุ่มจากช่วงทำให้ชุดดูเหมือนทราฟฟิกจริงแทนที่จะเป็นไฟล์เหมือนกันหนึ่งหมื่นไฟล์ + และการสุ่มมาจากซีด ชุดจึงเหมือนเดิมในวันพรุ่งนี้ +

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

+ ตรวจต้นทุนของการรันก่อนที่มันจะเขียนอะไร ซึ่งสำคัญเมื่อยอดรวมวัดเป็นกิกะไบต์: +

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

+ การรันที่ใหญ่กว่าพื้นที่ว่างบนดิสก์ถูกปฏิเสธก่อนจะเขียนไบต์แรก + แทนที่จะเติมดิสก์จนเต็มแล้วล้มเหลวกลางคัน +

+
+ +
+

ไฟล์บีบอัด

+

ทดสอบตัวแตกไฟล์ด้วยไฟล์บีบอัดที่มีไฟล์อยู่ข้างในจริงๆ

+

+ ไฟล์บีบอัดว่างที่มีนามสกุลถูกต้องไม่พิสูจน์อะไรเกี่ยวกับโค้ดที่เปิดและไล่ดูสิ่งที่อยู่ข้างใน + ประกาศเนื้อหา แล้วไฟล์บีบอัดจะมีมันอยู่จริง: +

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

+ ความลึกของการซ้อน จำนวนรายการ และขนาดของสิ่งที่อยู่ข้างใน ล้วนเป็นสิ่งที่ขั้นตอนนำเข้ามีความเห็น + และนี่คือวิธีที่คุณจะรู้ว่าความเห็นเหล่านั้นคืออะไร +

+
+ +
+

ตัวแยกวิเคราะห์และโปรแกรมดู

+

ตรวจสอบว่าโค้ดของคุณเองอ่านรูปแบบได้เหมือนซอฟต์แวร์จริง

+

+ ทุกรูปแบบที่นี่ถูกตรวจด้วยตัวอ่านอิสระก่อนปล่อย - PNG ถูกเปิดและเทียบพิกเซล DOCX + ถูกอ่านกลับด้วยไลบรารีแยกต่างหาก ไฟล์บีบอัดถูกแตกไฟล์ + นั่นหมายความว่าไฟล์ที่ตัวแยกวิเคราะห์ของคุณปฏิเสธเป็นข้อค้นพบเกี่ยวกับตัวแยกวิเคราะห์ของคุณ + ไม่ใช่เกี่ยวกับตัวสร้าง +

+
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
+

+ หน้ารูปแบบไฟล์แสดงการตั้งค่าที่แต่ละรูปแบบรับและไฟล์เล็กที่สุดที่แต่ละรูปแบบเป็นได้ +

+
+ +
+

คู่มือ

+

สองเรื่องนี้ในรายละเอียด

+
    +
  • + ไฟล์ทดสอบที่เสียหาย - ไฟล์ที่ตั้งใจทำให้เสีย ขนาดตรงเป๊ะ + และสิ่งที่ควรเกิดกับไฟล์นั้นเขียนไว้ในแมนิเฟสต์ +
  • +
  • + ไฟล์ทดสอบใน CI - เวิร์กโฟลว์ของ GitHub Actions งานของ GitLab + และรหัสออกที่ทำให้บิลด์ล้มเหลว +
  • +
+
+ +
+

เหมาะกับใคร

+

+ วิศวกร QA งานทดสอบอัตโนมัติ และทุกคนที่โค้ดมีฟอร์มอัปโหลด ขั้นตอนนำเข้า ตัวแยกวิเคราะห์ + หรือโควตาพื้นที่จัดเก็บอยู่เบื้องหลัง ทำงานบนเครื่องที่ไม่มีเครือข่ายเลย + ซึ่งสำคัญในสภาพแวดล้อมองค์กรที่ปิดซึ่งตัวสร้างบนเบราว์เซอร์ไม่ใช่ทางเลือก +

+ +

ฟรีและโอเพนซอร์ส GPL-3.0 ไม่ต้องสมัครสมาชิก ไฟล์ดาวน์โหลดของ Windows และ macOS ลงนามแล้วและเริ่มทำงานโดยไม่มีคำเตือน

+
+ +
+ + + + diff --git a/web/public/tr/bicimler/index.html b/web/public/tr/bicimler/index.html new file mode 100644 index 00000000..afe249d5 --- /dev/null +++ b/web/public/tr/bicimler/index.html @@ -0,0 +1,911 @@ + + + + + + +26 desteklenen dosya biçimi - PDF, DOCX, PNG, ZIP ve daha fazlası + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 dosya biçimi, her biri tam boyutta üretilir

+

+ Bunların her biri o biçimde gerçek bir dosyadır. Ait olduğu programda açılır ve tam + istediğiniz bayt sayısındadır. Hiçbiri yapıştırılmış uzantılı dolgu sıfırları değildir. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BiçimAdUzantıEn küçük dosyaBütünlükDoğrulayan
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fulluygulanamaz
mdMarkdown.md0fulluygulanamaz
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fulluygulanamaz
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Sütunların anlamı

+
    +
  • +

    En küçük dosya

    +

    + Bu aracın o biçim için kabul edeceği en az bayt sayısı, dosyanın içine yazdığı etiket dahil. Daha + azını isterseniz alt sınırı ve nedenini adlandıran bir hata alırsınız, asla yanlış boyutta + bir dosya değil. +

    +
  • +
  • +

    Bütünlük

    +

    + Dosyanın ne kadar tam olduğu. full, biçimi gerçekten ayrıştıran bir okuyucunun onu + kabul ettiği anlamına gelir, yalnızca uzantının uyduğu anlamına değil. +

    +
  • +
  • +

    Doğrulayan

    +

    + Biçim yayımlanmadan önce üretilen her dosyayı açan bağımsız okuyucu - ayrı bir uygulama, kendi + ödevini kendi notlayan bizim kodumuz değil. +

    +
  • +
+

+ Her biçim ayrıca bayta kadar tekrarlanır: aynı tarif ve aynı seed her makinede özdeş dosyalar üretir + ve bir tarifi fixture'ların kendisi yerine commit etmeyi güvenli kılan budur. +

+
+ +
+

Her biçimin kabul ettiği ayarlar

+

+ Çoğu biçimin kendi ayarları vardır - görüntü boyutları, JPEG kalitesi, PDF sayfa sayısı, bir + elektronik tablodaki satır ve sütunlar, bir arşivin içine kaç girdi gireceği. Bunları komut + satırında --set key=value ile veya bir tarifte properties: altında + ayarlayın. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BiçimAyarKabul eder
avifwidth1 - 16384 piksel
height1 - 16384 piksel
quality1 - 100
bmpwidth1 - 20000 piksel
height1 - 20000 piksel
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerdoğru veya yanlış
quote_styleall, minimal, none
columns2 - 32768 sütun
docxparagraphs1 - 50000 paragraf
gifwidth1 - 20000 piksel
height1 - 20000 piksel
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 piksel
height1 - 256 piksel
embedbmp, png
jpgwidth1 - 20000 piksel
height1 - 20000 piksel
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 piksel
height1 - 16384 piksel
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 saniyedeki girdi
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomdoğru veya yanlış
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleherhangi bir metin
authorherhangi bir metin
subjectherhangi bir metin
keywordsherhangi bir metin
creatorherhangi bir metin
producerherhangi bir metin
created2024-02-29 veya 2024-02-29T13:45:00+02:00 gibi bir tarih, veya none
modified2024-02-29 veya 2024-02-29T13:45:00+02:00 gibi bir tarih, veya none
pngwidth1 - 20000 piksel
height1 - 20000 piksel
pptxslides1 - 500 slayt
svgwidth1 - 20000 piksel
height1 - 20000 piksel
targzentries0 - 10000
entry_formattfg formats'ın listelediği gibi bir biçimin kimliği
entry_size2mb gibi bir boyut
compressionbest, default, fast, none
depth0 - 50
directory_entriesdoğru veya yanlış
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 piksel
height1 - 20000 piksel
txtencodingutf-16be, utf-16le, utf-8
bomdoğru veya yanlış
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 piksel
height1 - 16383 piksel
xlsxrows1 - 200000 satır
columns1 - 32768 sütun
xmlencodingutf-16be, utf-16le, utf-8
bomdoğru veya yanlış
zipentries0 - 10000
entry_formattfg formats'ın listelediği gibi bir biçimin kimliği
entry_size2mb gibi bir boyut
compressionbest, default, fast, none
depth0 - 50
directory_entriesdoğru veya yanlış
passwordparola, düz metin olarak
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Bir ayarın kabul ettiğinin dışındaki değer, ayarı, izin verilen aralığı ve onun yerine ne + kullanılacağını söyleyen bir iletiyle reddedilir. Bilinmeyen bir ayar da hatadır, asla sessiz + bir varsayılan değil - sessizce kabul edilen bir yazım hatası yanlış ayarlı bir dosya ve testin + geçmemesi gerekirken neden geçtiğini merak ederek geçen bir saat verir. +

+

+ Elinizdeki sürümde bir biçimin tam olarak ne kabul ettiğini görmek için tfg formats + <id> çalıştırın. +

+
+ +
+

Arşivler gerçek dosyalar içerir

+

+ targz ve zip boş + bir kabuk olarak bırakılmak yerine girdilerle doldurulabilir. Üretilmiş bir arşiv, içerdiğini + söylediği belgeleri gerçekten içerir, bu yüzden bir test sırasında onu açan her şey içinde + gerçek dosyalar bulur. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/tr/bozuk-test-dosyalari/index.html b/web/public/tr/bozuk-test-dosyalari/index.html new file mode 100644 index 00000000..f9bbc9d4 --- /dev/null +++ b/web/public/tr/bozuk-test-dosyalari/index.html @@ -0,0 +1,381 @@ + + + + + + +Bozuk test dosyaları - tam boyutta bozuk dosyalar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Kullanım senaryoları

+

Test için bozuk dosya nasıl yapılır

+

+ Yalnızca sağlam dosyalar gösterilmiş bir doğrulayıcı gerçekten sınanmış sayılmaz. İşte kasıtlı + bozulmuş, tam istediğiniz boyutta çıkan ve sisteminizin onunla ne yapması + gerektiğini söyleyen bir bildirimle gelen bir dosyayı nasıl elde edeceğiniz. +

+ +
+

Kısa yanıt

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out tam 2097152 bayt + boyutunda, ilk baytları sıfır olan bir PNG yazar ve yanındaki bildirim sisteminizin onu + reddetmesi gerektiğini kaydeder. +

+
+ +
+

Olağan yol

+

Elle bozulmuş bir dosya neden kötü bir testtir

+

+ Olağan yollar bir onaltılık düzenleyici, birkaç rastgele baytı çeviren bir betik ya da bir dosyayı + head veya truncate ile kısaltmaktır. Bir kez işe yarar, sonra size + pahalıya mal olur: +

+
    +
  • + Her seferinde farklıdır. Rastgele bir bayt her çalıştırmada başka bir yere düşer, + bu yüzden salı günkü bir hata çarşamba dönmeyebilir. +
  • +
  • + Boyutu değiştirir. Kesilmiş bir dosya, altında kalması gereken sınırdan küçüktür. + Böylece boyut denetimi içerik denetiminden önce yanıt verir ve test yanlış nedenle geçer. +
  • +
  • + Çoğu zaman fark edilmez. Düz metin ortasında değişmiş bir baytla da okunur, + hoşgörülü bir görüntü okuyucusu ise onu olduğu gibi çizer. Böylece bozuk olması gereken dosya + kabul edilir. +
  • +
  • + Ne olması gerektiğini söylemez. Dosya yalnızca bayttır ve testi sonradan okuyan, + kabulün mü reddin mi amaçlandığını tahmin etmek zorunda kalır. +
  • +
+
+ +
+

Ne elde edersiniz

+

Hasarlı bir dosya yine istediğiniz boyuttadır

+

+ Dosya normal üretilir, sonra diske giderken bozulur. İstediğiniz boyutu korur ve aynı komut yine + aynı baytları yazar. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Ayarlar iki noktadan sonra yazılır. Seçenek tekrarlanabilir ve hasarlar yazdığınız sırayla + uygulanır. 26 biçimin her biriyle çalışır. +

+
+ +
+

Neler yapabilir

+

Hangi hasarlar var?

+

+ Bu, programın yazdırdığı listedir ve bu sayfa oluşturulurken programdan okunur. tfg + damage aynısını yazdırır, tfg damage <id> ise birinin neyi kabul + ettiğini söyler. +

+
+ + + + + + + + + + + + + + + + + +
HasarBaytlara ne yaparEn küçük dosyaAyarlar
zero-headDosyanın ilk baytlarını uzunluğuna dokunmadan sıfırlarla ezer. Okuyucuların çoğu önce oraya bakar, bu yüzden hemen her şey bu hasarı fark eder.8bytes
+
+

+ zero-head dosyanın başına sıfırlar yazar. Okuyucuların çoğu önce oraya bakar, dosyanın + ne olduğunu söyleyen imzaya ve başlığa, bu yüzden hemen her okuyucu fark eder. Düz metin ve + günlüklerin imzası yoktur ve onlar da reddedilir, çünkü bir sıfır baytı dizisi metin değildir. + Dört baytın altında bazı biçimler hiçbir okuyucunun şikâyet etmediği bir hasarla çıkar, ayarın + dörtten başlamasının nedeni budur. +

+
+ +
+

Bildirim ne söyler

+

Ne olması gerektiğini söyleyen bir bildirim

+

+ Hasarlı her dosya, sisteminizin onu reddetmesi gerektiğini söyleyen bir kayıt alır ve hasar yanına + yazılır: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ İki istek, bir şey yazılmadan önce reddedilir, çünkü her biri diskte bildirimin yanlış tarif ettiği + bir dosya bırakırdı: +

+
    +
  • hasarın gerektirdiğinden küçük bir dosya, ki değişmeden çıkardı
  • +
  • + Bir hasarın yanında expected: accept, çünkü hiçbir şey bunu karşılayamaz. Sisteminiz + dosyayı onarmalıysa sanitize, tam da bunu soruyorsanız unspecified + yazın +
  • +
+
+ +
+

Bir tarifte

+

Tek çalıştırmada sağlam ve bozuk dosyalar

+

+ İkisini de tek bir tarife koyun, bildirim her dosyanın beklentisini taşır. Böylece testin hangisinin + hangisi olduğuna dair bir listeye ihtiyacı kalmaz: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Bir testte

+

Bunu bir teste dönüştürmek

+

+ Test bildirimi okur ve olanın bildirilenle aynı olup olmadığına bakar. Dosya adı listesine ihtiyacı + yoktur: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ İyi bir ret temiz bir rettir. Neyin yanlış olduğunu söyleyen bir ileti istediğiniz yanıttır. Sunucu + hatası, takılma ya da yarım kaydedilmiş dosya, bu testin bulmak için var olduğu kusurdur. +

+
+ +
+

Sonraki

+

Buradan nereye gidilir

+ +
+ +
+ + + + diff --git a/web/public/tr/ci-icinde-test-dosyalari/index.html b/web/public/tr/ci-icinde-test-dosyalari/index.html new file mode 100644 index 00000000..68df5853 --- /dev/null +++ b/web/public/tr/ci-icinde-test-dosyalari/index.html @@ -0,0 +1,376 @@ + + + + + + +CI'da test dosyaları - GitHub Actions, GitLab CI ve PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Kullanım senaryoları

+

CI hattında test dosyaları nasıl üretilir

+

+ Bir depodaki ikili fixture sonsuza dek geçmişinde kalır, bir diff'te incelenemez ve dosya + büyüdüğünde olanaksız hale gelir. Bunun yerine dosyaları hat içinde bir tariften üretin. Tarif + metindir, baytlar her seferinde aynı çıkar ve son bir adım hiçbir şeyin kaymadığını kanıtlar. +

+ +
+

Kısa yanıt

+

+ tfg'yi kurun, testlerden önce tfg generate fixtures.yaml --out ./fixtures, + sonra tfg verify ./fixtures/manifest.json çalıştırın. Her iki adım da derlemeyi + kendiliğinden başarısız kılar ve nedenini söyleyen bir çıkış koduyla bunu yapar. +

+
+ +
+

Neden commit edilmez

+

Bir fixture neden depoda durmamalı

+
    +
  • + Geçmişte kalır. Bir ikili dosyayı sonradan silmek klonu küçültmez, çünkü onun her + sürümü hâlâ oradadır. +
  • +
  • + Diff neyin değiştiğini göstermez. İnceleyen kişi bir PDF'nin farklı olduğunu görür, + başka bir şey değil. Bir tarif ise bir satırla değişir. +
  • +
  • + Büyük dosyalar sığmaz. GitHub, 100 MB'ın üzerinde bir dosya içeren bir push'u + reddeder. Bu yüzden 500 MB'lık bir yükleme sınırı testinin commit edecek bir şeyi olmaz. +
  • +
+

+ Commit edilecek olan tariftir. Aynı tarif ve aynı tohum her makinede aynı baytları yazar, bu yüzden + hatta üretilen dosya dizüstünüzde sahip olduğunuz dosyadır. +

+
+ +
+

Tarif

+

Testlerin yanında duran bir tarif

+

+ Bu tarif, kabul edilmesi gereken yirmi beş fatura ile bir sınırın üzerinde olup reddedilmesi gereken + iki görüntü yazar ve bildirim iki beklentiyi de kaydeder: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml onu hiçbir şey yazmadan denetler ve tüm sorunları tek + seferde adlandırır. +

+
+ +
+

GitHub Actions

+

Aracı kuran ve fixture'ları oluşturan bir iş akışı

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Sağlama toplamı satırı arşivi aynı sürümdeki verify-SHA256SUMS.txt ile karşılaştırır. + Sürüm sabitlenmiştir, bu yüzden yeni bir sürüm dokunmadığınız bir derlemeyi asla değiştirmez. +

+
+ +
+

GitLab CI

+

Aynısı bir GitLab işi olarak

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Kırmızıya döndüğünde

+

Bir adımı ne başarısız kılar ve neden

+

+ Her sonun kendi çıkış kodu vardır, bu yüzden adım kendiliğinden başarısız olur ve günlük hangisi + olduğunu söyler. Bir hattın karşılaştıkları: +

+
    +
  • 3 - tarif geçerli değil. Hiçbir şey yazılmadı ve her sorun adlandırıldı
  • +
  • 4 - biçim istenileni yapamıyor, örneğin kendi en küçüğünün altında bir boyut
  • +
  • 6 - yeterli disk alanı yok
  • +
  • 7 - tfg verify bildirimiyle uyuşmayan bir dosya buldu
  • +
  • 8 - çalıştırma bitti ama her şey üretilmedi
  • +
+

+ Başarısız bir çalıştırma standart çıktıya hiçbir şey yazmaz, bu yüzden bir günlük ayrıştırıcısı + hatayı asla veri sanmaz. Tablonun tamamı belgeler + sayfasında. +

+
+ +
+

PowerShell

+

Bir PowerShell betiği bir satır daha ister

+

+ PowerShell, bir programın çıkış kodunu bir .ps1 dosyasının dışına taşımaz. Birini + -File ile çalıştırın. İçindeki araç işi reddetse bile betik 0 yanıtı + verir ve kırmızı olması gereken bir derleme yeşile döner. Son satır düzeltmenin tamamıdır: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell böyle davranır, bu aracla ilgili bir şey değildir. cmd, bash ve + zsh fazladan hiçbir şeye gerek duymaz. +

+
+ +
+

Birkaç iş

+

Fixture'ları işler arasında paylaşmak

+

+ Genellikle yüklemeye gerek yoktur. Aynı tarif aynı baytları yazdığı için her iş kendi tfg + generate komutunu çalıştırabilir ve bu, yükleyip indirmekten daha hızlıdır. Bir işin + başka bir işten dosya alması gerekiyorsa, aktarımdan sonra bildirim üzerinde tfg + verify çalıştırın. Gelenin yazılanla aynı olup olmadığını söyler. +

+
+ +
+

Sonraki

+

Buradan nereye gidilir

+
    +
  • + Bozuk test dosyaları aynı tarife kasıtlı bozulmuş dosyalar + ekler. +
  • +
  • + Kullanım senaryoları bir hat içindeki çalıştırmanın başka + neleri denetleyebileceğini gösterir. +
  • +
  • + Belgeler her komutu, tarif anahtarını ve çıkış kodunu içerir. +
  • +
+
+ +
+ + + + diff --git a/web/public/tr/dokumantasyon/index.html b/web/public/tr/dokumantasyon/index.html new file mode 100644 index 00000000..4867e6a5 --- /dev/null +++ b/web/public/tr/dokumantasyon/index.html @@ -0,0 +1,556 @@ + + + + + + +Dokümantasyon - komutlar, tarifler, manifest, çıkış kodları + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Dokümantasyon

+

+ Aracın yaptığı her şey, insanların gerçekten geldiği sorular şeklinde düzenlendi. + Depodaki README tam başvurudur ve her zaman indirdiğiniz sürümle + eşleşir. +

+ +
+

Hangi komutlar var?

+

Her biri tek bir iş yapar:

+
tfg generate    tariften veya bayraklardan dosya üret
+tfg validate    bir tarifi denetle, hiçbir şey yazma
+tfg verify      bir dizini bir manifeste göre denetle
+tfg cleanup     bir manifestin listelediği dosyaları sil
+tfg recipe fmt  bir tarifi oturmuş biçiminde yazdır
+tfg preset      adlandırılmış bir test sorusundan dosya seti oluştur
+tfg formats     bu sürümün desteklediği biçimleri listele
+tfg damage      bu sürümün bir dosyayı kasıtlı bozma yollarını listele
+tfg tool        elinizdeki dosyalar için küçük araçlar
+tfg version     araç sürümünü yazdır
+tfg license     lisansı ve üretilen dosyalar için anlamını yazdır
+
+ +
+

Tam boyutta tek bir dosyayı nasıl üretirim?

+

+ Biçimi, boyutu ve nereye gideceğini söyleyin. Boyutlar 1024'lerle sayılır, yani 2mb + 2097152 bayttır. Düz bir bayt sayısı da olur, yani --size 10485761 tam o kadarını + ister. +

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

generate için işe yarar bayraklar:

+
+ + + + + + + + + + + + + + + + + +
BayrakNe yapar
--format <id>dosyaların biçimi, örneğin txt
--size <size>her dosyanın tam boyutu, 10mb gibi veya düz bir bayt sayısı
--size-range <a-b>bir aralıktan dosya başına çekilen boyut, 1kb-8kb gibi. Çekiliş seed'den gelir
--boundary <size>bir sınırın çevresinde üç dosya: bir bayt altı, sınırın kendisi, bir bayt üstü
--count <n>kaç dosya üretileceği. Varsayılan 1
--name <template>ad şablonu, örneğin invoice_{index:04}.txt
--out <dir>yazılacak dizin
--seed <n>çalıştırmanın seed'i. Aynı seed aynı baytları verir
--set <k>=<v>bir biçim ayarı, tekrarlanabilir
--damage <name>dosyaları kasıtlı bozar, tekrarlanabilir ve sırayla uygulanır. Liste için tfg damage çalıştırın
--expected <outcome>accept, reject, sanitize veya unspecified
--dry-runsay ve göster, hiçbir şey yazma
--jsonmanifesti standart çıktıya yaz
+
+
+ +
+

Kasıtlı bozuk bir dosyayı nasıl yaparım?

+

+ Bu aracın yazdığı diğer her dosya yapısı gereği doğrudur ve bu, bir yükleme doğrulayıcısının sorduğu + üç sorudan ikisini yanıtlar. --damage üçüncüsünü yanıtlar - dosya hiç açılıyor mu. + Dosya normal üretilir, sonra bozulur, böylece hâlâ istediğiniz boyuttadır. +

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

+ Ayarlar iki noktadan sonra gelir. Bayrak tekrarlanır ve yazdığınız sıra uygulanma sırasıdır. + tfg damage bu sürümün neler yapabildiğini ve her birinin ne aldığını listeler. +

+

Bir tarifte anahtar, adlardan veya ayarlardan oluşan bir listedir:

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

+ Hasarlı bir dosya manifestte expected: reject alır, hasar yanında kaydedilir. İki şey + bir şey yazılmadan önce reddedilir, çünkü her biri aksi hâlde diske manifestin yanlış tarif + ettiği bir dosya koyardı: +

+
    +
  • hasarın gerektirdiğinden küçük bir dosya, çünkü değişmeden çıkardı
  • +
  • + bir hasarın yanında expected: accept, çünkü hiçbir şey bunu karşılayamaz. Test edilen + sistemin dosyayı onarması amaçlanıyorsa sanitize, sorduğunuz soru buysa + unspecified yazın +
  • +
+

+ Üçüncüsü önceden bilinemez. Bir hasar çalışıp hiçbir baytı oynatmazsa o dosya yazılmak yerine atılır + - çalıştırma sürer, hangi dosya olduğunu söyler ve kısmi çıkış koduyla biter. +

+

+ Adım adım, bildirimi okuyan bir testle: test için bozuk dosya + nasıl yapılır. +

+
+ +
+

Bir tarif nasıl görünür?

+

+ Tarif, tüm bir çalıştırmayı anlatan bir YAML dosyasıdır. Testlerinizin yanına commit edin, + fixture'lar deponuzda ikili dosya olmaktan çıkar - herkes onları birkaç yüz karakterlik bir + dosyadan bayt bayt yeniden kurabilir. +

+
# 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
+

+ Her target, size, size-range, boundary veya + contains anahtarlarından tam birine ihtiyaç duyar. İkisi hatadır, hiçbiri de öyle. + Geçersiz bir tarif hiç dosya yazmaz ve yalnızca ilkini değil tüm sorunları bir + seferde bildirir, her biri ilgili ayarı adlandırır. +

+
+ +
+

Sistemimin bir dosyayla ne yapması gerektiğini nasıl bildiririm?

+

Sonuç yeterliyse kısa biçim, neden önemliyse uzun biçim:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Sonuçlar accept, reject, sanitize ve + unspecified. Nedenler, bir rapor onlara göre gruplayabilsin diye kapalı bir + listedir: 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 ve + size_zero. +

+

+ Bir neden söz konusu kuralı adlandırır, hükmü değil. Bu yüzden aynı neden iki + sonucun altında da durabilir - sınırın bir bayt altındaki dosya accept olur ve söz + konusu kural yine size_limit kalır. +

+
+ +
+

Manifestte ne var?

+

+ Her çalıştırmanın sonunda, kesilen çalıştırma dahil, dosyaların yanına yazılır. Dosya başına bir + girdi: +

+
{
+  "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"
+      }
+    }
+  ]
+}
+

+ Çalıştırma bir tariften geldiyse bir recipe_hash, bir hazır ayardan geldiyse + overrides ile birlikte preset eklenir, böylece bir manifest her zaman + onu üreten şeye kadar izlenebilir. +

+

+ Her girdi ayrıca dosyayı üreten tarifteki hedefin kimliği olan target_id taşır ve + summary.by_target her hedefin kaç dosyaya vardığını sayar. Birkaç hedefli bir tarif + böylece dosya adlarını okumadan hedef hedef denetlenebilir. +

+
+ +
+

Hazır ayar nedir?

+

+ Yaygın bir test sorusunu yanıtlayan hazır bir dosya seti, böylece seti kendiniz tasarlamanız + gerekmez. Hazır ayarlar altta sıradan tariflerdir ve eject tarifi yazdırır, oradan + düzenleyebilirsiniz. Her hazır ayarın genelde ne bulduğunu, sette ne olduğunu ve kabul ettiği + her ayarı anlatan kendi sayfası vardır. +

+
    +
  • +

    Boş ve asgari

    +

    Biçimin izin verdiği kadar küçük, geçerli bir dosya geçer mi?

    +

    empty-and-minimal

    +
  • +
  • +

    Dosya adı işleme

    +

    Sistemim beklemediği bir dosya adını saklayıp gösterecek ve geri verecek mi?

    +

    filename-handling

    +
  • +
  • +

    Boyut sınırları

    +

    Bir boyut sınırı tam bildirildiği yerde uygulanıyor mu?

    +

    size-boundaries

    +
  • +
  • +

    Tablo içe aktarma

    +

    Tablo içe aktarmam gerçek araçların dışa aktardıklarına dayanıyor mu?

    +

    tabular-import

    +
  • +
  • +

    Metin kodlaması

    +

    Okuyucum bir dosyanın hangi kodlamada olduğunu biliyor mu, yoksa tahmin mi ediyor?

    +

    text-encoding

    +
  • +
  • +

    Yükleme doğrulama

    +

    Yükleme formum alması gerekeni alıp geri kalanı reddediyor mu?

    +

    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, seti kurmadan önce neye mal olacağını söyler ve bir sayının sizin sınırınız değil + bizim geçici değerimiz olduğunu açıkça belirtir. +

+
+ +
+

Çıkış kodları ne anlama gelir?

+

+ Her sonun kendi kodu vardır, makine tarafından okunabilir çıktı standart çıktıya gider ve başarısız + bir çalıştırma orada hiçbir şey yazdırmaz. Tablo dondurulmuş bir sözleşmedir - bir kodun + anlamını değiştirmek büyük sürüm artışı gerektirir. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KodAnlamı
0Her şey çalıştı.
1Araç içinde beklenmeyen bir hata.
2Yanlış komut veya bayrak.
3Tarif geçerli değil.
4Biçim istenen şeyi yapamıyor.
5Bir okuma veya yazma başarısız oldu.
6Yeterli disk alanı yok.
7verify bir uyuşmazlık buldu.
8Çalıştırma bitti ama her şey üretilmedi.
130Ctrl+C ile kesildi.
143Bir sinyalle durduruldu, CI zaman aşımı böyle görünür.
+
+
- 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 ile durdurulan bir çalıştırma yine bir manifest bırakır ve asla yarım yazılmış bir dosya + bırakmaz, böylece iptal edilen bir işi bir sonraki temizleyebilir. +

+

+ GitHub Actions ve GitLab CI için hazır iş akışları: CI + hattında test dosyaları nasıl üretilir. +

+
+ +
+

Masaüstü penceresi var mı?

+

+ Evet, betiklenmeyen test için üzerine bir pencere konmuş aynı motor. Kırpılmış bir sürüm değildir: + bir test iki arayüzü yetenek yetenek karşılaştırır ve yalnızca birinin yapabildiği her şey + sessizce ayrışmak yerine bildirilip gerekçelendirilmelidir. +

+

+ Ekranlar tek bir grup, hazır ayarlar, aynı anda birkaç grup ve hakkında. Bir çalıştırmanın neye mal + olacağını bir şey yazmadan önce gösterir, çalışırken ilerlemeyi bildirir ve yarım yazılmış dosya + bırakmadan yarıda iptal edilebilir. Henüz bir tarif dosyası açmaz - tarifler şimdilik komut + satırının işidir ve pencere gruplarını formda kurar. +

+
+ +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/empty-and-minimal/index.html b/web/public/tr/hazir-ayarlar/empty-and-minimal/index.html new file mode 100644 index 00000000..3cde13da --- /dev/null +++ b/web/public/tr/hazir-ayarlar/empty-and-minimal/index.html @@ -0,0 +1,268 @@ + + + + + + +Her biçimde en küçük geçerli ve boş test dosyaları + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Boş ve asgari

+

Biçimin izin verdiği kadar küçük, geçerli bir dosya geçer mi?

+

+ empty-and-minimal hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • kontrol baytları okumak yerine saydığı için çok küçük diye reddedilen geçerli bir dosya
  • +
  • bildirilmek yerine okuyucuyu çökerten boş bir dosya
  • +
  • küçük resme giderken sıfıra bölen bir piksel genişliğinde görüntü
  • +
  • sıfır baytı başarısız yükleme sayıp durmadan yeniden deneyen depolama
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show empty-and-minimal çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya28
Tarifindeki hedefler28
Toplam boyut32 667 B
Biçimleravif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.26
unspecifiedSisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız.2
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--formatsvirgülle ayrılmış biçim kimlikleri veya allallSetin hangi biçimlerden oluştuğu. Bu sürümdeki tüm biçimler için all bırakın veya sisteminizin kabul ettiklerini yazın.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/filename-handling/index.html b/web/public/tr/hazir-ayarlar/filename-handling/index.html new file mode 100644 index 00000000..40ab8447 --- /dev/null +++ b/web/public/tr/hazir-ayarlar/filename-handling/index.html @@ -0,0 +1,267 @@ + + + + + + +Test için sorunlu dosya adları - Unicode ve uzunluk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Dosya adı işleme

+

Sistemim beklemediği bir dosya adını saklayıp gösterecek ve geri verecek mi?

+

+ filename-handling hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • ekranda, bir günlükte veya bir listede başka bir ad gibi görünen bir ad
  • +
  • yükleme ile depolama arasında kesilen, kırpılan veya yeniden yazılan bir ad
  • +
  • depolama bayt sayarken karakterle sayılan bir uzunluk sınırı
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show filename-handling çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya50
Tarifindeki hedefler50
Toplam boyut51 200 B
Biçimlertxt
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.4
unspecifiedSisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız.46
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--formatbiçimler sayfasındaki bir biçim kimliğitxtSetteki her dosyanın biçimi. Aracın kendi bayrağıdır ve hazır ayar yalnızca ona bir varsayılan verir.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/index.html b/web/public/tr/hazir-ayarlar/index.html new file mode 100644 index 00000000..d1a2d015 --- /dev/null +++ b/web/public/tr/hazir-ayarlar/index.html @@ -0,0 +1,245 @@ + + + + + + +Test dosyası hazır ayarları - QA için hazır setler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Test dosyası hazır ayarları, her test sorusu için bir set

+

+ Hazır ayar, tek bir soru etrafında tasarlanmış, sisteminizin her dosyaya nasıl tepki vermesi + gerektiğini söyleyen bir manifestle gelen bütün bir test dosyası setidir. Soruyu siz seçersiniz, + aracın seti kurar. Her hazır ayarın genelde ne bulduğunu, sette ne olduğunu ve kabul ettiği her + ayarı anlatan kendi sayfası vardır. +

+ + + +
+

Hazır ayar bir tariften nasıl farklıdır?

+

+ Altta, hiç farklı değildir. Hazır ayar, aracın sizin için birkaç ayardan yazdığı bir tariftir. + tfg preset eject o tarifi yazdırır, böylece testlerinizin yanında tutup + düzenleyebilirsiniz ve kendi tarifiniz tek satırla bir hazır ayarın üzerine kurulabilir: + extends: preset: ve ardından kimliği. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Varsayılanlara güvenebilir miyim?

+

+ Dosyalar için evet. Yükleme formunun sınırı gibi yalnızca sisteminizin bildiği bir sayı için + varsayılan bizim geçici değerimizdir ve araç birini kullandığı her seferde bunu söyler. Her + hazır ayarın sayfası bu ayarları işaretler ve tfg preset show bir şey yazılmadan + önce söyler. +

+
+ +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/size-boundaries/index.html b/web/public/tr/hazir-ayarlar/size-boundaries/index.html new file mode 100644 index 00000000..16e49024 --- /dev/null +++ b/web/public/tr/hazir-ayarlar/size-boundaries/index.html @@ -0,0 +1,281 @@ + + + + + + +Yükleme boyut sınırını test etme - tam sınırdaki dosyalar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Boyut sınırları

+

Bir boyut sınırı tam bildirildiği yerde uygulanıyor mu?

+

+ size-boundaries hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • sınırda bir eksik veya fazla hataları
  • +
  • MB ile MiB'in karıştırılması, yani yüzde 4,8, geçmemesi gereken bir dosyayı geçirmeye yeter
  • +
  • tarayıcıda uygulanan ama sunucuda uygulanmayan bir sınır
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show size-boundaries çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya7
Tarifindeki hedefler7
Toplam boyut73 400 320 B
Biçimlerpdf
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.4
rejectSisteminiz dosyayı reddetmeli.3
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--limit2mb gibi bir boyut10mbSisteminizin bildirdiği boyut sınırı. Geri kalan her şey buradan ölçülür. Bu varsayılan sizin sisteminizin değeri değil, bizim geçici değerimizdir. Kendinizinkini verin.
--spreadvirgülle ayrılmış boyutlar1B,1kb,1mbSınırın iki yanında ne kadar uzağa gidileceği, boyutlar listesi olarak.
--formatbiçimler sayfasındaki bir biçim kimliğipdfSetteki her dosyanın biçimi. Aracın kendi bayrağıdır ve hazır ayar yalnızca ona bir varsayılan verir.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

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

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/tabular-import/index.html b/web/public/tr/hazir-ayarlar/tabular-import/index.html new file mode 100644 index 00000000..0ea499c7 --- /dev/null +++ b/web/public/tr/hazir-ayarlar/tabular-import/index.html @@ -0,0 +1,275 @@ + + + + + + +CSV ve Excel içe aktarma test dosyaları - ayırıcılar, başlıklar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Tablo içe aktarma

+

Tablo içe aktarmam gerçek araçların dışa aktardıklarına dayanıyor mu?

+

+ tabular-import hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • ayırıcı aranmak yerine varsayıldığı için tek sütun olarak okunan noktalı virgüllü dosya
  • +
  • her satırdan sonra boş bir satırla satırlara bölünen CRLF dosyası
  • +
  • ilk veri satırı sütun adı diye yutulan başlıksız bir tablo
  • +
  • gösterebildiği sütunları tutup geri kalanını tek söz etmeden atan bir içe aktarma
  • +
  • JSON kayıtlarını satır satır alıp ilk girintili belgede duran bir okuyucu
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show tabular-import çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya13
Tarifindeki hedefler13
Toplam boyut3 080 060 B
Biçimlercsv, json, xlsx
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.8
unspecifiedSisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız.5
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--rows1 - 200000 satır1000Elektronik tablonun kaç satır içerdiği. O kadar satırın paketlendiği tam boyutta yazılır, bu yüzden yukarıdaki bütçe bu değerle kayar.
--columns1 - 32768 sütun10Elektronik tablonun her satırında kaç sütun olduğu. Satır çarpı sütunun bir tavanı vardır ve aşılması bir şey yazılmadan önce reddedilir.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/text-encoding/index.html b/web/public/tr/hazir-ayarlar/text-encoding/index.html new file mode 100644 index 00000000..d510a29f --- /dev/null +++ b/web/public/tr/hazir-ayarlar/text-encoding/index.html @@ -0,0 +1,268 @@ + + + + + + +Metin kodlaması test dosyaları - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Metin kodlaması

+

Okuyucum bir dosyanın hangi kodlamada olduğunu biliyor mu, yoksa tahmin mi ediyor?

+

+ text-encoding hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • UTF-8 varsayıp bir UTF-16 dosyasını üç karakterde bir karakter olarak veya kutu sıraları olarak gösteren okuyucu
  • +
  • içerik olarak okunan bir bayt sırası işareti, böylece bir içe aktarmanın ilk alanı üç yabancı karakterle başlar
  • +
  • kodlamayı ilk baytlardan tahmin edip daha uzun bir dosyada farklı tahmin eden bir içe aktarıcı
  • +
  • her satırdan sonra boş bir satırla satırlara bölünen CRLF dosyası veya son alanda kalan bir satır başı karakteri
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show text-encoding çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya20
Tarifindeki hedefler20
Toplam boyut81 920 B
Biçimlercsv, log, md, txt, xml
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.10
unspecifiedSisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız.10
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--sample2mb gibi bir boyut4kbSetteki her dosyanın büyüklüğü. UTF-16 her karakter için iki bayt saklar, bu yüzden tek sayı reddedilir.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/tr/hazir-ayarlar/upload-validation/index.html b/web/public/tr/hazir-ayarlar/upload-validation/index.html new file mode 100644 index 00000000..ef8b6d4d --- /dev/null +++ b/web/public/tr/hazir-ayarlar/upload-validation/index.html @@ -0,0 +1,297 @@ + + + + + + +Yükleme doğrulama test dosyaları - tür, boyut ve ad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Hazır ayarlar

+

Yükleme doğrulama

+

Yükleme formum alması gerekeni alıp geri kalanı reddediyor mu?

+

+ upload-validation hazır ayarı, bu soru için tek komutla gerçek test dosyalarından oluşan bütün + bir set ve yanında sisteminizin her dosyaya nasıl tepki vermesi gerektiğini söyleyen bir + manifest.json kurar. Aşağıdaki her şey programdan, bu sürümün varsayılanlarıyla + okunur. +

+ + +
+

Genelde ne bulur?

+
    +
  • tarayıcıda uygulanan ama sunucuda uygulanmayan bir sınır
  • +
  • resim veya düz metin sanılan bir SVG ya da HTML dosyası, yani bir betiği formdan geçirmenin yolu
  • +
  • uzantısına bakılıp hiç açılmayan bir dosya, böylece .jpg adlı bir PDF geçer
  • +
  • ne kadar büyük olduğuna bakmadan önce tüm gövdeyi belleğe okuyan bir form
  • +
  • photo.jpg kabul edilirken reddedilen PHOTO.JPG adlı bir yükleme veya tersi
  • +
  • boşluk, parantez veya ASCII dışı karakter içeren bir adın diske değişmeden yazılması
  • +
+
+ + +
+

Sette ne var?

+

Varsayılanlarda, tfg preset show upload-validation çıktısının bildirdiği gibi:

+
+ + + + + + + +
Dosya71
Tarifindeki hedefler22
Toplam boyut120 639 488 B
Biçimlerhtml, jpg, pdf, png, svg, txt
+
+

Ve o setin manifestinin sisteminizden beklediği:

+
+ + + + + + + + + +
BeklenenAnlamıDosya
acceptSisteminiz dosyayı kabul etmeli.56
rejectSisteminiz dosyayı reddetmeli.10
unspecifiedSisteminizin kurallarına bağlı. Siz karar verirsiniz, sonra olanın amaçladığınız şey olduğunu doğrularsınız.5
+
+
+ +
+

Neyi değiştirebilirsiniz?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AyarAldığıVarsayılanNe yapar
--limit2mb gibi bir boyut10mbYükleme formunuzun bildirdiği boyut sınırı. Bu set her iki yanda birer adım atar - her uzaklıktaki dosya için size-boundaries hazır ayarını çalıştırın. Bu varsayılan sizin sisteminizin değeri değil, bizim geçici değerimizdir. Kendinizinkini verin.
--allowvirgülle ayrılmış biçim kimliklerijpg,png,pdfFormunuzun hangi türleri kabul etmesi gerektiği. Her biri o türden gerçek bir dosya olur ve tüm setin pozitif kontrolünü oluşturur.
--denyvirgülle ayrılmış uzantılarsvg,html,exe,shFormunuzun hangi uzantıları reddetmesi gerektiği. Bu sürümde biçimi olmayan bir uzantı yine de o adla, düz metin içeren bir dosya alır.
--far-over10x, 2x, off2xTek büyük dosyanın sınırın ne kadar ötesine geçtiği. Sınırın birkaç katını yazmak diske değmiyorsa kapatın.
--bulk0 - 10000 dosya50Toplu yüklemenin kaç dosya içerdiği. Sıfır, bu grubu setten tamamen çıkarır.
+
+
+ +
+

Nasıl çalıştırılır?

+

Setin neye mal olacağına bakın, kurun veya düzenlemek için tarifini alın:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Ya da testlerinizin yanında kendi tarifinizde onun üzerine kurun:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/tr/index.html b/web/public/tr/index.html new file mode 100644 index 00000000..f370f2a7 --- /dev/null +++ b/web/public/tr/index.html @@ -0,0 +1,453 @@ + + + + + + +QA için test dosyası oluşturucu - tam boyut, 26 gerçek biçim + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Tam boyutta gerçek test dosyaları üretin

+

+ PDF, PNG, DOCX, ZIP - toplam 26 biçim ve her biri ait olduğu + programda açılan, tam istediğiniz boyutta gerçek bir dosya. Her çalıştırma + ayrıca uygulamanızın her dosyayla ne yapması gerektiğini de yazar. Komut satırı ve masaüstü + penceresi, ücretsiz ve açık kaynak, tamamen makinenizde çalışır. +

+ + +

Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.

+
+ +
+ Bir grup test dosyası yazmaya hazırlanmış Testing Files Generator masaüstü penceresi +
Bir dosya grubu yazmaya hazırlanmış masaüstü penceresi. Aynı motor komut satırının arkasında çalışır.
+
+
+ + + +
+

Sorun

+

Bir test dosyası yapmak kolay. Doğru bini yapmak sıkıcı kısım

+

İnsanlardan dosya kabul eden bir yazılımı test ediyorsunuz. Er ya da geç şunlara ihtiyacınız olur:

+
    +
  • yükleme sınırının gerçek olup olmadığını anlamak için tam 10 MB'lık bir PDF
  • +
  • bir eksik veya fazla hatalarını yakalamak için o sınırın iki yanındaki üç dosya
  • +
  • klasör büyükken gece işinin ne yaptığını görmek için 10.000 günlük dosyası
  • +
  • doğru uzantılı boş bir kabuk değil, gerçekten 200 belge içeren bir ZIP
  • +
  • deponuzda 4 GB'lık bir dosya tutmadan 4 GB'lık bir dosya
  • +
  • dizüstü bilgisayarınızda ve derleme sunucusunda aynı fixture'lar, bayt bayt
  • +
+

+ Bunun yerini alan şey bu. QA mühendisleri, test otomasyonu ve kodunun arkasında bir yükleme formu, + içe aktarma rutini, ayrıştırıcı veya depolama kotası olan herkes için yapıldı. +

+
+ +
+

Onu farklı kılan

+

Diğer üreticiler baytlarda durur. Bu, testinizin gerçekte ne sorduğunu yanıtlar

+

+ Bir dosya klasörü, her birinin neyi kanıtlaması gerektiğine yine sizin karar vermenize bırakır. + Burada her çalıştırma dosyaların yanına bir manifest.json yazar - üretilen her + şeyin düz bir listesi ve her girdi için bir bildirilmiş beklenti. +

+

Yükleme endpoint'inizin 1 MB'a izin verdiğini varsayalım. O çizgideki üç dosyayı isteyin:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
DosyaBaytSisteminizÇünkü
1mb_under_1b.pdf1048575kabul etmelisınırın içinde
1mb_at_limit.pdf1048576kabul etmelisınırın kendisine izin verilir
1mb_over_1b.pdf1048577reddetmelisize_limit
+
+ +

Üç dosya, üç farklı yanıt, makine tarafından okunabilir biçimde. Testiniz, sizin elle assertion yazmanız yerine manifesti okur:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Yanıt kendi politikanıza bağlıysa manifest bunu söyler

+

+ Bir beklenti uydurmak yerine unspecified kaydeder. Tahmin yürüten bir üretici yanlış + hatalar üretir ve sürekli yalancı alarm veren bir test takımı kapatılır. +

+
+
+ +
+

Hazır ayarlar

+

Soruyu seçin, setin tamamını alın

+

+ Hazır ayar, hangi dosyanın neyi kanıtladığını sizin çözmeniz gerekmesin diye tek bir test sorusu + etrafında tasarlanmış bir test dosyası setidir. Her birinin, genelde ne bulduğunu, sette ne + olduğunu ve kabul ettiği her ayarı anlatan bir sayfası vardır. +

+
    +
  • +

    Boş ve asgari

    +

    Biçimin izin verdiği kadar küçük, geçerli bir dosya geçer mi?

    +

    empty-and-minimal

    +
  • +
  • +

    Dosya adı işleme

    +

    Sistemim beklemediği bir dosya adını saklayıp gösterecek ve geri verecek mi?

    +

    filename-handling

    +
  • +
  • +

    Boyut sınırları

    +

    Bir boyut sınırı tam bildirildiği yerde uygulanıyor mu?

    +

    size-boundaries

    +
  • +
  • +

    Tablo içe aktarma

    +

    Tablo içe aktarmam gerçek araçların dışa aktardıklarına dayanıyor mu?

    +

    tabular-import

    +
  • +
  • +

    Metin kodlaması

    +

    Okuyucum bir dosyanın hangi kodlamada olduğunu biliyor mu, yoksa tahmin mi ediyor?

    +

    text-encoding

    +
  • +
  • +

    Yükleme doğrulama

    +

    Yükleme formum alması gerekeni alıp geri kalanı reddediyor mu?

    +

    upload-validation

    +
  • +
+

Tüm hazır ayarlar ve tariflerle ilişkileri

+
+ +
+

Hızlı başlangıç

+

Çalıştığını görmek için üç komut

+
    +
  1. +

    Bir dosya üretin

    +

    Bir PNG, tam iki megabayt:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Çok sayıda dosya üretin

    +

    + Her biri bir ile sekiz kilobayt arasında on bin günlük dosyası, boyutlar seed'den çekilir ki yarın + aynı seti versin. Her çalıştırmaya kendi dizinini verin - manifest bir + çalıştırmanın ne yazdığının tek kaydıdır, bu yüzden araç üzerine ikincisini yazmayı + reddeder: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Denetleyin, sonra silin

    +

    verify hiçbir şeyin kımıldamadığını söyler. cleanup yazılanı tam olarak ve başka hiçbir şeyi silmez:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Boyutlar, dosya yöneticinizin yaptığı gibi 1024'lerle sayılır, yani 2mb 2097152 bayt + demektir. Düz bir bayt sayısı da olur. Dokümantasyon tarifleri, + manifesti ve çıkış kodlarını kapsar. +

+
+ +
+

Neler elde edersiniz

+

Gözetimsiz çalışan bir test takımı için yapıldı

+
    +
  • +

    Tam boyut, bayta kadar

    +

    10485761 bayt isteyin ve tam olarak onu alın. Bir biçimin ulaşamayacağı boyut nedeni olan bir hatadır, asla yanlış boyutta bir dosya değil.

    +
  • +
  • +

    26 gerçek biçim

    +

    Uzantılı dolgu sıfırları değil. Üretilmiş bir PNG resim görüntüleyicide, bir DOCX Word'de açılır, bir ZIP çıkarılır. Her biri yayımlanmadan önce bağımsız okuyucularla doğrulanır.

    +
  • +
  • +

    Test oracle'ı olan bir manifest

    +

    Yol, boyut, SHA-256, biçim, seed, araç sürümü - ve sisteminizin dosyayla ne yapması gerektiği.

    +
  • +
  • +

    Tekrarlanabilir

    +

    Aynı tarif ve aynı seed, aynı baytlar, her makinede. Büyük ikili fixture'lar yerine küçük bir YAML tarifini commit edin.

    +
  • +
  • +

    İki arayüz, tek motor

    +

    CI için yapılmış bir komut satırı ve keşif amaçlı testler için bir masaüstü penceresi. Hiçbiri diğerinin kırpılmış sürümü değildir ve bir test ikisini yetenek yetenek karşılaştırır.

    +
  • +
  • +

    Tamamen çevrimdışı

    +

    Hesap yok, bulut yok, telemetri yok, güncelleme denetimi yok. Komut satırı ikilisinin içine hiç ağ yığını derlenmemiştir.

    +
  • +
+
+ +
+

İndirme

+

Sisteminiz için derlemeyi seçin

+

+ Arşivi açın ve çalıştırın. tfg komut satırı, tfg-gui masaüstü + penceresidir. Yükleyici yok ve makinenize eklenecek hiçbir şey yok. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SistemKomut satırıMasaüstü penceresi
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Neler imzalı, neler değil

+

+ Windows ve macOS indirmeleri imzalıdır, bu yüzden bilinmeyen geliştirici uyarısı olmadan başlar. + Linux olanlar değildir, çünkü masaüstü Linux'ta onları imzalayacak bir karşılık yoktur. Her + arşiv sürüm sayfasındaki verify-SHA256SUMS.txt içinde listelenir, böylece + indirdiğinizi doğrulayabilirsiniz. +

+
+ +

Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.

+
+ + +
+ + + + diff --git a/web/public/tr/kullanim-senaryolari/index.html b/web/public/tr/kullanim-senaryolari/index.html new file mode 100644 index 00000000..9db28559 --- /dev/null +++ b/web/public/tr/kullanim-senaryolari/index.html @@ -0,0 +1,317 @@ + + + + + + +Kullanım senaryoları - yükleme sınırları, CI fixture'ları, testler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

İnsanlar bunu ne için kullanıyor

+

+ İnsanlardan dosya kabul eden hemen her projede çıkan beş iş ve her birini yapan komut. Aşağıdaki her + örnek yazıldığı gibi çalışır. +

+ +
+

Yükleme sınırları

+

Bir dosya boyutu sınırının söylediği yerde uygulanıp uygulanmadığını test etmek

+

+ Bir sınır bir değil üç test durumudur: hemen altı, tam üstü ve hemen üzeri. Bunları elle yapmak bayt + sayıları hesaplamak ve bir kayma yapmadığınızı ummak demektir. Bunun yerine seti isteyin: +

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

+ 1048575, 1048576 ve 1048577 baytlık üç gerçek PDF ve ilk ikisinin kabul edilmesi, üçüncünün + size_limit nedeniyle reddedilmesi gerektiğini söyleyen bir manifest alırsınız. + Testiniz üç assertion'ı elle yazmanız yerine beklentiyi okur - sınır değiştiğinde bir sayıyı + değiştirip yeniden çalıştırırsınız. +

+

+ Satır içi tek bir sınır seti istediğinizde aynısı hazır ayar olmadan da çalışır: +

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

Sürekli entegrasyon

+

Fixture'ları kaybetmeden depodan uzak tutmak

+

+ Büyük ikili fixture'lar bir depoyu klonlamada yavaş, incelemede zahmetli yapar ve biri + değiştirildiğinde neyin değiştiğini kimse söyleyemez. Tarif, özdeş dosyaları yeniden kuran + birkaç yüz karakterlik YAML'dir - bayt bayt, her makinede - çünkü her dosya + çalıştırmanın seed'inden türetilir. +

+
- 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
+

+ Her sonun kendi çıkış kodu vardır, bu yüzden bir hat kötü bir tarifi dolu bir diskten ve bir + doğrulama uyuşmazlığından ayırt edebilir. Başarısız bir çalıştırma standart çıktıya hiçbir şey + yazdırmaz, bu da bir günlük ayrıştırıcısının hatayı veri sanmasını önler. +

+
+ +
+

Ölçek

+

Klasör büyükken ne olduğunu öğrenmek

+

+ İçe aktarma rutinleri, gece işleri ve dizin listeleri on bin dosyada ona göre farklı davranır. Bir + aralıktan çekilen boyutlar seti on bin özdeş dosya yerine gerçek trafiğe benzetir ve çekiliş + seed'den gelir, yani set yarın da aynıdır. +

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

+ Toplam gigabayt cinsinden ölçülüyorsa önem kazanan şeyi, bir çalıştırmanın bir şey yazmadan önce + neye mal olacağını denetleyin: +

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

+ Diskteki boş alandan büyük bir çalıştırma, diski doldurup yarıda başarısız olmak yerine ilk bayt + yazılmadan önce reddedilir. +

+
+ +
+

Arşivler

+

Bir açıcıyı gerçekten dosya içeren bir arşivle test etmek

+

+ Doğru uzantılı boş bir arşiv, onu açıp içindekini dolaşan kod hakkında hiçbir şey kanıtlamaz. + İçeriği bildirin, arşiv onu gerçekten içersin: +

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

+ İç içe geçme derinliği, girdi sayıları ve içindekilerin boyutu, bir içe aktarma rutininin görüş + sahibi olduğu şeylerdir ve bu görüşlerin ne olduğunu böyle öğrenirsiniz. +

+
+ +
+

Ayrıştırıcılar ve görüntüleyiciler

+

Kendi kodunuzun bir biçimi gerçek yazılım gibi okuduğunu denetlemek

+

+ Buradaki her biçim yayımlanmadan önce bağımsız bir okuyucuyla doğrulanır - bir PNG açılır ve + pikselleri karşılaştırılır, bir DOCX ayrı kitaplıklarca geri okunur, bir arşiv çıkarılır. Bu, + ayrıştırıcınızın reddettiği bir dosyanın üretici hakkında değil ayrıştırıcınız hakkında bir + bulgu olduğu anlamına gelir. +

+
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
+

+ Biçimler sayfası her birinin kabul ettiği ayarları ve her birinin + olabileceği en küçük dosyayı listeler. +

+
+ +
+

Rehberler

+

Bunlardan ikisi daha ayrıntılı

+
    +
  • + Bozuk test dosyaları - kasıtlı bozulmuş, tam boyutta bir + dosya ve ona ne olması gerektiği bildirimde yazılı. +
  • +
  • + CI'da test dosyaları - bir GitHub Actions iş akışı, bir + GitLab işi ve derlemeyi başarısız kılan çıkış kodları. +
  • +
+
+ +
+

Kimler için

+

+ QA mühendisleri, test otomasyonu ve kodunun arkasında bir yükleme formu, içe aktarma rutini, + ayrıştırıcı veya depolama kotası olan herkes. Hiç ağı olmayan bir makinede çalışır, bu da + tarayıcı tabanlı bir üreticinin seçenek olmadığı kapalı bir kurumsal ortamda önem taşır. +

+ +

Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.

+
+ +
+ + + + diff --git a/web/public/tr/sss/index.html b/web/public/tr/sss/index.html new file mode 100644 index 00000000..f750cf67 --- /dev/null +++ b/web/public/tr/sss/index.html @@ -0,0 +1,348 @@ + + + + + + +SSS - test dosyası üretimi hakkında sorular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Sık sorulan sorular

+

+ Lisans, gizlilik, tekrarlanabilirlik ve insanların bir üreticiyi derleme hattına koymadan önce + denetlediği şeyler. Sorunuz burada yoksa sorun takipçisi açık. +

+ +
+
+

dd, fsutil veya truncate'ten farkı nedir?

+
+

Onlar size doğru boyutta, içi bomboş bir dosya verir. Bu şekilde yapılmış photo.png adlı 2 MB'lık bir dosya PNG değildir, bu yüzden onu gerçekten ayrıştıran her şey yanlış nedenle reddeder ve testiniz de yanlış nedenle geçer. Bu araç tam 2 MB'lık gerçek bir PNG üretir, resim görüntüleyicide açılır ve sisteminizin onu nasıl ele alması gerektiğine dair bir bildirimle gelir.

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

Ücretsiz mi, ve işte kullanabilir miyim?

+
+

İkisi de evet. GPL-3.0 altında yayımlanır ve hiçbir şeye mal olmaz. Hesap, lisans anahtarı veya ücretli katman yoktur.

+
+
+
+

Üretilen dosyaları kapalı kaynaklı bir üründe kullanabilir miyim?

+
+

Evet. Lisans aracın kodunu kapsar, aracın ürettiğini değil. Üretilen dosyalar, tarifler ve manifestler türev eser değil çıktıdır, bu yüzden hiçbir yükümlülük olmadan commit edip dağıtabilirsiniz.

+
+
+
+

Üretilen dosyalar gerçek kişisel veri içeriyor mu?

+
+

Hayır. İçindeki her şey bir seed'den sentezlenir. Hiçbir veri kümesi okunmaz, hiçbir servise bağlanılmaz ve üçüncü taraf içeriği gömülmez. Üretilmiş bir e-posta adresini kullanılmamış değil kullanılamaz sayın, çünkü rastgele bir dize tesadüfen gerçek biriyle çakışabilir.

+
+
+
+

Başka bir makinede tam olarak aynı dosyaları alır mıyım?

+
+

Evet, aynı tarif ve aynı seed ile bayt bayt. Proje bunu her değişiklikte test eder ve bozmak büyük sürüm artışı gerektirir. Büyük ikili fixture'lar yerine küçük bir tarifi commit etmenizi sağlayan da budur.

+
+
+
+

İnternet bağlantısı gerekiyor mu?

+
+

Asla. Telemetri, güncelleme denetimi veya bulut istemcisi yoktur ve komut satırı ikilisinin içine hiç ağ yığını derlenmemiştir. Ağı olmayan bir makinede ve kapalı bir kurumsal ortamda çalışır.

+
+
+
+

Bir biçimin ulaşamayacağı bir boyut istersem ne olur?

+
+

Biçimi, olabilecek en küçük boyutu, bu alt sınırın nedenini ve bunun yerine ne yapılacağını söyleyen bir hata alırsınız ve hiçbir dosya yazılmaz. Araç bir boyutu asla sessizce yuvarlamaz. Her alt sınır biçimler sayfasında listelenir.

+
tfg formats png
+
+
+
+

Kasıtlı olarak bozuk bir dosya üretebilir miyim?

+
+

Evet. --damage zero-head ekleyin, dosya tam istediğiniz boyutta ve ilk baytları sıfırlarla ezilmiş olarak çıkar. Böylece bir okuyucu onu reddeder ve bildirim sisteminizin onu reddetmesi gerektiğini söyler. Ayrıntılar bozuk test dosyaları sayfasındadır.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Sırada hangi biçimler var?

+
+

7z, mp3 ve mp4. Bugün 26 biçim uçtan uca çalışıyor.

+
+
+
+

Hangi sistemlerde çalıştırabilirim?

+
+

Komut satırı Windows ve Linux'ta hem Intel hem ARM üzerinde, ayrıca Apple Silicon Mac'lerde çalışır. Masaüstü penceresi Intel üzerinde Windows, Intel üzerinde Linux ve Apple Silicon Mac'ler için sunulur. Intel Mac'ler desteklenmez ve onlar için hiçbir şey derlenmez.

+
+
+
+

Bir şey kurmam gerekiyor mu?

+
+

Hayır. Sisteminiz için arşivi indirin, açın ve ikiliyi çalıştırın. Yükleyici, eklenecek bir çalışma zamanı veya çözülecek bir bağımlılık yoktur. Go'nuz varsa tek bir go install komutu da işe yarar.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Binlerce dosya üzerindeki çalıştırma Windows'ta neden daha yavaş?

+
+

Çünkü Windows baktığı her yol için daha fazla bedel ister ve binlerce dosyayı dolaşan bir komut binlerce yola bakar. Her biri 1 kB'lık 3000 dosyalı bir makinede ölçüldü: verify Windows'ta yaklaşık 0,9 saniye, bir konteynerdeki Linux'ta yaklaşık 0,2 saniye sürer. Daha kısa bir çıktı yolu Windows rakamını küçültür, çünkü dosyaların üstündeki her klasör bakılanın parçasıdır.

+
+
+
+ + +
+

Hâlâ karar vermediniz mi?

+

+ Kullanım senaryoları sayfası aracın yapıldığı işleri + gösterir, biçimler sayfası her biçimi üretebildiği en küçük dosyayla + listeler. Depodaki README tam başvurudur. +

+ +

Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.

+
+ +
+ + + + diff --git a/web/public/tr/tam-boyutta-dosya-olusturma/index.html b/web/public/tr/tam-boyutta-dosya-olusturma/index.html new file mode 100644 index 00000000..65260be9 --- /dev/null +++ b/web/public/tr/tam-boyutta-dosya-olusturma/index.html @@ -0,0 +1,330 @@ + + + + + + +Belirli boyutta dosya oluşturma - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Tam boyutta dosya nasıl oluşturulur

+

+ Her sistemin bunun için bir komutu var ve üçü de aşağıda. Size tam doğru bayt sayısında bir dosya + verirler - ve birçok test için gereken tek şey budur. Bu sayfadaki her komut, + yayımlanmadan önce ait olduğu sistemde çalıştırıldı. +

+ +
+

Kısa yanıt

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Boyutlar bayt cinsindendir ve dosya + yöneticinizin saydığı gibi 10 MB, 10485760'tır. +

+
+ +
+

Windows

+

fsutil ve fazladan hiçbir şey gerektirmeyen bir PowerShell sürümü

+

+ fsutil Windows ile gelir. Boyutu bayt cinsinden alır, bu yüzden sayıyı + önce hesaplayın - 10 MB 10485760, 100 MB 104857600, 1 GB 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Windows 11'de ölçüldü: sıradan bir istemden çalışır, yükseltilmiş bir istem gerektirmez ve dosya tam + 10485760 bayt çıkar. +

+

PowerShell aynı şeyi başka bir programı çağırmadan yapabilir ve birimleri anlar:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell'de 10MB, Gezgin'in kullandığı aynı 1024 tabanlı sayımla 10485760 bayt + demektir, yani yukarıdaki iki komut aynı boyutu üretir. +

+
+ +
+

Linux

+

dd, truncate ve fallocate ve insanları yakalayan fark

+

dd herkesin bildiğidir. Baytları gerçekten yazar:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate anlıktır ve tuzak da budur. Alpine Linux'ta ölçüldü: dosya 10485760 bayt + bildirir ve sıfır blok kaplar - bir seyrek dosyadır. Onu + okuyan her şey on megabayt sıfır alır ama disk alanı hiç vermemiştir: +

+
truncate -s 10M test10mb.bin
+

+ Bu, yükleme sınırını sınamak için iyidir ve disk kotasını sınamak için yanıltıcıdır. Alan gerçek + olmalıysa başvurulacak olan fallocate'tir: +

+
fallocate -l 10M test10mb.bin
+

Ve içerik, bir arşivleyici onu yeniden sıkıştıramasın diye sıkıştırılamaz olmalıysa:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

seyrek olmayan mkfile ve zaten bildiğiniz iki komut

+

+ macOS mkfile ile gelir. macOS 26.6.2'de ölçüldü: 10485760 bayt ve 20480 blok, yani alan + söz verilmek yerine gerçekten ayrılır: +

+
mkfile 10m test10mb.bin
+

dd ve truncate da var ve Linux'taki gibi davranır:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Bunun işe yaramadığı yer

+

Doğru boyutta bir dosya doğru türde bir dosya değildir

+

+ Yukarıdakilerin hepsi size bir sıfır bloğu verir. Test edilen şey yalnızca boyuta bakıyorsa - + yükleme sınırı, kota, aktarım - bu yeterlidir. Bir şey dosyayı açtığı anda + yeterli olmaktan çıkar. +

+

+ Ölçüldü ve kendiniz yapmaya değer: fsutil ile 2 MB'lık bir dosya yapın, adını + photo.png koyun ve bir görüntü kitaplığına verin. Pillow cannot identify + image file yanıtını verir. PNG değil. Hiç de olmadı - yalnızca adı öyle diyordu. +

+

+ Bu, göründüğünden daha önemlidir, çünkü testin bundan sonra hangi yönde başarısız + olduğu belirleyicidir. Yükleme endpoint'iniz dosyayı reddeder, testiniz yeşile döner ve + boyut sınırının çalıştığı sonucuna varırsınız. Onu boyut yüzünden reddetmedi. Baytlar resim + olmadığı için reddetti ve sınamak istediğiniz kurala hiç ulaşılmadı. +

+
    +
  • bir ayrıştırıcı herhangi bir boyut kuralına bakılmadan önce onu reddeder
  • +
  • küçük resim adımı başarısız olur ve okuduğunuz hata küçük resimle ilgilidir
  • +
  • bir antivirüs veya içerik denetimi onu üçüncü bir nedenle reddeder
  • +
  • bir görüntüleyici hiçbir şey göstermez ve bunun hata olup olmadığını kimse söyleyemez
  • +
+
+ +
+

Öbür yol

+

O biçimden gerçek bir dosya, tam istediğiniz boyutta

+

+ Testing Files Generator'ın yaptığı budur. Dosya biçiminin gerçek bir örneğidir - ait olduğu + programda açılır - ve istediğiniz tam bayt sayısındadır, bayta kadar: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Bir biçimin ulaşamayacağı bir boyut isteyin, alt sınırı ve nedenini adlandıran bir hata alırsınız, + asla yanlış boyutta bir dosya değil. Biçimler sayfası her biçimi + üretebildiği en küçük dosyayla listeler. +

+

Ve bir sınır bir değil üç test durumudur, bu yüzden araç üçünü de kurar:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Bu size 10485759, 10485760 ve 10485761 bayt ile hangilerini sisteminizin kabul etmesi, hangilerini + reddetmesi gerektiğini söyleyen bir manifest verir. Kullanım + senaryoları sayfası bunu ve aracın yapıldığı dört işi daha anlatır. +

+ +

Ücretsiz ve açık kaynak, GPL-3.0. Kayıt gerekmez. Windows ve macOS indirmeleri imzalıdır ve uyarı vermeden başlar.

+
+ +
+

Peki hangisini kullanmalı?

+
    +
  • +

    Sistem komutunu kullanın

    +

    + Hiçbir şey dosyayı açmıyorsa. Önce boyuta bakan bir endpoint'te boyut sınırını sınamak, bir aktarım, + bir kota, disk dolu durumu. Tek satırdır ve zaten kuruludur. +

    +
  • +
  • +

    Gerçek bir üretici kullanın

    +

    + Bir şey dosyayı ayrıştırıyor, işliyor, içe aktarıyor veya çıkarıyorsa - ve yarın başka bir makinede + aynı fixture'lara bayt bayt ihtiyacınız varsa. +

    +
  • +
+

+ İkisi de bu sayfada çünkü ikisi de zamanın bir kısmında haklı. Kaçınılması gereken hata, ikincisinin + gerektiği yerde birincisini kullanmak ve yeşil testi kanıt saymaktır. +

+
+ +
+ + + + diff --git a/web/public/uk/corrupt-test-files/index.html b/web/public/uk/corrupt-test-files/index.html new file mode 100644 index 00000000..6f558cc9 --- /dev/null +++ b/web/public/uk/corrupt-test-files/index.html @@ -0,0 +1,382 @@ + + + + + + +Пошкоджені тестові файли - зламані файли точного розміру + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Сценарії

+

Як зробити пошкоджений файл для тестів

+

+ Валідатор, якому показували лише здорові файли, насправді не перевірений. Ось як отримати файл, + навмисно зіпсований, що виходить точно такого розміру, який ви просите, і несе + маніфест із вказівкою, що ваша система має з ним зробити. +

+ +
+

Коротка відповідь

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out записує PNG рівно в + 2097152 байти, перші байти якого нулі, а маніфест поруч фіксує, що ваша система має його + відхилити. +

+
+ +
+

Звичайний шлях

+

Чому файл, зіпсований вручну, - поганий тест

+

+ Зазвичай беруть шістнадцятковий редактор, скрипт, що перевертає кілька випадкових байтів, або + вкорочують файл через head чи truncate. Один раз це працює, а потім + коштує дорого: +

+
    +
  • + Щоразу по-різному. Випадковий байт при кожному запуску потрапляє в нове місце, тому + збій у вівторок у середу може не повторитися. +
  • +
  • + Змінюється розмір. Обрізаний файл менший за ліміт, під яким він мав залишатися, + тому перевірка розміру відповідає раніше за перевірку вмісту, і тест проходить із неправильної + причини. +
  • +
  • + Це часто лишається непоміченим. Простий текст читається і зі зміненим байтом + посередині, а поблажлива програма читання зображень просто малює його, тож файл, який мав бути + зіпсований, приймається. +
  • +
  • + Не сказано, що має статися. Файл - це лише байти, і тому, хто читатиме тест + пізніше, доведеться гадати, чи йшлося про прийняття, чи про відхилення. +
  • +
+
+ +
+

Що ви отримуєте

+

Пошкоджений файл лишається потрібного розміру

+

+ Файл створюється як зазвичай і псується потім, дорогою на диск. Він зберігає заданий розмір, а та + сама команда знову записує ті самі байти. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Налаштування пишуться після двокрапки. Параметр можна повторювати, а пошкодження застосовуються в + тому порядку, в якому ви їх записали. Це працює з кожним із 26 форматів. +

+
+ +
+

Що він уміє

+

Які бувають пошкодження?

+

+ Це список, який друкує програма, прочитаний із неї під час збирання цієї сторінки. tfg + damage друкує той самий список, а tfg damage <id> каже, що приймає + одне з них. +

+
+ + + + + + + + + + + + + + + + + +
ПошкодженняЩо воно робить із байтамиНайменший файлНалаштування
zero-headПерезаписує перші байти файлу нулями, не змінюючи його довжину. Більшість програм читання дивляться спочатку туди, тому це пошкодження помічає майже все.8bytes
+
+

+ zero-head записує нулі поверх початку файлу. Більшість програм читання дивляться + спочатку туди, на сигнатуру й заголовок, які кажуть, що це за файл, тому помічає майже будь-яка. + У простого тексту та журналів сигнатури немає, і їх теж відхиляють, бо послідовність нульових + байтів не є текстом. Менше ніж чотири байти - і в деяких форматів виходить пошкодження, на яке + не скаржиться жодна програма читання, тому налаштування починається з чотирьох. +

+
+ +
+

Що каже маніфест

+

Маніфест, який каже, що має статися

+

+ Кожен пошкоджений файл отримує запис про те, що ваша система має його відхилити, а поруч записано + пошкодження: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Два запити відхиляються, перш ніж щось буде записано, бо кожен залишив би на диску файл, який + маніфест описує хибно: +

+
    +
  • файл менший, ніж потрібно пошкодженню, який вийшов би недоторканим
  • +
  • + expected: accept поруч із пошкодженням, бо ніщо не могло б цього виконати. Напишіть + sanitize, якщо ваша система має полагодити файл, або unspecified, + якщо саме це ви й перевіряєте +
  • +
+
+ +
+

У рецепті

+

Здорові й зламані файли за один запуск

+

+ Покладіть обидва види в один рецепт, і маніфест несе очікування для кожного файлу, тож тесту не + потрібен список, який файл який: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

У тесті

+

Перетворюємо це на тест

+

+ Тест читає маніфест і перевіряє, що сталося те, що було заявлено. Список імен файлів йому не + потрібен: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Гарна відмова - це чиста відмова. Повідомлення, що каже, що було не так, - та відповідь, яка вам + потрібна. Помилка сервера, зависання або наполовину збережений файл - той дефект, заради якого + цей тест і існує. +

+
+ +
+

Далі

+

Куди йти звідси

+ +
+ +
+ + + + diff --git a/web/public/uk/create-file-exact-size/index.html b/web/public/uk/create-file-exact-size/index.html new file mode 100644 index 00000000..f3d188b1 --- /dev/null +++ b/web/public/uk/create-file-exact-size/index.html @@ -0,0 +1,332 @@ + + + + + + +Як створити файл точного розміру - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Як створити файл точного розміру

+

+ У кожній системі для цього є команда, і всі три наведено нижче. Вони дають файл із точною кількістю + байтів, а для багатьох тестів цього досить. Кожну команду на цій сторінці було виконано до + публікації у тій системі, до якої вона належить. +

+ +
+

Коротка відповідь

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Розміри вказуються в байтах, а 10 + МБ, пораховані так, як рахує ваш файловий менеджер, - це 10485760. +

+
+ +
+

Windows

+

fsutil і варіант на PowerShell, якому не потрібно нічого додаткового

+

+ fsutil входить до Windows. Він приймає розмір у байтах, тому спершу + порахуйте число: 10 МБ - це 10485760, 100 МБ - 104857600, 1 ГБ - 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Виміряно у Windows 11: працює зі звичайного командного рядка без підвищених прав, і файл виходить + рівно в 10485760 байт. +

+

PowerShell може зробити те саме, не викликаючи іншу програму, і розуміє одиниці:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB у PowerShell означає 10485760 байт, той самий рахунок за основою 1024, що його + використовує Провідник, тому дві команди вище дають той самий розмір. +

+
+ +
+

Linux

+

dd, truncate і fallocate, і різниця, що ловить людей

+

dd знають усі. Він справді записує байти:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate спрацьовує миттєво, і в цьому підступ. Виміряно в Alpine Linux: файл + повідомляє 10485760 байт і займає нуль блоків - це розріджений + файл. Усе, що його читає, отримує десять мегабайт нулів, але диск місця так і не + віддав: +

+
truncate -s 10M test10mb.bin
+

+ Для перевірки ліміту завантаження це нормально, а для перевірки дискової квоти вводить в оману. + fallocate - те, до чого варто вдатися, коли місце має бути справжнім: +

+
fallocate -l 10M test10mb.bin
+

А коли вміст має бути нестисливим, щоб архіватор не міг знову його стиснути:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, що не є розрідженим, і дві команди, які ви вже знаєте

+

+ У macOS є mkfile. Виміряно в macOS 26.6.2: 10485760 байт і 20480 блоків, тобто місце + справді виділено, а не обіцяно: +

+
mkfile 10m test10mb.bin
+

dd і truncate теж є й поводяться як у Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Де це перестає працювати

+

Файл правильного розміру - не файл правильного виду

+

+ Усе сказане вище дає блок нулів. Цього досить, коли тестоване дивиться лише на розмір: ліміт + завантаження, квота, передача. Цього перестає вистачати, щойно щось відкриває + файл. +

+

+ Виміряно, і варто перевірити самому: зробіть файл на 2 МБ командою fsutil, назвіть його + photo.png і передайте бібліотеці роботи із зображеннями. Pillow відповість + cannot identify image file. Це не PNG. Він ним ніколи й не був, так казало лише + ім'я. +

+

+ Це важливіше, ніж здається, через те, в який бік тест тоді провалюється. Ваша точка + завантаження відхиляє файл, ваш тест зеленіє, і ви робите висновок, що ліміт розміру працює. + Вона відхилила його не через розмір. Вона відхилила його тому, що байти не були зображенням, і + правило, яке ви хотіли перевірити, так і не було досягнуте. +

+
    +
  • парсер відхиляє його, не дійшовши до жодних правил розміру
  • +
  • крок створення мініатюри падає, і помилка, яку ви читаєте, стосується мініатюри
  • +
  • антивірус чи перевірка вмісту відхиляє його з третьої причини
  • +
  • переглядач нічого не показує, і ніхто не може сказати, чи в цьому помилка
  • +
+
+ +
+

Інший шлях

+

Справжній файл цього формату точно того розміру, який ви запросили

+

+ Саме це робить Testing Files Generator. Файл - справжній файл свого формату, він відкривається у + своїй програмі, і в ньому рівно стільки байтів, скільки ви запросили, з точністю до байта: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Запросіть розмір, якого формат не може досягти, і ви отримаєте помилку з назвою мінімуму та + причиною, а не файл неправильного розміру. Сторінка форматів + перелічує кожен формат з найменшим файлом, який він може створити. +

+

А ліміт - це три тестові випадки, а не один, тому інструмент збирає всі три:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Ви отримаєте 10485759, 10485760 і 10485761 байт та маніфест, що каже, які з них ваша система має + прийняти, а які відхилити. Сторінка сценаріїв розбирає це та ще + чотири завдання, для яких інструмент створений. +

+ +

Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.

+
+ +
+

Тож що використовувати?

+
    +
  • +

    Використовуйте системну команду

    +

    + Коли ніщо не відкриває файл. Перевірка ліміту розміру на точці, що спершу дивиться розмір, передача, + квота, переповнення диска. Це один рядок, і він уже встановлений. +

    +
  • +
  • +

    Використовуйте справжній генератор

    +

    + Коли будь-що розбирає, відображає, імпортує чи розпаковує файл - і коли завтра на іншій машині + потрібні ті самі фікстури, байт у байт. +

    +
  • +
+

+ Обидві є на цій сторінці, бо обидві бувають слушними. Помилка, якої слід уникати, - використати + першу там, де потрібна друга, і сприйняти зелений тест за доказ. +

+
+ +
+ + + + diff --git a/web/public/uk/docs/index.html b/web/public/uk/docs/index.html new file mode 100644 index 00000000..ef11f8c9 --- /dev/null +++ b/web/public/uk/docs/index.html @@ -0,0 +1,558 @@ + + + + + + +Документація - команди, рецепти, маніфест, коди завершення + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Документація

+

+ Усе, що робить інструмент, розкладено за питаннями, з якими люди справді приходять. + README у репозиторії - повний довідник, і він завжди відповідає + завантаженій вами збірці. +

+ +
+

Які є команди?

+

Кожна робить одну справу:

+
tfg generate    створити файли за рецептом або за прапорцями
+tfg validate    перевірити рецепт, нічого не записуючи
+tfg verify      звірити каталог із маніфестом
+tfg cleanup     видалити файли, перелічені в маніфесті
+tfg recipe fmt  вивести рецепт у усталеному вигляді
+tfg preset      зібрати набір файлів за іменованим тестовим питанням
+tfg formats     перелічити формати цієї збірки
+tfg damage      перелічити способи, якими ця збірка може навмисно зіпсувати файл
+tfg tool        невеликі інструменти для вже наявних файлів
+tfg version     вивести версію інструмента
+tfg license     вивести ліцензію та що вона означає для створених файлів
+
+ +
+

Як створити один файл точного розміру?

+

+ Укажіть формат, розмір і місце призначення. Розміри рахуються по 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. Вибір іде від seed
--boundary <size>три файли навколо ліміту: на байт менше, сам ліміт, на байт більше
--count <n>скільки файлів створити. За замовчуванням 1
--name <template>шаблон імені, наприклад invoice_{index:04}.txt
--out <dir>каталог, у який записувати
--seed <n>seed запуску. Той самий seed дає ті самі байти
--set <k>=<v>налаштування формату, можна повторювати
--damage <name>навмисно зіпсувати файли, можна повторювати, застосовується по порядку. Список виводить tfg damage
--expected <outcome>accept, reject, sanitize або unspecified
--dry-runпорахувати й показати, нічого не записуючи
--jsonзаписати маніфест у стандартний вивід
+
+
+ +
+

Як зробити навмисно зламаний файл?

+

+ Будь-який інший файл, що його записує цей інструмент, коректний за побудовою, і це відповідає на два + з трьох питань, які ставить перевірка завантаження. --damage відповідає на третє - + чи відкривається файл узагалі. Файл створюється як зазвичай, а потім псується, тому в нього + лишається запитаний розмір. +

+
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 із записаним поруч пошкодженням. + Дві речі відхиляються до запису чого-небудь, бо кожна залишила б на диску файл, неправильно + описаний маніфестом: +

+
    +
  • файл менший, ніж потрібно пошкодженню, бо він вийшов би без змін
  • +
  • + expected: accept поруч із пошкодженням, бо цьому не міг би відповідати жоден файл. + Пишіть sanitize, якщо тестована система має полагодити файл, або + unspecified, якщо саме це питання ви й ставите +
  • +
+

+ Третє наперед дізнатися не можна. Якщо пошкодження виконується й не змінює жодного байта, такий файл + відкидається, а не записується - запуск триває, повідомляє, що це був за файл, і завершується + кодом часткового завершення. +

+

+ Крок за кроком, з тестом, який читає маніфест: як зробити + пошкоджений файл для тестів. +

+
+ +
+

Як виглядає рецепт?

+

+ Рецепт - це файл 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. Два - це помилка, і жодного - теж. Недійсний + рецепт записує жодного файлу і повідомляє про всі проблеми одразу, а не лише + про першу, щоразу називаючи налаштування, якого вона стосується. +

+
+ +
+

Як оголосити, що моя система має робити з файлом?

+

Коротка форма, коли досить результату, і довга, коли важлива причина:

+
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. +

+

+ Причина називає чинне правило, а не вердикт. Тому та сама причина може стояти під + будь-яким результатом - файл на байт менший за ліміт отримує accept, а правило, про + яке йдеться, усе одно size_limit. +

+
+ +
+

Що в маніфесті?

+

+ Він записується поряд із файлами наприкінці кожного запуску, зокрема й перерваного. Один запис на + файл: +

+
{
+  "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 - якщо за пресетом, тож маніфест завжди можна простежити до того, що його + створило. +

+

+ Кожен запис також містить target_id - id цілі рецепта, що створила файл, а + summary.by_target рахує файли кожної цілі. Рецепт із кількома цілями можна тому + перевірити ціль за ціллю, не читаючи імена файлів. +

+
+ +
+

Що таке пресет?

+

+ Готовий набір файлів, що відповідає на поширене тестове питання, щоб вам не доводилося проєктувати + набір самостійно. Пресети - звичайні рецепти всередині, а eject виводить рецепт, + щоб ви могли його відредагувати. Кожен пресет має окрему сторінку про + те, що він зазвичай знаходить, що входить у набір і які налаштування приймає. +

+
    +
  • +

    Порожні та мінімальні

    +

    Чи пройде коректний файл, настільки малий, наскільки дозволяє формат?

    +

    empty-and-minimal

    +
  • +
  • +

    Обробка імен файлів

    +

    Чи збереже, покаже та поверне моя система ім'я файлу, якого не очікувала?

    +

    filename-handling

    +
  • +
  • +

    Межі розміру

    +

    Чи застосовується ліміт розміру саме там, де його оголошено?

    +

    size-boundaries

    +
  • +
  • +

    Імпорт таблиць

    +

    Чи переживе мій імпорт таблиць те, що експортують справжні інструменти?

    +

    tabular-import

    +
  • +
  • +

    Кодування тексту

    +

    Чи знає мій читач, у якому кодуванні файл, чи вгадує?

    +

    text-encoding

    +
  • +
  • +

    Перевірка завантаження

    +

    Чи приймає моя форма завантаження те, що має, і відхиляє решту?

    +

    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 повідомляє, скільки коштував би набір, перш ніж ви його зберете, і прямо каже, + коли число - наша тимчасова підстановка, а не ваш ліміт. +

+
+ +
+

Що означають коди завершення?

+

+ Кожен кінець має власний код, машиночитний вивід іде в стандартний вивід, а невдалий запуск нічого + туди не друкує. Таблиця - заморожений контракт: зміна значення коду вимагає підвищення мажорної + версії. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КодЗначення
0Усе спрацювало.
1Непередбачена помилка всередині інструмента.
2Неправильна команда або прапорець.
3Рецепт недійсний.
4Формат не може зробити те, що просили.
5Не вдалося прочитати або записати.
6Недостатньо місця на диску.
7verify виявив розбіжність.
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, усе одно залишає маніфест і ніколи не залишає наполовину + записаного файлу, тож скасоване завдання може бути прибране наступним. +

+

+ Готові workflow для GitHub Actions і GitLab CI: як генерувати + тестові файли в конвеєрі CI. +

+
+ +
+

Чи є десктопне вікно?

+

+ Так, той самий рушій із вікном згори, для тестування, яке не автоматизується. Це не урізана версія: + тест порівнює два інтерфейси можливість за можливістю, і все, що вміє лише один із них, має бути + оголошене й обґрунтоване, а не тихо розходитися. +

+

+ Екрани: одна партія, пресети, кілька партій одночасно та про програму. Вікно показує, скільки + коштував би запуск, перш ніж щось записати, відображає перебіг роботи й може бути скасоване на + півдорозі без наполовину записаного файлу. Файл рецепта воно поки не відкриває - рецепти поки + справа командного рядка, а вікно збирає свої партії у формі. +

+
+ +
+ + + + diff --git a/web/public/uk/faq/index.html b/web/public/uk/faq/index.html new file mode 100644 index 00000000..862fb28a --- /dev/null +++ b/web/public/uk/faq/index.html @@ -0,0 +1,349 @@ + + + + + + +FAQ - питання про створення тестових файлів + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Часті запитання

+

+ Ліцензія, приватність, відтворюваність і те, що люди перевіряють, перш ніж додавати генератор до + конвеєра збірки. Якщо вашого питання тут немає, трекер задач + відкритий. +

+ +
+
+

Чим це відрізняється від dd, fsutil чи truncate?

+
+

Вони дають файл потрібного розміру, набитий порожнечею. Файл photo.png на 2 МБ, зроблений так, не є PNG, тому все, що справді його розбирає, відхиляє його з хибної причини, і ваш тест теж проходить із хибної причини. Цей інструмент створює справжній PNG рівно на 2 МБ, який відкривається в переглядачі зображень, і супроводжує його заявою про те, як ваша система має з ним вчинити.

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

Це безкоштовно, і чи можна використовувати на роботі?

+
+

Так в обох випадках. Інструмент випущено під GPL-3.0, і він нічого не коштує. Немає ні облікового запису, ні ліцензійного ключа, ні платного тарифу.

+
+
+
+

Чи можна використовувати створені файли в продукті із закритим кодом?

+
+

Так. Ліцензія охоплює код інструмента, а не те, що він створює. Створені файли, рецепти й маніфести є результатом, а не похідними творами, тож їх можна комітити та постачати без жодних зобов'язань.

+
+
+
+

Чи містять створені файли справжні персональні дані?

+
+

Ні. Усе всередині синтезується з seed. Жоден набір даних не читається, до жодного сервісу не звертаються і жоден сторонній вміст не вбудовується. Вважайте створену адресу електронної пошти непридатною, а не невикористаною, бо будь-який випадковий рядок може випадково збігтися зі справжнім.

+
+
+
+

Чи отримаю я точно такі самі файли на іншій машині?

+
+

Так, байт у байт, за того самого рецепта й того самого seed. Проєкт перевіряє це при кожній зміні, а порушити це можна лише підвищенням мажорної версії. Саме тому ви можете комітити невеликий рецепт замість великих бінарних фікстур.

+
+
+
+

Чи потрібне підключення до інтернету?

+
+

Ніколи. Немає ні телеметрії, ні перевірки оновлень, ні хмарного клієнта, а в бінарний файл командного рядка взагалі не скомпільовано мережевий стек. Він працює на машині без мережі й у закритому корпоративному середовищі.

+
+
+
+

Що буде, якщо запросити розмір, якого формат не може досягти?

+
+

Ви отримаєте помилку з назвою формату, найменшим можливим розміром, причиною цього мінімуму та тим, що робити натомість, а файл записано не буде. Інструмент ніколи не округлює розмір мовчки. Кожен мінімум указано на сторінці форматів.

+
tfg formats png
+
+
+
+

Чи можна створити навмисно зламаний файл?

+
+

Так. Додайте --damage zero-head, і файл вийде точно заданого розміру, з першими байтами, перезаписаними нулями, тож програма читання його відхилить, а маніфест скаже, що ваша система має його відхилити. Подробиці на сторінці про пошкоджені тестові файли.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Які формати з'являться далі?

+
+

7z, mp3 і mp4. Сьогодні повністю працюють 26 форматів.

+
+
+
+

У яких системах це можна запускати?

+
+

Командний рядок працює у Windows і Linux на Intel та ARM, а також на Mac з Apple Silicon. Десктопне вікно постачається для Windows на Intel, Linux на Intel і Mac з Apple Silicon. Mac на Intel не підтримуються, і для них нічого не збирається.

+
+
+
+

Чи потрібно щось установлювати?

+
+

Ні. Завантажте архів для своєї системи, розпакуйте й запустіть бінарний файл. Немає інсталятора, середовища виконання, яке треба додавати, і залежностей, які треба розв'язувати. Якщо у вас є Go, підійде й одна команда go install.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Чому запуск на тисячах файлів у Windows повільніший?

+
+

Бо Windows бере більше за кожен шлях, який переглядає, а команда, що обходить тисячі файлів, переглядає тисячі шляхів. Виміряно на одній машині з 3000 файлів по 1 КБ: verify займає близько 0,9 секунди у Windows і близько 0,2 секунди в Linux у контейнері. Коротший шлях виводу зменшує цифру для Windows, бо кожна тека над файлами входить у те, що переглядається.

+
+
+
+ + +
+

Усе ще вирішуєте?

+

+ Сторінка сценаріїв показує завдання, для яких інструмент створений, а + сторінка форматів перелічує кожен формат з найменшим файлом, який він + може створити. README у репозиторії - повний довідник. +

+ +

Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.

+
+ +
+ + + + diff --git a/web/public/uk/formats/index.html b/web/public/uk/formats/index.html new file mode 100644 index 00000000..71fac197 --- /dev/null +++ b/web/public/uk/formats/index.html @@ -0,0 +1,911 @@ + + + + + + +26 форматів файлів - PDF, DOCX, PNG, ZIP та інші + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 форматів файлів, кожен створюється точного розміру

+

+ Кожен із них - справжній файл цього формату. Він відкривається у своїй програмі та + має рівно стільки байтів, скільки ви запросили. Жоден не є нулями-заповнювачами з приклеєним + розширенням. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ФорматНазваРозширенняНайменший файлПовнотаПеревіряється за допомогою
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullне застосовується
mdMarkdown.md0fullне застосовується
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullне застосовується
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Що означають стовпці

+
    +
  • +

    Найменший файл

    +

    + Найменша кількість байтів, яку цей інструмент приймає для формату, разом із позначкою, яку він пише + всередині файлу. Запросіть менше, і ви отримаєте помилку з назвою мінімуму та причиною, а не + файл неправильного розміру. +

    +
  • +
  • +

    Повнота

    +

    + Наскільки повний файл. full означає, що його приймає читач, який по-справжньому + розбирає формат, а не просто збігається розширення. +

    +
  • +
  • +

    Перевіряється за допомогою

    +

    + Незалежний читач, що відкриває кожен створений файл до випуску формату, - окрема реалізація, а не + наш власний код, що перевіряє власні домашні завдання. +

    +
  • +
+

+ Кожен формат до того ж повторюється до байта: той самий рецепт і той самий seed дають однакові файли + на будь-якій машині, і саме це робить безпечним коміт рецепта замість самих фікстур. +

+
+ +
+

Налаштування, які приймає кожен формат

+

+ Більшість форматів мають власні налаштування - розміри зображення, якість JPEG, кількість сторінок + PDF, рядки й стовпці в таблиці, скільки записів входить в архів. Задайте їх через --set + key=value у командному рядку або в розділі properties: рецепта. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ФорматНалаштуванняДопускає
avifwidth1 - 16384 пікселів
height1 - 16384 пікселів
quality1 - 100
bmpwidth1 - 20000 пікселів
height1 - 20000 пікселів
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerістина або хибність
quote_styleall, minimal, none
columns2 - 32768 стовпців
docxparagraphs1 - 50000 абзаців
gifwidth1 - 20000 пікселів
height1 - 20000 пікселів
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 пікселів
height1 - 256 пікселів
embedbmp, png
jpgwidth1 - 20000 пікселів
height1 - 20000 пікселів
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 пікселів
height1 - 16384 пікселів
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 записів на секунду
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomістина або хибність
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titleбудь-який текст
authorбудь-який текст
subjectбудь-який текст
keywordsбудь-який текст
creatorбудь-який текст
producerбудь-який текст
createdдата на кшталт 2024-02-29 або 2024-02-29T13:45:00+02:00, або none
modifiedдата на кшталт 2024-02-29 або 2024-02-29T13:45:00+02:00, або none
pngwidth1 - 20000 пікселів
height1 - 20000 пікселів
pptxslides1 - 500 слайдів
svgwidth1 - 20000 пікселів
height1 - 20000 пікселів
targzentries0 - 10000
entry_formatid формату в тому вигляді, як його виводить tfg formats
entry_sizeрозмір, наприклад 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesістина або хибність
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 пікселів
height1 - 20000 пікселів
txtencodingutf-16be, utf-16le, utf-8
bomістина або хибність
wavsample_rate8000 - 192000 герців
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 пікселів
height1 - 16383 пікселів
xlsxrows1 - 200000 рядків
columns1 - 32768 стовпців
xmlencodingutf-16be, utf-16le, utf-8
bomістина або хибність
zipentries0 - 10000
entry_formatid формату в тому вигляді, як його виводить tfg formats
entry_sizeрозмір, наприклад 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesістина або хибність
passwordпароль відкритим текстом
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Значення поза допустимим для налаштування відхиляється повідомленням із назвою налаштування, + допустимим діапазоном і тим, що використати натомість. Невідоме налаштування теж помилка, а не + мовчазне значення за замовчуванням - друкарська помилка, прийнята мовчки, дає файл із хибними + налаштуваннями та годину роздумів, чому тест проходить, хоча не мав би. +

+

+ Виконайте tfg formats <id>, щоб побачити, що саме приймає один формат у вашій + збірці. +

+
+ +
+

Архіви містять справжні файли

+

+ targz і zip + можна наповнити записами, а не лишати порожньою оболонкою. Створений архів справді містить + документи, які заявляє, тому все, що розпаковує його під час тесту, знаходить усередині справжні + файли. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/uk/index.html b/web/public/uk/index.html new file mode 100644 index 00000000..626e0a9a --- /dev/null +++ b/web/public/uk/index.html @@ -0,0 +1,453 @@ + + + + + + +Генератор тестових файлів для QA - точний розмір, 26 форматів + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Створюйте справжні тестові файли точного розміру

+

+ PDF, PNG, DOCX, ZIP - усього 26 форматів, і кожен із них - + справжній файл, що відкривається у своїй програмі, точно того розміру, який ви + запросили. Кожен запуск ще й записує, що ваш застосунок має робити з кожним файлом. + Командний рядок і десктопне вікно, безкоштовно та з відкритим кодом, усе працює на вашій машині. +

+ + +

Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.

+
+ +
+ Десктопне вікно Testing Files Generator, підготовлене до запису партії тестових файлів +
Десктопне вікно, підготовлене до запису партії файлів. За командним рядком працює той самий рушій.
+
+
+ + + +
+

Проблема

+

Зробити один тестовий файл легко. Зробити потрібну тисячу - ось виснажлива частина

+

Ви тестуєте програму, що приймає файли від людей. Рано чи пізно вам знадобляться:

+
    +
  • PDF рівно на 10 МБ, щоб з'ясувати, чи реальний ліміт завантаження
  • +
  • три файли по обидва боки цього ліміту, щоб упіймати помилки на одиницю
  • +
  • 10 000 файлів журналу, щоб побачити, що робить нічне завдання, коли тека велика
  • +
  • ZIP, який справді містить 200 документів, а не порожню оболонку з правильним розширенням
  • +
  • файл на 4 ГБ без зберігання файлу на 4 ГБ у вашому репозиторії
  • +
  • однакові фікстури на ноутбуці та на сервері збірки, байт у байт
  • +
+

+ Саме це він замінює. Він створений для QA-інженерів, автоматизації тестування та всіх, за чиїм кодом + стоїть форма завантаження, процедура імпорту, парсер чи квота сховища. +

+
+ +
+

Чим він відрізняється

+

Інші генератори зупиняються на байтах. Цей відповідає на те, про що насправді питає ваш тест

+

+ Тека з файлами все одно залишає вам вирішувати, що має доводити кожен із них. Кожен запуск тут + записує поряд із файлами manifest.json - простий перелік усього створеного та для + кожного запису заявлене очікування. +

+

Припустімо, ваша точка завантаження допускає 1 МБ. Запросіть три файли, що лежать на цій межі:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
ФайлБайтівВаша система маєТому що
1mb_under_1b.pdf1048575прийнятивін у межах ліміту
1mb_at_limit.pdf1048576прийнятисам ліміт дозволений
1mb_over_1b.pdf1048577відхилитиsize_limit
+
+ +

Три файли, три різні відповіді, у машиночитному вигляді. Ваш тест читає маніфест замість того, щоб ви писали перевірки вручну:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Там, де відповідь залежить від вашої власної політики, маніфест так і каже

+

+ Він записує unspecified, а не вигадує очікування. Генератор, що вгадує, дає хибні збої, + а набір тестів, що кричить «вовки», зрештою вимикають. +

+
+
+ +
+

Пресети

+

Виберіть питання, отримайте весь набір

+

+ Пресет - це набір тестових файлів, продуманий навколо одного тестового питання, щоб вам не довелося + з'ясовувати, які файли що доводять. Кожен має сторінку про те, що він зазвичай знаходить, що + входить у набір і які налаштування приймає. +

+
    +
  • +

    Порожні та мінімальні

    +

    Чи пройде коректний файл, настільки малий, наскільки дозволяє формат?

    +

    empty-and-minimal

    +
  • +
  • +

    Обробка імен файлів

    +

    Чи збереже, покаже та поверне моя система ім'я файлу, якого не очікувала?

    +

    filename-handling

    +
  • +
  • +

    Межі розміру

    +

    Чи застосовується ліміт розміру саме там, де його оголошено?

    +

    size-boundaries

    +
  • +
  • +

    Імпорт таблиць

    +

    Чи переживе мій імпорт таблиць те, що експортують справжні інструменти?

    +

    tabular-import

    +
  • +
  • +

    Кодування тексту

    +

    Чи знає мій читач, у якому кодуванні файл, чи вгадує?

    +

    text-encoding

    +
  • +
  • +

    Перевірка завантаження

    +

    Чи приймає моя форма завантаження те, що має, і відхиляє решту?

    +

    upload-validation

    +
  • +
+

Усі пресети та як вони пов'язані з рецептами

+
+ +
+

Швидкий старт

+

Три команди, щоб побачити роботу

+
    +
  1. +

    Створіть файл

    +

    Один PNG, рівно два мегабайти:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Створіть багато файлів

    +

    + Десять тисяч файлів журналу, кожен від одного до восьми кілобайтів, з розмірами з seed, щоб завтра + вийшов той самий набір. Давайте кожному запуску власний каталог - маніфест + лишається єдиним записом про те, що записав запуск, тому інструмент відмовляється записувати + другий поверх нього: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Перевірте їх, потім видаліть

    +

    verify повідомляє, що нічого не зсунулося. cleanup видаляє рівно те, що було записано, і нічого більше:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Розміри рахуються по 1024, як у вашому файловому менеджері, тому 2mb означає 2097152 + байти. Підійде й просте число байтів. Документація охоплює рецепти, + маніфест і коди завершення. +

+
+ +
+

Що ви отримуєте

+

Створений для набору тестів, що працює без нагляду

+
    +
  • +

    Точний розмір, до байта

    +

    Запросіть 10485761 байт і отримайте рівно стільки. Розмір, якого формат не може досягти, - це помилка з причиною, а не файл неправильного розміру.

    +
  • +
  • +

    26 справжніх форматів

    +

    Не нулі-заповнювачі з розширенням. Створений PNG відкривається в переглядачі зображень, DOCX - у Word, ZIP розпаковується. Кожен формат перевіряється незалежними читачами до випуску.

    +
  • +
  • +

    Маніфест, що править за тестовий оракул

    +

    Шлях, розмір, SHA-256, формат, seed, версія інструмента - і те, що ваша система має зробити з файлом.

    +
  • +
  • +

    Відтворюваність

    +

    Той самий рецепт і той самий seed, ті самі байти на будь-якій машині. Комітьте невеликий рецепт YAML замість великих бінарних фікстур.

    +
  • +
  • +

    Два інтерфейси, один рушій

    +

    Командний рядок, створений для CI, і десктопне вікно для дослідницького тестування. Жоден не є урізаною версією іншого, і тест порівнює їх можливість за можливістю.

    +
  • +
  • +

    Повністю офлайн

    +

    Немає облікового запису, хмари, телеметрії та перевірки оновлень. У бінарний файл командного рядка взагалі не скомпільовано мережевий стек.

    +
  • +
+
+ +
+

Завантаження

+

Виберіть збірку для вашої системи

+

+ Розпакуйте архів і запустіть. tfg - це командний рядок, а tfg-gui - + десктопне вікно. Немає інсталятора й нічого, що треба додавати на вашу машину. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
СистемаКомандний рядокДесктопне вікно
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Що підписано, а що ні

+

+ Збірки для Windows і macOS підписані, тому запускаються без попередження про невідомого розробника. + Збірки для Linux не підписані, бо в десктопного Linux немає еквівалента, яким їх можна + підписати. Кожен архів указано в verify-SHA256SUMS.txt на сторінці релізу, тож ви + можете перевірити, що завантажили. +

+
+ +

Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.

+
+ + +
+ + + + diff --git a/web/public/uk/presets/empty-and-minimal/index.html b/web/public/uk/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..ae5c528b --- /dev/null +++ b/web/public/uk/presets/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Мінімальні коректні та порожні тестові файли в кожному форматі + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Порожні та мінімальні

+

Чи пройде коректний файл, настільки малий, наскільки дозволяє формат?

+

+ Пресет empty-and-minimal однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • коректний файл, відхилений як надто малий, бо перевірка рахує байти, а не читає їх
  • +
  • порожній файл, який валить читальний код замість того, щоб бути поміченим
  • +
  • картинка завширшки один піксель, яка ділить на нуль дорогою до мініатюри
  • +
  • сховище, яке сприймає нуль байтів як невдале завантаження й безкінечно повторює спроби
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show empty-and-minimal:

+
+ + + + + + + +
Файлів28
Цілей у його рецепті28
Загальний розмір32 667 B
Форматиavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.26
unspecifiedЗалежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі.2
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--formatsid форматів через кому або allallЗ яких форматів складається набір. Залиште all для всіх форматів цієї збірки або перелічіть ті, які приймає ваша система.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/uk/presets/filename-handling/index.html b/web/public/uk/presets/filename-handling/index.html new file mode 100644 index 00000000..f5031568 --- /dev/null +++ b/web/public/uk/presets/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Проблемні імена файлів для тестів - Unicode і довжина + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Обробка імен файлів

+

Чи збереже, покаже та поверне моя система ім'я файлу, якого не очікувала?

+

+ Пресет filename-handling однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • ім'я, що на екрані, в журналі чи в списку виглядає як інше
  • +
  • ім'я, обрізане, скорочене або переписане між завантаженням і зберіганням
  • +
  • ліміт довжини, що рахується в символах там, де сховище рахує байти
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show filename-handling:

+
+ + + + + + + +
Файлів50
Цілей у його рецепті50
Загальний розмір51 200 B
Форматиtxt
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.4
unspecifiedЗалежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі.46
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--formatid формату зі сторінки форматівtxtФормат кожного файлу набору. Це прапорець самого інструмента, а пресет лише задає йому значення за замовчуванням.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/uk/presets/index.html b/web/public/uk/presets/index.html new file mode 100644 index 00000000..c2904892 --- /dev/null +++ b/web/public/uk/presets/index.html @@ -0,0 +1,245 @@ + + + + + + +Пресети тестових файлів - готові набори для QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Пресети тестових файлів, по набору на кожне тестове питання

+

+ Пресет - це цілий набір тестових файлів, продуманий навколо одного питання, з маніфестом про + очікувану реакцію вашої системи на кожен файл. Ви вибираєте питання, інструмент збирає набір. + Кожен пресет має власну сторінку про те, що він зазвичай знаходить, що входить у набір і які + налаштування приймає. +

+ + + +
+

Чим пресет відрізняється від рецепта?

+

+ По суті нічим. Пресет - це рецепт, який інструмент пише для вас із кількох налаштувань. tfg + preset eject виводить цей рецепт, щоб ви могли зберігати його поряд із тестами й + редагувати, а ваш власний рецепт може спиратися на пресет одним рядком: extends: + preset: і його id. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Чи можна довіряти значенням за замовчуванням?

+

+ Для файлів - так. Для числа, яке знає лише ваша система, як-от ліміту форми завантаження, значення + за замовчуванням - наша тимчасова підстановка, і інструмент каже про це щоразу, коли її + використовує. Сторінка кожного пресета позначає такі налаштування, а tfg preset + show повідомляє про це до запису чого-небудь. +

+
+ +
+ + + + diff --git a/web/public/uk/presets/size-boundaries/index.html b/web/public/uk/presets/size-boundaries/index.html new file mode 100644 index 00000000..d529272c --- /dev/null +++ b/web/public/uk/presets/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Перевірка ліміту розміру завантаження - файли на самій межі + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Межі розміру

+

Чи застосовується ліміт розміру саме там, де його оголошено?

+

+ Пресет size-boundaries однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • помилки на одиницю на межі ліміту
  • +
  • МБ, сплутані з МіБ, тобто 4,8 відсотка, чого досить, щоб пропустити файл, який не мав би пройти
  • +
  • ліміт, що застосовується в браузері, а не на сервері
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show size-boundaries:

+
+ + + + + + + +
Файлів7
Цілей у його рецепті7
Загальний розмір73 400 320 B
Форматиpdf
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.4
rejectВаша система має відхилити файл.3
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--limitрозмір, наприклад 2mb10mbЛіміт розміру, який оголошує ваша система. Усе інше відмірюється від нього. Це значення за замовчуванням - наша тимчасова підстановка, а не значення вашої системи. Передайте своє.
--spreadрозміри через кому1B,1kb,1mbЯк далеко відходити від ліміту в обидва боки, списком розмірів.
--formatid формату зі сторінки форматівpdfФормат кожного файлу набору. Це прапорець самого інструмента, а пресет лише задає йому значення за замовчуванням.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

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

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/uk/presets/tabular-import/index.html b/web/public/uk/presets/tabular-import/index.html new file mode 100644 index 00000000..558b4ea6 --- /dev/null +++ b/web/public/uk/presets/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Тестові файли для імпорту CSV та Excel - роздільники й заголовки + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Імпорт таблиць

+

Чи переживе мій імпорт таблиць те, що експортують справжні інструменти?

+

+ Пресет tabular-import однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • файл із крапкою з комою, прочитаний як один стовпець, бо роздільник припустили, а не шукали
  • +
  • файл CRLF, розбитий на рядки з порожнім рядком після кожного
  • +
  • таблиця без заголовка, перший рядок даних якої з'їдається як імена стовпців
  • +
  • імпорт, що залишає стовпці, які може показати, і мовчки відкидає решту
  • +
  • читач, що бере записи JSON по одному рядку й зупиняється на першому документі з відступами
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show tabular-import:

+
+ + + + + + + +
Файлів13
Цілей у його рецепті13
Загальний розмір3 080 060 B
Форматиcsv, json, xlsx
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.8
unspecifiedЗалежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі.5
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--rows1 - 200000 рядків1000Скільки рядків у таблиці. Файл записується рівно того розміру, у який пакується стільки рядків, тому бюджет вище змінюється разом із цим значенням.
--columns1 - 32768 стовпців10Скільки стовпців у кожному рядку таблиці. Добуток рядків на стовпці має стелю, і запит понад неї відхиляється до запису чого-небудь.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/uk/presets/text-encoding/index.html b/web/public/uk/presets/text-encoding/index.html new file mode 100644 index 00000000..e61b8767 --- /dev/null +++ b/web/public/uk/presets/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Тестові файли кодування тексту - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Кодування тексту

+

Чи знає мій читач, у якому кодуванні файл, чи вгадує?

+

+ Пресет text-encoding однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • читач, що припускає UTF-8 і показує файл UTF-16 з одним символом із трьох або рядами квадратиків
  • +
  • позначка порядку байтів, прочитана як вміст, через що перше поле імпорту починається з трьох зайвих символів
  • +
  • імпортер, що вгадує кодування за першими байтами й вгадує інакше для довшого файлу
  • +
  • файл CRLF, розбитий на рядки з порожнім рядком після кожного, або повернення каретки, що залишилося в останньому полі
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show text-encoding:

+
+ + + + + + + +
Файлів20
Цілей у його рецепті20
Загальний розмір81 920 B
Форматиcsv, log, md, txt, xml
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.10
unspecifiedЗалежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі.10
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--sampleрозмір, наприклад 2mb4kbРозмір кожного файлу набору. UTF-16 зберігає по два байти на символ, тому непарне число відхиляється.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/uk/presets/upload-validation/index.html b/web/public/uk/presets/upload-validation/index.html new file mode 100644 index 00000000..02d8b163 --- /dev/null +++ b/web/public/uk/presets/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Тестові файли перевірки завантаження - тип, розмір та ім'я + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Пресети

+

Перевірка завантаження

+

Чи приймає моя форма завантаження те, що має, і відхиляє решту?

+

+ Пресет upload-validation однією командою збирає цілий набір справжніх тестових файлів для цього + питання та поруч manifest.json з очікуваною реакцією вашої системи на кожен файл. Усе + нижче прочитано з програми зі значеннями за замовчуванням цієї версії. +

+ + +
+

Що він зазвичай знаходить?

+
    +
  • ліміт, що застосовується в браузері, а не на сервері
  • +
  • SVG або HTML, прийнятий за картинку чи простий текст, що дає змогу провести скрипт крізь форму
  • +
  • файл, перевірений за розширенням і жодного разу не відкритий, тож PDF з ім'ям .jpg проходить
  • +
  • форма, що читає все тіло в пам'ять, перш ніж подивитися, наскільки воно велике
  • +
  • завантаження з ім'ям PHOTO.JPG відхилене там, де photo.jpg приймається, або навпаки
  • +
  • ім'я з пробілами, дужками чи символами поза ASCII, записане на диск без змін
  • +
+
+ + +
+

Що входить у набір?

+

Зі значеннями за замовчуванням, як повідомляє tfg preset show upload-validation:

+
+ + + + + + + +
Файлів71
Цілей у його рецепті22
Загальний розмір120 639 488 B
Форматиhtml, jpg, pdf, png, svg, txt
+
+

І чого маніфест цього набору очікує від вашої системи:

+
+ + + + + + + + + +
ОчікуєтьсяЗначенняФайлів
acceptВаша система має прийняти файл.56
rejectВаша система має відхилити файл.10
unspecifiedЗалежить від правил вашої системи. Ви вирішуєте, а потім перевіряєте, що відбувається саме те, що ви мали на увазі.5
+
+
+ +
+

Що можна змінити?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
НалаштуванняПриймаєЗа замовчуваннямЩо робить
--limitрозмір, наприклад 2mb10mbЛіміт розміру, який оголошує ваша форма завантаження. Цей набір робить по одному кроку в обидва боки - для файлу на кожній відстані запустіть пресет size-boundaries. Це значення за замовчуванням - наша тимчасова підстановка, а не значення вашої системи. Передайте своє.
--allowid форматів через комуjpg,png,pdfЯкі типи має приймати ваша форма. Кожен стає справжнім файлом цього типу, і разом вони є позитивним контролем усього набору.
--denyрозширення через комуsvg,html,exe,shЯкі розширення має відхиляти ваша форма. Розширення, для якого в цій збірці немає формату, усе одно отримує файл із таким ім'ям і простим текстом усередині.
--far-over10x, 2x, off2xНаскільки далеко за ліміт заходить єдиний великий файл. Вимкніть, якщо запис кількох лімітів не вартий місця на диску.
--bulk0 - 10000 файлів50Скільки файлів у масовому завантаженні. Нуль повністю прибирає цю групу з набору.
+
+
+ +
+

Як його запустити?

+

Подивіться, скільки коштував би набір, зберіть його або візьміть його рецепт для правки:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Або будуйте на ньому у власному рецепті поряд із тестами:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/uk/test-files-in-ci/index.html b/web/public/uk/test-files-in-ci/index.html new file mode 100644 index 00000000..d4dad0e0 --- /dev/null +++ b/web/public/uk/test-files-in-ci/index.html @@ -0,0 +1,378 @@ + + + + + + +Тестові файли в CI - GitHub Actions, GitLab CI і PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Сценарії

+

Як генерувати тестові файли в конвеєрі CI

+

+ Двійкова фікстура в репозиторії лишається в його історії назавжди, її не можна перевірити в діфі, і + вона перестає бути можливою, коли файл великий. Генеруйте файли всередині конвеєра з рецепта. + Рецепт - це текст, байти щоразу виходять однакові, а останній крок доводить, що нічого не + зсунулося. +

+ +
+

Коротка відповідь

+

+ Установіть tfg, запустіть tfg generate fixtures.yaml --out ./fixtures + перед тестами і tfg verify ./fixtures/manifest.json після них. Обидва кроки самі + валять збірку, з кодом завершення, який каже чому. +

+
+ +
+

Чому не комітити

+

Чому фікстурі не місце в репозиторії

+
    +
  • + Вона лишається в історії. Видалення двійкового файлу пізніше не робить клон меншим, + бо кожна його версія все ще там. +
  • +
  • + Діф не показує, що змінилося. Рецензент бачить, що PDF інший, і нічого більше. + Рецепт змінюється на один рядок. +
  • +
  • + Великі файли не вміщаються. GitHub відхиляє push, у якому є файл більший за 100 МБ, + тож тесту ліміту завантаження в 500 МБ нічого комітити. +
  • +
+

+ Комітити потрібно рецепт. Той самий рецепт із тим самим зерном записує ті самі байти на будь-якій + машині, тож файл, створений у конвеєрі, - це файл, який був у вас на ноутбуці. +

+
+ +
+

Рецепт

+

Рецепт, що лежить поруч із тестами

+

+ Цей записує двадцять п'ять рахунків, які мають бути прийняті, і два зображення понад ліміт, які + мають бути відхилені, а маніфест фіксує обидва очікування: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml перевіряє його, нічого не записуючи, і називає одразу всі + проблеми. +

+
+ +
+

GitHub Actions

+

Workflow, що встановлює інструмент і збирає фікстури

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Рядок із контрольною сумою звіряє архів із verify-SHA256SUMS.txt з того самого випуску. + Версію закріплено, тож новий випуск ніколи не змінить збірку, якої ви не торкалися. +

+
+ +
+

GitLab CI

+

Те саме як завдання GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Коли стає червоно

+

Що валить крок і чому

+

+ У кожного завершення свій код, тож крок падає сам, а журнал каже, який саме. Ті, що трапляються + конвеєру: +

+
    +
  • 3 - рецепт недопустимий. Нічого не записано, і названо кожну проблему
  • +
  • 4 - формат не вміє того, про що попросили, наприклад розміру менше за свій мінімум
  • +
  • 6 - не вистачає місця на диску
  • +
  • 7 - tfg verify знайшов файл, що не збігається зі своїм маніфестом
  • +
  • 8 - запуск закінчився, але створено не все
  • +
+

+ Невдалий запуск нічого не друкує у стандартний вивід, тож розбирач журналів ніколи не сприйме + помилку за дані. Уся таблиця на сторінці документації. +

+
+ +
+

PowerShell

+

Скрипту PowerShell потрібен ще один рядок

+

+ PowerShell не виносить код завершення програми з файлу .ps1. Запустіть такий файл із + -File, і скрипт відповість 0, навіть коли інструмент усередині + відмовився працювати, тож збірка, яка мала б бути червоною, стає зеленою. Останній рядок - це + все виправлення: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ Так поводиться PowerShell, а не цей інструмент. cmd, bash і + zsh нічого зайвого не потребують. +

+
+ +
+

Кілька завдань

+

Як ділитися фікстурами між завданнями

+

+ Зазвичай завантажувати їх не треба. Оскільки той самий рецепт записує ті самі байти, кожне завдання + може запустити власний tfg generate, що швидше за завантаження й скачування. Коли + завдання має отримати файли від іншого, запустіть після передачі tfg verify на + маніфесті, і він скаже, чи збігається отримане із записаним. +

+
+ +
+

Далі

+

Куди йти звідси

+ +
+ +
+ + + + diff --git a/web/public/uk/use-cases/index.html b/web/public/uk/use-cases/index.html new file mode 100644 index 00000000..56e50e18 --- /dev/null +++ b/web/public/uk/use-cases/index.html @@ -0,0 +1,317 @@ + + + + + + +Сценарії - ліміти завантаження, фікстури для CI, масові тести + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Для чого це використовують

+

+ П'ять завдань, що виникають майже в кожному проєкті, який приймає файли від людей, і команда, що + розв'язує кожне. Кожен приклад нижче запускається як написано. +

+ +
+

Ліміти завантаження

+

Перевірка того, що ліміт розміру файлу застосовується там, де заявлено

+

+ Ліміт - це три тестові випадки, а не один: трохи нижче, рівно за лімітом і трохи вище. Отримати їх + вручну означає рахувати числа байтів і сподіватися, що ви не помилилися на одиницю. Запросіть + натомість набір: +

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

+ Ви отримаєте три справжні PDF по 1048575, 1048576 і 1048577 байт та маніфест, що каже: перші два + слід прийняти, а третій відхилити за size_limit. Ваш тест читає очікування, замість + того щоб ви писали три перевірки вручну, а коли ліміт змінюється, ви змінюєте одне число й + запускаєте знову. +

+

+ Те саме працює й без пресета, коли потрібен один набір меж просто в команді: +

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

Безперервна інтеграція

+

Тримати фікстури поза репозиторієм, не втрачаючи їх

+

+ Великі бінарні фікстури сповільнюють клонування репозиторію й заважають рев'ю, а при заміні ніхто не + може сказати, що змінилося. Рецепт - це кілька сотень символів YAML, що відтворюють ті самі + файли - байт у байт, на будь-якій машині - бо кожен файл виводиться з 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
+

+ Кожен кінець має власний код завершення, тому конвеєр відрізняє поганий рецепт від повного диска й + від розбіжності під час перевірки. Невдалий запуск нічого не друкує в стандартний вивід, і + розбірник журналів не сприймає помилку за дані. +

+
+ +
+

Масштаб

+

З'ясувати, що відбувається, коли тека велика

+

+ Процедури імпорту, нічні завдання та списки каталогів поводяться інакше за десяти тисяч файлів, ніж + за десяти. Розміри, вибрані з діапазону, роблять набір схожим на справжній трафік, а не на + десять тисяч однакових файлів, і вибір іде від seed, тож завтра набір буде той самий. +

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

+ Перевірте, скільки коштував би запуск, перш ніж він щось запише, це важливо, коли підсумок + вимірюється гігабайтами: +

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

+ Запуск, більший за вільне місце на диску, відхиляється до запису першого байта, а не заповнює диск і + не падає на півдорозі. +

+
+ +
+

Архіви

+

Перевірка розпакувальника на архіві, що справді містить файли

+

+ Порожній архів із правильним розширенням нічого не доводить про код, який його відкриває й обходить + вміст. Оголосіть вміст, і архів справді його містить: +

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

+ Глибина вкладеності, кількість записів і розмір вмісту - це те, про що в процедури імпорту є власна + думка, і так ви дізнаєтеся, яка вона. +

+
+ +
+

Парсери та переглядачі

+

Перевірка того, що ваш власний код читає формат так само, як справжнє ПЗ

+

+ Кожен формат тут перевіряється незалежним читачем до випуску: PNG відкривається й порівнюються його + пікселі, DOCX перечитується окремими бібліотеками, архів розпаковується. Це означає, що файл, + який відхиляє ваш парсер, - знахідка про ваш парсер, а не про генератор. +

+
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
+

+ Сторінка форматів перелічує налаштування кожного формату та найменший + файл, яким він може бути. +

+
+ +
+

Посібники

+

Два з них докладніше

+
    +
  • + Пошкоджені тестові файли - файл, навмисно зіпсований, точного + розміру, із записаним у маніфесті тим, що з ним має статися. +
  • +
  • + Тестові файли в CI - workflow для GitHub Actions, завдання + GitLab і коди завершення, що валять збірку. +
  • +
+
+ +
+

Для кого це

+

+ QA-інженери, автоматизація тестування та всі, за чиїм кодом стоїть форма завантаження, процедура + імпорту, парсер чи квота сховища. Працює на машині взагалі без мережі, що важливо в закритому + корпоративному середовищі, де генератор у браузері - не варіант. +

+ +

Безкоштовно, відкритий код, GPL-3.0. Без реєстрації. Збірки для Windows і macOS підписані та запускаються без попереджень.

+
+ +
+ + + + diff --git a/web/public/use-cases/index.html b/web/public/use-cases/index.html index e4555b96..8d26abd4 100644 --- a/web/public/use-cases/index.html +++ b/web/public/use-cases/index.html @@ -3,15 +3,36 @@ + Use Cases - Upload Limits, CI Fixtures, Bulk File Testing + + + + + + + + + + + + + + + + + + + + - + @@ -19,7 +40,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +109,35 @@ Exact size FAQ -
- Polski -
+
+ + + English + + +
@@ -182,6 +249,19 @@

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

+
+

Guides

+

Two of these in more detail

+ +
+

Who this is for

diff --git a/web/public/vi/dinh-dang/index.html b/web/public/vi/dinh-dang/index.html new file mode 100644 index 00000000..aaf86fd2 --- /dev/null +++ b/web/public/vi/dinh-dang/index.html @@ -0,0 +1,908 @@ + + + + + + +26 định dạng tệp được hỗ trợ - PDF, DOCX, PNG, ZIP và hơn nữa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ +
+ +
+

26 định dạng tệp, mỗi định dạng được tạo ở kích thước chính xác

+

+ Mỗi cái là một tệp thật của định dạng đó. Nó mở được bằng phần mềm của nó và có + đúng số byte bạn đã yêu cầu. Không cái nào là số không độn với phần mở rộng dán vào. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Định dạngTênPhần mở rộngTệp nhỏ nhấtĐộ đầy đủKiểm tra bằng
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155fullkhông áp dụng
mdMarkdown.md0fullkhông áp dụng
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0fullkhông áp dụng
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

Ý nghĩa các cột

+
    +
  • +

    Tệp nhỏ nhất

    +

    + Số byte ít nhất mà công cụ này chấp nhận cho định dạng đó, gồm cả nhãn nó ghi vào trong tệp. Yêu cầu + ít hơn và bạn nhận một lỗi nêu mức sàn cùng lý do, không bao giờ là tệp sai kích thước. +

    +
  • +
  • +

    Độ đầy đủ

    +

    + Tệp đầy đủ đến đâu. full nghĩa là một trình đọc thật sự phân tích định dạng sẽ chấp + nhận nó, chứ không chỉ là phần mở rộng khớp. +

    +
  • +
  • +

    Kiểm tra bằng

    +

    + Trình đọc độc lập mở mọi tệp được tạo trước khi định dạng được phát hành - một bản cài đặt riêng, + không phải mã của chính chúng tôi tự chấm bài tập của mình. +

    +
  • +
+

+ Mỗi định dạng cũng lặp lại đến từng byte: cùng công thức và cùng seed cho các tệp giống hệt trên mọi + máy, điều làm cho việc commit một công thức thay cho chính các fixture trở nên an toàn. +

+
+ +
+

Các thiết lập mỗi định dạng nhận

+

+ Hầu hết định dạng có thiết lập riêng - kích thước ảnh, chất lượng JPEG, số trang PDF, số dòng và cột + trong bảng tính, số mục nằm trong một tệp nén. Đặt chúng bằng --set key=value trên + dòng lệnh, hoặc dưới properties: trong công thức. +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Định dạngThiết lậpChấp nhận
avifwidth1 - 16384 pixel
height1 - 16384 pixel
quality1 - 100
bmpwidth1 - 20000 pixel
height1 - 20000 pixel
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
headerđúng hoặc sai
quote_styleall, minimal, none
columns2 - 32768 cột
docxparagraphs1 - 50000 đoạn văn
gifwidth1 - 20000 pixel
height1 - 20000 pixel
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 pixel
height1 - 256 pixel
embedbmp, png
jpgwidth1 - 20000 pixel
height1 - 20000 pixel
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 pixel
height1 - 16384 pixel
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 mục mỗi giây
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bomđúng hoặc sai
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
titlevăn bản bất kỳ
authorvăn bản bất kỳ
subjectvăn bản bất kỳ
keywordsvăn bản bất kỳ
creatorvăn bản bất kỳ
producervăn bản bất kỳ
createdngày như 2024-02-29 hoặc 2024-02-29T13:45:00+02:00, hoặc none
modifiedngày như 2024-02-29 hoặc 2024-02-29T13:45:00+02:00, hoặc none
pngwidth1 - 20000 pixel
height1 - 20000 pixel
pptxslides1 - 500 trang chiếu
svgwidth1 - 20000 pixel
height1 - 20000 pixel
targzentries0 - 10000
entry_formatid của một định dạng, như tfg formats liệt kê
entry_sizekích thước như 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesđúng hoặc sai
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 pixel
height1 - 20000 pixel
txtencodingutf-16be, utf-16le, utf-8
bomđúng hoặc sai
wavsample_rate8000 - 192000 hertz
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 pixel
height1 - 16383 pixel
xlsxrows1 - 200000 dòng
columns1 - 32768 cột
xmlencodingutf-16be, utf-16le, utf-8
bomđúng hoặc sai
zipentries0 - 10000
entry_formatid của một định dạng, như tfg formats liệt kê
entry_sizekích thước như 2mb
compressionbest, default, fast, none
depth0 - 50
directory_entriesđúng hoặc sai
passwordmật khẩu, ở dạng văn bản thuần
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ Giá trị nằm ngoài thứ một thiết lập chấp nhận bị từ chối bằng thông báo nêu thiết lập, khoảng cho + phép và nên dùng gì thay thế. Thiết lập lạ cũng là lỗi, không bao giờ là mặc định im lặng - lỗi + gõ được chấp nhận trong im lặng cho ra tệp sai thiết lập và một giờ tự hỏi vì sao bài kiểm thử + qua khi lẽ ra không. +

+

+ Chạy tfg formats <id> để xem chính xác một định dạng nhận gì trong bản dựng bạn + có. +

+
+ +
+

Tệp nén chứa tệp thật

+

+ targz và zip có + thể được nhồi các mục thay vì để thành cái vỏ rỗng. Tệp nén được tạo thật sự chứa các tài liệu + nó tuyên bố chứa, nên bất cứ thứ gì giải nén nó trong lúc kiểm thử đều thấy tệp thật bên trong. +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/vi/faq/index.html b/web/public/vi/faq/index.html new file mode 100644 index 00000000..db83d84f --- /dev/null +++ b/web/public/vi/faq/index.html @@ -0,0 +1,350 @@ + + + + + + +FAQ - câu hỏi về việc tạo tệp kiểm thử + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Câu hỏi thường gặp

+

+ Giấy phép, quyền riêng tư, khả năng tái lập và những điều mọi người kiểm tra trước khi đưa một trình + tạo vào pipeline build. Nếu câu hỏi của bạn chưa có ở đây, trình + theo dõi issue luôn mở. +

+ +
+
+

Điều này khác gì dd, fsutil hay truncate?

+
+

Chúng cho bạn một tệp đúng kích thước nhưng đầy sự trống rỗng. Tệp 2 MB tên photo.png tạo kiểu đó không phải PNG, nên bất cứ thứ gì thực sự phân tích nó sẽ từ chối vì lý do sai, và bài kiểm thử của bạn cũng qua vì lý do sai. Công cụ này tạo ra một PNG thật đúng 2 MB, mở được trong trình xem ảnh, và đi kèm lời khai về cách hệ thống của bạn cần xử lý nó.

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

Nó có miễn phí không, và tôi dùng ở chỗ làm được không?

+
+

Có cho cả hai. Nó phát hành theo GPL-3.0 và không tốn gì. Không có tài khoản, khóa giấy phép hay gói trả phí.

+
+
+
+

Tôi có dùng tệp được tạo trong sản phẩm mã nguồn đóng được không?

+
+

Được. Giấy phép áp dụng cho mã của công cụ, không áp dụng cho thứ công cụ tạo ra. Tệp, công thức và manifest được tạo là đầu ra chứ không phải tác phẩm phái sinh, nên bạn có thể commit và phân phối mà không có nghĩa vụ nào.

+
+
+
+

Tệp được tạo có chứa dữ liệu cá nhân thật không?

+
+

Không. Mọi thứ bên trong đều được tổng hợp từ một seed. Không có tập dữ liệu nào được đọc, không dịch vụ nào được liên hệ và không nội dung bên thứ ba nào được nhúng. Hãy coi địa chỉ e-mail được tạo là không dùng được thay vì chưa dùng, vì chuỗi ngẫu nhiên nào cũng có thể ngẫu nhiên trùng với địa chỉ thật.

+
+
+
+

Tôi có nhận đúng các tệp giống hệt trên máy khác không?

+
+

Có, từng byte, với cùng công thức và cùng seed. Dự án kiểm thử điều đó ở mỗi thay đổi, và phá vỡ nó đòi hỏi tăng phiên bản chính. Đó là điều cho phép bạn commit một công thức nhỏ thay vì các fixture nhị phân lớn.

+
+
+
+

Nó có cần kết nối internet không?

+
+

Không bao giờ. Không có telemetry, không kiểm tra cập nhật và không có máy khách đám mây, và bản nhị phân dòng lệnh hoàn toàn không biên dịch sẵn ngăn xếp mạng. Nó chạy trên máy không có mạng và trong môi trường doanh nghiệp đóng.

+
+
+
+

Chuyện gì xảy ra nếu tôi yêu cầu kích thước mà một định dạng không thể đạt tới?

+
+

Bạn nhận một lỗi nêu định dạng, kích thước nhỏ nhất có thể, lý do của mức sàn đó và việc nên làm thay thế, và không có tệp nào được ghi. Công cụ không bao giờ làm tròn kích thước một cách lặng lẽ. Mỗi mức sàn đều được liệt kê trên trang định dạng.

+
tfg formats png
+
+
+
+

Tôi có thể tạo một tệp cố ý bị hỏng không?

+
+

Có. Thêm --damage zero-head và tệp ra đúng kích thước bạn yêu cầu, với các byte đầu bị ghi đè bằng số không, nên trình đọc từ chối nó, và manifest nói hệ thống của bạn phải từ chối nó. Chi tiết nằm ở trang về tệp kiểm thử bị hỏng.

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

Những định dạng nào sắp có?

+
+

7z, mp3 và mp4. Hôm nay có 26 định dạng hoạt động trọn vẹn từ đầu đến cuối.

+
+
+
+

Tôi chạy nó trên những hệ thống nào?

+
+

Dòng lệnh chạy trên Windows và Linux cả Intel lẫn ARM, và trên Mac Apple Silicon. Cửa sổ desktop được cung cấp cho Windows trên Intel, Linux trên Intel và Mac Apple Silicon. Mac Intel không được hỗ trợ và không có gì được dựng cho chúng.

+
+
+
+

Tôi có phải cài gì không?

+
+

Không. Tải kho lưu trữ cho hệ thống của bạn, giải nén và chạy bản nhị phân. Không có trình cài đặt, không có runtime cần thêm và không có phụ thuộc cần giải quyết. Nếu bạn có Go, một lệnh go install duy nhất cũng được.

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

Vì sao chạy trên hàng nghìn tệp chậm hơn trên Windows?

+
+

Vì Windows tính phí nhiều hơn cho mỗi đường dẫn nó xem, và một lệnh duyệt hàng nghìn tệp xem hàng nghìn đường dẫn. Đo trên một máy với 3000 tệp 1 kB, verify mất khoảng 0,9 giây trên Windows và khoảng 0,2 giây trên Linux trong container. Đường dẫn đầu ra ngắn hơn làm con số Windows nhỏ đi, vì mỗi thư mục phía trên các tệp đều nằm trong thứ được xem.

+
+
+
+ + +
+

Vẫn đang cân nhắc?

+

+ Trang trường hợp sử dụng cho thấy các việc nó được làm ra để + giải quyết, và trang định dạng liệt kê mỗi định dạng cùng tệp nhỏ + nhất nó có thể tạo. README trong kho mã là tài liệu tham chiếu + đầy đủ. +

+ +

Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.

+
+ +
+ + + + diff --git a/web/public/vi/index.html b/web/public/vi/index.html new file mode 100644 index 00000000..e10d96fc --- /dev/null +++ b/web/public/vi/index.html @@ -0,0 +1,452 @@ + + + + + + +Trình tạo tệp kiểm thử cho QA - kích thước chính xác, 26 định dạng + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

Tạo tệp kiểm thử thật đúng kích thước

+

+ PDF, PNG, DOCX, ZIP - tổng cộng 26 định dạng, và mỗi tệp là + tệp thật mở được bằng phần mềm của nó, ở đúng kích thước bạn yêu cầu. Mỗi lần + chạy còn ghi lại ứng dụng của bạn cần làm gì với từng tệp. Dòng lệnh và cửa sổ desktop, miễn + phí, mã nguồn mở, chạy hoàn toàn trên máy của bạn. +

+ + +

Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.

+
+ +
+ Cửa sổ desktop của Testing Files Generator, sẵn sàng ghi một lô tệp kiểm thử +
Cửa sổ desktop, sẵn sàng ghi một lô tệp. Cùng một động cơ chạy phía sau dòng lệnh.
+
+
+ + + +
+

Vấn đề

+

Làm một tệp kiểm thử thì dễ. Làm đúng một nghìn tệp mới là phần mệt mỏi

+

Bạn đang kiểm thử phần mềm nhận tệp từ con người. Sớm hay muộn bạn sẽ cần:

+
    +
  • một PDF đúng 10 MB, để biết giới hạn tải lên có thật không
  • +
  • ba tệp nằm hai bên giới hạn đó, để bắt lỗi lệch một
  • +
  • 10.000 tệp nhật ký, để xem tác vụ ban đêm làm gì khi thư mục lớn
  • +
  • một ZIP thật sự chứa 200 tài liệu, không phải cái vỏ rỗng với đuôi đúng
  • +
  • một tệp 4 GB, mà không phải giữ tệp 4 GB trong kho mã của bạn
  • +
  • các fixture giống hệt trên laptop và trên máy chủ build, từng byte
  • +
+

+ Đó là thứ nó thay thế. Nó được làm cho kỹ sư QA, tự động hóa kiểm thử và bất kỳ ai có mã đứng sau là + biểu mẫu tải lên, quy trình nhập, bộ phân tích cú pháp hoặc hạn ngạch lưu trữ. +

+
+ +
+

Điều làm nó khác biệt

+

Các trình tạo khác dừng ở các byte. Cái này trả lời điều bài kiểm thử của bạn thật sự hỏi

+

+ Một thư mục tệp vẫn để bạn tự quyết định mỗi tệp chứng minh điều gì. Mỗi lần chạy ở đây ghi một + manifest.json bên cạnh các tệp - danh sách đơn giản mọi thứ đã tạo, và với mỗi mục + là một kỳ vọng được khai báo. +

+

Giả sử endpoint tải lên của bạn cho phép 1 MB. Hãy yêu cầu ba tệp nằm trên ranh giới đó:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
TệpByteHệ thống của bạn nênVì
1mb_under_1b.pdf1048575chấp nhậnnó nằm trong giới hạn
1mb_at_limit.pdf1048576chấp nhậnchính giới hạn được cho phép
1mb_over_1b.pdf1048577từ chốisize_limit
+
+ +

Ba tệp, ba câu trả lời khác nhau, ở dạng máy đọc được. Bài kiểm thử của bạn đọc manifest thay vì bạn tự viết các câu khẳng định:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

Khi câu trả lời phụ thuộc chính sách của riêng bạn, manifest sẽ nói rõ

+

+ Nó ghi unspecified thay vì bịa ra kỳ vọng. Một trình tạo đoán mò tạo ra thất bại giả, + và bộ kiểm thử cứ báo động giả sẽ bị tắt. +

+
+
+ +
+

Preset

+

Chọn câu hỏi, nhận cả bộ

+

+ Preset là một bộ tệp kiểm thử được thiết kế quanh một câu hỏi kiểm thử, để bạn không phải tự tìm ra + tệp nào chứng minh điều gì. Mỗi preset có một trang nói nó thường tìm thấy gì, trong bộ có gì và + mọi thiết lập nó nhận. +

+
    +
  • +

    Rỗng và tối thiểu

    +

    Một tệp hợp lệ và nhỏ nhất mà định dạng cho phép có qua được không?

    +

    empty-and-minimal

    +
  • +
  • +

    Xử lý tên tệp

    +

    Hệ thống của tôi có lưu, hiển thị và trả lại một tên tệp mà nó không ngờ tới không?

    +

    filename-handling

    +
  • +
  • +

    Ranh giới kích thước

    +

    Giới hạn kích thước có được áp dụng đúng nơi nó được khai báo không?

    +

    size-boundaries

    +
  • +
  • +

    Nhập bảng

    +

    Việc nhập bảng của tôi có chịu được những gì công cụ thật xuất ra không?

    +

    tabular-import

    +
  • +
  • +

    Mã hóa văn bản

    +

    Trình đọc của tôi có biết tệp ở mã hóa nào, hay chỉ đoán?

    +

    text-encoding

    +
  • +
  • +

    Kiểm tra tải lên

    +

    Biểu mẫu tải lên của tôi có nhận đúng thứ nó cần và từ chối phần còn lại không?

    +

    upload-validation

    +
  • +
+

Mọi preset, và chúng liên quan thế nào đến công thức

+
+ +
+

Bắt đầu nhanh

+

Ba lệnh để thấy nó hoạt động

+
    +
  1. +

    Tạo một tệp

    +

    Một PNG, đúng hai megabyte:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    Tạo nhiều tệp

    +

    + Mười nghìn tệp nhật ký, mỗi tệp từ một đến tám kilobyte, với kích thước rút từ seed để ngày mai ra + cùng một bộ. Cho mỗi lần chạy một thư mục riêng - manifest là bản ghi duy + nhất về những gì một lần chạy đã ghi, nên công cụ từ chối ghi cái thứ hai đè lên: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    Kiểm tra chúng, rồi xóa

    +

    verify cho bạn biết không có gì đổi chỗ. cleanup xóa đúng những gì đã ghi và không gì khác:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ Kích thước đếm theo 1024, như trình quản lý tệp của bạn, nên 2mb nghĩa là 2097152 byte. + Số byte thuần cũng được. Tài liệu bao gồm công thức, manifest và các + mã thoát. +

+
+ +
+

Bạn nhận được gì

+

Làm cho bộ kiểm thử chạy không cần người trông

+
    +
  • +

    Kích thước chính xác, đến từng byte

    +

    Yêu cầu 10485761 byte và nhận đúng như vậy. Kích thước mà định dạng không thể đạt là một lỗi có lý do, không bao giờ là tệp sai kích thước.

    +
  • +
  • +

    26 định dạng thật

    +

    Không phải số không độn kèm một phần mở rộng. PNG được tạo mở trong trình xem ảnh, DOCX mở trong Word, ZIP giải nén được. Mỗi định dạng được kiểm tra bằng các trình đọc độc lập trước khi phát hành.

    +
  • +
  • +

    Một manifest là một oracle kiểm thử

    +

    Đường dẫn, kích thước, SHA-256, định dạng, seed, phiên bản công cụ - và việc hệ thống của bạn cần làm với tệp.

    +
  • +
  • +

    Tái lập được

    +

    Cùng công thức và cùng seed, cùng các byte, trên mọi máy. Hãy commit một công thức YAML nhỏ thay vì các fixture nhị phân lớn.

    +
  • +
  • +

    Hai giao diện, một động cơ

    +

    Một dòng lệnh làm cho CI và một cửa sổ desktop cho kiểm thử khám phá. Cái nào cũng không phải bản cắt giảm của cái kia, và một bài kiểm thử so sánh chúng từng khả năng một.

    +
  • +
  • +

    Hoàn toàn ngoại tuyến

    +

    Không tài khoản, không đám mây, không telemetry, không kiểm tra cập nhật. Bản nhị phân dòng lệnh hoàn toàn không biên dịch sẵn ngăn xếp mạng.

    +
  • +
+
+ +
+

Tải xuống

+

Chọn bản dựng cho hệ thống của bạn

+

+ Giải nén kho lưu trữ rồi chạy. tfg là dòng lệnh và tfg-gui là cửa sổ + desktop. Không có trình cài đặt và không có gì phải thêm vào máy của bạn. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Hệ thốngDòng lệnhCửa sổ desktop
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

Cái nào được ký, cái nào không

+

+ Bản tải cho Windows và macOS đã được ký, nên khởi động mà không có cảnh báo nhà phát triển không xác + định. Bản Linux thì không, vì Linux desktop không có gì tương đương để ký. Mỗi kho lưu trữ + được liệt kê trong verify-SHA256SUMS.txt trên trang phát hành, để bạn kiểm tra + thứ mình đã tải. +

+
+ +

Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.

+
+ + +
+ + + + diff --git a/web/public/vi/preset/empty-and-minimal/index.html b/web/public/vi/preset/empty-and-minimal/index.html new file mode 100644 index 00000000..4bdb0f31 --- /dev/null +++ b/web/public/vi/preset/empty-and-minimal/index.html @@ -0,0 +1,267 @@ + + + + + + +Tệp kiểm thử hợp lệ nhỏ nhất và tệp rỗng ở mọi định dạng + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Rỗng và tối thiểu

+

Một tệp hợp lệ và nhỏ nhất mà định dạng cho phép có qua được không?

+

+ Preset empty-and-minimal dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • tệp hợp lệ bị từ chối vì quá nhỏ, khi bước kiểm tra đếm byte thay vì đọc chúng
  • +
  • tệp rỗng làm trình đọc sập thay vì được báo cáo
  • +
  • ảnh rộng một pixel chia cho không trên đường tạo ảnh thu nhỏ
  • +
  • bộ lưu trữ đọc không byte như một lần tải lên thất bại và cứ thử lại mãi
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show empty-and-minimal báo cáo:

+
+ + + + + + + +
Tệp28
Target trong công thức của nó28
Tổng kích thước32 667 B
Định dạngavif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.26
unspecifiedTùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không.2
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--formatscác id định dạng cách nhau bằng dấu phẩy, hoặc allallBộ được dựng từ những định dạng nào. Để all cho mọi định dạng của bản dựng này, hoặc nêu những định dạng hệ thống của bạn chấp nhận.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/vi/preset/filename-handling/index.html b/web/public/vi/preset/filename-handling/index.html new file mode 100644 index 00000000..afbcee53 --- /dev/null +++ b/web/public/vi/preset/filename-handling/index.html @@ -0,0 +1,266 @@ + + + + + + +Tên tệp gây rắc rối để kiểm thử - Unicode và độ dài + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Xử lý tên tệp

+

Hệ thống của tôi có lưu, hiển thị và trả lại một tên tệp mà nó không ngờ tới không?

+

+ Preset filename-handling dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • một tên trông như tên khác trên màn hình, trong nhật ký hoặc trong danh sách
  • +
  • một tên bị cắt, xén hoặc viết lại giữa lúc tải lên và lưu trữ
  • +
  • giới hạn độ dài tính bằng ký tự trong khi bộ lưu trữ tính bằng byte
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show filename-handling báo cáo:

+
+ + + + + + + +
Tệp50
Target trong công thức của nó50
Tổng kích thước51 200 B
Định dạngtxt
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.4
unspecifiedTùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không.46
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--formatid định dạng từ trang định dạngtxtĐịnh dạng của mọi tệp trong bộ. Đây là một cờ của chính công cụ, và preset chỉ cho nó một giá trị mặc định.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/vi/preset/index.html b/web/public/vi/preset/index.html new file mode 100644 index 00000000..3c96c218 --- /dev/null +++ b/web/public/vi/preset/index.html @@ -0,0 +1,244 @@ + + + + + + +Preset tệp kiểm thử - bộ tệp dựng sẵn cho câu hỏi QA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Preset tệp kiểm thử, một bộ cho mỗi câu hỏi kiểm thử

+

+ Preset là cả một bộ tệp kiểm thử được thiết kế quanh một câu hỏi, kèm manifest nêu cách hệ thống của + bạn cần phản ứng với từng tệp. Bạn chọn câu hỏi, công cụ dựng bộ. Mỗi preset có trang riêng nói nó + thường tìm thấy gì, trong bộ có gì và mọi thiết lập nó nhận. +

+ + + +
+

Preset khác công thức thế nào?

+

+ Về bản chất thì không khác. Preset là công thức mà công cụ viết cho bạn từ vài thiết lập. tfg + preset eject in công thức đó ra để bạn giữ cạnh các bài kiểm thử và chỉnh sửa, và công + thức của riêng bạn có thể xây trên một preset bằng một dòng, extends: preset: theo + sau là id của nó. +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

Tôi có thể tin các giá trị mặc định không?

+

+ Với các tệp thì có. Với con số chỉ hệ thống của bạn biết, như giới hạn của một biểu mẫu tải lên, giá + trị mặc định là giá trị tạm của chúng tôi, và công cụ nói vậy mỗi lần dùng một giá trị như thế. + Trang của mỗi preset đánh dấu các thiết lập đó, và tfg preset show nói điều đó + trước khi ghi bất cứ gì. +

+
+ +
+ + + + diff --git a/web/public/vi/preset/size-boundaries/index.html b/web/public/vi/preset/size-boundaries/index.html new file mode 100644 index 00000000..0dc87591 --- /dev/null +++ b/web/public/vi/preset/size-boundaries/index.html @@ -0,0 +1,280 @@ + + + + + + +Kiểm thử giới hạn kích thước tải lên - tệp đúng ranh giới + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Ranh giới kích thước

+

Giới hạn kích thước có được áp dụng đúng nơi nó được khai báo không?

+

+ Preset size-boundaries dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • lỗi lệch một ở giới hạn
  • +
  • nhầm MB với MiB, tức 4,8 phần trăm và đủ để lọt một tệp lẽ ra không được qua
  • +
  • giới hạn được áp dụng ở trình duyệt chứ không phải ở máy chủ
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show size-boundaries báo cáo:

+
+ + + + + + + +
Tệp7
Target trong công thức của nó7
Tổng kích thước73 400 320 B
Định dạngpdf
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.4
rejectHệ thống của bạn nên từ chối tệp.3
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--limitkích thước như 2mb10mbGiới hạn kích thước mà hệ thống của bạn khai báo. Mọi thứ khác được đo từ đó. Giá trị mặc định này là giá trị tạm của chúng tôi, không phải giá trị của hệ thống bạn. Hãy truyền giá trị của riêng bạn.
--spreadcác kích thước cách nhau bằng dấu phẩy1B,1kb,1mbVươn ra xa bao nhiêu về hai phía của giới hạn, dưới dạng danh sách kích thước.
--formatid định dạng từ trang định dạngpdfĐịnh dạng của mọi tệp trong bộ. Đây là một cờ của chính công cụ, và preset chỉ cho nó một giá trị mặc định.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

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

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/vi/preset/tabular-import/index.html b/web/public/vi/preset/tabular-import/index.html new file mode 100644 index 00000000..5e3013dd --- /dev/null +++ b/web/public/vi/preset/tabular-import/index.html @@ -0,0 +1,274 @@ + + + + + + +Tệp kiểm thử nhập CSV và Excel - dấu phân cách, tiêu đề + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Nhập bảng

+

Việc nhập bảng của tôi có chịu được những gì công cụ thật xuất ra không?

+

+ Preset tabular-import dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • tệp dùng dấu chấm phẩy bị đọc thành một cột, vì dấu phân cách được giả định thay vì được dò tìm
  • +
  • tệp CRLF bị tách thành các dòng với một dòng trống sau mỗi dòng
  • +
  • bảng không có tiêu đề mà dòng dữ liệu đầu bị nuốt làm tên cột
  • +
  • lần nhập giữ các cột nó hiển thị được và lặng lẽ bỏ phần còn lại
  • +
  • trình đọc lấy bản ghi JSON từng dòng một và dừng ở tài liệu thụt lề đầu tiên
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show tabular-import báo cáo:

+
+ + + + + + + +
Tệp13
Target trong công thức của nó13
Tổng kích thước3 080 060 B
Định dạngcsv, json, xlsx
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.8
unspecifiedTùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không.5
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--rows1 - 200000 dòng1000Bảng tính có bao nhiêu dòng. Tệp được ghi đúng bằng kích thước mà chừng đó dòng đóng gói thành, nên ngân sách ở trên dịch chuyển theo giá trị này.
--columns1 - 32768 cột10Mỗi dòng của bảng tính có bao nhiêu cột. Số dòng nhân số cột có trần, và yêu cầu vượt trần sẽ bị từ chối trước khi ghi bất cứ thứ gì.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/vi/preset/text-encoding/index.html b/web/public/vi/preset/text-encoding/index.html new file mode 100644 index 00000000..8cca97ae --- /dev/null +++ b/web/public/vi/preset/text-encoding/index.html @@ -0,0 +1,267 @@ + + + + + + +Tệp kiểm thử mã hóa văn bản - UTF-8, UTF-16, BOM, CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Mã hóa văn bản

+

Trình đọc của tôi có biết tệp ở mã hóa nào, hay chỉ đoán?

+

+ Preset text-encoding dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • trình đọc giả định UTF-8 và hiện tệp UTF-16 thành cứ ba ký tự mới có một, hoặc thành hàng ô vuông
  • +
  • dấu thứ tự byte bị đọc như nội dung, nên trường đầu tiên của lần nhập bắt đầu bằng ba ký tự lạ
  • +
  • trình nhập đoán mã hóa từ các byte đầu và đoán khác đi với tệp dài hơn
  • +
  • tệp CRLF bị tách thành các dòng với một dòng trống sau mỗi dòng, hoặc ký tự xuống dòng còn sót trong trường cuối
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show text-encoding báo cáo:

+
+ + + + + + + +
Tệp20
Target trong công thức của nó20
Tổng kích thước81 920 B
Định dạngcsv, log, md, txt, xml
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.10
unspecifiedTùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không.10
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--samplekích thước như 2mb4kbMỗi tệp trong bộ lớn bao nhiêu. UTF-16 lưu hai byte cho mỗi ký tự, nên số lẻ bị từ chối.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/vi/preset/upload-validation/index.html b/web/public/vi/preset/upload-validation/index.html new file mode 100644 index 00000000..cd054356 --- /dev/null +++ b/web/public/vi/preset/upload-validation/index.html @@ -0,0 +1,296 @@ + + + + + + +Tệp kiểm thử kiểm tra tải lên - loại, kích thước và tên + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Preset

+

Kiểm tra tải lên

+

Biểu mẫu tải lên của tôi có nhận đúng thứ nó cần và từ chối phần còn lại không?

+

+ Preset upload-validation dựng bằng một lệnh cả một bộ tệp kiểm thử thật cho câu hỏi này, kèm + một manifest.json bên cạnh nêu cách hệ thống của bạn cần phản ứng với từng tệp. Mọi + thứ bên dưới được đọc từ chương trình, ở các giá trị mặc định của phiên bản này. +

+ + +
+

Nó thường tìm thấy gì?

+
    +
  • giới hạn được áp dụng ở trình duyệt chứ không phải ở máy chủ
  • +
  • tệp SVG hoặc HTML bị tưởng là ảnh hay văn bản thuần, một cách để lách tập lệnh qua biểu mẫu
  • +
  • tệp chỉ được kiểm bằng phần mở rộng mà không bao giờ mở, nên PDF đặt tên .jpg vẫn qua
  • +
  • biểu mẫu đọc cả phần thân vào bộ nhớ trước khi xem nó lớn đến đâu
  • +
  • lần tải lên tên PHOTO.JPG bị từ chối trong khi photo.jpg được nhận, hoặc ngược lại
  • +
  • tên có dấu cách, ngoặc hoặc ký tự ngoài ASCII được ghi xuống đĩa không thay đổi
  • +
+
+ + +
+

Trong bộ có gì?

+

Ở các giá trị mặc định, như tfg preset show upload-validation báo cáo:

+
+ + + + + + + +
Tệp71
Target trong công thức của nó22
Tổng kích thước120 639 488 B
Định dạnghtml, jpg, pdf, png, svg, txt
+
+

Và điều manifest của bộ đó mong đợi từ hệ thống của bạn:

+
+ + + + + + + + + +
Mong đợiÝ nghĩaTệp
acceptHệ thống của bạn nên nhận tệp.56
rejectHệ thống của bạn nên từ chối tệp.10
unspecifiedTùy vào quy tắc của hệ thống bạn. Bạn quyết định, rồi kiểm tra điều xảy ra có đúng ý bạn không.5
+
+
+ +
+

Bạn có thể đổi gì?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Thiết lậpNhậnMặc địnhTác dụng
--limitkích thước như 2mb10mbGiới hạn kích thước mà biểu mẫu tải lên của bạn khai báo. Bộ này đi một bước về mỗi phía - muốn tệp ở mọi khoảng cách, hãy chạy preset size-boundaries. Giá trị mặc định này là giá trị tạm của chúng tôi, không phải giá trị của hệ thống bạn. Hãy truyền giá trị của riêng bạn.
--allowcác id định dạng cách nhau bằng dấu phẩyjpg,png,pdfBiểu mẫu của bạn nên chấp nhận những loại nào. Mỗi loại trở thành một tệp thật thuộc loại đó, và chúng là đối chứng dương của cả bộ.
--denycác phần mở rộng cách nhau bằng dấu phẩysvg,html,exe,shBiểu mẫu của bạn nên từ chối những phần mở rộng nào. Phần mở rộng mà bản dựng này không có định dạng vẫn nhận một tệp mang tên đó, chứa văn bản thuần.
--far-over10x, 2x, off2xTệp lớn duy nhất vượt giới hạn bao xa. Tắt đi nếu ghi gấp nhiều lần giới hạn không đáng với dung lượng đĩa.
--bulk0 - 10000 tệp50Số tệp trong lần tải lên hàng loạt. Bằng không thì bỏ hẳn nhóm đó khỏi bộ.
+
+
+ +
+

Chạy nó thế nào?

+

Xem bộ sẽ tốn bao nhiêu, dựng nó, hoặc lấy công thức của nó để chỉnh sửa:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

Hoặc xây trên nó trong công thức của riêng bạn, bên cạnh các bài kiểm thử:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/vi/tai-lieu/index.html b/web/public/vi/tai-lieu/index.html new file mode 100644 index 00000000..37ca06a6 --- /dev/null +++ b/web/public/vi/tai-lieu/index.html @@ -0,0 +1,552 @@ + + + + + + +Tài liệu - lệnh, công thức, manifest, mã thoát + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Tài liệu

+

+ Mọi thứ công cụ làm, sắp xếp theo những câu hỏi mà mọi người thật sự mang đến. + README trong kho mã là tài liệu tham chiếu đầy đủ và luôn khớp với + bản dựng bạn đã tải. +

+ +
+

Có những lệnh nào?

+

Mỗi lệnh làm đúng một việc:

+
tfg generate    tạo tệp, từ công thức hoặc từ các cờ
+tfg validate    kiểm tra công thức và không ghi gì cả
+tfg verify      kiểm tra một thư mục đối chiếu với manifest
+tfg cleanup     xóa các tệp mà manifest liệt kê
+tfg recipe fmt  in công thức ở dạng chuẩn hóa
+tfg preset      dựng một bộ tệp từ một câu hỏi kiểm thử có tên
+tfg formats     liệt kê các định dạng bản dựng này hỗ trợ
+tfg damage      liệt kê các cách bản dựng này có thể cố ý làm hỏng một tệp
+tfg tool        các tiện ích nhỏ cho tệp bạn đã có
+tfg version     in phiên bản công cụ
+tfg license     in giấy phép và ý nghĩa của nó với tệp được tạo
+
+ +
+

Làm sao tạo một tệp đơn có kích thước chính xác?

+

+ Nêu định dạng, kích thước và nơi đặt. Kích thước đếm theo 1024, nên 2mb là 2097152 + byte. Số byte thuần cũng được, nên --size 10485761 yêu cầu đúng chừng đó. +

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

Các cờ hữu ích của generate:

+
+ + + + + + + + + + + + + + + + + +
CờTác dụng
--format <id>định dạng của các tệp, ví dụ txt
--size <size>kích thước chính xác của mỗi tệp, như 10mb hoặc số byte thuần
--size-range <a-b>kích thước rút cho từng tệp từ một khoảng, như 1kb-8kb. Lần rút lấy từ seed
--boundary <size>ba tệp quanh một giới hạn: thấp hơn một byte, đúng giới hạn, cao hơn một byte
--count <n>tạo bao nhiêu tệp. Mặc định 1
--name <template>mẫu tên, ví dụ invoice_{index:04}.txt
--out <dir>thư mục để ghi vào
--seed <n>seed của lần chạy. Cùng seed cho cùng các byte
--set <k>=<v>một thiết lập định dạng, lặp lại được
--damage <name>cố ý làm hỏng tệp, lặp lại được và áp dụng theo thứ tự. Chạy tfg damage để xem danh sách
--expected <outcome>accept, reject, sanitize hoặc unspecified
--dry-runđếm và hiển thị, hoàn toàn không ghi gì
--jsonghi manifest ra đầu ra chuẩn
+
+
+ +
+

Làm sao tạo một tệp cố ý bị hỏng?

+

+ Mọi tệp khác mà công cụ này ghi đều đúng theo cách xây dựng, điều đó trả lời hai trong ba câu hỏi mà + trình kiểm tra tải lên đặt ra. --damage trả lời câu thứ ba - tệp có mở được không. + Tệp được tạo bình thường rồi bị làm hỏng, nên nó vẫn có kích thước bạn đã yêu cầu. +

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

+ Các thiết lập đặt sau dấu hai chấm. Cờ lặp lại được, và thứ tự bạn viết là thứ tự chúng được áp + dụng. tfg damage liệt kê những gì bản dựng này làm được và mỗi kiểu nhận gì. +

+

Trong công thức, khóa là một danh sách, gồm tên hoặc thiết lập:

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

+ Tệp bị làm hỏng nhận expected: reject trong manifest, kèm kiểu hỏng được ghi bên cạnh. + Hai thứ bị từ chối trước khi ghi bất cứ gì, vì mỗi thứ sẽ đặt lên đĩa một tệp mà manifest mô tả + sai: +

+
    +
  • tệp nhỏ hơn mức kiểu hỏng cần, vì nó sẽ ra mà không thay đổi
  • +
  • + expected: accept bên cạnh một kiểu hỏng, vì không gì có thể đáp ứng. Hãy viết + sanitize nếu hệ thống được kiểm thử phải sửa tệp, hoặc unspecified + nếu đó chính là câu hỏi bạn đang đặt +
  • +
+

+ Thứ ba không thể biết trước. Nếu một kiểu hỏng chạy mà không đổi byte nào, tệp đó bị bỏ thay vì được + ghi - lần chạy tiếp tục, nói đó là tệp nào và kết thúc bằng mã thoát một phần. +

+

+ Từng bước, với một bài kiểm thử đọc manifest: cách tạo tệp bị + hỏng để kiểm thử. +

+
+ +
+

Một công thức trông thế nào?

+

+ Công thức là một tệp YAML mô tả cả một lần chạy. Hãy commit nó bên cạnh các bài kiểm thử và fixture + thôi là tệp nhị phân trong kho mã - ai cũng có thể dựng lại chúng, từng byte, từ một tệp vài + trăm ký tự. +

+
# 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
+

+ Mỗi target cần đúng một trong size, size-range, boundary hoặc + contains. Hai cái là lỗi và không cái nào cũng là lỗi. Công thức không hợp lệ ghi + không tệp nào và báo mọi vấn đề cùng lúc thay vì chỉ cái đầu, mỗi cái nêu thiết + lập mà nó nói đến. +

+
+ +
+

Làm sao khai báo hệ thống của tôi cần làm gì với một tệp?

+

Dạng ngắn khi kết quả là đủ, dạng dài khi lý do quan trọng:

+
expected: accept
+
expected:
+  outcome: reject
+  reason: size_limit
+

+ Các kết quả là accept, reject, sanitize và + unspecified. Các lý do là một danh sách đóng để báo cáo có thể nhóm theo chúng: + 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 và size_zero. +

+

+ Một lý do nêu quy tắc đang áp dụng, không phải phán quyết. Vì vậy cùng một lý do có + thể nằm dưới cả hai kết quả - tệp thấp hơn giới hạn một byte là accept, và quy tắc + liên quan vẫn là size_limit. +

+
+ +
+

Manifest chứa gì?

+

+ Nó được ghi bên cạnh các tệp ở cuối mỗi lần chạy, kể cả lần chạy bị ngắt. Một mục cho mỗi tệp: +

+
{
+  "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 được thêm khi lần chạy đến từ một công thức, và preset cùng + overrides khi nó đến từ một preset, nên manifest luôn truy ngược được về thứ đã tạo + ra nó. +

+

+ Mỗi mục còn mang target_id, id của target trong công thức đã tạo tệp, và + summary.by_target đếm số tệp mà mỗi target tạo ra. Một công thức có nhiều target + nhờ vậy kiểm tra được từng target mà không cần đọc tên tệp. +

+
+ +
+

Preset là gì?

+

+ Một bộ tệp dựng sẵn trả lời một câu hỏi kiểm thử thường gặp, để bạn không phải tự thiết kế bộ. + Preset thực chất là công thức bình thường, và eject in công thức ra để bạn chỉnh + sửa từ đó. Mỗi preset có trang riêng nói nó thường tìm thấy gì, trong + bộ có gì và mọi thiết lập nó nhận. +

+
    +
  • +

    Rỗng và tối thiểu

    +

    Một tệp hợp lệ và nhỏ nhất mà định dạng cho phép có qua được không?

    +

    empty-and-minimal

    +
  • +
  • +

    Xử lý tên tệp

    +

    Hệ thống của tôi có lưu, hiển thị và trả lại một tên tệp mà nó không ngờ tới không?

    +

    filename-handling

    +
  • +
  • +

    Ranh giới kích thước

    +

    Giới hạn kích thước có được áp dụng đúng nơi nó được khai báo không?

    +

    size-boundaries

    +
  • +
  • +

    Nhập bảng

    +

    Việc nhập bảng của tôi có chịu được những gì công cụ thật xuất ra không?

    +

    tabular-import

    +
  • +
  • +

    Mã hóa văn bản

    +

    Trình đọc của tôi có biết tệp ở mã hóa nào, hay chỉ đoán?

    +

    text-encoding

    +
  • +
  • +

    Kiểm tra tải lên

    +

    Biểu mẫu tải lên của tôi có nhận đúng thứ nó cần và từ chối phần còn lại không?

    +

    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 cho bạn biết bộ sẽ tốn bao nhiêu trước khi dựng, và nói thẳng khi một con số là + giá trị tạm của chúng tôi chứ không phải giới hạn của bạn. +

+
+ +
+

Các mã thoát có nghĩa gì?

+

+ Mỗi kết cục có mã riêng, đầu ra máy đọc được đi ra đầu ra chuẩn, và lần chạy thất bại không in gì ở + đó. Bảng này là một hợp đồng đóng băng - đổi nghĩa của một mã đòi hỏi tăng phiên bản chính. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MãÝ nghĩa
0Mọi thứ đều chạy tốt.
1Lỗi bất ngờ bên trong công cụ.
2Lệnh hoặc cờ sai.
3Công thức không hợp lệ.
4Định dạng không làm được điều được yêu cầu.
5Đọc hoặc ghi thất bại.
6Không đủ dung lượng đĩa.
7verify phát hiện sai lệch.
8Lần chạy đã xong nhưng không phải mọi thứ đều được tạo.
130Bị ngắt bằng Ctrl+C.
143Bị dừng bởi một tín hiệu, đó là hình dạng của việc CI hết thời gian.
+
+
- 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
+

+ Lần chạy bị dừng bằng Ctrl+C vẫn để lại manifest và không bao giờ để lại tệp ghi dở, nên tác vụ bị + hủy vẫn có thể được dọn bởi tác vụ sau. +

+

+ Workflow có sẵn cho GitHub Actions và GitLab CI: cách tạo tệp + kiểm thử trong pipeline CI. +

+
+ +
+

Có cửa sổ desktop không?

+

+ Có, cùng một động cơ với một cửa sổ phủ lên, cho kiểu kiểm thử không viết kịch bản. Nó không phải + bản cắt giảm: một bài kiểm thử so sánh hai giao diện từng khả năng một, và bất cứ điều gì chỉ + một bên làm được đều phải được khai báo và biện minh thay vì lặng lẽ lệch nhau. +

+

+ Các màn hình là một lô, preset, nhiều lô cùng lúc và giới thiệu. Nó cho biết một lần chạy sẽ tốn bao + nhiêu trước khi ghi gì, báo tiến độ khi đang chạy và có thể hủy giữa chừng mà không để lại tệp + ghi dở. Nó chưa mở được tệp công thức - hiện công thức là việc của dòng lệnh, còn cửa sổ dựng + các lô trong biểu mẫu. +

+
+ +
+ + + + diff --git a/web/public/vi/tao-tep-kich-thuoc-chinh-xac/index.html b/web/public/vi/tao-tep-kich-thuoc-chinh-xac/index.html new file mode 100644 index 00000000..7c914f8f --- /dev/null +++ b/web/public/vi/tao-tep-kich-thuoc-chinh-xac/index.html @@ -0,0 +1,330 @@ + + + + + + +Cách tạo tệp có kích thước chính xác - Windows, Linux, macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Cách tạo tệp có kích thước chính xác

+

+ Hệ thống nào cũng có một lệnh cho việc này, và cả ba nằm bên dưới. Chúng cho bạn một tệp có đúng số + byte cần thiết - và với nhiều bài kiểm thử, thế là đủ. Mọi lệnh trên trang này đã được + chạy trước khi đăng, trên hệ thống mà nó thuộc về. +

+ +
+

Câu trả lời ngắn

+

+ Windows: fsutil file createnew name 10485760. Linux: dd if=/dev/zero of=name + bs=1M count=10. macOS: mkfile 10m name. Kích thước tính bằng byte, và 10 MB + đếm theo cách trình quản lý tệp của bạn đếm là 10485760. +

+
+ +
+

Windows

+

fsutil, và một bản PowerShell không cần thêm gì

+

+ fsutil có sẵn trong Windows. Nó nhận kích thước bằng byte, nên hãy + tính số trước - 10 MB là 10485760, 100 MB là 104857600, 1 GB là 1073741824. +

+
fsutil file createnew test10mb.bin 10485760
+

+ Đo trên Windows 11: nó chạy từ một dấu nhắc thường mà không cần quyền nâng cao, và tệp ra đúng + 10485760 byte. +

+

PowerShell làm được điều tương tự mà không gọi chương trình khác, và hiểu đơn vị:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ 10MB trong PowerShell nghĩa là 10485760 byte, cùng cách đếm cơ số 1024 mà Explorer + dùng, nên hai lệnh ở trên cho cùng một kích thước. +

+
+ +
+

Linux

+

dd, truncate và fallocate, và sự khác biệt làm người ta vấp

+

dd là lệnh ai cũng biết. Nó thật sự ghi các byte:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate chạy tức thì, và đó là cái bẫy. Đo trên Alpine Linux, tệp báo 10485760 byte và + chiếm không khối nào - nó là một tệp thưa. Bất cứ thứ gì đọc + nó nhận mười megabyte số không, nhưng đĩa chưa bao giờ nhường chỗ: +

+
truncate -s 10M test10mb.bin
+

+ Điều đó ổn để kiểm thử giới hạn tải lên và gây hiểu lầm khi kiểm thử hạn ngạch đĩa. + fallocate là lệnh nên dùng khi dung lượng phải là thật: +

+
fallocate -l 10M test10mb.bin
+

Và khi nội dung phải không nén được, để trình nén không thể ép nó nhỏ lại:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile, không phải tệp thưa, và hai lệnh bạn đã biết

+

+ macOS có sẵn mkfile. Đo trên macOS 26.6.2: 10485760 byte và 20480 khối, nên dung lượng + thật sự được cấp phát chứ không chỉ hứa hẹn: +

+
mkfile 10m test10mb.bin
+

dd và truncate cũng có và hoạt động như trên Linux:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

Khi điều này ngừng hiệu quả

+

Tệp đúng kích thước không phải tệp đúng loại

+

+ Mọi thứ ở trên cho bạn một khối số không. Điều đó đủ khi thứ được kiểm thử chỉ nhìn kích thước - + giới hạn tải lên, hạn ngạch, một lần truyền. Nó thôi đủ ngay khi có thứ gì mở + tệp. +

+

+ Đã đo, và đáng để tự làm: tạo tệp 2 MB bằng fsutil, đặt tên photo.png rồi + đưa cho một thư viện ảnh. Pillow trả lời cannot identify image file. Nó không phải + PNG. Nó chưa bao giờ là - chỉ cái tên nói vậy. +

+

+ Điều đó quan trọng hơn vẻ ngoài, vì bài kiểm thử sau đó hỏng theo hướng nào. + Endpoint tải lên từ chối tệp, bài kiểm thử của bạn xanh và bạn kết luận giới hạn kích thước hoạt + động. Nó không từ chối vì kích thước. Nó từ chối vì các byte không phải ảnh, và quy tắc bạn định + kiểm thử chưa bao giờ được chạm tới. +

+
    +
  • bộ phân tích từ chối nó trước khi xét bất kỳ quy tắc kích thước nào
  • +
  • bước tạo ảnh thu nhỏ hỏng và lỗi bạn đọc là về ảnh thu nhỏ
  • +
  • phần mềm diệt virus hoặc bước kiểm tra nội dung từ chối nó vì lý do thứ ba
  • +
  • trình xem không hiện gì, và không ai biết đó có phải lỗi hay không
  • +
+
+ +
+

Con đường còn lại

+

Một tệp thật của định dạng đó, đúng kích thước bạn đã yêu cầu

+

+ Đây là việc Testing Files Generator làm. Tệp là tệp thật của định dạng - mở được bằng phần mềm của + nó - và có đúng số byte bạn đã yêu cầu, chính xác đến từng byte: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ Yêu cầu kích thước mà định dạng không thể đạt và bạn nhận một lỗi nêu mức sàn cùng lý do, không bao + giờ là tệp sai kích thước. Trang định dạng liệt kê mỗi định dạng + cùng tệp nhỏ nhất nó có thể tạo. +

+

Và một giới hạn là ba trường hợp kiểm thử chứ không phải một, nên công cụ dựng cả ba:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ Điều đó cho bạn 10485759, 10485760 và 10485761 byte, cùng manifest nói tệp nào hệ thống của bạn nên + chấp nhận và tệp nào nên từ chối. Trang trường hợp sử dụng + đi qua việc đó và bốn việc khác mà nó được làm ra để giải quyết. +

+ +

Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.

+
+ +
+

Vậy nên dùng cái nào?

+
    +
  • +

    Dùng lệnh của hệ thống

    +

    + Khi không có gì mở tệp. Kiểm thử giới hạn kích thước trên endpoint kiểm tra kích thước trước, một + lần truyền, một hạn ngạch, tình trạng đầy đĩa. Chỉ một dòng và đã được cài sẵn. +

    +
  • +
  • +

    Dùng một trình tạo thật

    +

    + Khi có thứ gì phân tích, kết xuất, nhập hoặc giải nén tệp - và khi ngày mai bạn cần cùng các fixture + đó, trên máy khác, từng byte. +

    +
  • +
+

+ Cả hai đều có trên trang này vì cả hai đúng trong một phần thời gian. Sai lầm cần tránh là dùng cái + đầu ở nơi cần cái sau và coi bài kiểm thử xanh là bằng chứng. +

+
+ +
+ + + + diff --git a/web/public/vi/tep-kiem-thu-bi-hong/index.html b/web/public/vi/tep-kiem-thu-bi-hong/index.html new file mode 100644 index 00000000..611e9b57 --- /dev/null +++ b/web/public/vi/tep-kiem-thu-bi-hong/index.html @@ -0,0 +1,379 @@ + + + + + + +Tệp kiểm thử bị hỏng - tệp hỏng đúng kích thước + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Trường hợp sử dụng

+

Cách tạo tệp bị hỏng để kiểm thử

+

+ Một trình kiểm tra chỉ từng được cho xem tệp lành thì chưa thực sự được kiểm thử. Đây là cách có + được một tệp cố ý làm hỏng, ra đúng kích thước bạn yêu cầu và mang theo manifest + nói hệ thống của bạn phải làm gì với nó. +

+ +
+

Câu trả lời ngắn

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out ghi một tệp PNG + đúng 2097152 byte với các byte đầu là số không, và manifest bên cạnh ghi rằng hệ thống của bạn + phải từ chối nó. +

+
+ +
+

Cách thường dùng

+

Vì sao tệp làm hỏng bằng tay là một bài kiểm thử tồi

+

+ Cách thường dùng là trình soạn thảo hex, một script đảo vài byte ngẫu nhiên, hoặc cắt ngắn tệp bằng + head hay truncate. Dùng được một lần, rồi nó làm bạn tốn công: +

+
    +
  • + Mỗi lần một khác. Byte ngẫu nhiên rơi vào chỗ mới ở mỗi lần chạy, nên lỗi hôm thứ + Ba có thể không quay lại vào thứ Tư. +
  • +
  • + Nó đổi kích thước. Tệp bị cắt ngắn nhỏ hơn giới hạn mà nó phải nằm dưới, nên bước + kiểm tra kích thước trả lời trước bước kiểm tra nội dung và bài kiểm thử đạt vì lý do sai. +
  • +
  • + Nó thường không ai nhận ra. Văn bản thuần vẫn đọc được khi đổi một byte ở giữa, và + một trình đọc ảnh dễ tính chỉ việc vẽ nó ra, nên tệp lẽ ra phải hỏng lại được chấp nhận. +
  • +
  • + Nó không nói gì về điều phải xảy ra. Tệp chỉ là các byte, và ai đọc bài kiểm thử + sau đó phải đoán xem ý định là chấp nhận hay từ chối. +
  • +
+
+ +
+

Bạn nhận được gì

+

Tệp bị hỏng vẫn có kích thước bạn đã yêu cầu

+

+ Tệp được tạo bình thường rồi mới bị làm hỏng, trên đường ghi xuống đĩa. Nó giữ kích thước bạn yêu + cầu, và cùng một lệnh ghi lại đúng các byte đó. +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ Cài đặt viết sau dấu hai chấm. Tùy chọn có thể lặp lại, và các hỏng hóc được áp dụng theo thứ tự bạn + viết. Nó dùng được với từng định dạng trong 26 định dạng. +

+
+ +
+

Nó làm được gì

+

Có những kiểu hỏng nào?

+

+ Đây là danh sách chương trình in ra, được đọc từ chính nó khi trang này được dựng. tfg + damage in ra cùng danh sách đó, và tfg damage <id> cho biết một kiểu + nhận những gì. +

+
+ + + + + + + + + + + + + + + + + +
Hỏng hócNó làm gì với các byteTệp nhỏ nhấtCài đặt
zero-headGhi đè các byte đầu của tệp bằng số không, giữ nguyên độ dài. Hầu hết trình đọc nhìn vào đó trước, nên gần như mọi thứ đều nhận ra hỏng hóc này.8bytes
+
+

+ zero-head ghi số không đè lên phần đầu tệp. Hầu hết trình đọc nhìn vào đó trước, vào + chữ ký và phần đầu cho biết tệp là gì, nên gần như trình đọc nào cũng nhận ra. Văn bản thuần và + nhật ký không có chữ ký và cũng bị từ chối, vì một chuỗi byte không không phải là văn bản. Dưới + bốn byte, một số định dạng ra với hỏng hóc mà không trình đọc nào phàn nàn, đó là lý do cài đặt + bắt đầu từ bốn. +

+
+ +
+

Manifest nói gì

+

Một manifest nói điều phải xảy ra

+

+ Mỗi tệp bị hỏng nhận một mục nói rằng hệ thống của bạn phải từ chối nó, với hỏng hóc được ghi bên + cạnh: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ Hai yêu cầu bị từ chối trước khi có gì được ghi, vì mỗi yêu cầu sẽ để lại trên đĩa một tệp mà + manifest mô tả sai: +

+
    +
  • một tệp nhỏ hơn mức hỏng hóc cần, sẽ ra mà không bị đổi
  • +
  • + expected: accept cạnh một hỏng hóc, vì không gì có thể đáp ứng được. Viết + sanitize nếu hệ thống của bạn phải sửa tệp, hoặc unspecified nếu đó + chính là câu hỏi bạn đang đặt ra +
  • +
+
+ +
+

Trong một công thức

+

Tệp lành và tệp hỏng trong một lần chạy

+

+ Đặt cả hai vào một công thức, và manifest mang kỳ vọng của từng tệp, nên bài kiểm thử không cần danh + sách tệp nào là tệp nào: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

Trong một bài kiểm thử

+

Biến nó thành một bài kiểm thử

+

+ Bài kiểm thử đọc manifest và kiểm tra điều đã xảy ra có đúng như điều đã khai báo. Nó không cần danh + sách tên tệp: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ Một lần từ chối tốt là một lần từ chối gọn. Một thông báo nói điều gì sai là câu trả lời bạn muốn. + Lỗi máy chủ, treo máy hoặc một tệp lưu dở là khiếm khuyết mà bài kiểm thử này sinh ra để tìm. +

+
+ +
+

Tiếp theo

+

Đi đâu từ đây

+ +
+ +
+ + + + diff --git a/web/public/vi/tep-kiem-thu-trong-ci/index.html b/web/public/vi/tep-kiem-thu-trong-ci/index.html new file mode 100644 index 00000000..09f194d0 --- /dev/null +++ b/web/public/vi/tep-kiem-thu-trong-ci/index.html @@ -0,0 +1,375 @@ + + + + + + +Tệp kiểm thử trong CI - GitHub Actions, GitLab CI và PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Trường hợp sử dụng

+

Cách tạo tệp kiểm thử trong pipeline CI

+

+ Một fixture nhị phân trong kho mã nằm lại mãi trong lịch sử của nó, không thể review trong diff và + trở nên bất khả thi khi tệp lớn. Hãy tạo tệp ngay trong pipeline từ một công thức. Công thức là + văn bản, các byte ra giống hệt mỗi lần, và một bước cuối chứng minh không có gì xê dịch. +

+ +
+

Câu trả lời ngắn

+

+ Cài tfg, chạy tfg generate fixtures.yaml --out ./fixtures trước các bài + kiểm thử và tfg verify ./fixtures/manifest.json sau đó. Cả hai bước tự làm bản dựng + thất bại, với một mã thoát nói lý do. +

+
+ +
+

Vì sao không commit

+

Vì sao fixture không nên nằm trong kho mã

+
    +
  • + Nó ở lại trong lịch sử. Xóa một tệp nhị phân sau này không làm bản clone nhỏ đi, vì + mọi phiên bản của nó vẫn còn đó. +
  • +
  • + Diff không cho thấy cái gì đã đổi. Người review thấy một tệp PDF khác đi và không + biết gì thêm. Công thức thì đổi một dòng. +
  • +
  • + Tệp lớn không vừa. GitHub từ chối một lần push có tệp lớn hơn 100 MB, nên bài kiểm + thử giới hạn tải lên 500 MB không có gì để commit. +
  • +
+

+ Thứ cần commit là công thức. Cùng công thức và cùng seed ghi ra cùng các byte trên mọi máy, nên tệp + tạo trong pipeline chính là tệp bạn có trên laptop. +

+
+ +
+

Công thức

+

Một công thức nằm cạnh các bài kiểm thử

+

+ Công thức này ghi hai mươi lăm hóa đơn phải được chấp nhận và hai ảnh vượt giới hạn phải bị từ chối, + và manifest ghi cả hai kỳ vọng: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml kiểm tra nó mà không ghi gì, và nêu mọi vấn đề cùng một lúc. +

+
+ +
+

GitHub Actions

+

Một workflow cài công cụ và dựng các fixture

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ Dòng checksum so sánh tệp lưu trữ với verify-SHA256SUMS.txt của cùng bản phát hành. + Phiên bản được ghim cố định, nên một bản phát hành mới không bao giờ đổi một bản dựng bạn chưa + đụng tới. +

+
+ +
+

GitLab CI

+

Cùng việc đó dưới dạng job GitLab

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

Khi nó chuyển đỏ

+

Điều gì làm một bước thất bại, và vì sao

+

+ Mỗi kết cục có mã thoát riêng, nên bước tự thất bại và nhật ký nói là mã nào. Những mã một pipeline + gặp: +

+
    +
  • 3 - công thức không hợp lệ. Không có gì được ghi, và mọi vấn đề đều được nêu
  • +
  • 4 - định dạng không làm được điều được yêu cầu, ví dụ kích thước dưới mức nhỏ nhất của nó
  • +
  • 6 - không đủ dung lượng đĩa
  • +
  • 7 - tfg verify tìm thấy một tệp không khớp với manifest của nó
  • +
  • 8 - lần chạy đã xong, nhưng không phải mọi thứ đều được tạo ra
  • +
+

+ Lần chạy thất bại không in gì ra đầu ra chuẩn, nên trình phân tích nhật ký không bao giờ nhầm một + lỗi là dữ liệu. Cả bảng nằm ở trang tài liệu. +

+
+ +
+

PowerShell

+

Script PowerShell cần thêm một dòng

+

+ PowerShell không mang mã thoát của một chương trình ra khỏi tệp .ps1. Chạy một script + với -File và script trả lời 0 ngay cả khi công cụ bên trong đã từ chối + công việc, nên một bản dựng lẽ ra phải đỏ lại thành xanh. Dòng cuối là toàn bộ cách sửa: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ PowerShell hành xử như vậy, không phải điều gì của công cụ này. cmd, bash + và zsh không cần thêm gì. +

+
+ +
+

Nhiều job

+

Chia sẻ fixture giữa các job

+

+ Thường không cần tải chúng lên. Vì cùng công thức ghi cùng các byte, mỗi job có thể chạy tfg + generate của riêng nó, nhanh hơn một lần tải lên rồi tải xuống. Khi một job phải nhận tệp + từ job khác, hãy chạy tfg verify trên manifest sau khi chuyển, và nó cho biết thứ + đến nơi có đúng là thứ đã được ghi không. +

+
+ +
+

Tiếp theo

+

Đi đâu từ đây

+ +
+ +
+ + + + diff --git a/web/public/vi/truong-hop-su-dung/index.html b/web/public/vi/truong-hop-su-dung/index.html new file mode 100644 index 00000000..943bf9c5 --- /dev/null +++ b/web/public/vi/truong-hop-su-dung/index.html @@ -0,0 +1,315 @@ + + + + + + +Trường hợp sử dụng - giới hạn tải lên, fixture CI, kiểm thử + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Mọi người dùng nó để làm gì

+

+ Năm việc xuất hiện trong gần như mọi dự án nhận tệp từ con người, và lệnh làm từng việc. Mỗi ví dụ + bên dưới chạy đúng như được viết. +

+ +
+

Giới hạn tải lên

+

Kiểm thử xem giới hạn kích thước tệp có được áp dụng đúng nơi nó nói không

+

+ Một giới hạn là ba trường hợp kiểm thử chứ không phải một: ngay dưới, đúng bằng và ngay trên. Làm + tay thì phải tính số byte và hy vọng không lệch một. Hãy yêu cầu cả bộ: +

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

+ Bạn nhận ba PDF thật có 1048575, 1048576 và 1048577 byte, cùng manifest nói hai tệp đầu nên được + chấp nhận và tệp thứ ba bị từ chối vì size_limit. Bài kiểm thử của bạn đọc kỳ vọng + thay vì bạn viết tay ba câu khẳng định - và khi giới hạn đổi, bạn đổi một con số rồi chạy lại. +

+

+ Điều tương tự dùng được không cần preset khi bạn muốn một bộ ranh giới đơn ngay trong lệnh: +

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

Tích hợp liên tục

+

Giữ fixture ngoài kho mã mà không mất chúng

+

+ Fixture nhị phân lớn làm kho mã clone chậm và khó review, và không ai biết cái gì đã đổi khi thay + một tệp. Công thức là vài trăm ký tự YAML dựng lại các tệp giống hệt - từng byte, trên + mọi máy - vì mọi tệp đều suy ra từ seed của lần chạy. +

+
- 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
+

+ Mỗi kết cục có mã thoát riêng, nên pipeline phân biệt được công thức xấu, đĩa đầy và sai lệch khi + xác minh. Lần chạy thất bại không in gì ra đầu ra chuẩn, nhờ vậy trình phân tích nhật ký không + đọc lỗi thành dữ liệu. +

+
+ +
+

Quy mô

+

Tìm hiểu chuyện gì xảy ra khi thư mục lớn

+

+ Quy trình nhập, tác vụ ban đêm và danh sách thư mục hoạt động khác nhau ở mười nghìn tệp so với mười + tệp. Kích thước rút từ một khoảng làm bộ trông như lưu lượng thật thay vì mười nghìn tệp giống + hệt, và lần rút lấy từ seed, nên bộ ngày mai vẫn như cũ. +

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

+ Kiểm tra một lần chạy sẽ tốn bao nhiêu trước khi nó ghi gì, điều quan trọng khi tổng được đo bằng + gigabyte: +

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

+ Lần chạy lớn hơn dung lượng trống của đĩa bị từ chối trước khi byte đầu tiên được ghi, thay vì làm + đầy đĩa rồi hỏng giữa chừng. +

+
+ +
+

Tệp nén

+

Kiểm thử trình giải nén với tệp nén thật sự chứa tệp

+

+ Tệp nén rỗng có đuôi đúng chẳng chứng minh gì về mã mở nó và duyệt những gì bên trong. Hãy khai báo + nội dung và tệp nén thật sự chứa nó: +

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

+ Độ sâu lồng nhau, số mục và kích thước phần bên trong đều là những thứ mà quy trình nhập có ý kiến + riêng, và đây là cách bạn biết ý kiến đó là gì. +

+
+ +
+

Bộ phân tích và trình xem

+

Kiểm tra mã của chính bạn đọc một định dạng như phần mềm thật

+

+ Mỗi định dạng ở đây được kiểm tra bằng trình đọc độc lập trước khi phát hành - PNG được mở và so + sánh pixel, DOCX được các thư viện riêng đọc lại, tệp nén được giải nén. Nghĩa là tệp mà bộ phân + tích của bạn từ chối là một phát hiện về bộ phân tích của bạn, không phải về trình tạo. +

+
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
+

+ Trang định dạng liệt kê các thiết lập mỗi định dạng nhận và tệp nhỏ + nhất mà mỗi định dạng có thể có. +

+
+ +
+

Hướng dẫn

+

Hai trong số đó, chi tiết hơn

+
    +
  • + Tệp kiểm thử bị hỏng - một tệp cố ý làm hỏng, đúng kích + thước, với điều phải xảy ra với nó được ghi trong manifest. +
  • +
  • + Tệp kiểm thử trong CI - một workflow GitHub Actions, một + job GitLab và các mã thoát làm bản dựng thất bại. +
  • +
+
+ +
+

Dành cho ai

+

+ Kỹ sư QA, tự động hóa kiểm thử và bất kỳ ai có mã đứng sau là biểu mẫu tải lên, quy trình nhập, bộ + phân tích cú pháp hoặc hạn ngạch lưu trữ. Nó chạy trên máy hoàn toàn không có mạng, điều quan + trọng trong môi trường doanh nghiệp đóng nơi trình tạo chạy trên trình duyệt không phải một lựa + chọn. +

+ +

Miễn phí, mã nguồn mở, GPL-3.0. Không cần đăng ký. Bản tải cho Windows và macOS đã được ký nên khởi động không cảnh báo.

+
+ +
+ + + + diff --git a/web/public/zh-hans/corrupt-test-files/index.html b/web/public/zh-hans/corrupt-test-files/index.html new file mode 100644 index 00000000..36fd64d2 --- /dev/null +++ b/web/public/zh-hans/corrupt-test-files/index.html @@ -0,0 +1,357 @@ + + + + + + +损坏的测试文件 - 大小精确的损坏文件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

使用场景

+

如何制作用于测试的损坏文件

+

+ 一个只见过完好文件的校验器,并没有真正被测试过。下面介绍如何得到一个故意弄坏的文件:它的大小恰好就是你要求的大小,并附带一份清单,说明你的系统该如何处理它。 +

+ +
+

简短回答

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out 会写出一个恰好 2097152 字节的 + PNG,它的开头几个字节是零,旁边的清单则记录你的系统应该拒绝它。 +

+
+ +
+

常见做法

+

为什么手工弄坏的文件不是好测试

+

+ 常见做法是用十六进制编辑器、用脚本翻转几个随机字节,或用 head 或 truncate 把文件截短。它们能用一次,之后就要付出代价: +

+
    +
  • + 每次都不一样。随机字节每次运行都落在新的位置,所以周二出现的失败,周三可能不再出现。 +
  • +
  • + 它会改变大小。被截短的文件比它本应低于的限制还要小,于是大小检查先于内容检查给出回答,测试因为错误的原因而通过。 +
  • +
  • + 它常常没被发现。纯文本中间改了一个字节仍然可以读,宽容的图像读取器只会照样画出来,于是本该损坏的文件被接受了。 +
  • +
  • + 它没有说明应该发生什么。文件只是一堆字节,之后读这个测试的人只能猜测当初想要的是接受还是拒绝。 +
  • +
+
+ +
+

你会得到什么

+

损坏的文件仍然是你要求的大小

+

+ 文件先正常生成,再在写入磁盘的途中被弄坏。它保持你要求的大小,同一条命令再次写出的字节也完全相同。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 设置写在冒号之后。该选项可以重复,损坏按你写下的顺序依次应用。它适用于全部 26 种格式。 +

+
+ +
+

它能做什么

+

有哪些损坏方式?

+

+ 这是程序打印出的列表,在构建本页时从程序中读取。tfg damage 打印的是同一份列表,tfg damage <id> + 则说明其中某一项接受什么设置。 +

+
+ + + + + + + + + + + + + + + + + +
损坏方式对字节做了什么最小文件设置
zero-head用零覆盖文件开头的若干字节,长度保持不变。大多数读取器最先看的就是那里,所以几乎任何东西都会发现这种损坏。8bytes
+
+

+ zero-head + 把文件开头写成零。大多数读取器最先看的就是那里,也就是说明文件是什么的签名和文件头,所以几乎任何读取器都会发现。纯文本和日志没有签名,同样会被拒绝,因为一串零字节不是文本。低于四个字节时,有些格式产生的损坏没有任何读取器会抱怨,这就是该设置从四开始的原因。 +

+
+ +
+

清单怎么说

+

一份说明应发生什么的清单

+

+ 每个损坏的文件都会得到一条记录,说明你的系统应该拒绝它,损坏方式记在旁边: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 有两种请求会在写入任何内容之前被拒绝,因为各自都会在磁盘上留下一个清单描述有误的文件: +

+
    +
  • 比损坏所需更小的文件,它会原样输出
  • +
  • + 在损坏旁边写 expected: accept,因为没有什么能满足它。如果你的系统本应修复文件,请写 + sanitize,如果你要问的恰恰就是这一点,请写 unspecified +
  • +
+
+ +
+

在配方中

+

一次运行中的完好文件和损坏文件

+

+ 把两者放进同一个配方,清单就带有每个文件的预期,测试因此不需要一份说明哪个是哪个的列表: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

在测试中

+

把它变成测试

+

+ 测试读取清单,检查实际发生的是否就是所声明的。它不需要文件名列表: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 好的拒绝是干净的拒绝。一条说明错在哪里的消息,就是你想要的答案。服务器错误、卡死或只保存了一半的文件,正是这个测试要找出来的缺陷。 +

+
+ +
+

接下来

+

从这里去哪里

+ +
+ +
+ + + + diff --git a/web/public/zh-hans/create-file-exact-size/index.html b/web/public/zh-hans/create-file-exact-size/index.html new file mode 100644 index 00000000..0356e549 --- /dev/null +++ b/web/public/zh-hans/create-file-exact-size/index.html @@ -0,0 +1,309 @@ + + + + + + +如何创建指定大小的文件 - Windows、Linux、macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

如何创建大小精确的文件

+

+ 每个系统都有对应的命令,下面列出了全部三个。它们能给你一个字节数恰好正确的文件,对许多测试来说这就够了。本页的每条命令在发布前都在对应系统上运行过。 +

+ +
+

简短回答

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。大小以字节计,按文件管理器的算法,10 MB 就是 10485760 字节。 +

+
+ +
+

Windows

+

fsutil,以及无需额外工具的 PowerShell 写法

+

+ fsutil 随 Windows 提供。它接受以字节为单位的大小,所以先算出数字:10 MB 是 10485760,100 MB 是 + 104857600,1 GB 是 1073741824。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ 在 Windows 11 上实测:它可以在普通命令提示符下运行,不需要管理员权限,生成的文件恰好是 10485760 字节。 +

+

PowerShell 不需要调用其他程序也能做到同样的事,并且认识单位:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell 中的 10MB 表示 10485760 字节,与资源管理器使用的 1024 进制算法相同,所以上面两条命令得到的大小一样。 +

+
+ +
+

Linux

+

dd、truncate 和 fallocate,以及容易坑人的差别

+

dd 是人人皆知的那个。它真的会写入这些字节:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate 是瞬间完成的,而这正是陷阱所在。在 Alpine Linux 上实测,该文件报告 10485760 + 字节,却占用零个块,它是一个稀疏文件。任何读取它的程序会得到十兆字节的零,但磁盘从未真正让出空间: +

+
truncate -s 10M test10mb.bin
+

+ 用它测试上传限制没问题,但用来测试磁盘配额就会误导人。当空间必须真实占用时,应该使用 fallocate: +

+
fallocate -l 10M test10mb.bin
+

而当内容必须不可压缩,让归档程序无法再把它压小时:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile(不是稀疏文件),以及你已经熟悉的另外两个

+

+ macOS 自带 mkfile。在 macOS 26.6.2 上实测:10485760 字节和 20480 个块,所以空间是真正分配的,而不只是承诺: +

+
mkfile 10m test10mb.bin
+

dd 和 truncate 也都有,行为与 Linux 上相同:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

这种办法在哪里失效

+

大小正确的文件不等于类型正确的文件

+

+ 以上所有方法给你的都是一块零。如果被测对象只看大小,比如上传限制、配额或传输,这就够了。一旦有任何东西打开这个文件,就不够了。 +

+

+ 实测过,而且值得你自己试一试:用 fsutil 做一个 2 MB 的文件,把它命名为 photo.png,再交给图像库处理。Pillow 会回答 + cannot identify image file。它不是 PNG,从来就不是,只是名字这么说。 +

+

+ 这比听起来更重要,因为测试随后会以哪种方式失败。你的上传接口拒绝了这个文件,测试变绿,于是你断定大小限制有效。其实它并不是因为大小而拒绝的,而是因为这些字节不是图片,你本想测试的规则根本没有被触及。 +

+
    +
  • 解析器在检查任何大小规则之前就拒绝了它
  • +
  • 缩略图步骤失败,你读到的错误是关于缩略图的
  • +
  • 杀毒软件或内容检查出于第三个原因拒绝了它
  • +
  • 查看器什么也不显示,没人说得清这是不是那个 bug
  • +
+
+ +
+

另一种办法

+

该格式的真实文件,大小恰好是你要求的

+

+ 这就是 Testing Files Generator 所做的事。文件是该格式的真实文件,能在对应软件中打开,字节数恰好等于你的要求,精确到字节: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 请求格式无法达到的大小,你会得到一个说明下限及其原因的错误,绝不会得到大小错误的文件。格式页面列出了每种格式及其能生成的最小文件。 +

+

而一个限制对应的是三个测试用例,而不是一个,所以工具会把三个都构建出来:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 这会给你 10485759、10485760 和 10485761 + 字节的文件,以及一份清单,说明你的系统应该接受哪些、拒绝哪些。使用场景页面会讲解这一点,以及它为之而生的另外四项任务。 +

+ +

免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。

+
+ +
+

那么该用哪个?

+
    +
  • +

    使用系统命令

    +

    + 当没有任何东西会打开这个文件时。例如在先检查大小的接口上测试大小限制、传输、配额、磁盘写满的情况。只要一行,而且已经装好了。 +

    +
  • +
  • +

    使用真正的生成器

    +

    + 当有任何东西要解析、渲染、导入或解压这个文件时,以及当你明天要在另一台机器上拿到逐字节相同的 fixture 时。 +

    +
  • +
+

+ 两种办法都在本页,因为它们各自在一部分情况下是对的。要避免的错误,是在需要后者的地方用了前者,还把变绿的测试当成证明。 +

+
+ +
+ + + + diff --git a/web/public/zh-hans/docs/index.html b/web/public/zh-hans/docs/index.html new file mode 100644 index 00000000..c3e26a1a --- /dev/null +++ b/web/public/zh-hans/docs/index.html @@ -0,0 +1,522 @@ + + + + + + +文档 - 命令、配方、清单、退出码 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

文档

+

+ 工具的全部功能,按人们实际会问的问题来组织。仓库中的 README 是完整参考,并且始终与你下载的版本一致。 +

+ +
+

有哪些命令?

+

每个命令只做一件事:

+
tfg generate    根据配方或参数生成文件
+tfg validate    检查配方,不写入任何内容
+tfg verify      对照清单检查目录
+tfg cleanup     删除清单中列出的文件
+tfg recipe fmt  以规范形式打印配方
+tfg preset      根据具名测试问题构建一组文件
+tfg formats     列出此版本支持的格式
+tfg damage      列出此版本可以故意破坏文件的方式
+tfg tool        处理现有文件的小工具
+tfg version     打印工具版本
+tfg license     打印许可证及其对生成文件的含义
+
+ +
+

如何生成一个大小精确的文件?

+

+ 指定格式、大小和输出位置。大小按 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>围绕一个限制的三个文件:小一字节、恰好等于限制、大一字节
--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将清单写到标准输出
+
+
+ +
+

如何做一个故意损坏的文件?

+

+ 本工具写出的其他所有文件在构造上都是正确的,这回答了上传校验器会问的三个问题中的两个。--damage + 回答第三个,也就是文件到底能不能打开。文件先正常生成,再被破坏,因此仍然保持你请求的大小。 +

+
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,并在旁边记录所做的破坏。有两种情况会在写入任何内容之前被拒绝,因为各自都会在磁盘上留下清单描述有误的文件: +

+
    +
  • 文件小于破坏所需的大小,因为它会原样输出
  • +
  • + 在破坏旁边写 expected: accept,因为没有任何文件能满足它。如果被测系统应该修复该文件,请写 + sanitize;如果你问的正是这个问题,请写 unspecified +
  • +
+

+ 第三种无法提前得知。如果某个破坏运行后没有改动任何字节,该文件会被丢弃而不是写出,运行会继续,指出是哪个文件,并以部分完成的退出码结束。 +

+

+ 一步一步来,附带一个读取清单的测试:如何制作用于测试的损坏文件。 +

+
+ +
+

配方是什么样子?

+

+ 配方是一个描述整次运行的 YAML 文件。把它与测试放在一起提交,fixture 就不再是仓库里的二进制文件,任何人都可以用一个只有几百个字符的文件逐字节重建它们。 +

+
# 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
+

+ 每个 target 必须恰好有 size、size-range、boundary 或 + contains + 中的一个。两个是错误,一个都没有也是错误。无效的配方不会写入任何文件,并且会一次报告所有问题,而不是只报第一个,每个问题都会指明所涉及的设置。 +

+
+ +
+

如何声明我的系统应如何处理某个文件?

+

只需结果时用短写法,原因重要时用长写法:

+
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。 +

+

+ 原因指明的是起作用的规则,而不是裁决。所以同一个原因可以出现在两种结果之下:比限制小一字节的文件是 accept,而它所涉及的规则仍然是 + size_limit。 +

+
+ +
+

清单里有什么?

+

+ 每次运行结束时,包括被中断的运行,它都会写在文件旁边。每个文件一项: +

+
{
+  "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,因此清单总能追溯到产生它的来源。 +

+

+ 每一项还带有 target_id,即配方中生成该文件的 target 的 id,summary.by_target 则统计每个 target + 生成的文件数。因此有多个 target 的配方可以逐个 target 检查,无需阅读文件名。 +

+
+ +
+

什么是预设?

+

+ 预设是回答常见测试问题的现成文件集,你不必自己设计。预设底层就是普通配方,eject + 会把配方打印出来,供你从那里开始编辑。每个预设都有自己的页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+
    +
  • +

    空文件与最小文件

    +

    一个合法且达到格式允许的最小大小的文件能通过吗?

    +

    empty-and-minimal

    +
  • +
  • +

    文件名处理

    +

    我的系统能否正确保存、显示并返回它没料到的文件名?

    +

    filename-handling

    +
  • +
  • +

    大小边界

    +

    大小限制是否恰好在声明的位置生效?

    +

    size-boundaries

    +
  • +
  • +

    表格导入

    +

    我的表格导入能应付真实工具导出的内容吗?

    +

    tabular-import

    +
  • +
  • +

    文本编码

    +

    我的读取器知道文件是什么编码,还是在猜?

    +

    text-encoding

    +
  • +
  • +

    上传校验

    +

    我的上传表单是否接受该接受的,并拒绝其余的?

    +

    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 会在你构建之前告诉你这个集合的开销,并且在某个数字只是我们的占位值而不是你的限制时直接说明。 +

+
+ +
+

退出码是什么意思?

+

+ 每种结束方式都有自己的代码,机器可读的输出写到标准输出,失败的运行不会在那里打印任何内容。这张表是冻结的约定,改变某个代码的含义需要提升主版本号。 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
代码含义
0一切正常。
1工具内部出现意外错误。
2命令或参数有误。
3配方无效。
4该格式无法完成所请求的操作。
5读取或写入失败。
6磁盘空间不足。
7verify 发现了不一致。
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 流水线中生成测试文件。 +

+
+ +
+

有桌面窗口吗?

+

+ 有,它就是在同一个引擎上加了一个窗口,用于不走脚本的测试。它不是缩水版:有测试逐项对比这两种界面,只有其中一方能做的事必须被声明并说明理由,而不是悄悄地渐行渐远。 +

+

+ 界面有单批生成、预设、同时多批和关于。它会在写入任何内容之前显示一次运行的开销,运行时报告进度,并且可以在中途取消而不会留下写了一半的文件。它目前还不能打开配方文件,配方暂时只属于命令行,窗口通过表单来构建批次。 +

+
+ +
+ + + + diff --git a/web/public/zh-hans/faq/index.html b/web/public/zh-hans/faq/index.html new file mode 100644 index 00000000..5185adf2 --- /dev/null +++ b/web/public/zh-hans/faq/index.html @@ -0,0 +1,346 @@ + + + + + + +常见问题 - 关于生成测试文件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

常见问题

+

+ 许可证、隐私、可复现性,以及人们在把生成器放进构建流水线之前会确认的事项。如果这里没有你的问题,问题跟踪器是开放的。 +

+ +
+
+

这与 dd、fsutil 或 truncate 有何不同?

+
+

它们给你的是大小正确但内容空空如也的文件。用这种方式做出的名为 photo.png 的 2 MB 文件并不是 PNG,所以任何真正解析它的程序都会因为错误的原因拒绝它,而你的测试也会因为错误的原因通过。本工具生成的是大小恰好 2 MB 的真实 PNG,可以在图片查看器中打开,并附带一份说明,告诉你的系统该如何处理它。

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

它免费吗,我能在工作中使用吗?

+
+

两者都可以。它以 GPL-3.0 发布,不收取任何费用。没有账号,没有许可证密钥,也没有付费版本。

+
+
+
+

我能在闭源产品中使用生成的文件吗?

+
+

可以。许可证涵盖的是工具的代码,而不是工具生成的内容。生成的文件、配方和清单属于输出而非衍生作品,所以你可以提交它们并随产品分发,不负任何义务。

+
+
+
+

生成的文件包含真实的个人数据吗?

+
+

不包含。里面的一切都由种子合成。不读取任何数据集,不联系任何服务,也不嵌入任何第三方内容。请把生成的电子邮件地址视为不可用,而不是未被使用,因为任何随机字符串都有可能碰巧与真实地址相同。

+
+
+
+

在另一台机器上能得到完全相同的文件吗?

+
+

能,只要配方和种子相同,就能逐字节一致。项目在每次改动时都会测试这一点,要打破它必须提升主版本号。这正是你可以提交一个小配方,而不是大型二进制 fixture 的原因。

+
+
+
+

它需要联网吗?

+
+

从不需要。没有遥测,没有更新检查,也没有云客户端,命令行二进制文件里甚至没有编译进网络栈。它可以在没有网络的机器上运行,也能在封闭的企业环境中使用。

+
+
+
+

如果我请求格式无法达到的大小会怎样?

+
+

你会收到一个错误,说明格式、可能的最小大小、该下限的原因以及应改用什么,并且不会写入任何文件。工具从不会悄悄取整。每个下限都列在格式页面上。

+
tfg formats png
+
+
+
+

我能生成故意损坏的文件吗?

+
+

可以。加上 --damage zero-head,文件就会以恰好所要求的大小输出,开头几个字节被零覆盖,读取器会拒绝它,清单也会说明你的系统应该拒绝它。详情见关于损坏测试文件的页面。

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

接下来会支持哪些格式?

+
+

7z、mp3 和 mp4。目前有 26 种格式可以端到端使用。

+
+
+
+

我可以在哪些系统上运行?

+
+

命令行可在 Windows 和 Linux 上运行,支持 Intel 和 ARM,也支持 Apple 芯片的 Mac。桌面窗口提供 Windows(Intel)、Linux(Intel)和 Apple 芯片 Mac 版本。不支持 Intel Mac,也不会为其构建。

+
+
+
+

我需要安装什么吗?

+
+

不需要。下载适合你系统的压缩包,解压后运行二进制文件即可。没有安装程序,没有需要添加的运行时,也没有需要解决的依赖。如果你装有 Go,一条 go install 命令同样可用。

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

为什么在 Windows 上处理数千个文件更慢?

+
+

因为 Windows 对查看的每个路径收取更多开销,而遍历数千个文件的命令要查看数千个路径。在一台有 3000 个 1 kB 文件的机器上实测,verify 在 Windows 上约需 0.9 秒,在容器中的 Linux 上约需 0.2 秒。输出路径更短会让 Windows 的数字变小,因为文件上方的每一级文件夹都属于被查看的内容。

+
+
+
+ + +
+

还在犹豫?

+

+ 使用场景页面展示了它为之而生的任务,格式页面列出了每种格式及其能生成的最小文件。仓库中的 + README 是完整参考。 +

+ +

免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。

+
+ +
+ + + + diff --git a/web/public/zh-hans/formats/index.html b/web/public/zh-hans/formats/index.html new file mode 100644 index 00000000..3582b380 --- /dev/null +++ b/web/public/zh-hans/formats/index.html @@ -0,0 +1,897 @@ + + + + + + +26 种支持的文件格式 - PDF、DOCX、PNG、ZIP 等 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 种文件格式,每一种都按精确大小生成

+

+ 它们每一个都是该格式的真实文件。它能在对应软件中打开,字节数恰好等于你的要求。没有一个是粘上扩展名的填充零。 +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
格式名称扩展名最小文件完整度验证方式
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155full不适用
mdMarkdown.md0full不适用
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0full不适用
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

各列的含义

+
    +
  • +

    最小文件

    +

    + 本工具对该格式接受的最少字节数,包括它写在文件里的标签。请求更小的值,你会得到说明下限及其原因的错误,绝不会得到大小错误的文件。 +

    +
  • +
  • +

    完整度

    +

    + 文件有多完整。full 表示真正解析该格式的读取器会接受它,而不只是扩展名匹配。 +

    +
  • +
  • +

    验证方式

    +

    + 在格式发布之前打开每个生成文件的独立读取器,它是另一套独立实现,而不是我们自己的代码给自己批改作业。 +

    +
  • +
+

+ 每种格式也都能精确到字节地重复:相同的配方和种子在任何机器上都生成相同的文件,这正是提交配方来代替 fixture 本身是安全的原因。 +

+
+ +
+

每种格式接受的设置

+

+ 大多数格式有自己的设置,比如图片尺寸、JPEG 质量、PDF 页数、电子表格的行数和列数、压缩包里放多少条目。在命令行用 --set key=value 设置,或在配方的 + properties: 下设置。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
格式设置接受
avifwidth1 - 16384 像素
height1 - 16384 像素
quality1 - 100
bmpwidth1 - 20000 像素
height1 - 20000 像素
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
header真或假
quote_styleall, minimal, none
columns2 - 32768 列
docxparagraphs1 - 50000 段落
gifwidth1 - 20000 像素
height1 - 20000 像素
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 像素
height1 - 256 像素
embedbmp, png
jpgwidth1 - 20000 像素
height1 - 20000 像素
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 像素
height1 - 16384 像素
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 条目每秒
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bom真或假
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
title任意文本
author任意文本
subject任意文本
keywords任意文本
creator任意文本
producer任意文本
created形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none
modified形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none
pngwidth1 - 20000 像素
height1 - 20000 像素
pptxslides1 - 500 幻灯片
svgwidth1 - 20000 像素
height1 - 20000 像素
targzentries0 - 10000
entry_format格式的 id,与 tfg formats 列出的一致
entry_size形如 2mb 的大小
compressionbest, default, fast, none
depth0 - 50
directory_entries真或假
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 像素
height1 - 20000 像素
txtencodingutf-16be, utf-16le, utf-8
bom真或假
wavsample_rate8000 - 192000 赫兹
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 像素
height1 - 16383 像素
xlsxrows1 - 200000 行
columns1 - 32768 列
xmlencodingutf-16be, utf-16le, utf-8
bom真或假
zipentries0 - 10000
entry_format格式的 id,与 tfg formats 列出的一致
entry_size形如 2mb 的大小
compressionbest, default, fast, none
depth0 - 50
directory_entries真或假
password明文密码
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ 超出设置所接受范围的值会被拒绝,并给出指明该设置、允许范围以及应改用什么的消息。未知的设置同样是错误,绝不会静默使用默认值,因为悄悄接受的拼写错误会生成设置有误的文件,让你花一小时纳闷为什么该失败的测试却通过了。 +

+

+ 运行 tfg formats <id> 即可查看某个格式在你当前版本中接受哪些设置。 +

+
+ +
+

压缩包里装的是真实文件

+

+ targz 和 zip + 可以填入条目,而不是只留一个空壳。生成的压缩包确实包含它声称包含的文档,所以测试期间解压它的任何程序都会在里面找到真实文件。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/zh-hans/index.html b/web/public/zh-hans/index.html new file mode 100644 index 00000000..73b90c6d --- /dev/null +++ b/web/public/zh-hans/index.html @@ -0,0 +1,440 @@ + + + + + + +测试文件生成器 - 精确大小,26 种真实格式 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

生成大小精确的真实测试文件

+

+ PDF、PNG、DOCX、ZIP,共 26 + 种格式,每一种都是能在对应软件中打开的真实文件,大小恰好等于你的要求。每次运行还会写下你的应用应该如何处理每个文件。命令行加桌面窗口,免费开源,完全在你的机器上运行。 +

+ + +

免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。

+
+ +
+ Testing Files Generator 的桌面窗口,已准备好写出一批测试文件 +
桌面窗口,已准备好写出一批文件。命令行背后运行的是同一个引擎。
+
+
+ + + +
+

问题所在

+

做一个测试文件很容易,做出对的一千个才是麻烦所在

+

你在测试接收用户文件的软件。迟早你会需要:

+
    +
  • 一个恰好 10 MB 的 PDF,用来弄清上传限制是否真实
  • +
  • 位于该限制两侧的三个文件,用来抓出差一错误
  • +
  • 10,000 个日志文件,用来看夜间任务在文件夹很大时会怎样
  • +
  • 一个真正包含 200 份文档的 ZIP,而不是只有正确扩展名的空壳
  • +
  • 一个 4 GB 的文件,同时不必在仓库里保存 4 GB 的文件
  • +
  • 笔记本和构建服务器上完全相同的 fixture,逐字节一致
  • +
+

+ 这正是它要取代的。它为 QA 工程师、测试自动化,以及代码背后有上传表单、导入程序、解析器或存储配额的所有人而做。 +

+
+ +
+

它的与众不同之处

+

其他生成器止步于字节。这个工具回答你的测试真正要问的问题

+

+ 一个满是文件的文件夹仍然要你自己判断每个文件应该证明什么。这里每次运行都会在文件旁写出一个 + manifest.json,它是所生成内容的简单清单,并为每一项给出声明的预期。 +

+

假设你的上传接口允许 1 MB。请求恰好位于这条线上的三个文件:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
文件字节你的系统应该原因
1mb_under_1b.pdf1048575接受在限制之内
1mb_at_limit.pdf1048576接受限制本身是允许的
1mb_over_1b.pdf1048577拒绝size_limit
+
+ +

三个文件,三种不同的答案,以机器可读的形式给出。你的测试读取清单,而不是由你手写断言:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

当答案取决于你自己的策略时,清单会如实说明

+

+ 它记录的是 unspecified,而不是凭空编造预期。会猜测的生成器会制造误报,而总是误报的测试套件最终会被关掉。 +

+
+
+ +
+

预设

+

选好问题,拿到整套文件

+

+ 预设是围绕一个测试问题设计的测试文件集,你不必自己琢磨哪些文件能证明什么。每个预设都有一个页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+
    +
  • +

    空文件与最小文件

    +

    一个合法且达到格式允许的最小大小的文件能通过吗?

    +

    empty-and-minimal

    +
  • +
  • +

    文件名处理

    +

    我的系统能否正确保存、显示并返回它没料到的文件名?

    +

    filename-handling

    +
  • +
  • +

    大小边界

    +

    大小限制是否恰好在声明的位置生效?

    +

    size-boundaries

    +
  • +
  • +

    表格导入

    +

    我的表格导入能应付真实工具导出的内容吗?

    +

    tabular-import

    +
  • +
  • +

    文本编码

    +

    我的读取器知道文件是什么编码,还是在猜?

    +

    text-encoding

    +
  • +
  • +

    上传校验

    +

    我的上传表单是否接受该接受的,并拒绝其余的?

    +

    upload-validation

    +
  • +
+

全部预设,以及它们与配方的关系

+
+ +
+

快速开始

+

三条命令,看它如何工作

+
    +
  1. +

    生成一个文件

    +

    一个 PNG,恰好两兆字节:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    生成大量文件

    +

    + 一万个日志文件,每个在 1 到 8 KB + 之间,大小由种子抽取,因此明天会得到同样的文件集。给每次运行一个独立的目录,清单是一次运行所写内容的唯一记录,所以工具拒绝在其上再写第二份: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    先检查,再删除

    +

    verify 告诉你没有任何变动。cleanup 只删除写出的内容,不动其他任何东西:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 大小按 1024 进制计算,与你的文件管理器一致,所以 2mb 表示 2097152 + 字节。直接写字节数也可以。文档涵盖配方、清单和退出码。 +

+
+ +
+

你将得到什么

+

为无人值守的测试套件而生

+
    +
  • +

    精确大小,精确到字节

    +

    请求 10485761 字节,就得到恰好这么多。格式无法达到的大小会得到带原因的错误,绝不会得到大小错误的文件。

    +
  • +
  • +

    26 种真实格式

    +

    不是带扩展名的填充零。生成的 PNG 能在图片查看器中打开,DOCX 能在 Word 中打开,ZIP 能解压。每种格式在发布前都经过独立读取器验证。

    +
  • +
  • +

    本身就是测试依据的清单

    +

    路径、大小、SHA-256、格式、种子、工具版本,以及你的系统应该如何处理该文件。

    +
  • +
  • +

    可复现

    +

    配方和种子相同,字节就相同,在任何机器上都一样。提交一个小小的 YAML 配方,而不是庞大的二进制 fixture。

    +
  • +
  • +

    两种界面,一个引擎

    +

    一个为 CI 打造的命令行,和一个用于探索性测试的桌面窗口。两者都不是对方的缩水版,并且有测试逐项对比它们的功能。

    +
  • +
  • +

    完全离线

    +

    没有账号,没有云,没有遥测,没有更新检查。命令行二进制文件里根本没有编译进网络栈。

    +
  • +
+
+ +
+

下载

+

选择适合你系统的版本

+

+ 解压压缩包后运行即可。tfg 是命令行,tfg-gui 是桌面窗口。没有安装程序,也无需向你的机器添加任何东西。 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
系统命令行桌面窗口
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

哪些已签名,哪些没有

+

+ Windows 和 macOS 的下载包已签名,因此启动时不会出现未知开发者的警告。Linux 的没有签名,因为桌面 Linux 没有可用的对应签名机制。每个压缩包都列在发布页面的 + verify-SHA256SUMS.txt 中,你可以据此核对所下载的内容。 +

+
+ +

免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。

+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/empty-and-minimal/index.html b/web/public/zh-hans/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..d47a5ffa --- /dev/null +++ b/web/public/zh-hans/presets/empty-and-minimal/index.html @@ -0,0 +1,266 @@ + + + + + + +各格式最小的合法文件与空文件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

空文件与最小文件

+

一个合法且达到格式允许的最小大小的文件能通过吗?

+

+ empty-and-minimal 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 合法文件因过小被拒绝,因为检查按字节数判断而不是去读取内容
  • +
  • 空文件让读取器崩溃,而不是被如实报告
  • +
  • 只有一像素宽的图片在生成缩略图的途中发生除零错误
  • +
  • 存储把零字节当成上传失败,并不断重试
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show empty-and-minimal 所报告的:

+
+ + + + + + + +
文件数28
其配方中的 target 数28
总大小32 667 B
格式avif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。26
unspecified取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。2
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + +
设置接受默认值作用
--formats以逗号分隔的格式 id,或 allall集合由哪些格式构成。填 all 表示此版本的所有格式,也可以只列出你的系统接受的格式。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/filename-handling/index.html b/web/public/zh-hans/presets/filename-handling/index.html new file mode 100644 index 00000000..a5d7a94e --- /dev/null +++ b/web/public/zh-hans/presets/filename-handling/index.html @@ -0,0 +1,265 @@ + + + + + + +用于测试的问题文件名 - Unicode 与长度 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

文件名处理

+

我的系统能否正确保存、显示并返回它没料到的文件名?

+

+ filename-handling 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 在屏幕、日志或列表中看起来像另一个名字的文件名
  • +
  • 在上传与存储之间被截断、裁剪或改写的文件名
  • +
  • 按字符计数的长度限制,而存储是按字节计数的
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show filename-handling 所报告的:

+
+ + + + + + + +
文件数50
其配方中的 target 数50
总大小51 200 B
格式txt
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。4
unspecified取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。46
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + +
设置接受默认值作用
--format格式页面中的格式 idtxt集合中每个文件的格式。它是工具本身的参数,预设只是给它一个默认值。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/index.html b/web/public/zh-hans/presets/index.html new file mode 100644 index 00000000..50f646ea --- /dev/null +++ b/web/public/zh-hans/presets/index.html @@ -0,0 +1,238 @@ + + + + + + +测试文件预设 - 面向 QA 问题的现成文件集 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

测试文件预设,每个测试问题一套文件

+

+ 预设是围绕一个问题设计的整套测试文件,并附带说明你的系统应如何响应每个文件的清单。你选择问题,工具构建文件集。每个预设都有自己的页面,说明它通常能发现什么、集合里有什么,以及它接受的每项设置。 +

+ + + +
+

预设与配方有何不同?

+

+ 在底层没有不同。预设就是工具根据几项设置替你写出的配方。tfg preset eject + 会把这个配方打印出来,方便你与测试放在一起并加以编辑,你自己的配方也可以用一行基于某个预设,即 extends: preset: 后面跟上它的 id。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

我可以信任默认值吗?

+

+ 对文件来说可以。对于只有你的系统才知道的数字,比如上传表单的限制,默认值是我们的占位值,工具每次使用时都会这样说明。每个预设的页面都会标出这些设置,tfg preset + show 会在写入任何内容之前告知你。 +

+
+ +
+ + + + diff --git a/web/public/zh-hans/presets/size-boundaries/index.html b/web/public/zh-hans/presets/size-boundaries/index.html new file mode 100644 index 00000000..7a89317d --- /dev/null +++ b/web/public/zh-hans/presets/size-boundaries/index.html @@ -0,0 +1,279 @@ + + + + + + +测试上传大小限制 - 恰好在边界上的文件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

大小边界

+

大小限制是否恰好在声明的位置生效?

+

+ size-boundaries 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 限制处的差一错误
  • +
  • 把 MB 与 MiB 混淆,相差 4.8%,足以放过本不该通过的文件
  • +
  • 限制只在浏览器中生效,而不在服务器上
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show size-boundaries 所报告的:

+
+ + + + + + + +
文件数7
其配方中的 target 数7
总大小73 400 320 B
格式pdf
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。4
reject你的系统应该拒绝这个文件。3
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
设置接受默认值作用
--limit形如 2mb 的大小10mb你的系统声明的大小限制。其他一切都以它为基准测量。 这个默认值是我们的占位值,不是你的系统的值。请传入你自己的值。
--spread以逗号分隔的大小1B,1kb,1mb在限制两侧各延伸多远,以大小列表表示。
--format格式页面中的格式 idpdf集合中每个文件的格式。它是工具本身的参数,预设只是给它一个默认值。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

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

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/tabular-import/index.html b/web/public/zh-hans/presets/tabular-import/index.html new file mode 100644 index 00000000..7fbfb0ba --- /dev/null +++ b/web/public/zh-hans/presets/tabular-import/index.html @@ -0,0 +1,273 @@ + + + + + + +CSV 与 Excel 导入测试文件 - 分隔符、表头 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

表格导入

+

我的表格导入能应付真实工具导出的内容吗?

+

+ tabular-import 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 用分号分隔的文件被读成单列,因为分隔符是假定的而不是探测出来的
  • +
  • CRLF 文件被拆成行,每行后面多出一个空行
  • +
  • 没有表头的表格,第一行数据被当成列名吞掉
  • +
  • 导入只保留能显示的列,其余的悄悄丢弃
  • +
  • 读取器逐行读取 JSON 记录,遇到第一个带缩进的文档就停下
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show tabular-import 所报告的:

+
+ + + + + + + +
文件数13
其配方中的 target 数13
总大小3 080 060 B
格式csv, json, xlsx
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。8
unspecified取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。5
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + + + + + + + +
设置接受默认值作用
--rows1 - 200000 行1000表格有多少行。文件会写成这么多行恰好打包出的大小,所以上面的预算会随这个值变化。
--columns1 - 32768 列10表格每行有多少列。行数乘列数有上限,超出时会在写入任何内容之前被拒绝。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/text-encoding/index.html b/web/public/zh-hans/presets/text-encoding/index.html new file mode 100644 index 00000000..d143fe62 --- /dev/null +++ b/web/public/zh-hans/presets/text-encoding/index.html @@ -0,0 +1,266 @@ + + + + + + +文本编码测试文件 - UTF-8、UTF-16、BOM、CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

文本编码

+

我的读取器知道文件是什么编码,还是在猜?

+

+ text-encoding 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 读取器假定为 UTF-8,把 UTF-16 文件显示成每三个字符一个,或一排排方框
  • +
  • 字节顺序标记被当成内容读取,导致导入的第一个字段以三个多余字符开头
  • +
  • 导入器根据开头几个字节猜测编码,遇到更长的文件却猜成了别的
  • +
  • CRLF 文件被拆成行,每行后面多出一个空行,或回车符残留在最后一个字段里
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show text-encoding 所报告的:

+
+ + + + + + + +
文件数20
其配方中的 target 数20
总大小81 920 B
格式csv, log, md, txt, xml
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。10
unspecified取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。10
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + +
设置接受默认值作用
--sample形如 2mb 的大小4kb集合中每个文件的大小。UTF-16 每个字符占两个字节,所以奇数会被拒绝。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/zh-hans/presets/upload-validation/index.html b/web/public/zh-hans/presets/upload-validation/index.html new file mode 100644 index 00000000..e5bb2882 --- /dev/null +++ b/web/public/zh-hans/presets/upload-validation/index.html @@ -0,0 +1,295 @@ + + + + + + +上传校验测试文件 - 类型、大小与文件名 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

预设

+

上传校验

+

我的上传表单是否接受该接受的,并拒绝其余的?

+

+ upload-validation 预设用一条命令为这个问题构建出整套真实测试文件,并在旁边放一个 + manifest.json,说明你的系统应如何响应每个文件。以下所有内容都按此版本的默认值从程序中读取。 +

+ + +
+

它通常能发现什么?

+
    +
  • 限制只在浏览器中生效,而不在服务器上
  • +
  • SVG 或 HTML 文件被当成图片或纯文本,这是让脚本绕过表单的一种办法
  • +
  • 只按扩展名检查而从不打开文件,于是名为 .jpg 的 PDF 蒙混过关
  • +
  • 表单在查看大小之前就把整个请求体读进内存
  • +
  • 名为 PHOTO.JPG 的上传被拒绝,而 photo.jpg 被接受,或者相反
  • +
  • 含空格、括号或非 ASCII 字符的文件名被原样写入磁盘
  • +
+
+ + +
+

集合里有什么?

+

使用默认值时,如 tfg preset show upload-validation 所报告的:

+
+ + + + + + + +
文件数71
其配方中的 target 数22
总大小120 639 488 B
格式html, jpg, pdf, png, svg, txt
+
+

以及该集合的清单对你的系统有何预期:

+
+ + + + + + + + + +
预期含义文件数
accept你的系统应该接受这个文件。56
reject你的系统应该拒绝这个文件。10
unspecified取决于你的系统规则。由你决定,然后检查实际发生的是否符合你的本意。5
+
+
+ +
+

你可以更改什么?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
设置接受默认值作用
--limit形如 2mb 的大小10mb你的上传表单声明的大小限制。这个集合在限制两侧各取一步,若要覆盖任意距离的文件,请运行 size-boundaries 预设。 这个默认值是我们的占位值,不是你的系统的值。请传入你自己的值。
--allow以逗号分隔的格式 idjpg,png,pdf你的表单应该接受哪些类型。每种类型都会变成该类型的真实文件,它们构成整个集合的阳性对照。
--deny以逗号分隔的扩展名svg,html,exe,sh你的表单应该拒绝哪些扩展名。此版本没有对应格式的扩展名,仍会得到一个同名文件,内容为纯文本。
--far-over10x, 2x, off2x那个超大文件超出限制多少。如果写入限制数倍大小的文件不值得占用磁盘,可以关闭。
--bulk0 - 10000 个文件50批量上传包含多少个文件。设为零则完全不包含这一组。
+
+
+ +
+

如何运行?

+

查看集合的开销、构建它,或取出它的配方来编辑:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

也可以在你自己的配方中基于它构建,放在测试旁边:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/zh-hans/test-files-in-ci/index.html b/web/public/zh-hans/test-files-in-ci/index.html new file mode 100644 index 00000000..36c36be3 --- /dev/null +++ b/web/public/zh-hans/test-files-in-ci/index.html @@ -0,0 +1,358 @@ + + + + + + +CI 中的测试文件 - GitHub Actions、GitLab CI 和 PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

使用场景

+

如何在 CI 流水线中生成测试文件

+

+ 仓库里的二进制 fixture 会永远留在历史中,无法在 diff + 里审查,文件一大就根本行不通。请改为在流水线内部用配方生成这些文件。配方是文本,每次生成的字节都相同,最后一步还能证明什么都没有变动。 +

+ +
+

简短回答

+

+ 安装 tfg,在测试之前运行 tfg generate fixtures.yaml --out ./fixtures,在测试之后运行 + tfg verify ./fixtures/manifest.json。这两步都会自行让构建失败,并给出说明原因的退出码。 +

+
+ +
+

为什么不提交

+

为什么 fixture 不该放在仓库里

+
    +
  • + 它会留在历史中。之后再删除二进制文件也不会让克隆变小,因为它的每个版本都还在。 +
  • +
  • + diff 看不出改了什么。审查者只看到一个 PDF 不同了,仅此而已。配方的变化只有一行。 +
  • +
  • + 大文件放不下。GitHub 会拒绝包含超过 100 MB 文件的推送,所以一个 500 MB 上传限制的测试没有什么可提交的。 +
  • +
+

+ 该提交的是配方。相同的配方和种子在每台机器上写出相同的字节,所以在流水线里生成的文件,就是你在笔记本上用过的那个文件。 +

+
+ +
+

配方

+

放在测试旁边的配方

+

+ 这个配方写出二十五张应被接受的发票和两张超过限制、应被拒绝的图片,清单会记录这两种预期: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml 会检查它而不写入任何内容,并一次列出所有问题。 +

+
+ +
+

GitHub Actions

+

安装工具并构建 fixture 的工作流

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 校验和那一行把压缩包与同一发行版中的 verify-SHA256SUMS.txt 比对。版本是固定的,所以新发行版绝不会改变你没动过的构建。 +

+
+ +
+

GitLab CI

+

同样的事,写成 GitLab 作业

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

变红的时候

+

什么会让一个步骤失败,为什么

+

+ 每种结局都有自己的退出码,所以步骤会自行失败,日志会说明是哪一种。流水线会遇到的有: +

+
    +
  • 3 - 配方无效。没有写入任何内容,每个问题都会被指出
  • +
  • 4 - 格式做不到所要求的事,例如小于它最小值的大小
  • +
  • 6 - 磁盘空间不足
  • +
  • 7 - tfg verify 发现一个与其清单不符的文件
  • +
  • 8 - 运行已结束,但并非所有内容都已生成
  • +
+

+ 失败的运行不会向标准输出打印任何内容,所以日志解析器永远不会把错误当成数据。完整的表格在文档页面上。 +

+
+ +
+

PowerShell

+

PowerShell 脚本还需要多写一行

+

+ PowerShell 不会把程序的退出码带出 .ps1 文件。用 -File 运行一个脚本,即使里面的工具拒绝了工作,脚本也会返回 + 0,于是本该变红的构建变成了绿色。最后一行就是全部的修复: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 这是 PowerShell 的行为,与本工具无关。cmd、bash 和 zsh 不需要额外处理。 +

+
+ +
+

多个作业

+

在作业之间共享 fixture

+

+ 通常不需要上传它们。因为相同的配方写出相同的字节,每个作业都可以运行自己的 tfg + generate,这比上传再下载更快。当一个作业必须接收另一个作业的文件时,在传输之后对清单运行 tfg verify,它会告诉你收到的是否就是写出的。 +

+
+ +
+

接下来

+

从这里去哪里

+
    +
  • + 损坏的测试文件把故意弄坏的文件加入同一个配方。 +
  • +
  • + 使用场景展示流水线中的运行还能检查什么。 +
  • +
  • + 文档包含每条命令、每个配方键和每个退出码。 +
  • +
+
+ +
+ + + + diff --git a/web/public/zh-hans/use-cases/index.html b/web/public/zh-hans/use-cases/index.html new file mode 100644 index 00000000..123c2f61 --- /dev/null +++ b/web/public/zh-hans/use-cases/index.html @@ -0,0 +1,295 @@ + + + + + + +使用场景 - 上传限制、CI fixture、批量测试 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

人们用它来做什么

+

+ 几乎每个接收用户文件的项目都会遇到的五项任务,以及完成每一项的命令。下面的每个示例都能按原样运行。 +

+ +
+

上传限制

+

测试文件大小限制是否在声称的位置生效

+

+ 一个限制对应三个测试用例,而不是一个:刚好低于、恰好等于和刚好高于。手工做这些意味着计算字节数,并祈祷自己没有算错一位。不如直接请求整套文件: +

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

+ 你会得到三个真实的 PDF,大小分别是 1048575、1048576 和 1048577 字节,以及一份清单,说明前两个应被接受,第三个应因 size_limit + 被拒绝。你的测试读取预期,而不是由你手写三个断言,限制改变时,你只需改一个数字再重新运行。 +

+

+ 如果你只想要一组内联的边界文件,不用预设也可以做到: +

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

持续集成

+

让 fixture 留在仓库之外又不丢失

+

+ 大型二进制 fixture 会拖慢仓库克隆,也让评审变得别扭,而且替换其中一个时没有人能看出改了什么。配方只是几百个字符的 + YAML,就能重建出完全相同的文件,在任何机器上逐字节一致,因为每个文件都由运行的种子派生。 +

+
- 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
+

+ 每种结束方式都有自己的退出码,所以流水线可以区分配方错误、磁盘已满和校验不一致。失败的运行不会在标准输出上打印任何内容,这样日志解析器就不会把错误当成数据。 +

+
+ +
+

规模

+

弄清文件夹很大时会发生什么

+

+ 导入程序、夜间任务和目录列表在一万个文件时的表现与十个文件时不同。从范围中抽取的大小让文件集看起来像真实流量,而不是一万个完全相同的文件,并且抽取来自种子,所以明天文件集依然相同。 +

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

+ 在运行写入任何内容之前先查看它的开销,当总量以 GB 计时这一点很重要: +

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

+ 比磁盘可用空间更大的运行会在写入第一个字节之前就被拒绝,而不是把磁盘写满再半途失败。 +

+
+ +
+

压缩包

+

用真正装有文件的压缩包测试解压程序

+

+ 只有正确扩展名的空压缩包,无法证明任何关于打开它并遍历内容的代码的事情。声明内容,压缩包就真的包含它们: +

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

+ 嵌套深度、条目数量和内部内容的大小,导入程序都有自己的看法,而这正是你弄清这些看法的办法。 +

+
+ +
+

解析器与查看器

+

检查你自己的代码读取格式的方式是否与真实软件一致

+

+ 这里的每种格式在发布前都用独立读取器验证过:PNG 被打开并比对像素,DOCX 由另外的库读回,压缩包被解压。这意味着你的解析器拒绝的文件,是关于你的解析器的发现,而不是关于生成器的。 +

+
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
+

+ 格式页面列出了每种格式接受的设置,以及每种格式能达到的最小文件。 +

+
+ +
+

指南

+

其中两项的详细说明

+
    +
  • + 损坏的测试文件 - 一个故意弄坏、大小精确的文件,应对它做出的处理写在清单里。 +
  • +
  • + CI 中的测试文件 - 一个 GitHub Actions 工作流、一个 GitLab 作业,以及让构建失败的退出码。 +
  • +
+
+ +
+

适合谁

+

+ QA 工程师、测试自动化,以及代码背后有上传表单、导入程序、解析器或存储配额的所有人。它可以在完全没有网络的机器上运行,这在基于浏览器的生成器行不通的封闭企业环境中尤为重要。 +

+ +

免费开源,GPL-3.0。无需注册。Windows 和 macOS 的下载包已签名,启动时没有警告。

+
+ +
+ + + + diff --git a/web/public/zh-hant/corrupt-test-files/index.html b/web/public/zh-hant/corrupt-test-files/index.html new file mode 100644 index 00000000..21ee8e44 --- /dev/null +++ b/web/public/zh-hant/corrupt-test-files/index.html @@ -0,0 +1,357 @@ + + + + + + +損毀的測試檔案 - 大小精確的損毀檔案 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

使用情境

+

如何製作用於測試的損毀檔案

+

+ 一個只見過完好檔案的驗證器,並沒有真正被測試過。以下說明如何取得一個刻意弄壞的檔案:它的大小恰好就是你要求的大小,並附帶一份清單,說明你的系統該如何處理它。 +

+ +
+

簡短回答

+

+ tfg generate --format png --size 2mb --damage zero-head --out ./out 會寫出一個恰好 2097152 + 位元組的 PNG,它開頭的幾個位元組是零,旁邊的清單則記錄你的系統應該拒絕它。 +

+
+ +
+

常見做法

+

為什麼手工弄壞的檔案不是好測試

+

+ 常見做法是用十六進位編輯器、用指令碼翻轉幾個隨機位元組,或用 head 或 truncate 把檔案截短。這些做法能用一次,之後就要付出代價: +

+
    +
  • + 每次都不一樣。隨機位元組每次執行都落在新的位置,所以週二出現的失敗,週三可能不再出現。 +
  • +
  • + 它會改變大小。被截短的檔案比它本應低於的限制還要小,於是大小檢查先於內容檢查給出回答,測試因為錯誤的原因而通過。 +
  • +
  • + 它常常沒被發現。純文字中間改了一個位元組仍然可以讀,寬容的影像讀取器只會照樣畫出來,於是本該損毀的檔案被接受了。 +
  • +
  • + 它沒有說明應該發生什麼。檔案只是一堆位元組,之後讀這個測試的人只能猜測當初想要的是接受還是拒絕。 +
  • +
+
+ +
+

你會得到什麼

+

損毀的檔案仍然是你要求的大小

+

+ 檔案先正常產生,再在寫入磁碟的途中被弄壞。它保持你要求的大小,同一個指令再次寫出的位元組也完全相同。 +

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
+

+ 設定寫在冒號之後。該選項可以重複,損毀依你寫下的順序逐一套用。它適用於全部 26 種格式。 +

+
+ +
+

它能做什麼

+

有哪些損毀方式?

+

+ 這是程式印出的清單,在建置本頁時從程式中讀取。tfg damage 印出的是同一份清單,tfg damage <id> + 則說明其中某一項接受什麼設定。 +

+
+ + + + + + + + + + + + + + + + + +
損毀方式對位元組做了什麼最小檔案設定
zero-head用零覆蓋檔案開頭的若干位元組,長度保持不變。大多數讀取器最先看的就是那裡,所以幾乎任何東西都會發現這種損毀。8bytes
+
+

+ zero-head + 把檔案開頭寫成零。大多數讀取器最先看的就是那裡,也就是說明檔案是什麼的簽章和檔頭,所以幾乎任何讀取器都會發現。純文字和日誌沒有簽章,同樣會被拒絕,因為一串零位元組不是文字。低於四個位元組時,有些格式產生的損毀沒有任何讀取器會抱怨,這就是該設定從四開始的原因。 +

+
+ +
+

清單怎麼說

+

一份說明應發生什麼的清單

+

+ 每個損毀的檔案都會得到一筆記錄,說明你的系統應該拒絕它,損毀方式記在旁邊: +

+
"expected": {
+  "outcome": "reject",
+  "reason": "content_malformed",
+  "confidence": "certain"
+},
+"damage": [
+  {
+    "type": "zero-head",
+    "settings": {
+      "bytes": "8"
+    }
+  }
+]
+

+ 有兩種請求會在寫入任何內容之前被拒絕,因為各自都會在磁碟上留下一個清單描述有誤的檔案: +

+
    +
  • 比損毀所需更小的檔案,它會原樣輸出
  • +
  • + 在損毀旁邊寫 expected: accept,因為沒有什麼能滿足它。如果你的系統本應修復檔案,請寫 + sanitize,如果你要問的恰恰就是這一點,請寫 unspecified +
  • +
+
+ +
+

在配方中

+

一次執行中的完好檔案和損毀檔案

+

+ 把兩者放進同一個配方,清單就帶有每個檔案的預期,測試因此不需要一份說明哪個是哪個的列表: +

+
version: 1
+targets:
+  - id: healthy
+    format: pdf
+    size: 1mb
+    expected: accept
+  - id: broken
+    format: pdf
+    size: 1mb
+    damage:
+      - zero-head
+
+ +
+

在測試中

+

把它變成測試

+

+ 測試讀取清單,檢查實際發生的是否就是所宣告的。它不需要檔名列表: +

+
import json, os
+
+directory = "healthy-and-broken"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    if entry["expected"]["outcome"] == "reject":
+        assert not response.ok
+    else:
+        assert response.ok
+

+ 好的拒絕是乾淨的拒絕。一則說明錯在哪裡的訊息,就是你想要的答案。伺服器錯誤、卡死或只儲存了一半的檔案,正是這個測試要找出來的缺陷。 +

+
+ +
+

接下來

+

從這裡去哪裡

+ +
+ +
+ + + + diff --git a/web/public/zh-hant/create-file-exact-size/index.html b/web/public/zh-hant/create-file-exact-size/index.html new file mode 100644 index 00000000..c44b39e9 --- /dev/null +++ b/web/public/zh-hant/create-file-exact-size/index.html @@ -0,0 +1,309 @@ + + + + + + +如何建立指定大小的檔案 - Windows、Linux、macOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

如何建立大小精確的檔案

+

+ 每個系統都有對應的指令,下面列出了全部三個。它們能給你一個位元組數恰好正確的檔案,對許多測試來說這就夠了。本頁的每個指令在發布前都在對應系統上執行過。 +

+ +
+

簡短回答

+

+ Windows:fsutil file createnew name 10485760。Linux:dd if=/dev/zero of=name bs=1M + count=10。macOS:mkfile 10m name。大小以位元組計,依檔案管理員的算法,10 MB 就是 10485760 位元組。 +

+
+ +
+

Windows

+

fsutil,以及無需額外工具的 PowerShell 寫法

+

+ fsutil 隨 Windows 提供。它接受以位元組為單位的大小,所以先算出數字:10 MB 是 10485760,100 MB 是 + 104857600,1 GB 是 1073741824。 +

+
fsutil file createnew test10mb.bin 10485760
+

+ 在 Windows 11 上實測:它可以在一般的命令提示字元下執行,不需要系統管理員權限,產生的檔案恰好是 10485760 位元組。 +

+

PowerShell 不需要呼叫其他程式也能做到同樣的事,並且認得單位:

+
$file = New-Object System.IO.FileStream "test10mb.bin", Create, ReadWrite
+$file.SetLength(10MB)
+$file.Close()
+

+ PowerShell 中的 10MB 代表 10485760 位元組,與檔案總管使用的 1024 進位算法相同,所以上面兩個指令得到的大小一樣。 +

+
+ +
+

Linux

+

dd、truncate 與 fallocate,以及容易坑人的差別

+

dd 是人人皆知的那個。它真的會寫入這些位元組:

+
dd if=/dev/zero of=test10mb.bin bs=1M count=10
+

+ truncate 是瞬間完成的,而這正是陷阱所在。在 Alpine Linux 上實測,該檔案回報 10485760 + 位元組,卻占用零個區塊,它是一個稀疏檔案。任何讀取它的程式會得到十 MB 的零,但磁碟從未真正讓出空間: +

+
truncate -s 10M test10mb.bin
+

+ 用它測試上傳限制沒問題,但用來測試磁碟配額就會誤導人。當空間必須真實占用時,應該使用 fallocate: +

+
fallocate -l 10M test10mb.bin
+

而當內容必須無法壓縮,讓封存程式無法再把它壓小時:

+
head -c 10485760 /dev/urandom > test10mb.bin
+
+ +
+

macOS

+

mkfile(不是稀疏檔案),以及你已經熟悉的另外兩個

+

+ macOS 內建 mkfile。在 macOS 26.6.2 上實測:10485760 位元組與 20480 個區塊,所以空間是真正配置的,而不只是承諾: +

+
mkfile 10m test10mb.bin
+

dd 與 truncate 也都有,行為與 Linux 上相同:

+
dd if=/dev/zero of=test10mb.bin bs=1m count=10
+truncate -s 10M test10mb.bin
+
+ +
+

這種辦法在哪裡失效

+

大小正確的檔案不等於類型正確的檔案

+

+ 以上所有方法給你的都是一塊零。如果受測對象只看大小,比如上傳限制、配額或傳輸,這就夠了。一旦有任何東西開啟這個檔案,就不夠了。 +

+

+ 實測過,而且值得你自己試一試:用 fsutil 做一個 2 MB 的檔案,把它命名為 photo.png,再交給影像函式庫處理。Pillow 會回答 + cannot identify image file。它不是 PNG,從來就不是,只是名字這麼說。 +

+

+ 這比聽起來更重要,因為測試隨後會以哪種方式失敗。你的上傳端點拒絕了這個檔案,測試變綠,於是你斷定大小限制有效。其實它並不是因為大小而拒絕的,而是因為這些位元組不是圖片,你本想測試的規則根本沒有被觸及。 +

+
    +
  • 剖析器在檢查任何大小規則之前就拒絕了它
  • +
  • 縮圖步驟失敗,你讀到的錯誤是關於縮圖的
  • +
  • 防毒軟體或內容檢查基於第三個原因拒絕了它
  • +
  • 檢視器什麼也不顯示,沒人說得清這是不是那個 bug
  • +
+
+ +
+

另一種辦法

+

該格式的真實檔案,大小恰好是你要求的

+

+ 這就是 Testing Files Generator 所做的事。檔案是該格式的真實檔案,能在對應軟體中開啟,位元組數恰好等於你的要求,精確到位元組: +

+
tfg generate --format png --size 10mb --out ./fixtures
+

+ 要求格式無法達到的大小,你會得到一個說明下限及其原因的錯誤,絕不會得到大小錯誤的檔案。格式頁面列出了每種格式及其能產生的最小檔案。 +

+

而一個限制對應的是三個測試案例,而不是一個,所以工具會把三個都建置出來:

+
tfg generate --format pdf --boundary 10mb --out ./edges
+

+ 這會給你 10485759、10485760 與 10485761 + 位元組的檔案,以及一份清單,說明你的系統應該接受哪些、拒絕哪些。使用情境頁面會講解這一點,以及它為之而生的另外四項任務。 +

+ +

免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。

+
+ +
+

那麼該用哪個?

+
    +
  • +

    使用系統指令

    +

    + 當沒有任何東西會開啟這個檔案時。例如在先檢查大小的端點上測試大小限制、傳輸、配額、磁碟寫滿的情況。只要一行,而且已經裝好了。 +

    +
  • +
  • +

    使用真正的產生器

    +

    + 當有任何東西要剖析、轉譯、匯入或解壓縮這個檔案時,以及當你明天要在另一台電腦上拿到逐位元組相同的 fixture 時。 +

    +
  • +
+

+ 兩種辦法都在本頁,因為它們各自在一部分情況下是對的。要避免的錯誤,是在需要後者的地方用了前者,還把變綠的測試當成證明。 +

+
+ +
+ + + + diff --git a/web/public/zh-hant/docs/index.html b/web/public/zh-hant/docs/index.html new file mode 100644 index 00000000..dbac2475 --- /dev/null +++ b/web/public/zh-hant/docs/index.html @@ -0,0 +1,522 @@ + + + + + + +文件 - 指令、配方、清單、結束碼 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

文件

+

+ 工具的全部功能,依人們實際會問的問題來組織。儲存庫中的 README 是完整參考,並且始終與你下載的版本一致。 +

+ +
+

有哪些指令?

+

每個指令只做一件事:

+
tfg generate    依配方或參數產生檔案
+tfg validate    檢查配方,不寫入任何內容
+tfg verify      對照清單檢查目錄
+tfg cleanup     刪除清單中列出的檔案
+tfg recipe fmt  以標準形式列印配方
+tfg preset      依具名的測試問題建立一組檔案
+tfg formats     列出此版本支援的格式
+tfg damage      列出此版本可以刻意破壞檔案的方式
+tfg tool        處理現有檔案的小工具
+tfg version     列印工具版本
+tfg license     列印授權條款及其對產生檔案的意義
+
+ +
+

如何產生一個大小精確的檔案?

+

+ 指定格式、大小與輸出位置。大小以 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>圍繞一個限制的三個檔案:小一位元組、恰好等於限制、大一位元組
--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將清單寫到標準輸出
+
+
+ +
+

如何做出刻意損壞的檔案?

+

+ 本工具寫出的其他所有檔案在構造上都是正確的,這回答了上傳驗證器會問的三個問題中的兩個。--damage + 回答第三個,也就是檔案到底能不能開啟。檔案先正常產生,再被破壞,因此仍然維持你要求的大小。 +

+
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,並在旁邊記錄所做的破壞。有兩種情況會在寫入任何內容之前被拒絕,因為各自都會在磁碟上留下清單描述有誤的檔案: +

+
    +
  • 檔案小於破壞所需的大小,因為它會原樣輸出
  • +
  • + 在破壞旁邊寫 expected: accept,因為沒有任何檔案能滿足它。如果受測系統應該修復該檔案,請寫 + sanitize,如果你問的正是這個問題,請寫 unspecified +
  • +
+

+ 第三種無法事先得知。如果某個破壞執行後沒有改動任何位元組,該檔案會被捨棄而不是寫出,執行會繼續,指出是哪個檔案,並以部分完成的結束碼收尾。 +

+

+ 一步一步來,附帶一個讀取清單的測試:如何製作用於測試的損毀檔案。 +

+
+ +
+

配方長什麼樣子?

+

+ 配方是一個描述整次執行的 YAML 檔案。把它與測試放在一起提交,fixture 就不再是儲存庫裡的二進位檔,任何人都可以用一個只有幾百個字元的檔案逐位元組重建它們。 +

+
# 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
+

+ 每個 target 必須恰好有 size、size-range、boundary 或 + contains + 其中一個。兩個是錯誤,一個都沒有也是錯誤。無效的配方不會寫入任何檔案,並且會一次回報所有問題,而不是只報第一個,每個問題都會指明所涉及的設定。 +

+
+ +
+

如何宣告我的系統應如何處理某個檔案?

+

只需結果時用簡短寫法,原因重要時用完整寫法:

+
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。 +

+

+ 原因指明的是起作用的規則,而不是裁決。所以同一個原因可以出現在兩種結果之下:比限制小一位元組的檔案是 accept,而它所涉及的規則仍然是 + size_limit。 +

+
+ +
+

清單裡有什麼?

+

+ 每次執行結束時,包括被中斷的執行,它都會寫在檔案旁邊。每個檔案一項: +

+
{
+  "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,因此清單總能追溯到產生它的來源。 +

+

+ 每一項還帶有 target_id,也就是配方中產生該檔案的 target 的 id,summary.by_target 則統計每個 target + 產生的檔案數。因此有多個 target 的配方可以逐個 target 檢查,無需閱讀檔名。 +

+
+ +
+

什麼是預設集?

+

+ 預設集是回答常見測試問題的現成檔案組,你不必自己設計。預設集底層就是普通配方,eject + 會把配方列印出來,供你從那裡開始編輯。每個預設集都有自己的頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+
    +
  • +

    空檔案與最小檔案

    +

    一個合法且達到格式允許最小大小的檔案能通過嗎?

    +

    empty-and-minimal

    +
  • +
  • +

    檔名處理

    +

    我的系統能否正確儲存、顯示並傳回它沒料到的檔名?

    +

    filename-handling

    +
  • +
  • +

    大小邊界

    +

    大小限制是否恰好在宣告的位置生效?

    +

    size-boundaries

    +
  • +
  • +

    表格匯入

    +

    我的表格匯入能應付真實工具匯出的內容嗎?

    +

    tabular-import

    +
  • +
  • +

    文字編碼

    +

    我的讀取器知道檔案是什麼編碼,還是在猜?

    +

    text-encoding

    +
  • +
  • +

    上傳驗證

    +

    我的上傳表單是否接受該接受的,並拒絕其餘的?

    +

    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 會在你建置之前告訴你這個組合的開銷,並且在某個數字只是我們的預留值而不是你的限制時直接說明。 +

+
+ +
+

結束碼是什麼意思?

+

+ 每種結束方式都有自己的代碼,機器可讀的輸出寫到標準輸出,失敗的執行不會在那裡列印任何內容。這張表是凍結的約定,改變某個代碼的意義需要提升主版本號。 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
代碼意義
0一切正常。
1工具內部發生非預期的錯誤。
2指令或參數有誤。
3配方無效。
4該格式無法完成所要求的操作。
5讀取或寫入失敗。
6磁碟空間不足。
7verify 發現不一致。
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 流程中產生測試檔案。 +

+
+ +
+

有桌面視窗嗎?

+

+ 有,它就是在同一個引擎上加了一個視窗,用於不走腳本的測試。它不是縮水版:有測試逐項比對這兩種介面,只有其中一方能做的事必須被宣告並說明理由,而不是悄悄地漸行漸遠。 +

+

+ 畫面有單批產生、預設集、同時多批與關於。它會在寫入任何內容之前顯示一次執行的開銷,執行時回報進度,並且可以在中途取消而不會留下寫了一半的檔案。它目前還不能開啟配方檔,配方暫時只屬於命令列,視窗透過表單來建立批次。 +

+
+ +
+ + + + diff --git a/web/public/zh-hant/faq/index.html b/web/public/zh-hant/faq/index.html new file mode 100644 index 00000000..ad77dbdb --- /dev/null +++ b/web/public/zh-hant/faq/index.html @@ -0,0 +1,346 @@ + + + + + + +常見問題 - 關於產生測試檔案 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

常見問題

+

+ 授權、隱私、可重現性,以及人們在把產生器放進建置流程之前會確認的事項。如果這裡沒有你的問題,問題追蹤器是開放的。 +

+ +
+
+

這與 dd、fsutil 或 truncate 有何不同?

+
+

它們給你的是大小正確但內容空空如也的檔案。用這種方式做出的名為 photo.png 的 2 MB 檔案並不是 PNG,所以任何真正剖析它的程式都會因為錯誤的原因拒絕它,而你的測試也會因為錯誤的原因通過。本工具產生的是大小恰好 2 MB 的真實 PNG,可以在圖片檢視器中開啟,並附上一份說明,告訴你的系統該如何處理它。

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

它免費嗎?我能在工作中使用嗎?

+
+

兩者都可以。它以 GPL-3.0 發布,不收取任何費用。沒有帳號,沒有授權金鑰,也沒有付費方案。

+
+
+
+

我能在閉源產品中使用產生的檔案嗎?

+
+

可以。授權涵蓋的是工具的程式碼,而不是工具產生的內容。產生的檔案、配方與清單屬於輸出而非衍生作品,所以你可以提交它們並隨產品散布,不負任何義務。

+
+
+
+

產生的檔案包含真實的個人資料嗎?

+
+

不包含。裡面的一切都由種子合成。不讀取任何資料集,不聯繫任何服務,也不嵌入任何第三方內容。請把產生的電子郵件地址視為無法使用,而不是尚未使用,因為任何隨機字串都有可能碰巧與真實地址相同。

+
+
+
+

在另一台電腦上能得到完全相同的檔案嗎?

+
+

能,只要配方與種子相同,就能逐位元組一致。專案在每次變更時都會測試這一點,要打破它必須提升主版本號。這正是你可以提交一個小配方,而不是大型二進位 fixture 的原因。

+
+
+
+

它需要連上網際網路嗎?

+
+

從不需要。沒有遙測,沒有更新檢查,也沒有雲端用戶端,命令列執行檔裡甚至沒有編譯進網路堆疊。它可以在沒有網路的電腦上執行,也能在封閉的企業環境中使用。

+
+
+
+

如果我要求格式無法達到的大小會怎樣?

+
+

你會收到一個錯誤,說明格式、可能的最小大小、該下限的原因以及應改用什麼,而且不會寫入任何檔案。工具絕不會默默四捨五入。每個下限都列在格式頁面上。

+
tfg formats png
+
+
+
+

我能產生刻意損壞的檔案嗎?

+
+

可以。加上 --damage zero-head,檔案就會以恰好所要求的大小輸出,開頭幾個位元組被零覆蓋,讀取器會拒絕它,清單也會說明你的系統應該拒絕它。詳情見關於損毀測試檔案的頁面。

+
tfg generate --format png --size 2mb --damage zero-head --out ./out
+
+
+
+

接下來會支援哪些格式?

+
+

7z、mp3 與 mp4。目前有 26 種格式可以端到端使用。

+
+
+
+

我可以在哪些系統上執行?

+
+

命令列可在 Windows 與 Linux 上執行,支援 Intel 與 ARM,也支援 Apple 晶片的 Mac。桌面視窗提供 Windows(Intel)、Linux(Intel)與 Apple 晶片 Mac 版本。不支援 Intel Mac,也不會為其建置。

+
+
+
+

我需要安裝什麼嗎?

+
+

不需要。下載適合你系統的壓縮檔,解壓縮後執行執行檔即可。沒有安裝程式,沒有需要新增的執行階段,也沒有需要解決的相依套件。如果你裝有 Go,一個 go install 指令同樣可用。

+
go install github.com/donislawdev/TestingFilesGenerator/cmd/tfg@latest
+
+
+
+

為什麼在 Windows 上處理數千個檔案比較慢?

+
+

因為 Windows 對查看的每個路徑收取較多開銷,而走訪數千個檔案的指令要查看數千個路徑。在一台有 3000 個 1 kB 檔案的電腦上實測,verify 在 Windows 上約需 0.9 秒,在容器中的 Linux 上約需 0.2 秒。輸出路徑較短會讓 Windows 的數字變小,因為檔案上方的每一層資料夾都屬於被查看的內容。

+
+
+
+ + +
+

還在猶豫?

+

+ 使用情境頁面展示了它為之而生的任務,格式頁面列出了每種格式及其能產生的最小檔案。儲存庫中的 + README 是完整參考。 +

+ +

免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。

+
+ +
+ + + + diff --git a/web/public/zh-hant/formats/index.html b/web/public/zh-hant/formats/index.html new file mode 100644 index 00000000..61a2ca25 --- /dev/null +++ b/web/public/zh-hant/formats/index.html @@ -0,0 +1,897 @@ + + + + + + +26 種支援的檔案格式 - PDF、DOCX、PNG、ZIP 等 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

26 種檔案格式,每一種都以精確大小產生

+

+ 它們每一個都是該格式的真實檔案。它能在對應軟體中開啟,位元組數恰好等於你的要求。沒有一個是黏上副檔名的填充零。 +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
格式名稱副檔名最小檔案完整度驗證方式
avifAV1 Image File Format.avif311fullpillow
bmpWindows Bitmap.bmp58fullpillow
csvComma-Separated Values.csv115fullpython-csv
docxWord (Office Open XML).docx1220fulllibreoffice
gifGraphics Interchange Format.gif114fullpillow
htmlHyperText Markup Language.html118fullpython-html
icoWindows Icon.ico70fullpillow
jpgJPEG.jpg602fullpillow
jsonJavaScript Object Notation.json219fullnode-json
jxlJPEG XL.jxl147fullpillow-jxl
logServer and application log.log155full不適用
mdMarkdown.md0full不適用
pdfPortable Document Format.pdf3415fullpdftotext
pngPortable Network Graphics.png74fullpillow
pptxPowerPoint (Office Open XML).pptx4809fulllibreoffice
svgScalable Vector Graphics.svg194fullinkscape
targztar + gzip.tar.gz9790full7z
tiffTagged Image File Format.tiff183fullpillow
tomlTOML.toml212fullpython-toml
txtPlain text.txt0full不適用
wavWaveform Audio.wav98fullffprobe
webpWebP.webp148fullpillow
xlsxExcel (Office Open XML).xlsx1726fulllibreoffice
xmlExtensible Markup Language.xml264fullpython-xml
yamlYAML.yaml241fullpython-yaml
zipZIP.zip8382full7z
+
+ +
+

各欄的意義

+
    +
  • +

    最小檔案

    +

    + 本工具對該格式接受的最少位元組數,包括它寫在檔案裡的標籤。要求更小的值,你會得到說明下限及其原因的錯誤,絕不會得到大小錯誤的檔案。 +

    +
  • +
  • +

    完整度

    +

    + 檔案有多完整。full 表示真正剖析該格式的讀取器會接受它,而不只是副檔名相符。 +

    +
  • +
  • +

    驗證方式

    +

    + 在格式發布之前開啟每個產生檔案的獨立讀取器,它是另一套獨立實作,而不是我們自己的程式碼給自己批改作業。 +

    +
  • +
+

+ 每種格式也都能精確到位元組地重複:相同的配方與種子在任何電腦上都產生相同的檔案,這正是提交配方來取代 fixture 本身是安全的原因。 +

+
+ +
+

每種格式接受的設定

+

+ 大多數格式有自己的設定,例如圖片尺寸、JPEG 品質、PDF 頁數、試算表的列數與欄數、壓縮檔裡放多少項目。在命令列用 --set key=value 設定,或在配方的 + properties: 下設定。 +

+
tfg generate --format jpg --size 500kb --set width=1920 --set height=1080 --set quality=85
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
格式設定接受
avifwidth1 - 16384 像素
height1 - 16384 像素
quality1 - 100
bmpwidth1 - 20000 像素
height1 - 20000 像素
csvdelimitercomma, pipe, semicolon, tab
line_endingcrlf, lf
header真或假
quote_styleall, minimal, none
columns2 - 32768 欄
docxparagraphs1 - 50000 段落
gifwidth1 - 20000 像素
height1 - 20000 像素
frames1 - 60
htmlstructuredocument, fragment
icowidth1 - 256 像素
height1 - 256 像素
embedbmp, png
jpgwidth1 - 20000 像素
height1 - 20000 像素
quality1 - 100
jsonformattingindented, minified, record-per-line
jxlwidth1 - 16384 像素
height1 - 16384 像素
quality1 - 100
logentry_formatapache-combined, apache-common, json-lines, nginx, plain, syslog
timestampsadvancing, fixed
rate1 - 1000000 每秒項目數
methodsget, mixed, read
status_mixclient-errors, realistic, server-errors, success
level_mixdebug, errors, quiet, realistic
ip_versionmixed, v4, v6
line_endingcrlf, lf
mdencodingutf-16be, utf-16le, utf-8
bom真或假
pdfpages1 - 5000
page_sizea3, a4, a5, legal, letter, mixed
orientationlandscape, mixed, portrait
rotate0, 90, 180, 270
pdf_version1.4, 1.7
title任意文字
author任意文字
subject任意文字
keywords任意文字
creator任意文字
producer任意文字
created形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none
modified形如 2024-02-29 或 2024-02-29T13:45:00+02:00 的日期,或 none
pngwidth1 - 20000 像素
height1 - 20000 像素
pptxslides1 - 500 投影片
svgwidth1 - 20000 像素
height1 - 20000 像素
targzentries0 - 10000
entry_format格式的 id,與 tfg formats 列出的相同
entry_size形如 2mb 的大小
compressionbest, default, fast, none
depth0 - 50
directory_entries真或假
entry_mode000, 400, 444, 600, 644, 664, 666, 700, 755, 777
entry_ownerroot, unset, user
tiffwidth1 - 20000 像素
height1 - 20000 像素
txtencodingutf-16be, utf-16le, utf-8
bom真或假
wavsample_rate8000 - 192000 赫茲
bit_depth8, 16, 24, 32
channels1 - 8
contentnoise, silence, sweep, tone
webpwidth1 - 16383 像素
height1 - 16383 像素
xlsxrows1 - 200000 列
columns1 - 32768 欄
xmlencodingutf-16be, utf-16le, utf-8
bom真或假
zipentries0 - 10000
entry_format格式的 id,與 tfg formats 列出的相同
entry_size形如 2mb 的大小
compressionbest, default, fast, none
depth0 - 50
directory_entries真或假
password明文密碼
encryptionaes-128, aes-192, aes-256, none, zipcrypto
+
+

+ 超出設定所接受範圍的值會被拒絕,並附上指明該設定、允許範圍以及應改用什麼的訊息。未知的設定同樣是錯誤,絕不會靜默使用預設值,因為悄悄被接受的拼字錯誤會產生設定有誤的檔案,讓你花一小時納悶為什麼該失敗的測試卻通過了。 +

+

+ 執行 tfg formats <id> 即可查看某個格式在你目前版本中接受哪些設定。 +

+
+ +
+

壓縮檔裡裝的是真實檔案

+

+ targz 與 zip + 可以填入項目,而不是只留一個空殼。產生的壓縮檔確實包含它宣稱包含的文件,所以測試期間解壓縮它的任何程式都會在裡面找到真實檔案。 +

+
targets:
+  - id: bundle
+    format: zip
+    contains:
+      - format: txt
+        count: 200
+        size: 4kb
+
+ + +
+ + + + diff --git a/web/public/zh-hant/index.html b/web/public/zh-hant/index.html new file mode 100644 index 00000000..cd062f48 --- /dev/null +++ b/web/public/zh-hant/index.html @@ -0,0 +1,440 @@ + + + + + + +測試檔案產生器 - 精確大小,26 種真實格式 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+

產生大小精確的真實測試檔案

+

+ PDF、PNG、DOCX、ZIP,共 26 + 種格式,每一種都是能在對應軟體中開啟的真實檔案,大小恰好等於你的要求。每次執行還會寫下你的應用程式應該如何處理每個檔案。命令列加桌面視窗,免費開源,完全在你的電腦上執行。 +

+ + +

免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。

+
+ +
+ Testing Files Generator 的桌面視窗,已準備好寫出一批測試檔案 +
桌面視窗,已準備好寫出一批檔案。命令列背後執行的是同一個引擎。
+
+
+ + + +
+

問題所在

+

做一個測試檔案很容易,做出對的一千個才是麻煩所在

+

你在測試接收使用者檔案的軟體。遲早你會需要:

+
    +
  • 一個恰好 10 MB 的 PDF,用來弄清上傳限制是否真實
  • +
  • 位於該限制兩側的三個檔案,用來抓出差一錯誤
  • +
  • 10,000 個記錄檔,用來看夜間工作在資料夾很大時會怎樣
  • +
  • 一個真正包含 200 份文件的 ZIP,而不是只有正確副檔名的空殼
  • +
  • 一個 4 GB 的檔案,同時不必在儲存庫裡保存 4 GB 的檔案
  • +
  • 筆電與建置伺服器上完全相同的 fixture,逐位元組一致
  • +
+

+ 這正是它要取代的。它為 QA 工程師、測試自動化,以及程式碼背後有上傳表單、匯入程式、剖析器或儲存配額的所有人而做。 +

+
+ +
+

它的與眾不同之處

+

其他產生器止步於位元組。這個工具回答你的測試真正要問的問題

+

+ 一個滿是檔案的資料夾仍然要你自己判斷每個檔案應該證明什麼。這裡每次執行都會在檔案旁寫出一個 + manifest.json,它是所產生內容的簡單清單,並為每一項給出宣告的預期。 +

+

假設你的上傳端點允許 1 MB。請求恰好位於這條線上的三個檔案:

+
tfg generate --preset size-boundaries --limit 1mb --spread 1B --format pdf --out ./edges
+ +
+ + + + + + + + + +
檔案位元組你的系統應該原因
1mb_under_1b.pdf1048575接受在限制之內
1mb_at_limit.pdf1048576接受限制本身是允許的
1mb_over_1b.pdf1048577拒絕size_limit
+
+ +

三個檔案,三種不同的答案,以機器可讀的形式給出。你的測試讀取清單,而不是由你手寫斷言:

+
import json, os
+
+directory = "edges"
+manifest = json.load(open(os.path.join(directory, "manifest.json")))
+
+for entry in manifest["files"]:
+    response = upload(os.path.join(directory, entry["path"]))
+    outcome = entry["expected"]["outcome"]
+    if outcome == "accept":
+        assert response.ok, entry["path"]
+    elif outcome == "reject":
+        assert not response.ok, entry["path"]
+ +
+

當答案取決於你自己的政策時,清單會如實說明

+

+ 它記錄的是 unspecified,而不是憑空捏造預期。會猜測的產生器會製造誤報,而總是誤報的測試套件最終會被關掉。 +

+
+
+ +
+

預設集

+

選好問題,拿到整組檔案

+

+ 預設集是圍繞一個測試問題設計的測試檔案組,你不必自己琢磨哪些檔案能證明什麼。每個預設集都有一個頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+
    +
  • +

    空檔案與最小檔案

    +

    一個合法且達到格式允許最小大小的檔案能通過嗎?

    +

    empty-and-minimal

    +
  • +
  • +

    檔名處理

    +

    我的系統能否正確儲存、顯示並傳回它沒料到的檔名?

    +

    filename-handling

    +
  • +
  • +

    大小邊界

    +

    大小限制是否恰好在宣告的位置生效?

    +

    size-boundaries

    +
  • +
  • +

    表格匯入

    +

    我的表格匯入能應付真實工具匯出的內容嗎?

    +

    tabular-import

    +
  • +
  • +

    文字編碼

    +

    我的讀取器知道檔案是什麼編碼,還是在猜?

    +

    text-encoding

    +
  • +
  • +

    上傳驗證

    +

    我的上傳表單是否接受該接受的,並拒絕其餘的?

    +

    upload-validation

    +
  • +
+

全部預設集,以及它們與配方的關係

+
+ +
+

快速開始

+

三個指令,看它如何運作

+
    +
  1. +

    產生一個檔案

    +

    一個 PNG,恰好兩 MB:

    +
    tfg generate --format png --size 2mb --out ./fixtures
    +
  2. +
  3. +

    產生大量檔案

    +

    + 一萬個記錄檔,每個介於 1 到 8 KB + 之間,大小由種子抽取,因此明天會得到同樣的檔案組。給每次執行一個獨立的目錄,清單是一次執行所寫內容的唯一記錄,所以工具拒絕在其上再寫第二份: +

    +
    tfg generate --format log --size-range 1kb-8kb --count 10000 --out ./logs
    +
  4. +
  5. +

    先檢查,再刪除

    +

    verify 告訴你沒有任何變動。cleanup 只刪除寫出的內容,不動其他任何東西:

    +
    tfg verify ./logs/manifest.json
    +tfg cleanup ./logs/manifest.json --yes
    +
  6. +
+

+ 大小以 1024 進位計算,與你的檔案管理員一致,所以 2mb 代表 2097152 + 位元組。直接寫位元組數也可以。文件涵蓋配方、清單與結束碼。 +

+
+ +
+

你將得到什麼

+

為無人看管的測試套件而生

+
    +
  • +

    精確大小,精確到位元組

    +

    要求 10485761 位元組,就得到恰好這麼多。格式無法達到的大小會得到附上原因的錯誤,絕不會得到大小錯誤的檔案。

    +
  • +
  • +

    26 種真實格式

    +

    不是帶副檔名的填充零。產生的 PNG 能在圖片檢視器中開啟,DOCX 能在 Word 中開啟,ZIP 能解壓縮。每種格式在發布前都經過獨立讀取器驗證。

    +
  • +
  • +

    本身就是測試依據的清單

    +

    路徑、大小、SHA-256、格式、種子、工具版本,以及你的系統應該如何處理該檔案。

    +
  • +
  • +

    可重現

    +

    配方與種子相同,位元組就相同,在任何電腦上都一樣。提交一個小小的 YAML 配方,而不是龐大的二進位 fixture。

    +
  • +
  • +

    兩種介面,一個引擎

    +

    一個為 CI 打造的命令列,和一個用於探索式測試的桌面視窗。兩者都不是對方的縮水版,並且有測試逐項比對它們的功能。

    +
  • +
  • +

    完全離線

    +

    沒有帳號,沒有雲端,沒有遙測,沒有更新檢查。命令列執行檔裡根本沒有編譯進網路堆疊。

    +
  • +
+
+ +
+

下載

+

選擇適合你系統的版本

+

+ 解壓縮後執行即可。tfg 是命令列,tfg-gui 是桌面視窗。沒有安裝程式,也無需向你的電腦新增任何東西。 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
系統命令列桌面視窗
Windowsamd64, arm64amd64
Linuxamd64, arm64amd64
macOSarm64arm64
+
+
+

哪些已簽署,哪些沒有

+

+ Windows 與 macOS 的下載檔已簽署,因此啟動時不會出現未知開發者的警告。Linux 的沒有簽署,因為桌面 Linux 沒有可用的對應簽署機制。每個壓縮檔都列在發布頁面的 + verify-SHA256SUMS.txt 中,你可以據此核對所下載的內容。 +

+
+ +

免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。

+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/empty-and-minimal/index.html b/web/public/zh-hant/presets/empty-and-minimal/index.html new file mode 100644 index 00000000..586e528d --- /dev/null +++ b/web/public/zh-hant/presets/empty-and-minimal/index.html @@ -0,0 +1,266 @@ + + + + + + +各格式最小的合法檔案與空檔案 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

空檔案與最小檔案

+

一個合法且達到格式允許最小大小的檔案能通過嗎?

+

+ empty-and-minimal 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 合法檔案因過小而被拒絕,因為檢查是以位元組數判斷,而不是去讀取內容
  • +
  • 空檔案讓讀取器當機,而不是被如實回報
  • +
  • 只有一個像素寬的圖片在產生縮圖的途中發生除以零的錯誤
  • +
  • 儲存空間把零位元組當成上傳失敗,並不斷重試
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show empty-and-minimal 所回報的:

+
+ + + + + + + +
檔案數28
其配方中的 target 數28
總大小32 667 B
格式avif, bmp, csv, docx, gif, html, ico, jpg, json, jxl, log, md, pdf, png, pptx, svg, targz, tiff, toml, txt, wav, webp, xlsx, xml, yaml, zip
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。26
unspecified取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。2
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + +
設定接受預設值作用
--formats以逗號分隔的格式 id,或 allall組合由哪些格式構成。填 all 代表此版本的所有格式,也可以只列出你的系統接受的格式。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show empty-and-minimal
+tfg generate --preset empty-and-minimal --out ./empty-and-minimal
+tfg preset eject empty-and-minimal > empty-and-minimal.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:empty-and-minimal
+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/filename-handling/index.html b/web/public/zh-hant/presets/filename-handling/index.html new file mode 100644 index 00000000..04029543 --- /dev/null +++ b/web/public/zh-hant/presets/filename-handling/index.html @@ -0,0 +1,265 @@ + + + + + + +用於測試的問題檔名 - Unicode 與長度 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

檔名處理

+

我的系統能否正確儲存、顯示並傳回它沒料到的檔名?

+

+ filename-handling 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 在畫面、記錄或清單中看起來像另一個名稱的檔名
  • +
  • 在上傳與儲存之間被截斷、修剪或改寫的檔名
  • +
  • 以字元計算的長度限制,而儲存空間是以位元組計算的
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show filename-handling 所回報的:

+
+ + + + + + + +
檔案數50
其配方中的 target 數50
總大小51 200 B
格式txt
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。4
unspecified取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。46
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + +
設定接受預設值作用
--format格式頁面中的格式 idtxt組合中每個檔案的格式。它是工具本身的參數,預設集只是給它一個預設值。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show filename-handling
+tfg generate --preset filename-handling --out ./filename-handling
+tfg preset eject filename-handling > filename-handling.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:filename-handling
+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/index.html b/web/public/zh-hant/presets/index.html new file mode 100644 index 00000000..b3a186db --- /dev/null +++ b/web/public/zh-hant/presets/index.html @@ -0,0 +1,238 @@ + + + + + + +測試檔案預設集 - 針對 QA 問題的現成檔案組 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

測試檔案預設集,每個測試問題一組檔案

+

+ 預設集是圍繞一個問題設計的整組測試檔案,並附上說明你的系統應如何回應每個檔案的清單。你選擇問題,工具建置檔案組。每個預設集都有自己的頁面,說明它通常能發現什麼、組合裡有什麼,以及它接受的每項設定。 +

+ + + +
+

預設集與配方有何不同?

+

+ 在底層沒有不同。預設集就是工具根據幾項設定替你寫出的配方。tfg preset eject + 會把這個配方列印出來,方便你與測試放在一起並加以編輯,你自己的配方也可以用一行以某個預設集為基礎,也就是 extends: preset: 後面接上它的 id。 +

+
tfg preset list
+tfg preset show size-boundaries
+tfg preset eject size-boundaries > my.yaml
+
+ +
+

我可以信任預設值嗎?

+

+ 對檔案來說可以。對於只有你的系統才知道的數字,比如上傳表單的限制,預設值是我們的預留值,工具每次使用時都會這樣說明。每個預設集的頁面都會標出這些設定,tfg preset + show 會在寫入任何內容之前告知你。 +

+
+ +
+ + + + diff --git a/web/public/zh-hant/presets/size-boundaries/index.html b/web/public/zh-hant/presets/size-boundaries/index.html new file mode 100644 index 00000000..15f5d982 --- /dev/null +++ b/web/public/zh-hant/presets/size-boundaries/index.html @@ -0,0 +1,279 @@ + + + + + + +測試上傳大小限制 - 恰好落在邊界上的檔案 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

大小邊界

+

大小限制是否恰好在宣告的位置生效?

+

+ size-boundaries 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 限制處的差一錯誤
  • +
  • 把 MB 與 MiB 搞混,相差 4.8%,足以放過本不該通過的檔案
  • +
  • 限制只在瀏覽器中生效,而不在伺服器上
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show size-boundaries 所回報的:

+
+ + + + + + + +
檔案數7
其配方中的 target 數7
總大小73 400 320 B
格式pdf
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。4
reject你的系統應該拒絕這個檔案。3
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
設定接受預設值作用
--limit形如 2mb 的大小10mb你的系統宣告的大小限制。其他一切都以它為基準測量。 這個預設值是我們的預留值,不是你的系統的值。請傳入你自己的值。
--spread以逗號分隔的大小1B,1kb,1mb在限制兩側各延伸多遠,以大小清單表示。
--format格式頁面中的格式 idpdf組合中每個檔案的格式。它是工具本身的參數,預設集只是給它一個預設值。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

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

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:size-boundaries
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/tabular-import/index.html b/web/public/zh-hant/presets/tabular-import/index.html new file mode 100644 index 00000000..3b189337 --- /dev/null +++ b/web/public/zh-hant/presets/tabular-import/index.html @@ -0,0 +1,273 @@ + + + + + + +CSV 與 Excel 匯入測試檔案 - 分隔符號、標題列 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

表格匯入

+

我的表格匯入能應付真實工具匯出的內容嗎?

+

+ tabular-import 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 以分號分隔的檔案被讀成單一欄位,因為分隔符號是假設的,而不是偵測出來的
  • +
  • CRLF 檔案被拆成多列,每列後面多出一個空列
  • +
  • 沒有標題列的表格,第一列資料被當成欄位名稱吞掉
  • +
  • 匯入只保留能顯示的欄位,其餘的默默丟棄
  • +
  • 讀取器逐行讀取 JSON 記錄,遇到第一個有縮排的文件就停下來
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show tabular-import 所回報的:

+
+ + + + + + + +
檔案數13
其配方中的 target 數13
總大小3 080 060 B
格式csv, json, xlsx
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。8
unspecified取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。5
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + + + + + + + +
設定接受預設值作用
--rows1 - 200000 列1000試算表有多少列。檔案會寫成這麼多列恰好打包出的大小,所以上面的預算會隨這個值變動。
--columns1 - 32768 欄10試算表每列有多少欄。列數乘以欄數有上限,超出時會在寫入任何內容之前被拒絕。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show tabular-import
+tfg generate --preset tabular-import --out ./tabular-import
+tfg preset eject tabular-import > tabular-import.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:tabular-import
+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/text-encoding/index.html b/web/public/zh-hant/presets/text-encoding/index.html new file mode 100644 index 00000000..c54cc214 --- /dev/null +++ b/web/public/zh-hant/presets/text-encoding/index.html @@ -0,0 +1,266 @@ + + + + + + +文字編碼測試檔案 - UTF-8、UTF-16、BOM、CRLF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

文字編碼

+

我的讀取器知道檔案是什麼編碼,還是在猜?

+

+ text-encoding 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 讀取器假設為 UTF-8,把 UTF-16 檔案顯示成每三個字元一個,或一排排方框
  • +
  • 位元組順序標記被當成內容讀取,導致匯入的第一個欄位以三個多餘字元開頭
  • +
  • 匯入器依據開頭幾個位元組猜測編碼,遇到較長的檔案卻猜成別的
  • +
  • CRLF 檔案被拆成多列,每列後面多出一個空列,或歸位字元殘留在最後一個欄位裡
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show text-encoding 所回報的:

+
+ + + + + + + +
檔案數20
其配方中的 target 數20
總大小81 920 B
格式csv, log, md, txt, xml
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。10
unspecified取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。10
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + +
設定接受預設值作用
--sample形如 2mb 的大小4kb組合中每個檔案的大小。UTF-16 每個字元佔兩個位元組,所以奇數會被拒絕。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show text-encoding
+tfg generate --preset text-encoding --out ./text-encoding
+tfg preset eject text-encoding > text-encoding.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:text-encoding
+
+ + +
+ + + + diff --git a/web/public/zh-hant/presets/upload-validation/index.html b/web/public/zh-hant/presets/upload-validation/index.html new file mode 100644 index 00000000..b4ea47cb --- /dev/null +++ b/web/public/zh-hant/presets/upload-validation/index.html @@ -0,0 +1,295 @@ + + + + + + +上傳驗證測試檔案 - 類型、大小與檔名 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

預設集

+

上傳驗證

+

我的上傳表單是否接受該接受的,並拒絕其餘的?

+

+ upload-validation 預設集用一個指令為這個問題建立出整組真實測試檔案,並在旁邊放一個 + manifest.json,說明你的系統應如何回應每個檔案。以下所有內容都依此版本的預設值從程式中讀取。 +

+ + +
+

它通常能發現什麼?

+
    +
  • 限制只在瀏覽器中生效,而不在伺服器上
  • +
  • SVG 或 HTML 檔案被當成圖片或純文字,這是讓指令碼繞過表單的一種辦法
  • +
  • 只依副檔名檢查而從不開啟檔案,於是名為 .jpg 的 PDF 蒙混過關
  • +
  • 表單在查看大小之前就把整個請求本文讀進記憶體
  • +
  • 名為 PHOTO.JPG 的上傳被拒絕,而 photo.jpg 被接受,或者相反
  • +
  • 含空格、括號或非 ASCII 字元的檔名被原封不動寫入磁碟
  • +
+
+ + +
+

組合裡有什麼?

+

使用預設值時,如 tfg preset show upload-validation 所回報的:

+
+ + + + + + + +
檔案數71
其配方中的 target 數22
總大小120 639 488 B
格式html, jpg, pdf, png, svg, txt
+
+

以及該組合的清單對你的系統有何預期:

+
+ + + + + + + + + +
預期意義檔案數
accept你的系統應該接受這個檔案。56
reject你的系統應該拒絕這個檔案。10
unspecified取決於你的系統規則。由你決定,然後檢查實際發生的是否符合你的本意。5
+
+
+ +
+

你可以變更什麼?

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
設定接受預設值作用
--limit形如 2mb 的大小10mb你的上傳表單宣告的大小限制。這個組合在限制兩側各取一步,若要涵蓋任意距離的檔案,請執行 size-boundaries 預設集。 這個預設值是我們的預留值,不是你的系統的值。請傳入你自己的值。
--allow以逗號分隔的格式 idjpg,png,pdf你的表單應該接受哪些類型。每種類型都會變成該類型的真實檔案,它們構成整個組合的陽性對照。
--deny以逗號分隔的副檔名svg,html,exe,sh你的表單應該拒絕哪些副檔名。此版本沒有對應格式的副檔名,仍會得到一個同名檔案,內容為純文字。
--far-over10x, 2x, off2x那個超大檔案超出限制多少。如果寫入限制數倍大小的檔案不值得占用磁碟,可以關閉。
--bulk0 - 10000 個檔案50大量上傳包含多少個檔案。設為零則完全不包含這一組。
+
+
+ +
+

如何執行?

+

查看組合的開銷、建置它,或取出它的配方來編輯:

+
tfg preset show upload-validation
+tfg generate --preset upload-validation --limit 10mb --out ./upload-validation
+tfg preset eject upload-validation > upload-validation.yaml
+

也可以在你自己的配方中以它為基礎,放在測試旁邊:

+
version: 1
+extends: preset:upload-validation
+with:
+  limit: 10mb
+
+ + +
+ + + + diff --git a/web/public/zh-hant/test-files-in-ci/index.html b/web/public/zh-hant/test-files-in-ci/index.html new file mode 100644 index 00000000..595feefe --- /dev/null +++ b/web/public/zh-hant/test-files-in-ci/index.html @@ -0,0 +1,358 @@ + + + + + + +CI 中的測試檔案 - GitHub Actions、GitLab CI 和 PowerShell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

使用情境

+

如何在 CI 流程中產生測試檔案

+

+ 儲存庫裡的二進位 fixture 會永遠留在歷史中,無法在 diff + 裡審查,檔案一大就根本行不通。請改為在流程內部用配方產生這些檔案。配方是文字,每次產生的位元組都相同,最後一步還能證明什麼都沒有變動。 +

+ +
+

簡短回答

+

+ 安裝 tfg,在測試之前執行 tfg generate fixtures.yaml --out ./fixtures,在測試之後執行 + tfg verify ./fixtures/manifest.json。這兩步都會自行讓建置失敗,並給出說明原因的結束碼。 +

+
+ +
+

為什麼不提交

+

為什麼 fixture 不該放在儲存庫裡

+
    +
  • + 它會留在歷史中。之後再刪除二進位檔案也不會讓複本變小,因為它的每個版本都還在。 +
  • +
  • + diff 看不出改了什麼。審查者只看到一個 PDF 不同了,僅此而已。配方的變化只有一行。 +
  • +
  • + 大檔案放不下。GitHub 會拒絕包含超過 100 MB 檔案的推送,所以一個 500 MB 上傳限制的測試沒有什麼可提交的。 +
  • +
+

+ 該提交的是配方。相同的配方和種子在每台機器上寫出相同的位元組,所以在流程裡產生的檔案,就是你在筆電上用過的那個檔案。 +

+
+ +
+

配方

+

放在測試旁邊的配方

+

+ 這個配方寫出二十五張應被接受的發票和兩張超過限制、應被拒絕的圖片,清單會記錄這兩種預期: +

+
version: 1
+seed: 7741
+
+targets:
+  - id: invoices
+    format: pdf
+    count: 25
+    size: 300kb
+    expected: accept
+
+  - id: over_the_limit
+    format: png
+    count: 2
+    size: 12mb
+    expected:
+      outcome: reject
+      reason: size_limit
+

+ tfg validate fixtures.yaml 會檢查它而不寫入任何內容,並一次列出所有問題。 +

+
+ +
+

GitHub Actions

+

安裝工具並建置 fixture 的工作流程

+
jobs:
+  test:
+    runs-on: ubuntu-latest
+    env:
+      TFG_VERSION: "0.4.0"
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: install tfg
+        run: |
+          base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+          curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+          curl -fsSLO "$base/verify-SHA256SUMS.txt"
+          sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+          tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+          sudo mv tfg /usr/local/bin/
+
+      - 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
+

+ 檢查碼那一行把壓縮檔與同一發行版中的 verify-SHA256SUMS.txt 比對。版本是固定的,所以新發行版絕不會改變你沒動過的建置。 +

+
+ +
+

GitLab CI

+

同樣的事,寫成 GitLab 作業

+
fixtures:
+  image: ubuntu:24.04
+  variables:
+    TFG_VERSION: "0.4.0"
+  script:
+    - apt-get update -qq && apt-get install -y -qq curl ca-certificates
+    - base=https://github.com/donislawdev/TestingFilesGenerator/releases/download/v$TFG_VERSION
+    - curl -fsSLO "$base/tfg_${TFG_VERSION}_linux_amd64.tar.gz"
+    - curl -fsSLO "$base/verify-SHA256SUMS.txt"
+    - sha256sum --check --ignore-missing verify-SHA256SUMS.txt
+    - tar -xzf "tfg_${TFG_VERSION}_linux_amd64.tar.gz" ./tfg
+    - ./tfg generate fixtures.yaml --out ./fixtures
+    - pytest tests/
+    - ./tfg verify ./fixtures/manifest.json
+
+ +
+

變紅的時候

+

什麼會讓一個步驟失敗,為什麼

+

+ 每種結局都有自己的結束碼,所以步驟會自行失敗,日誌會說明是哪一種。流程會遇到的有: +

+
    +
  • 3 - 配方無效。沒有寫入任何內容,每個問題都會被指出
  • +
  • 4 - 格式做不到所要求的事,例如小於它最小值的大小
  • +
  • 6 - 磁碟空間不足
  • +
  • 7 - tfg verify 發現一個與其清單不符的檔案
  • +
  • 8 - 執行已結束,但並非所有內容都已產生
  • +
+

+ 失敗的執行不會向標準輸出印出任何內容,所以日誌剖析器永遠不會把錯誤當成資料。完整的表格在文件頁面上。 +

+
+ +
+

PowerShell

+

PowerShell 指令碼還需要多寫一行

+

+ PowerShell 不會把程式的結束碼帶出 .ps1 檔案。用 -File 執行一個指令碼,即使裡面的工具拒絕了工作,指令碼也會回傳 + 0,於是本該變紅的建置變成了綠色。最後一行就是全部的修正: +

+
tfg generate fixtures.yaml --out ./fixtures
+exit $LASTEXITCODE
+

+ 這是 PowerShell 的行為,與本工具無關。cmd、bash 和 zsh 不需要額外處理。 +

+
+ +
+

多個作業

+

在作業之間共用 fixture

+

+ 通常不需要上傳它們。因為相同的配方寫出相同的位元組,每個作業都可以執行自己的 tfg + generate,這比上傳再下載更快。當一個作業必須接收另一個作業的檔案時,在傳輸之後對清單執行 tfg verify,它會告訴你收到的是否就是寫出的。 +

+
+ +
+

接下來

+

從這裡去哪裡

+
    +
  • + 損毀的測試檔案把刻意弄壞的檔案加入同一個配方。 +
  • +
  • + 使用情境展示流程中的執行還能檢查什麼。 +
  • +
  • + 文件包含每個指令、每個配方鍵和每個結束碼。 +
  • +
+
+ +
+ + + + diff --git a/web/public/zh-hant/use-cases/index.html b/web/public/zh-hant/use-cases/index.html new file mode 100644 index 00000000..09b6d9c3 --- /dev/null +++ b/web/public/zh-hant/use-cases/index.html @@ -0,0 +1,296 @@ + + + + + + +使用情境 - 上傳限制、CI fixture、大量測試 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

人們用它來做什麼

+

+ 幾乎每個接收使用者檔案的專案都會遇到的五項任務,以及完成每一項的指令。下面的每個範例都能照原樣執行。 +

+ +
+

上傳限制

+

測試檔案大小限制是否在宣稱的位置生效

+

+ 一個限制對應三個測試案例,而不是一個:剛好低於、恰好等於和剛好高於。手工做這些意味著計算位元組數,並祈禱自己沒有算錯一位。不如直接要求整組檔案: +

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

+ 你會得到三個真實的 PDF,大小分別是 1048575、1048576 與 1048577 位元組,以及一份清單,說明前兩個應被接受,第三個應因 size_limit + 被拒絕。你的測試讀取預期,而不是由你手寫三個斷言,限制改變時,你只需改一個數字再重新執行。 +

+

+ 如果你只想要一組內嵌的邊界檔案,不用預設集也可以做到: +

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

持續整合

+

讓 fixture 留在儲存庫之外又不遺失

+

+ 大型二進位 fixture 會拖慢儲存庫複製,也讓審查變得彆扭,而且替換其中一個時沒有人能看出改了什麼。配方只是幾百個字元的 + YAML,就能重建出完全相同的檔案,在任何電腦上逐位元組一致,因為每個檔案都由執行的種子衍生。 +

+
- 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
+

+ 每種結束方式都有自己的結束碼,所以流程可以區分配方錯誤、磁碟已滿和驗證不一致。失敗的執行不會在標準輸出上列印任何內容,這樣記錄剖析器就不會把錯誤當成資料。 +

+
+ +
+

規模

+

弄清資料夾很大時會發生什麼

+

+ 匯入程式、夜間工作與目錄列表在一萬個檔案時的表現與十個檔案時不同。從範圍中抽取的大小讓檔案組看起來像真實流量,而不是一萬個完全相同的檔案,並且抽取來自種子,所以明天檔案組依然相同。 +

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

+ 在執行寫入任何內容之前先查看它的開銷,當總量以 GB 計時這一點很重要: +

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

+ 比磁碟可用空間更大的執行會在寫入第一個位元組之前就被拒絕,而不是把磁碟寫滿再半途失敗。 +

+
+ +
+

壓縮檔

+

用真正裝有檔案的壓縮檔測試解壓縮程式

+

+ 只有正確副檔名的空壓縮檔,無法證明任何關於開啟它並走訪內容的程式碼的事情。宣告內容,壓縮檔就真的包含它們: +

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

+ 巢狀深度、項目數量和內部內容的大小,匯入程式都有自己的看法,而這正是你弄清這些看法的辦法。 +

+
+ +
+

剖析器與檢視器

+

檢查你自己的程式碼讀取格式的方式是否與真實軟體一致

+

+ 這裡的每種格式在發布前都用獨立讀取器驗證過:PNG 被開啟並比對像素,DOCX 由另外的函式庫讀回,壓縮檔被解壓縮。這意味著你的剖析器拒絕的檔案,是關於你的剖析器的發現,而不是關於產生器的。 +

+
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
+

+ 格式頁面列出了每種格式接受的設定,以及每種格式能達到的最小檔案。 +

+
+ +
+

指南

+

其中兩項的詳細說明

+
    +
  • + 損毀的測試檔案 - 一個刻意弄壞、大小精確的檔案,對它應有的處理寫在清單裡。 +
  • +
  • + CI 中的測試檔案 - 一個 GitHub Actions 工作流程、一個 GitLab + 作業,以及讓建置失敗的結束碼。 +
  • +
+
+ +
+

適合誰

+

+ QA 工程師、測試自動化,以及程式碼背後有上傳表單、匯入程式、剖析器或儲存配額的所有人。它可以在完全沒有網路的電腦上執行,這在以瀏覽器為基礎的產生器行不通的封閉企業環境中尤為重要。 +

+ +

免費開源,GPL-3.0。無需註冊。Windows 與 macOS 的下載檔已簽署,啟動時不會出現警告。

+
+ +
+ + + + diff --git a/web/templates/layout.html b/web/templates/layout.html index 5c189582..4d8aa5be 100644 --- a/web/templates/layout.html +++ b/web/templates/layout.html @@ -1,8 +1,9 @@ - + + {{ .Page.Title }} @@ -11,7 +12,7 @@ {{- end }} - + @@ -20,7 +21,7 @@ {{- range .Switches }} - + {{- end }} @@ -54,11 +55,19 @@ {{ .Label }} {{- end }} -
- {{- range .Switches }} - {{ .Name }} - {{- end }} -
+ {{- if .Switches }} +
+ + + {{ .Lang.Name }} + + +
+ {{- end }} diff --git a/web/templates/partials.html b/web/templates/partials.html index bc3a54a0..5258c450 100644 --- a/web/templates/partials.html +++ b/web/templates/partials.html @@ -124,6 +124,31 @@ {{- end -}} +{{- define "damagesTable" -}} +
+ + + + + + + + + + + {{- range .DamageList }} + + + + + + + {{- end }} + +
{{ .Word "colDamage" }}{{ .Word "colEffect" }}{{ .Word "colSmallest" }}{{ .Word "colSettings" }}
{{ .ID }}{{ .Effect }}{{ .Smallest }}{{ if .Settings }}{{ range $i, $name := .Settings }}{{ if $i }}, {{ end }}{{ $name }}{{ end }}{{ else }}{{ .None }}{{ end }}
+
+{{- end -}} + {{- define "propertiesTable" -}}