{"id":13413881,"url":"https://github.com/maargenton/go-testpredicate","last_synced_at":"2026-01-17T18:28:04.197Z","repository":{"id":46015116,"uuid":"158880127","full_name":"maargenton/go-testpredicate","owner":"maargenton","description":"Unit-testing predicates for Go.","archived":false,"fork":false,"pushed_at":"2025-10-30T10:01:30.000Z","size":178,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-30T10:27:56.183Z","etag":null,"topics":["bdd","go","golang","predicate","test","testing","tests","unit-testing","unittest"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maargenton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-23T21:39:11.000Z","updated_at":"2025-10-30T09:55:34.000Z","dependencies_parsed_at":"2022-09-26T19:32:34.229Z","dependency_job_id":null,"html_url":"https://github.com/maargenton/go-testpredicate","commit_stats":null,"previous_names":["marcus999/go-testpredicate"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/maargenton/go-testpredicate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maargenton%2Fgo-testpredicate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maargenton%2Fgo-testpredicate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maargenton%2Fgo-testpredicate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maargenton%2Fgo-testpredicate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maargenton","download_url":"https://codeload.github.com/maargenton/go-testpredicate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maargenton%2Fgo-testpredicate/sbom","scorecard":{"id":608920,"data":{"date":"2025-08-11","repo":{"name":"github.com/maargenton/go-testpredicate","commit":"be114a7c4b0414faef468b031fa756b36ee1e06e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/build.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/build.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yaml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/build.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/build.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/maargenton/go-testpredicate/release.yaml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yaml:1","Warn: no topLevel permission defined: .github/workflows/release.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.5.0 not signed: https://api.github.com/repos/maargenton/go-testpredicate/releases/184851154","Warn: release artifact v1.4.0 not signed: https://api.github.com/repos/maargenton/go-testpredicate/releases/184653085","Warn: release artifact v1.5.0 does not have provenance: https://api.github.com/repos/maargenton/go-testpredicate/releases/184851154","Warn: release artifact v1.4.0 does not have provenance: https://api.github.com/repos/maargenton/go-testpredicate/releases/184653085"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 26 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T02:12:07.384Z","repository_id":46015116,"created_at":"2025-08-21T02:12:07.384Z","updated_at":"2025-08-21T02:12:07.384Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28515518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:28:00.501Z","status":"ssl_error","status_checked_at":"2026-01-17T18:28:00.150Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bdd","go","golang","predicate","test","testing","tests","unit-testing","unittest"],"created_at":"2024-07-30T20:01:51.864Z","updated_at":"2026-01-17T18:28:04.175Z","avatar_url":"https://github.com/maargenton.png","language":"Go","readme":"# go-testpredicate\n\nTest predicate style assertions library with extensive diagnostics output.\n\n[![Latest](\n  https://img.shields.io/github/v/tag/maargenton/go-testpredicate?color=blue\u0026label=latest\u0026logo=go\u0026logoColor=white\u0026sort=semver)](\n  https://pkg.go.dev/github.com/maargenton/go-testpredicate)\n[![Build](\n  https://img.shields.io/github/actions/workflow/status/maargenton/go-testpredicate/build.yaml?branch=master\u0026label=build\u0026logo=github\u0026logoColor=aaaaaa)](\n  https://github.com/maargenton/go-testpredicate/actions?query=branch%3Amaster)\n[![Codecov](\n  https://img.shields.io/codecov/c/github/maargenton/go-testpredicate?label=codecov\u0026logo=codecov\u0026logoColor=aaaaaa\u0026token=fVZ3ZMAgfo)](\n  https://codecov.io/gh/maargenton/go-testpredicate)\n[![Go Report Card](\n  https://goreportcard.com/badge/github.com/maargenton/go-testpredicate)](\n  https://goreportcard.com/report/github.com/maargenton/go-testpredicate)\n\n\n---------------------------\n\nPackage `go-testpredicate` is an assertions library exposing a test predicate\nstyle syntax for use with the built-in Go `testing` package, producing extensive\ndiagnostics output and reducing the need for debugging failing tests.\n\nThe library contains an extensive collection of built-in predicates covering:\n\n- basic tests for nil, true, false\n- equality between any type of value\n- ordered comparison on numeric, string and sequence values\n- regexp match on strings\n- sub-sequences match on strings and sequences\n- set conditions on unordered collections\n- panic conditions on code fragment execution\n\nIt also includes a BDD-style bifurcated evaluation context, where each test\nsection is potentially evaluated multiple times in order to evaluate each branch\nindependently.\n\n\n## Installation\n\n```\ngo get github.com/maargenton/go-testpredicate\n```\n\nOptionally, you can add predefined code snippets for your text editor or IDE to\nassist in writing  your test code. Snippets for VSCode are available\n[here](docs/snippets.md)\n\n## Usage\n\n```go\npackage example_test\n\nimport (\n    \"testing\"\n\n    \"github.com/maargenton/go-testpredicate/pkg/bdd\"\n    \"github.com/maargenton/go-testpredicate/pkg/require\"\n    \"github.com/maargenton/go-testpredicate/pkg/verify\"\n)\n\nfunc TestExample(t *testing.T) {\n    bdd.Given(t, \"something\", func(t *bdd.T) {\n        require.That(t, 123).ToString().Length().Eq(3)\n\n        t.When(\"doing something\", func(t *bdd.T) {\n            t.Then(\"something happens \", func(t *bdd.T) {\n                verify.That(t, \"123\").Eq(123)\n                verify.That(t, 123).ToString().Length().Eq(4)\n            })\n        })\n    })\n}\n```\n\nOutput:\n```\n--- FAIL: TestExample (0.00s)\n    --- FAIL: TestExample/Given_something (0.00s)\n        --- FAIL: TestExample/Given_something/when_doing_something (0.00s)\n            --- FAIL: TestExample/Given_something/when_doing_something/then_something_happens_ (0.00s)\n                example_test.go:17:\n                    expected: value == 123\n                    error:    values of type 'string' and 'int' are never equal\n                    value:    \"123\"\n                example_test.go:18:\n                    expected: length(value.String()) == 4\n                    value:    123\n                    string:   \"123\"\n                    length:   3\n```\n\n## API changes and stability\n\nOlder version of this package where exposing a different API that has since been\ndeprecated, and has now been remove for the v1.0.0 release. The latest version\nsupporting the legacy API is v0.6.4.\n\nPredicates are constructed starting with either `require.That(t, \u003cvalue\u003e)` or\n`verify.That(t, \u003cvalue\u003e)`, where _require_ will abort the test on error, while\n_verify_ will keep going. Both variants take the testing context `t`, and the\nvalue to test.\n\nAdditional diagnostic context can be added to either functions with\n`require.Context{}` / `verify.Context{}` passed as additional arguments.\n\n```go\npackage example_test\n\nimport (\n    \"testing\"\n    \"github.com/maargenton/go-testpredicate/pkg/require\"\n    \"github.com/maargenton/go-testpredicate/pkg/verify\"\n)\n\nfunc TestExample(t *testing.T) {\n    v := 123\n    require.That(t, v).ToString().Length().Eq(3)\n    verify.That(t, v).ToString().Length().Eq(3)\n    verify.That(t, v,\n        verify.Context{Name: \"double\", Value: v * 2},\n    ).ToString().Length().Eq(3)\n}\n```\n\n## Built-in predicates\n\nAll predicates are built through call chaining on the builder object returned by\n`require.That()` or `verify.That()`. For an up-to-date full list of supported\npredicates and their use, take a look at\n`pkg/internal/builder/builder_api_test.go`\n\n```go\nfunc TestCollectionAPI(t *testing.T) {\n    verify.That(t, []string{\"a\", \"bb\", \"ccc\"}).All(\n        subexpr.Value().Length().Lt(5))\n    verify.That(t, []string{\"a\", \"bb\", \"ccc\"}).Any(\n        subexpr.Value().Length().Ge(3))\n}\n\nfunc TestCompareAPI(t *testing.T) {\n    verify.That(t, true).IsTrue()\n    verify.That(t, false).IsFalse()\n    verify.That(t, nil).IsNil()\n    verify.That(t, \u0026struct{}{}).IsNotNil()\n    verify.That(t, 123).IsEqualTo(123)\n    verify.That(t, 123).IsNotEqualTo(124)\n\n    verify.That(t, 123).Eq(123)\n    verify.That(t, 123).Ne(124)\n}\n\nfunc TestErrorAPI(t *testing.T) {\n    var sentinel = fmt.Errorf(\"sentinel\")\n    var err = fmt.Errorf(\"error: %w\", sentinel)\n    var re = regexp.MustCompile(\"^error: sentinel$\")\n\n    verify.That(t, nil).IsError(nil)        // No error\n    verify.That(t, err).IsError(\"\")         // Any error\n    verify.That(t, err).IsError(sentinel)   // Specific error or nested error\n    verify.That(t, err).IsError(\"sentinel\") // Message contains string\n    verify.That(t, err).IsError(re)         // Message matches regexp\n\n    var err2 = fmt.Errorf(\"error: %w\", \u0026MyError{Code: 123})\n    var myError *MyError\n    verify.That(t, err2).AsError(\u0026myError).Field(\"Code\").Eq(123)\n}\n\nfunc TestExtAPI(t *testing.T) {\n    var customPredicate = func() (desc string, f predicate.PredicateFunc) {\n        // ...\n    }\n    verify.That(t, nil).Is(customPredicate())\n\n    var customTransform = func() (desc string, f predicate.TransformFunc) {\n        // ...\n    }\n    verify.That(t, nil).Eval(customTransform()).Is(customPredicate())\n\n    verify.That(t, 9).Passes(subexpr.Value().Lt(10))\n}\n\nfunc TestMapAPI(t *testing.T) {\n    var m = map[string]string{ \"aaa\": \"bbb\", \"ccc\": \"ddd\" }\n\n    verify.That(t, m).MapKeys().IsEqualSet([]string{\"aaa\", \"ccc\"})\n    verify.That(t, m).MapValues().IsEqualSet([]string{\"bbb\", \"ddd\"})\n}\n\nfunc TestOrderedAPI(t *testing.T) {\n    verify.That(t, 123).IsLessThan(124)\n    verify.That(t, 123).IsLessOrEqualTo(123)\n    verify.That(t, 123).IsGreaterThan(122)\n    verify.That(t, 123).IsGreaterOrEqualTo(123)\n    verify.That(t, 123).IsCloseTo(133, 10)\n\n    verify.That(t, 123).Lt(124)\n    verify.That(t, 123).Le(123)\n    verify.That(t, 123).Gt(122)\n    verify.That(t, 123).Ge(123)\n}\n\nfunc TestPanicAPI(t *testing.T) {\n    verify.That(t, func() {\n        panic(123)\n    }).Panics()\n\n    verify.That(t, func() {\n        panic(123)\n    }).PanicsAndRecoveredValue().Eq(123)\n}\n\nfunc TestSequenceAPI(t *testing.T) {\n    verify.That(t, make([]int, 3, 5)).Length().Eq(3)\n    verify.That(t, make([]int, 3, 5)).Capacity().Eq(5)\n\n    verify.That(t, []int{}).IsEmpty()\n    verify.That(t, []int{1, 2, 3, 4, 5}).IsNotEmpty()\n    verify.That(t, []int{1, 2, 3, 4, 5}).StartsWith([]int{1, 2})\n    verify.That(t, []int{1, 2, 3, 4, 5}).Contains([]int{2, 3, 4})\n    verify.That(t, []int{1, 2, 3, 4, 5}).EndsWith([]int{4, 5})\n\n    verify.That(t, []int{1, 2, 3, 4, 5}).HasPrefix([]int{1, 2})\n    verify.That(t, []int{1, 2, 3, 4, 5}).HasSuffix([]int{4, 5})\n}\n\nfunc TestSetAPI(t *testing.T) {\n    verify.That(t, []int{1, 2, 3, 4, 5}).IsEqualSet([]int{1, 4, 3, 2, 5})\n    verify.That(t, []int{1, 2, 3, 4, 5}).IsDisjointSetFrom([]int{6, 9, 8, 7})\n    verify.That(t, []int{1, 2, 3, 4, 5}).IsSubsetOf([]int{1, 4, 3, 2, 5, 6})\n    verify.That(t, []int{1, 2, 3, 4, 5}).IsSupersetOf([]int{1, 4, 5})\n}\n\nfunc TestStringAPI(t *testing.T) {\n    verify.That(t, \"123\").Matches(`\\d+`)\n    verify.That(t, 123).ToString().Eq(\"123\")\n    verify.That(t, \"aBc\").ToLower().Eq(\"abc\")\n    verify.That(t, \"aBc\").ToUpper().Eq(\"ABC\")\n}\n```\n\n## BDD-style bifurcated tests\n\n### Rationale\n\nFirst of all, the Go `testing` package is great and the fact that it is\nstandard, built in and integrated with the Go tooling infrastructure is awesome.\nThis is why the `go-testpredicate` packages strives to enhance it instead of\nreplacing it, unlike many other testing packages.\n\nIf you look at other unit-testing packages, in other languages, you will find\neither traditional xUnit style packages relying on classes to define test suites\nand fixtures and test cases, or more recent testing packages (like\n[Catch-2](https://github.com/catchorg/Catch2) for C++) that provide, through\nother means, ways to define setup and test cases than run independently. The\ncommon pattern is that setup code, that may be shared by multiple test cases, is\nusually re-evaluated for every test case so that, despite their potentially\nmutating interactions with the setup, test cases don't affect each other.\n\nSome great articles and blog posts have explained how the leverage nested\n`t.Run()` calls to structure tests in way that is closer to BDD-style given /\nwhen / then paradigm. Unfortunately, when using thees approaches, and especially\nwith shared setup sections, the test cases are no longer independent, as all\nbranches are run sequentially, going up and down each branch and into the next\nbranch, without resetting the setup.\n\nThe `bdd` package in `go-testpredicate` provides a way to write tests with a\nBDD-style structure, using the built-in `testing.T`, but evaluating the test\ncases in a bifurcated fashion, repeating the evaluation of each entire branch\nfor every leaf test case, so that test cases are independent from each other\nagain.\n\n### Usage overview\n\n`bdd.Wrap()` or `bdd.Given()` are the root level function that setup and iterate\nthrough the bifurcated test evaluation context. They define blocks that receive\na `bdd.T` instead of `testing.T`, but `bdd.T` is fully compatible with\n`testing.T` and can be used with any third party library that expect either the\n`testing.TB` interface or a subset of it (including out own `verify.That()` /\n`require.That()`).\n\nNested and sibling bifurcated branches are defined with `t.Run()` (on `bdd.T`)\nor `t.When()` / `t.With()` / `t.Then()` for BDD style.\n\n\u003e **IMPORTANT:** In a bifurcated evaluation context, as defined by `bdd.T`, test\n\u003e scenarios are run repeatedly in order to evaluate each branch (from root to\n\u003e leaf) independently of each other. When a particular branch is being\n\u003e evaluated, all the other forks and sub-branches are skipped; the other\n\u003e branches are run in separated independent iterations of the scenario.\n\n### Usage, traditional style\n\n```go\npackage example_test\n\nimport (\n    \"testing\"\n    \"github.com/maargenton/go-testpredicate/pkg/bdd\"\n)\n\nfunc TesTraditional(t *testing.T) {\n\n    // Global immutable setup code can go here\n\n    bdd.Wrap(t, \"Given something\", func(t *bdd.T) {\n\n        // Local mutable setup code goes here\n\n        t.Run(\"something happens\", func(t *bdd.T) {\n\n            // When this code runs, the code in following `t.Run()` blocks\n            // will be skipped.\n        })\n        t.Run(\"something else happens\", func(t *bdd.T) {\n\n            // When this code runs, all code in preceding `t.Run()` blocks\n            // has been skipped and did not affect the local setup.\n        })\n    })\n}\n```\n\n### Usage, BDD style\n\n```go\npackage bdd_test\n\nimport (\n    \"testing\"\n    \"github.com/maargenton/go-testpredicate/pkg/bdd\"\n)\n\nfunc TestBDDStyle(t *testing.T) {\n\n    // Global immutable setup code can go here\n\n    bdd.Given(t, \"something\", func(t *bdd.T) {\n\n        // Local mutable setup code goes here\n\n        t.When(\"doing something\", func(t *bdd.T) {\n\n            // or here\n\n            t.With(\"something\", func(t *bdd.T) {\n\n                // or here\n\n                t.Then(\"something happens\", func(t *bdd.T) {\n\n                    // When this code runs, the code in the following `t.Then()`\n                    // blocks will be skipped.\n                })\n                t.Then(\"something else happens\", func(t *bdd.T) {\n\n                    // When this code runs, all code in preceding `t.Then()`\n                    // blocks has been skipped and did not affect the local setup.\n                })\n            })\n        })\n    })\n}\n```\n","funding_links":[],"categories":["Testing","测试","Testing Frameworks","Template Engines"],"sub_categories":["HTTP Clients","Testing Frameworks","HTTP客户端"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaargenton%2Fgo-testpredicate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaargenton%2Fgo-testpredicate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaargenton%2Fgo-testpredicate/lists"}