diff --git a/.mdsf.json b/.mdsf.json new file mode 100644 index 000000000..c3f53e2e3 --- /dev/null +++ b/.mdsf.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/hougesen/mdsf/main/schemas/v0.11.1/mdsf.schema.json", + "format_finished_document": false, + "languages": { + "go": "golangci-lint:fmt", + "shell": "shfmt" + }, + "language_aliases": { + "sh": "shell", + "cmd": "shell", + "bash": "shell" + } +} diff --git a/README.md b/README.md index 8f876507a..ad3892d3b 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ thus reducing their dependencies footprint. Go-swagger will be adapted over Q1 2026. -Features will probably be added to support our main use cases there. +Features will be added to support our main use cases there. ## Change log @@ -144,6 +144,7 @@ distributed with this fork, including internalized libraries. * [Motivations](https://go-openapi.github.io/testify/project/readme) * [Roadmap][doc-roadmap] * [Internal architecture](https://go-openapi.github.io/testify/project/maintainers/architecture) +* [Benchmarks](https://go-openapi.github.io/testify/project/maintainers/benchmarks) * [All-time contributors](./CONTRIBUTORS.md) * [Contributing guidelines](https://go-openapi.github.io/testify/project/contributing/) diff --git a/SECURITY.md b/SECURITY.md index b1969f387..86b3a423e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ This policy outlines the commitment and practices of the go-openapi maintainers | Version | Supported | | ------- | ------------------ | -| 2.1.x | :white_check_mark: | +| 2.2.x | :white_check_mark: | ## Vulnerability checks in place diff --git a/assert/assert_assertions.go b/assert/assert_assertions.go index 37dfaff76..7d0cb908f 100644 --- a/assert/assert_assertions.go +++ b/assert/assert_assertions.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert @@ -436,7 +436,11 @@ func Eventually(t T, condition func() bool, waitFor time.Duration, tick time.Dur // assertions.EventuallyWithT(t, func(c *assertions.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assertions.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") +// }, +// 10*time.Second, +// 1*time.Second, +// "external state has not changed to 'true'; still false", +// ) // // # Concurrency // @@ -532,6 +536,8 @@ func False(t T, value bool, msgAndArgs ...any) bool { // FalseT asserts that the specified value is false. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool @@ -1256,7 +1262,7 @@ func IsNonIncreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice return assertions.IsNonIncreasingT[OrderedSlice, E](t, collection, msgAndArgs...) } -// IsNotOfTypeT asserts that an object is of a given type. +// IsNotOfTypeT asserts that an object is not of a given type. // // # Usage // @@ -1332,7 +1338,7 @@ func IsType(t T, expectedType any, object any, msgAndArgs ...any) bool { return assertions.IsType(t, expectedType, object, msgAndArgs...) } -// JSONEq asserts that two JSON strings are equivalent. +// JSONEq asserts that two JSON strings are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -1353,7 +1359,7 @@ func JSONEq(t T, expected string, actual string, msgAndArgs ...any) bool { return assertions.JSONEq(t, expected, actual, msgAndArgs...) } -// JSONEqBytes asserts that two JSON slices of bytes are equivalent. +// JSONEqBytes asserts that two JSON slices of bytes are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -1374,7 +1380,7 @@ func JSONEqBytes(t T, expected []byte, actual []byte, msgAndArgs ...any) bool { return assertions.JSONEqBytes(t, expected, actual, msgAndArgs...) } -// JSONEqT asserts that two JSON documents are equivalent. +// JSONEqT asserts that two JSON documents are semantically equivalent. // // The expected and actual arguments may be string or []byte. They do not need to be of the same type. // @@ -1557,6 +1563,8 @@ func LessT[Orderable Ordered](t T, e1 Orderable, e2 Orderable, msgAndArgs ...any // MapContainsT asserts that the specified map contains a key. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.MapContainsT(t, map[string]string{"Hello": "x","World": "y"}, "World") @@ -1567,6 +1575,8 @@ func LessT[Orderable Ordered](t T, e1 Orderable, e2 Orderable, msgAndArgs ...any // failure: map[string]string{"A": "B"}, "C" // // Upon failure, the test [T] is marked as failed and continues execution. +// +// [comparable-types]: https://go.dev/blog/comparable func MapContainsT[Map ~map[K]V, K comparable, V any](t T, m Map, key K, msgAndArgs ...any) bool { if h, ok := t.(H); ok { h.Helper() @@ -2326,6 +2336,10 @@ func SameT[P any](t T, expected *P, actual *P, msgAndArgs ...any) bool { // SeqContainsT asserts that the specified iterator contains a comparable element. // +// The sequence may not be consumed entirely: the iteration stops as soon as the specified element is found. +// +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -2336,6 +2350,8 @@ func SameT[P any](t T, expected *P, actual *P, msgAndArgs ...any) bool { // failure: slices.Values([]string{"A","B"}), "C" // // Upon failure, the test [T] is marked as failed and continues execution. +// +// [comparable-types]: https://go.dev/blog/comparable func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ...any) bool { if h, ok := t.(H); ok { h.Helper() @@ -2345,6 +2361,8 @@ func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ... // SeqNotContainsT asserts that the specified iterator does not contain a comparable element. // +// See [SeqContainsT]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -2364,6 +2382,8 @@ func SeqNotContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs // SliceContainsT asserts that the specified slice contains a comparable element. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SliceContainsT(t, []{"Hello","World"}, "World") @@ -2374,6 +2394,8 @@ func SeqNotContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs // failure: []string{"A","B"}, "C" // // Upon failure, the test [T] is marked as failed and continues execution. +// +// [comparable-types]: https://go.dev/blog/comparable func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArgs ...any) bool { if h, ok := t.(H); ok { h.Helper() @@ -2383,6 +2405,8 @@ func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArg // SliceNotContainsT asserts that the specified slice does not contain a comparable element. // +// See [SliceContainsT]. +// // # Usage // // assertions.SliceNotContainsT(t, []{"Hello","World"}, "hi") @@ -2463,7 +2487,7 @@ func SortedT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndA // StringContainsT asserts that a string contains the specified substring. // -// Strings may be go strings or []byte. +// Strings may be go strings or []byte according to the type constraint [Text]. // // # Usage // @@ -2484,7 +2508,7 @@ func StringContainsT[ADoc, EDoc Text](t T, str ADoc, substring EDoc, msgAndArgs // StringNotContainsT asserts that a string does not contain the specified substring. // -// Strings may be go strings or []byte. +// See [StringContainsT]. // // # Usage // @@ -2552,6 +2576,8 @@ func True(t T, value bool, msgAndArgs ...any) bool { // TrueT asserts that the specified value is true. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool diff --git a/assert/assert_assertions_test.go b/assert/assert_assertions_test.go index 732ef80fe..b39eebfa4 100644 --- a/assert/assert_assertions_test.go +++ b/assert/assert_assertions_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_examples_test.go b/assert/assert_examples_test.go index 8a82b030a..d0044c142 100644 --- a/assert/assert_examples_test.go +++ b/assert/assert_examples_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert_test diff --git a/assert/assert_format.go b/assert/assert_format.go index 43a430475..b83f7f7ba 100644 --- a/assert/assert_format.go +++ b/assert/assert_format.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_format_test.go b/assert/assert_format_test.go index d917114d0..708337fbc 100644 --- a/assert/assert_format_test.go +++ b/assert/assert_format_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_forward.go b/assert/assert_forward.go index 12586b47c..1bc3a7bc2 100644 --- a/assert/assert_forward.go +++ b/assert/assert_forward.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_forward_test.go b/assert/assert_forward_test.go index 545710836..22d6a764f 100644 --- a/assert/assert_forward_test.go +++ b/assert/assert_forward_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_helpers.go b/assert/assert_helpers.go index c9f848042..e130b9d60 100644 --- a/assert/assert_helpers.go +++ b/assert/assert_helpers.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_helpers_test.go b/assert/assert_helpers_test.go index 7bf508455..e24414c1e 100644 --- a/assert/assert_helpers_test.go +++ b/assert/assert_helpers_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/assert_types.go b/assert/assert_types.go index 9991493cb..d303fdf10 100644 --- a/assert/assert_types.go +++ b/assert/assert_types.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package assert diff --git a/assert/doc.go b/assert/doc.go index 97862edbe..7f9ef3a7b 100644 --- a/assert/doc.go +++ b/assert/doc.go @@ -17,15 +17,13 @@ // ) // // func TestSomething(t *testing.T) { -// // var a string = "Hello" // var b string = "Hello" // // assert.Equal(t, a, b, "The two words should be the same.") -// // } // -// if you assert many times, use the format below: +// if you assert many times, you might find the format below more concise: // // import ( // "testing" @@ -43,16 +41,17 @@ // // # Assertions // -// Assertions allow you to easily write test code. +// Assertions allow you to easily write test code using go's standard testing library. // // All assertion functions take as the first argument, the [*testing.T] object provided by the // standard testing framework. // -// This allows the assertion functions to write the failings and other details to the correct place. +// This allows the assertion functions to write their failings and other details to the correct place. // -// Every assertion function also takes an optional string message as the final argument, +// Every assertion function takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. // -// See [our doc site](https://go-openapi.github.io/testify/) for usage and examples and -// [go docs](https://pkg.go/dev/go-openapi/testify) for complete reference. +// See our doc site at https://go-openapi.github.io/testify/ for usage, examples and searchable reference. +// +// See https://pkg.go/dev/go-openapi/testify/ for complete reference. package assert diff --git a/codegen/internal/generator/funcmaps/doc.go b/codegen/internal/generator/funcmaps/doc.go index 420a75df6..ecf5eb7a9 100644 --- a/codegen/internal/generator/funcmaps/doc.go +++ b/codegen/internal/generator/funcmaps/doc.go @@ -6,6 +6,6 @@ // This package contains all template helper functions used by both the code generator // (for assert/require packages) and the documentation generator (for markdown docs). // -// The main entry point is FuncMap(), which returns a complete template.FuncMap +// The main entry point is [FuncMap], which returns a complete [template.FuncMap] // with all available functions registered. package funcmaps diff --git a/codegen/internal/generator/funcmaps/funcmaps.go b/codegen/internal/generator/funcmaps/funcmaps.go index cba923ef0..d6cb5745e 100644 --- a/codegen/internal/generator/funcmaps/funcmaps.go +++ b/codegen/internal/generator/funcmaps/funcmaps.go @@ -60,6 +60,7 @@ func FuncMap() template.FuncMap { "sourceLink": sourceLink, "titleize": titleize, "slugize": slugize, + "blockquote": blockquote, } } @@ -364,3 +365,16 @@ func slugize(in string) string { in, )) } + +// blockquote prints a text as a markdown blockquote. +func blockquote(in string) string { + result := make([]string, 0, sensiblePrealloc) + for line := range strings.SplitSeq(in, "\n") { + result = append(result, "> "+line) + if strings.HasSuffix(line, ".") { + result = append(result, ">") + } + } + + return strings.Join(result, "\n") +} diff --git a/codegen/internal/generator/funcmaps/markdown.go b/codegen/internal/generator/funcmaps/markdown.go index 1dd417de5..f1e563041 100644 --- a/codegen/internal/generator/funcmaps/markdown.go +++ b/codegen/internal/generator/funcmaps/markdown.go @@ -9,14 +9,22 @@ import ( "strings" ) -var refLinkPattern = regexp.MustCompile(`(?m)^\[([^\]]+)\]:\s+(.+)$`) +var ( + refLinkPattern = regexp.MustCompile(`(?m)^\[([^\]]+)\]:\s+(.+)$`) + // Find godoc-style links: [word.word]. + godocPattern = regexp.MustCompile(`\[([a-zA-Z0-9_]+\.[a-zA-Z0-9_.]+)\]`) // there is a dot + godocPatternLocal = regexp.MustCompile(`\[([a-zA-Z0-9_]+)\]`) // no dot + tabSectionPattern = regexp.MustCompile(`^#\s+(Examples?|Usage|Use)$`) + sectionPattern = regexp.MustCompile(`^#\s+`) +) + +const sensiblePrealloc = 20 // FormatMarkdown carries out a formatting of inline markdown in comments that handles: // // 1. Reference-style markdown links: [text]: url // 2. Godoc-style links: [errors.Is], [testing.T], etc. func FormatMarkdown(in string) string { - const sensiblePrealloc = 20 // Step 1: Extract reference-style link definitions // Pattern: [text]: url (at start of line or after whitespace) @@ -64,9 +72,7 @@ func FormatMarkdown(in string) string { continue } - // Find godoc-style links: [word.word] - godocPattern := regexp.MustCompile(`\[([a-zA-Z0-9_]+\.[a-zA-Z0-9_.]+)\]`) - lines[i] = godocPattern.ReplaceAllStringFunc(line, func(match string) string { + replacedStdLib := godocPattern.ReplaceAllStringFunc(line, func(match string) string { identifier := strings.Trim(match, "[]") // Has package qualifier - link to pkg.go.dev @@ -86,11 +92,25 @@ func FormatMarkdown(in string) string { // Assume standard library for simple package names return fmt.Sprintf("[%s](https://pkg.go.dev/%s#%s)", identifier, pkgPath, symbol) }) + + // check for links with current package, e.g. [Boolean]. Those don't have a dot. + replacedLocal := godocPatternLocal.ReplaceAllStringFunc(replacedStdLib, func(match string) string { + identifier := strings.Trim(match, "[]") + return fmt.Sprintf("[%s](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#%s)", identifier, identifier) + }) + + lines[i] = replacedLocal } + processed = strings.Join(lines, "\n") - // Step 4: Do existing processing (Hugo shortcodes) + // Step 4: render Usage and Examples sections with Hugo shortcodes + // These are rendered as tabs. result := make([]string, 0, sensiblePrealloc) + trailer := make([]string, 0, sensiblePrealloc) + + // parse state + tabsCollection := false expanded := false tab := false @@ -99,44 +119,61 @@ func FormatMarkdown(in string) string { continue } - if strings.HasPrefix(line, "#") { - if !expanded { - result = append(result, `{{% expand title="Examples" %}}`) - result = append(result, `{{< tabs >}}`) - expanded = true + matches := tabSectionPattern.FindStringSubmatch(line) + const expectedCapture = 1 + if len(matches) != expectedCapture+1 { + // either a regular line or a section header that we don't want in the trailer tabs + if sectionPattern.MatchString(line) { + // found a new section + expanded = false + line = strings.ReplaceAll(line, "#", "####") // containing function heading is ### } - title := Titleize(strings.TrimLeft(line, "# \t")) - if tab { - result = append(result, "```") - result = append(result, `{{< /tab >}}`) + if expanded { + trailer = append(trailer, line) + } else { + result = append(result, line) } - result = append(result, fmt.Sprintf(`{{%% tab title="%s" %%}}`, title)) - result = append(result, "```go") - tab = true - continue } - result = append(result, line) + // interesting section to catch as a tab + section := matches[expectedCapture] + expanded = true + + if !tabsCollection { + trailer = append(trailer, `{{% expand title="Examples" %}}`) // the title of the collapsible section + trailer = append(trailer, `{{< tabs >}}`) + tabsCollection = true + } + + title := titleize(section) + if tab { + trailer = append(trailer, "```") + trailer = append(trailer, `{{< /tab >}}`) + } + + trailer = append(trailer, fmt.Sprintf(`{{%% tab title="%s" %%}}`, title)) + trailer = append(trailer, "```go") + tab = true } if tab { - result = append(result, "```") - result = append(result, `{{< /tab >}}`) + trailer = append(trailer, "```") + trailer = append(trailer, `{{< /tab >}}`) } - if expanded { - result = append(result, `{{< /tabs >}}`) - result = append(result, `{{% /expand %}}`) + if tabsCollection { + trailer = append(trailer, `{{< /tabs >}}`) + trailer = append(trailer, `{{% /expand %}}`) + } - // Append dangling reference links as additional context - if len(danglingRefs) > 0 { - result = append(result, "") - result = append(result, danglingRefs...) - } + // Append dangling reference links as additional context + if len(danglingRefs) > 0 { + result = append(result, "") + result = append(result, danglingRefs...) } - return strings.Join(result, "\n") + return strings.Join(append(result, trailer...), "\n") } diff --git a/codegen/internal/generator/funcmaps/markdown_test.go b/codegen/internal/generator/funcmaps/markdown_test.go index 258de28fa..fa455f500 100644 --- a/codegen/internal/generator/funcmaps/markdown_test.go +++ b/codegen/internal/generator/funcmaps/markdown_test.go @@ -4,17 +4,62 @@ package funcmaps import ( + "iter" + "slices" "strings" "testing" ) func TestMarkdownFormatEnhanced(t *testing.T) { - tests := []struct { - name string - input string - contains []string // strings that should appear in output - notContains []string // strings that should NOT appear - }{ + for tt := range markdownTestCases() { + t.Run(tt.name, func(t *testing.T) { + result := FormatMarkdown(tt.input) + + for _, want := range tt.contains { + if !strings.Contains(result, want) { + t.Errorf("FormatMarkdown() missing expected string:\nwant: %q\ngot: %s", want, result) + } + } + + for _, notWant := range tt.notContains { + if strings.Contains(result, notWant) { + t.Errorf("FormatMarkdown() contains unexpected string:\ndon't want: %q\ngot: %s", notWant, result) + } + } + }) + } +} + +func TestMarkdownFormatEnhanced_Output(t *testing.T) { + input := `Empty asserts that the given value is "empty". + +Zero values are "empty". + +Values can be of type [strings.Builder] or [Boolean]. + +# Usage + + assertions.Empty(t, obj) + +# Examples + + success: "" + failure: "not empty" +[Zero values]: https://go.dev/ref/spec#The_zero_value` + + result := FormatMarkdown(input) + t.Logf("Output:\n%s", result) +} + +type markdownTestCase struct { + name string + input string + contains []string // strings that should appear in output + notContains []string // strings that should NOT appear +} + +func markdownTestCases() iter.Seq[markdownTestCase] { + return slices.Values([]markdownTestCase{ { name: "reference-style markdown link (dangling)", input: `Empty asserts that the given value is "empty". @@ -110,50 +155,13 @@ It also references [TestingT] interface. assertions.Something[T TestingT](t)`, contains: []string{ - `[T]`, // No package qualifier, left unchanged - `[TestingT]`, // No package qualifier, left unchanged + `[T](https://pkg.go.dev/github.com/go-openapi`, // No package qualifier, link to the go doc for our lib + `[TestingT](https://pkg.go.dev/github.com/go-openapi`, // No package qualifier, link to the go doc for our lib }, notContains: []string{ - `[T](https://`, // Should NOT be converted to a link - `[TestingT](https://`, + `[T](https://pkg.go.dev#T`, // Should not be appended directly + `[TestingT](https://pkg.go.dev#T`, }, }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := FormatMarkdown(tt.input) - - for _, want := range tt.contains { - if !strings.Contains(result, want) { - t.Errorf("FormatMarkdown() missing expected string:\nwant: %q\ngot: %s", want, result) - } - } - - for _, notWant := range tt.notContains { - if strings.Contains(result, notWant) { - t.Errorf("FormatMarkdown() contains unexpected string:\ndon't want: %q\ngot: %s", notWant, result) - } - } - }) - } -} - -func TestMarkdownFormatEnhanced_Output(t *testing.T) { - input := `Empty asserts that the given value is "empty". - -Zero values are "empty". - -# Usage - - assertions.Empty(t, obj) - -# Examples - - success: "" - failure: "not empty" -[Zero values]: https://go.dev/ref/spec#The_zero_value` - - result := FormatMarkdown(input) - t.Logf("Output:\n%s", result) + }) } diff --git a/codegen/internal/generator/templates/doc_page.md.gotmpl b/codegen/internal/generator/templates/doc_page.md.gotmpl index 4ee3540fd..a90bc2aa6 100644 --- a/codegen/internal/generator/templates/doc_page.md.gotmpl +++ b/codegen/internal/generator/templates/doc_page.md.gotmpl @@ -32,7 +32,7 @@ _All links point to <{{ $godoc }}>_ This domain exposes {{ .RefCount }} functionalities. {{- if .HasGenerics }} -Generic assertions are marked with a {{ print "{{" }}% icon icon="star" color=orange %{{ print "}}" }} +Generic assertions are marked with a {{ print "{{" }}% icon icon="star" color=orange %{{ print "}}" }}. {{- end }} ```tree @@ -97,11 +97,13 @@ Generic assertions are marked with a {{ print "{{" }}% icon icon="star" color=or {{- if eq .Tag 2 }}{{/* maintainers section */}} > **Maintainer Note** -> {{ .Text }}{{/* Proposal for enhancement: clean rendered markdown for multi-line comments */}} +> +{{ blockquote .Text }} {{- else if eq .Tag 4 }}{{/* notes section */}} > **Note** -> {{ .Text }} +> +{{ blockquote .Text }} {{- end }} {{- end }} {{ print "{{" }}% /tab %{{ print "}}" }} @@ -159,11 +161,13 @@ Generic assertions are marked with a {{ print "{{" }}% icon icon="star" color=or {{- if eq .Tag 2 }}{{/* maintainers section */}} > **Maintainer Note** -> {{ .Text }}{{/* Proposal for enhancement: clean rendered markdown for multi-line comments */}} +> +{{ blockquote .Text }} {{- else if eq .Tag 4 }}{{/* notes section */}} > **Note** -> {{ .Text }} +> +{{ blockquote .Text }} {{- end }} {{- end }} {{ print "{{" }}% /tab %{{ print "}}" }} diff --git a/codegen/internal/model/model.go b/codegen/internal/model/model.go index e06761630..2ba412d4f 100644 --- a/codegen/internal/model/model.go +++ b/codegen/internal/model/model.go @@ -230,6 +230,26 @@ const ( type CommentTag uint8 +// String representation of a comment tag, mostly useful for debugging purpose. +func (t CommentTag) String() string { + switch t { + case CommentTagNone: + return "comment-tag-none" + case CommentTagDomain: + return "comment-tag-domain" + case CommentTagMaintainer: + return "comment-tag-maintainer" + case CommentTagMention: + return "comment-tag-mention" + case CommentTagNote: + return "comment-tag-note" + case CommentTagDomainDescription: + return "comment-tag-domain-description" + default: + return "invalid-value" + } +} + const ( CommentTagNone CommentTag = iota CommentTagDomain diff --git a/codegen/internal/scanner/comments-parser/matchers.go b/codegen/internal/scanner/comments-parser/matchers.go index c70b1dd59..5403b4737 100644 --- a/codegen/internal/scanner/comments-parser/matchers.go +++ b/codegen/internal/scanner/comments-parser/matchers.go @@ -26,12 +26,12 @@ func StartSectionFunc(placeholder string) func(string) bool { // StartValueFunc creates a matcher function for key-value lines. // -// A value line has the format: "placeholder: value" +// A value line has the format: "placeholder: value" or "placeholders: value" (plural form). // Returns the value part (everything after the colon) and true if matched. // Matching is case-insensitive. func StartValueFunc(placeholder string) func(string) (string, bool) { valueRex := regexp.MustCompile( - fmt.Sprintf(`(?i)^\s*%[1]s\s*:\s*`, regexp.QuoteMeta(placeholder)), + fmt.Sprintf(`(?i)^\s*%[1]ss?\s*:\s*`, regexp.QuoteMeta(placeholder)), ) return func(text string) (string, bool) { diff --git a/codegen/internal/scanner/comments-parser/tags.go b/codegen/internal/scanner/comments-parser/tags.go index 2fbe252c1..30a5509a3 100644 --- a/codegen/internal/scanner/comments-parser/tags.go +++ b/codegen/internal/scanner/comments-parser/tags.go @@ -32,6 +32,7 @@ func ParseTaggedComments(text string) []model.ExtraComment { startValueMaintainer := StartValueFunc(maintainerPrefix) startValueNote := StartValueFunc(notePrefix) startValueMention := StartValueFunc(mentionPrefix) + startTaggedValue := func(line string) (key string, val string, tag model.CommentTag, multiline bool, ok bool) { val, ok = startValueDomain(line) if ok { diff --git a/docs/doc-site/_index.md b/docs/doc-site/_index.md index 67acae8ba..4e3c90ee5 100644 --- a/docs/doc-site/_index.md +++ b/docs/doc-site/_index.md @@ -20,32 +20,11 @@ This is the go-openapi fork of the great [testify](https://github.com/stretchr/t {{% button href="https://github.com/go-openapi/testify/fork" hint="fork me on github" style=primary icon=code-fork %}}Fork me{{% /button %}} Design and exploration phase. Feedback, contributions and proposals are welcome. -### Motivation - -From the maintainers of `testify`, it looks like a v2 will eventually be released, but they'll do it at their own pace. - -We like all the principles they exposed to build this v2. [See discussion about v2](https://github.com/stretchr/testify/discussions/1560). - -However, at `go-openapi` we would like to address the well-known issues in `testify` with different priorities. - -With this fork, we want to: -1. [x] remove all external dependencies. -2. [x] make it easy to maintain and extend. -3. [x] pare down some of the chrome that has been added over the years. +See our [ROADMAP](./maintainers/ROADMAP.md). -{{% notice style="primary" title="Extended hand" icon="hand" %}} -We hope that this endeavor will help the original project with a live-drill of what a v2 could look like. - -Hopefully, some of our ideas will eventually percolate back into the original project and help the wider -community of go developers write better, clearer test code. - -Feedback is welcome and we are always happy to discuss with people who face the same problems as we do: avoid breaking changes, -APIs that became bloated over a decade or so, uncontrolled dependencies, difficult choices when it comes to introduce -breaking changes, conflicting demands from users etc. -{{% /notice %}} +### Motivation -Find more about our motivations in the project's [README](README.md#motivation). -You might also be curious about our [ROADMAP](project/maintainers/ROADMAP.md). +See [why we wanted a v2](./MOTIVATION.md). ### Getting started @@ -179,6 +158,7 @@ See also our [CONTRIBUTING guidelines](./project/contributing/CONTRIBUTING.md). - [Generics Guide](./usage/GENERICS.md) - Type-safe assertions with 38 generic functions - [Migration Guide](./usage/MIGRATION.md) - Migrating from stretchr/testify v1 - [Changes from v1](./usage/CHANGES.md) - All changes and improvements in v2 +- [Benchmarks](./project/maintainers/benchmarks.md) - Performance improvements in v2 **Reference:** - [API Reference](./api/_index.md) - Complete assertion catalog organized by domain diff --git a/docs/doc-site/api/_index.md b/docs/doc-site/api/_index.md index f6eac4150..f0d2179e0 100644 --- a/docs/doc-site/api/_index.md +++ b/docs/doc-site/api/_index.md @@ -6,7 +6,7 @@ description: | Find the assertion function you need for your data. weight: 1 -modified: 2026-01-26 +modified: 2026-01-27 --- **The v2 our tests wanted** @@ -67,5 +67,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/boolean.md b/docs/doc-site/api/boolean.md index a0869116a..c25f88fce 100644 --- a/docs/doc-site/api/boolean.md +++ b/docs/doc-site/api/boolean.md @@ -1,7 +1,7 @@ --- title: "Boolean" description: "Asserting Boolean Values" -modified: 2026-01-26 +modified: 2026-01-27 weight: 1 domains: - "boolean" @@ -26,7 +26,7 @@ Asserting Boolean Values _All links point to _ This domain exposes 4 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [False](#false) | angles-right @@ -78,7 +78,7 @@ False asserts that the specified value is false. |--|--| | [`assertions.False(t T, value bool, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#False) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#False](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L63) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#False](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L65) {{% /tab %}} {{< /tabs >}} @@ -86,6 +86,8 @@ False asserts that the specified value is false. FalseT asserts that the specified value is false. +The type constraint [Boolean](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Boolean) accepts any type which underlying type is bool. + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -123,7 +125,7 @@ FalseT asserts that the specified value is false. |--|--| | [`assertions.FalseT(t T, value B, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#FalseT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#FalseT](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L88) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#FalseT](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L92) {{% /tab %}} {{< /tabs >}} @@ -178,6 +180,8 @@ True asserts that the specified value is true. TrueT asserts that the specified value is true. +The type constraint [Boolean](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Boolean) accepts any type which underlying type is bool. + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -215,7 +219,7 @@ TrueT asserts that the specified value is true. |--|--| | [`assertions.TrueT(t T, value B, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#TrueT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#TrueT](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L41) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#TrueT](https://github.com/go-openapi/testify/blob/master/internal/assertions/boolean.go#L43) {{% /tab %}} {{< /tabs >}} @@ -235,5 +239,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/collection.md b/docs/doc-site/api/collection.md index cc7f06c09..da49b672a 100644 --- a/docs/doc-site/api/collection.md +++ b/docs/doc-site/api/collection.md @@ -1,7 +1,7 @@ --- title: "Collection" description: "Asserting Slices And Maps" -modified: 2026-01-26 +modified: 2026-01-27 weight: 2 domains: - "collection" @@ -56,7 +56,7 @@ Asserting Slices And Maps _All links point to _ This domain exposes 19 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [Contains](#contains) | angles-right @@ -91,7 +91,7 @@ specified substring or element. ```go assertions.Contains(t, "Hello World", "World") assertions.Contains(t, []string{"Hello", "World"}, "World") - assertions.Contains(t, map[string]string{"Hello": "World"}, "Hello") + assertions.Contains(t, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"Hello": "World"}, "Hello") ``` {{< /tab >}} {{% tab title="Examples" %}} @@ -175,7 +175,7 @@ the number of appearances of each of them in both lists should match. |--|--| | [`assertions.ElementsMatch(t T, listA any, listB any, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#ElementsMatch) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#ElementsMatch](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L520) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#ElementsMatch](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L540) {{% /tab %}} {{< /tabs >}} @@ -220,7 +220,7 @@ the number of appearances of each of them in both lists should match. |--|--| | [`assertions.ElementsMatchT(t T, listA []E, listB []E, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#ElementsMatchT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#ElementsMatchT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L593) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#ElementsMatchT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L613) {{% /tab %}} {{< /tabs >}} @@ -278,7 +278,9 @@ See also [reflect.Len](https://pkg.go.dev/reflect#Len). **Source:** [github.com/go-openapi/testify/v2/internal/assertions#Len](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L33) > **Note** +> > (proposals) this does not currently support iterators, or collection objects that have a Len() method. +> {{% /tab %}} {{< /tabs >}} @@ -286,17 +288,19 @@ See also [reflect.Len](https://pkg.go.dev/reflect#Len). MapContainsT asserts that the specified map contains a key. +Go native comparable types are explained there: [comparable-types](https://go.dev/blog/comparable). + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} ```go - assertions.MapContainsT(t, map[string]string{"Hello": "x","World": "y"}, "World") + assertions.MapContainsT(t, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"Hello": "x","World": "y"}, "World") ``` {{< /tab >}} {{% tab title="Examples" %}} ```go - success: map[string]string{"A": "B"}, "A" - failure: map[string]string{"A": "B"}, "C" + success: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"A": "B"}, "A" + failure: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"A": "B"}, "C" ``` {{< /tab >}} {{< /tabs >}} @@ -321,7 +325,7 @@ MapContainsT asserts that the specified map contains a key. |--|--| | [`assertions.MapContainsT(t T, m Map, key K, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#MapContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#MapContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L164) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#MapContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L179) {{% /tab %}} {{< /tabs >}} @@ -333,13 +337,13 @@ MapNotContainsT asserts that the specified map does not contain a key. {{< tabs >}} {{% tab title="Usage" %}} ```go - assertions.MapNotContainsT(t, map[string]string{"Hello": "x","World": "y"}, "hi") + assertions.MapNotContainsT(t, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"Hello": "x","World": "y"}, "hi") ``` {{< /tab >}} {{% tab title="Examples" %}} ```go - success: map[string]string{"A": "B"}, "C" - failure: map[string]string{"A": "B"}, "A" + success: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"A": "B"}, "C" + failure: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)string{"A": "B"}, "A" ``` {{< /tab >}} {{< /tabs >}} @@ -364,7 +368,7 @@ MapNotContainsT asserts that the specified map does not contain a key. |--|--| | [`assertions.MapNotContainsT(t T, m Map, key K, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#MapNotContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#MapNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L290) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#MapNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L310) {{% /tab %}} {{< /tabs >}} @@ -414,7 +418,7 @@ specified substring or element. |--|--| | [`assertions.NotContains(t T, s any, contains any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotContains) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotContains](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L191) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotContains](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L206) {{% /tab %}} {{< /tabs >}} @@ -466,7 +470,7 @@ This is an inverse of ElementsMatch. |--|--| | [`assertions.NotElementsMatch(t T, listA any, listB any, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatch) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatch](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L557) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatch](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L577) {{% /tab %}} {{< /tabs >}} @@ -514,7 +518,7 @@ This is an inverse of ElementsMatch. |--|--| | [`assertions.NotElementsMatchT(t T, listA []E, listB []E, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatchT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatchT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L629) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotElementsMatchT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L649) {{% /tab %}} {{< /tabs >}} @@ -567,7 +571,7 @@ only the map key is evaluated. |--|--| | [`assertions.NotSubset(t T, list any, subset any, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotSubset) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotSubset](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L426) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotSubset](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L446) {{% /tab %}} {{< /tabs >}} @@ -575,6 +579,10 @@ only the map key is evaluated. SeqContainsT asserts that the specified iterator contains a comparable element. +The sequence may not be consumed entirely: the iteration stops as soon as the specified element is found. + +Go native comparable types are explained there: [comparable-types](https://go.dev/blog/comparable). + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -610,7 +618,7 @@ SeqContainsT asserts that the specified iterator contains a comparable element. |--|--| | [`assertions.SeqContainsT(t T, iter iter.Seq[E], element E, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SeqContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SeqContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L140) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SeqContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L150) {{% /tab %}} {{< /tabs >}} @@ -618,6 +626,8 @@ SeqContainsT asserts that the specified iterator contains a comparable element. SeqNotContainsT asserts that the specified iterator does not contain a comparable element. +See [SeqContainsT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#SeqContainsT). + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -653,7 +663,7 @@ SeqNotContainsT asserts that the specified iterator does not contain a comparabl |--|--| | [`assertions.SeqNotContainsT(t T, iter iter.Seq[E], element E, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SeqNotContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SeqNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L266) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SeqNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L285) {{% /tab %}} {{< /tabs >}} @@ -661,6 +671,8 @@ SeqNotContainsT asserts that the specified iterator does not contain a comparabl SliceContainsT asserts that the specified slice contains a comparable element. +Go native comparable types are explained there: [comparable-types](https://go.dev/blog/comparable). + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -696,7 +708,7 @@ SliceContainsT asserts that the specified slice contains a comparable element. |--|--| | [`assertions.SliceContainsT(t T, s Slice, element E, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SliceContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L117) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L121) {{% /tab %}} {{< /tabs >}} @@ -704,6 +716,8 @@ SliceContainsT asserts that the specified slice contains a comparable element. SliceNotContainsT asserts that the specified slice does not contain a comparable element. +See [SliceContainsT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#SliceContainsT). + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -739,7 +753,7 @@ SliceNotContainsT asserts that the specified slice does not contain a comparable |--|--| | [`assertions.SliceNotContainsT(t T, s Slice, element E, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SliceNotContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L243) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L260) {{% /tab %}} {{< /tabs >}} @@ -782,7 +796,7 @@ SliceNotSubsetT asserts that a slice of comparable elements does not contain all |--|--| | [`assertions.SliceNotSubsetT(t T, list Slice, subset Slice, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SliceNotSubsetT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceNotSubsetT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L493) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceNotSubsetT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L513) {{% /tab %}} {{< /tabs >}} @@ -825,7 +839,7 @@ SliceSubsetT asserts that a slice of comparable elements contains all the elemen |--|--| | [`assertions.SliceSubsetT(t T, list Slice, subset Slice, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SliceSubsetT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceSubsetT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L395) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SliceSubsetT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L415) {{% /tab %}} {{< /tabs >}} @@ -833,7 +847,7 @@ SliceSubsetT asserts that a slice of comparable elements contains all the elemen StringContainsT asserts that a string contains the specified substring. -Strings may be go strings or []byte. +Strings may be go strings or []byte according to the type constraint [Text](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Text). {{% expand title="Examples" %}} {{< tabs >}} @@ -878,7 +892,7 @@ Strings may be go strings or []byte. StringNotContainsT asserts that a string does not contain the specified substring. -Strings may be go strings or []byte. +See [StringContainsT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#StringContainsT). {{% expand title="Examples" %}} {{< tabs >}} @@ -915,7 +929,7 @@ Strings may be go strings or []byte. |--|--| | [`assertions.StringNotContainsT(t T, str ADoc, substring EDoc, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#StringNotContainsT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#StringNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L220) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#StringNotContainsT](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L235) {{% /tab %}} {{< /tabs >}} @@ -935,8 +949,8 @@ nil values are considered as empty sets. ```go assertions.Subset(t, []int{1, 2, 3}, []int{1, 2}) assertions.Subset(t, []string{"x": 1, "y": 2}, []string{"x": 1}) - assertions.Subset(t, []int{1, 2, 3}, map[int]string{1: "one", 2: "two"}) - assertions.Subset(t, map[string]int{"x": 1, "y": 2}, []string{"x"}) + assertions.Subset(t, []int{1, 2, 3}, map[int](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#int)string{1: "one", 2: "two"}) + assertions.Subset(t, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)int{"x": 1, "y": 2}, []string{"x"}) ``` {{< /tab >}} {{% tab title="Examples" %}} @@ -971,7 +985,7 @@ nil values are considered as empty sets. |--|--| | [`assertions.Subset(t T, list any, subset any, msgAndArgs ...any) (ok bool)`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#Subset) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Subset](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L325) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Subset](https://github.com/go-openapi/testify/blob/master/internal/assertions/collection.go#L345) {{% /tab %}} {{< /tabs >}} @@ -991,5 +1005,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/common.md b/docs/doc-site/api/common.md index 3755724c7..70c0da4f2 100644 --- a/docs/doc-site/api/common.md +++ b/docs/doc-site/api/common.md @@ -1,7 +1,7 @@ --- title: "Common" description: "Other Uncategorized Helpers" -modified: 2026-01-26 +modified: 2026-01-27 weight: 18 domains: - "common" @@ -59,7 +59,9 @@ failed. **Source:** [github.com/go-openapi/testify/v2/internal/assertions#CallerInfo](https://github.com/go-openapi/testify/blob/master/internal/assertions/testing.go#L19) > **Maintainer Note** +> > it is not necessary to export CallerInfo. This should remain an internal implementation detail. +> {{% /tab %}} {{< /tabs >}} @@ -132,5 +134,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/comparison.md b/docs/doc-site/api/comparison.md index a32080125..311e29896 100644 --- a/docs/doc-site/api/comparison.md +++ b/docs/doc-site/api/comparison.md @@ -1,7 +1,7 @@ --- title: "Comparison" description: "Comparing Ordered Values" -modified: 2026-01-26 +modified: 2026-01-27 weight: 3 domains: - "comparison" @@ -42,7 +42,7 @@ Comparing Ordered Values _All links point to _ This domain exposes 12 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [Greater](#greater) | angles-right @@ -115,7 +115,7 @@ To compare values that need a type conversion (e.g. float32 against float64), yo GreaterOrEqual asserts that the first element is greater than or equal to the second. -See also [Greater]. +See also [Greater](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Greater). {{% expand title="Examples" %}} {{< tabs >}} @@ -168,13 +168,13 @@ See also [Greater]. GreaterOrEqualT asserts that for two elements of the same type, the first element is greater than or equal to the second. -The [Ordered] type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), +The [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), []byte (uses [bytes.Compare](https://pkg.go.dev/bytes#Compare)) and [time.Time](https://pkg.go.dev/time#Time) (uses [time.Time.Compare](https://pkg.go.dev/time#Time.Compare). -Notice that pointers are not [Ordered], but uintptr are. So you can't call [GreaterOrEqualT] with [*time.Time]. +Notice that pointers are not [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered), but uintptr are. So you can't call [GreaterOrEqualT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#GreaterOrEqualT) with [*time.Time]. -[GreaterOrEqualT] ensures type safety at build time. If you need to compare values with a dynamically assigned type, -use [GreaterOrEqual] instead. +[GreaterOrEqualT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#GreaterOrEqualT) ensures type safety at build time. If you need to compare values with a dynamically assigned type, +use [GreaterOrEqual](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#GreaterOrEqual) instead. To compare values that need a type conversion (e.g. float32 against float64), you need to convert types beforehand. @@ -225,12 +225,12 @@ To compare values that need a type conversion (e.g. float32 against float64), yo GreaterT asserts that for two elements of the same type, the first element is strictly greater than the second. -The [Ordered] type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), +The [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), []byte (uses [bytes.Compare](https://pkg.go.dev/bytes#Compare)) and [time.Time](https://pkg.go.dev/time#Time) (uses [time.Time.Compare](https://pkg.go.dev/time#Time.Compare). -Notice that pointers are not [Ordered], but uintptr are. So you can't call [GreaterT] with [*time.Time]. +Notice that pointers are not [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered), but uintptr are. So you can't call [GreaterT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#GreaterT) with [*time.Time]. -[GreaterT] ensures type safety at build time. If you need to compare values with a dynamically assigned type, use [Greater] instead. +[GreaterT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#GreaterT) ensures type safety at build time. If you need to compare values with a dynamically assigned type, use [Greater](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Greater) instead. To compare values that need a type conversion (e.g. float32 against float64), you need to convert types beforehand. @@ -382,15 +382,15 @@ LessOrEqual asserts that the first element is less than or equal to the second. LessOrEqualT asserts that for two elements of the same type, the first element is less than or equal to the second. -The [Ordered] type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), +The [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), []byte (uses [bytes.Compare](https://pkg.go.dev/bytes#Compare)) and [time.Time](https://pkg.go.dev/time#Time) (uses [time.Time.Compare](https://pkg.go.dev/time#Time.Compare). -Notice that pointers are not [Ordered], but uintptr are. So you can't call [LessOrEqualT] with [*time.Time]. +Notice that pointers are not [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered), but uintptr are. So you can't call [LessOrEqualT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessOrEqualT) with [*time.Time]. -[LessOrEqualT] ensures type safety at build time. If you need to compare values with a dynamically assigned type, -use [LessOrEqual] instead. +[LessOrEqualT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessOrEqualT) ensures type safety at build time. If you need to compare values with a dynamically assigned type, +use [LessOrEqual](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessOrEqual) instead. -To compare values that need a type conversion (e.g. float32 against float64), you should use [LessOrEqual] instead. +To compare values that need a type conversion (e.g. float32 against float64), you should use [LessOrEqual](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessOrEqual) instead. {{% expand title="Examples" %}} {{< tabs >}} @@ -438,13 +438,13 @@ To compare values that need a type conversion (e.g. float32 against float64), yo LessT asserts that for two elements of the same type, the first element is strictly less than the second. -The [Ordered] type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), +The [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) type can be any of Go's [cmp.Ordered](https://pkg.go.dev/cmp#Ordered) (strings, numeric types), []byte (uses [bytes.Compare](https://pkg.go.dev/bytes#Compare)) and [time.Time](https://pkg.go.dev/time#Time) (uses [time.Time.Compare](https://pkg.go.dev/time#Time.Compare). -Notice that pointers are not [Ordered], but uintptr are. So you can't call [LessT] with [*time.Time]. +Notice that pointers are not [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered), but uintptr are. So you can't call [LessT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessT) with [*time.Time]. -[LessT] ensures type safety at build time. If you need to compare values with a dynamically assigned type, -use [Less] instead. +[LessT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#LessT) ensures type safety at build time. If you need to compare values with a dynamically assigned type, +use [Less](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Less) instead. To compare values that need a type conversion (e.g. float32 against float64), you need to convert types beforehand. @@ -689,5 +689,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/condition.md b/docs/doc-site/api/condition.md index 257d7927d..2a93a5e21 100644 --- a/docs/doc-site/api/condition.md +++ b/docs/doc-site/api/condition.md @@ -1,7 +1,7 @@ --- title: "Condition" description: "Expressing Assertions Using Conditions" -modified: 2026-01-26 +modified: 2026-01-27 weight: 4 domains: - "condition" @@ -36,7 +36,7 @@ This domain exposes 4 functionalities. ### Condition{#condition} -Condition uses a [Comparison] to assert a complex condition. +Condition uses a [Comparison](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Comparison) to assert a complex condition. {{% expand title="Examples" %}} {{< tabs >}} @@ -86,15 +86,22 @@ Condition uses a [Comparison] to assert a complex condition. Eventually asserts that the given condition will be met in waitFor time, periodically checking the target function on each tick. -[Eventually] waits until the condition returns true, for at most waitFor, +[Eventually](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Eventually) waits until the condition returns true, for at most waitFor, or until the parent context of the test is cancelled. -If the condition takes longer than waitFor to complete, [Eventually] fails +If the condition takes longer than waitFor to complete, [Eventually](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Eventually) fails but waits for the current condition execution to finish before returning. For long-running conditions to be interrupted early, check [testing.T.Context](https://pkg.go.dev/testing#T.Context) which is cancelled on test failure. +#### Concurrency + +The condition function is never executed in parallel: only one goroutine executes it. +It may write to variables outside its scope without triggering race conditions. + +A blocking condition will cause [Eventually](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Eventually) to hang until it returns. + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -102,13 +109,6 @@ which is cancelled on test failure. assertions.Eventually(t, func() bool { return true }, time.Second, 10*time.Millisecond) ``` {{< /tab >}} -{{% tab title="Concurrency" %}} -```go -The condition function is never executed in parallel: only one goroutine executes it. -It may write to variables outside its scope without triggering race conditions. -A blocking condition will cause [Eventually] to hang until it returns. -``` -{{< /tab >}} {{% tab title="Examples" %}} ```go success: func() bool { return true }, 100*time.Millisecond, 20*time.Millisecond @@ -150,17 +150,22 @@ A blocking condition will cause [Eventually] to hang until it returns. EventuallyWithT asserts that the given condition will be met in waitFor time, periodically checking the target function at each tick. -In contrast to [Eventually], the condition function is supplied with a [CollectT] +In contrast to [Eventually](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Eventually), the condition function is supplied with a [CollectT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#CollectT) to accumulate errors from calling other assertions. The condition is considered "met" if no errors are raised in a tick. -The supplied [CollectT] collects all errors from one tick. +The supplied [CollectT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#CollectT) collects all errors from one tick. If the condition is not met before waitFor, the collected errors from the last tick are copied to t. Calling [CollectT.FailNow](https://pkg.go.dev/CollectT#FailNow) cancels the condition immediately and fails the assertion. +#### Concurrency + +The condition function is never executed in parallel: only one goroutine executes it. +It may write to variables outside its scope without triggering race conditions. + {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -173,13 +178,11 @@ Calling [CollectT.FailNow](https://pkg.go.dev/CollectT#FailNow) cancels the cond assertions.EventuallyWithT(t, func(c *assertions.CollectT) { // add assertions as needed; any assertion failure will fail the current tick assertions.True(c, externalValue, "expected 'externalValue' to be true") - }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") -``` -{{< /tab >}} -{{% tab title="Concurrency" %}} -```go -The condition function is never executed in parallel: only one goroutine executes it. -It may write to variables outside its scope without triggering race conditions. + }, + 10*time.Second, + 1*time.Second, + "external state has not changed to 'true'; still false", + ) ``` {{< /tab >}} {{% tab title="Examples" %}} @@ -214,7 +217,7 @@ It may write to variables outside its scope without triggering race conditions. |--|--| | [`assertions.EventuallyWithT(t T, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#EventuallyWithT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#EventuallyWithT](https://github.com/go-openapi/testify/blob/master/internal/assertions/condition.go#L144) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#EventuallyWithT](https://github.com/go-openapi/testify/blob/master/internal/assertions/condition.go#L148) {{% /tab %}} {{< /tabs >}} @@ -223,10 +226,17 @@ It may write to variables outside its scope without triggering race conditions. Never asserts that the given condition is never satisfied within waitFor time, periodically checking the target function at each tick. -[Never] is the opposite of [Eventually]. It succeeds if the waitFor timeout +[Never](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Never) is the opposite of [Eventually](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Eventually). It succeeds if the waitFor timeout is reached without the condition ever returning true. -If the parent context is cancelled before the timeout, [Never] fails. +If the parent context is cancelled before the timeout, [Never](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Never) fails. + +#### Concurrency + +The condition function is never executed in parallel: only one goroutine executes it. +It may write to variables outside its scope without triggering race conditions. + +A blocking condition will cause [Never](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Never) to hang until it returns. {{% expand title="Examples" %}} {{< tabs >}} @@ -235,13 +245,6 @@ If the parent context is cancelled before the timeout, [Never] fails. assertions.Never(t, func() bool { return false }, time.Second, 10*time.Millisecond) ``` {{< /tab >}} -{{% tab title="Concurrency" %}} -```go -The condition function is never executed in parallel: only one goroutine executes it. -It may write to variables outside its scope without triggering race conditions. -A blocking condition will cause [Never] to hang until it returns. -``` -{{< /tab >}} {{% tab title="Examples" %}} ```go success: func() bool { return false }, 100*time.Millisecond, 20*time.Millisecond @@ -294,5 +297,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/equality.md b/docs/doc-site/api/equality.md index 6cc7f64de..3ed5c6b21 100644 --- a/docs/doc-site/api/equality.md +++ b/docs/doc-site/api/equality.md @@ -1,7 +1,7 @@ --- title: "Equality" description: "Asserting Two Things Are Equal" -modified: 2026-01-26 +modified: 2026-01-27 weight: 5 domains: - "equality" @@ -50,7 +50,7 @@ Asserting Two Things Are Equal _All links point to _ This domain exposes 16 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [Empty](#empty) | angles-right @@ -83,6 +83,8 @@ Slices, maps and channels with zero length are "empty". Pointer values are "empty" if the pointer is nil or if the pointed value is "empty". + +[Zero values]: https://go.dev/ref/spec#The_zero_value {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} @@ -99,8 +101,6 @@ Pointer values are "empty" if the pointer is nil or if the pointed value is "emp {{< /tabs >}} {{% /expand %}} -[Zero values]: https://go.dev/ref/spec#The_zero_value - {{< tabs >}} {{% tab title="assert" style="secondary" %}} | Signature | Usage | @@ -241,12 +241,12 @@ Function equality cannot be determined and will always fail. EqualT asserts that two objects of the same comparable type are equal. -Pointer variable equality is determined based on the equality of the memory addresses (unlike [Equal], but like [Same]). +Pointer variable equality is determined based on the equality of the memory addresses (unlike [Equal](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Equal), but like [Same](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Same)). Functions, slices and maps are not comparable. See also [ComparisonOperators](https://go.dev/ref/spec#Comparison_operators.). If you need to compare values of non-comparable types, or compare pointers by the value they point to, -use [Equal] instead. +use [Equal](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Equal) instead. {{% expand title="Examples" %}} {{< tabs >}} @@ -433,14 +433,14 @@ Nil asserts that the specified object is nil. ### NotEmpty{#notempty} -NotEmpty asserts that the specified object is NOT [Empty]. +NotEmpty asserts that the specified object is NOT [Empty](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Empty). {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} ```go if assert.NotEmpty(t, obj) { - assertions.Equal(t, "two", obj[1]) + assertions.Equal(t, "two", obj[1](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#1)) } ``` {{< /tab >}} @@ -534,7 +534,7 @@ Function equality cannot be determined and will always fail. NotEqualT asserts that the specified values of the same comparable type are NOT equal. -See [EqualT]. +See [EqualT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#EqualT). {{% expand title="Examples" %}} {{< tabs >}} @@ -675,7 +675,7 @@ assertions.NotNil(t, err) NotSame asserts that two pointers do not reference the same object. -See [Same]. +See [Same](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Same). {{% expand title="Examples" %}} {{< tabs >}} @@ -724,7 +724,7 @@ See [Same]. NotSameT asserts that two pointers do not reference the same object. -See [SameT]. +See [SameT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#SameT). {{% expand title="Examples" %}} {{< tabs >}} @@ -773,7 +773,7 @@ Both arguments must be pointer variables. Pointer variable sameness is determined based on the equality of both type and value. -Unlike [Equal] pointers, [Same] pointers point to the same memory address. +Unlike [Equal](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Equal) pointers, [Same](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Same) pointers point to the same memory address. {{% expand title="Examples" %}} {{< tabs >}} @@ -822,7 +822,7 @@ Unlike [Equal] pointers, [Same] pointers point to the same memory address. SameT asserts that two pointers of the same type reference the same object. -See [Same]. +See [Same](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Same). {{% expand title="Examples" %}} {{< tabs >}} @@ -879,5 +879,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/error.md b/docs/doc-site/api/error.md index 8c35822bf..4d60c4f9b 100644 --- a/docs/doc-site/api/error.md +++ b/docs/doc-site/api/error.md @@ -1,7 +1,7 @@ --- title: "Error" description: "Asserting Errors" -modified: 2026-01-26 +modified: 2026-01-27 weight: 6 domains: - "error" @@ -453,5 +453,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/file.md b/docs/doc-site/api/file.md index 930f0ec8b..28426a741 100644 --- a/docs/doc-site/api/file.md +++ b/docs/doc-site/api/file.md @@ -1,7 +1,7 @@ --- title: "File" description: "Asserting OS Files" -modified: 2026-01-26 +modified: 2026-01-27 weight: 7 domains: - "file" @@ -344,5 +344,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/http.md b/docs/doc-site/api/http.md index 5c1dee8c6..cb19f4eef 100644 --- a/docs/doc-site/api/http.md +++ b/docs/doc-site/api/http.md @@ -1,7 +1,7 @@ --- title: "Http" description: "Asserting HTTP Response And Body" -modified: 2026-01-26 +modified: 2026-01-27 weight: 8 domains: - "http" @@ -382,5 +382,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/json.md b/docs/doc-site/api/json.md index 408073ddf..1e51b69e2 100644 --- a/docs/doc-site/api/json.md +++ b/docs/doc-site/api/json.md @@ -1,7 +1,7 @@ --- title: "Json" description: "Asserting JSON Documents" -modified: 2026-01-26 +modified: 2026-01-27 weight: 9 domains: - "json" @@ -24,7 +24,7 @@ Asserting JSON Documents _All links point to _ This domain exposes 3 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [JSONEq](#jsoneq) | angles-right @@ -34,7 +34,7 @@ Generic assertions are marked with a {{% icon icon="star" color=orange %}} ### JSONEq{#jsoneq} -JSONEq asserts that two JSON strings are equivalent. +JSONEq asserts that two JSON strings are semantically equivalent. Expected and actual must be valid JSON. @@ -77,13 +77,13 @@ Expected and actual must be valid JSON. |--|--| | [`assertions.JSONEq(t T, expected string, actual string, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#JSONEq) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#JSONEq](https://github.com/go-openapi/testify/blob/master/internal/assertions/json.go#L62) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#JSONEq](https://github.com/go-openapi/testify/blob/master/internal/assertions/json.go#L63) {{% /tab %}} {{< /tabs >}} ### JSONEqBytes{#jsoneqbytes} -JSONEqBytes asserts that two JSON slices of bytes are equivalent. +JSONEqBytes asserts that two JSON slices of bytes are semantically equivalent. Expected and actual must be valid JSON. @@ -129,14 +129,18 @@ Expected and actual must be valid JSON. **Source:** [github.com/go-openapi/testify/v2/internal/assertions#JSONEqBytes](https://github.com/go-openapi/testify/blob/master/internal/assertions/json.go#L25) > **Maintainer Note** -> proposal for enhancement. We could use and indirection for users to inject their favorite JSON -library like we do for YAML. +> +> Proposal for enhancement. +> +> We could use and indirection for users to inject their favorite JSON +> library like we do for YAML. +> {{% /tab %}} {{< /tabs >}} ### JSONEqT[EDoc, ADoc Text] {{% icon icon="star" color=orange %}}{#jsoneqtedoc-adoc-text} -JSONEqT asserts that two JSON documents are equivalent. +JSONEqT asserts that two JSON documents are semantically equivalent. The expected and actual arguments may be string or []byte. They do not need to be of the same type. @@ -177,7 +181,7 @@ Expected and actual must be valid JSON. |--|--| | [`assertions.JSONEqT(t T, expected EDoc, actual ADoc, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#JSONEqT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#JSONEqT](https://github.com/go-openapi/testify/blob/master/internal/assertions/json.go#L85) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#JSONEqT](https://github.com/go-openapi/testify/blob/master/internal/assertions/json.go#L86) {{% /tab %}} {{< /tabs >}} @@ -197,5 +201,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/number.md b/docs/doc-site/api/number.md index 66a009073..005f3c515 100644 --- a/docs/doc-site/api/number.md +++ b/docs/doc-site/api/number.md @@ -1,7 +1,7 @@ --- title: "Number" description: "Asserting Numbers" -modified: 2026-01-26 +modified: 2026-01-27 weight: 10 domains: - "number" @@ -32,7 +32,7 @@ Asserting Numbers _All links point to _ This domain exposes 7 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [InDelta](#indelta) | angles-right @@ -52,17 +52,16 @@ Delta must be greater than or equal to zero. Expected and actual values should convert to float64. To compare large integers that can't be represented accurately as float64 (eg. uint64), -prefer [InDeltaT] to preserve the original type. +prefer [InDeltaT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDeltaT) to preserve the original type. + +#### Behavior with IEEE floating point arithmetics -{{% expand title="Examples" %}} -{{< tabs >}} -{{% tab title="Behavior With IEEE Floating Point Arithmetics" %}} -```go - expected NaN is matched only by a NaN, e.g. this works: InDeltaT(math.NaN(), math.Sqrt(-1), 0.0) - expected +Inf is matched only by a +Inf - expected -Inf is matched only by a -Inf -``` -{{< /tab >}} + +{{% expand title="Examples" %}} +{{< tabs >}} {{% tab title="Usage" %}} ```go assertions.InDelta(t, math.Pi, 22/7.0, 0.01) @@ -106,21 +105,21 @@ assertions.InDelta(t, math.Pi, 22/7.0, 0.01) ### InDeltaMapValues{#indeltamapvalues} -InDeltaMapValues is the same as [InDelta], but it compares all values between two maps. Both maps must have exactly the same keys. +InDeltaMapValues is the same as [InDelta](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDelta), but it compares all values between two maps. Both maps must have exactly the same keys. -See [InDelta]. +See [InDelta](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDelta). {{% expand title="Examples" %}} {{< tabs >}} {{% tab title="Usage" %}} ```go - assertions.InDeltaMapValues(t, map[string]float64{"a": 1.0}, map[string]float64{"a": 1.01}, 0.02) + assertions.InDeltaMapValues(t, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.0}, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.01}, 0.02) ``` {{< /tab >}} {{% tab title="Examples" %}} ```go - success: map[string]float64{"a": 1.0}, map[string]float64{"a": 1.01}, 0.02 - failure: map[string]float64{"a": 1.0}, map[string]float64{"a": 1.1}, 0.05 + success: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.0}, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.01}, 0.02 + failure: map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.0}, map[string](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#string)float64{"a": 1.1}, 0.05 ``` {{< /tab >}} {{< /tabs >}} @@ -155,9 +154,9 @@ See [InDelta]. ### InDeltaSlice{#indeltaslice} -InDeltaSlice is the same as [InDelta], except it compares two slices. +InDeltaSlice is the same as [InDelta](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDelta), except it compares two slices. -See [InDelta]. +See [InDelta](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDelta). {{% expand title="Examples" %}} {{< tabs >}} @@ -206,21 +205,20 @@ See [InDelta]. InDeltaT asserts that the two numerals of the same type numerical type are within delta of each other. -[InDeltaT] accepts any go numeric type, including integer types. +[InDeltaT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDeltaT) accepts any go numeric type, including integer types. -The main difference with [InDelta] is that the delta is expressed with the same type as the values, not necessarily a float64. +The main difference with [InDelta](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDelta) is that the delta is expressed with the same type as the values, not necessarily a float64. Delta must be greater than or equal to zero. -{{% expand title="Examples" %}} -{{< tabs >}} -{{% tab title="Behavior With IEEE Floating Point Arithmetics" %}} -```go +#### Behavior with IEEE floating point arithmetics + - expected NaN is matched only by a NaN, e.g. this works: InDeltaT(math.NaN(), math.Sqrt(-1), 0.0) - expected +Inf is matched only by a +Inf - expected -Inf is matched only by a -Inf -``` -{{< /tab >}} + +{{% expand title="Examples" %}} +{{< tabs >}} {{% tab title="Usage" %}} ```go assertions.InDeltaT(t, math.Pi, 22/7.0, 0.01) @@ -262,20 +260,22 @@ assertions.InDeltaT(t, math.Pi, 22/7.0, 0.01) InEpsilon asserts that expected and actual have a relative error less than epsilon. -{{% expand title="Examples" %}} -{{< tabs >}} -{{% tab title="Behavior With IEEE Floating Point Arithmetics" %}} -```go +#### Behavior with IEEE floating point arithmetics + - expected NaN is matched only by a NaN, e.g. this works: InDeltaT(math.NaN(), math.Sqrt(-1), 0.0) - expected +Inf is matched only by a +Inf - expected -Inf is matched only by a -Inf -Edge case: for very large integers that do not convert accurately to a float64 (e.g. uint64), prefer [InDeltaT]. + +Edge case: for very large integers that do not convert accurately to a float64 (e.g. uint64), prefer [InDeltaT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDeltaT). + Formula: - If expected == 0: fail if |actual - expected| > epsilon - If expected != 0: fail if |actual - expected| > epsilon * |expected| -This allows [InEpsilonT] to work naturally across the full numeric range including zero. -``` -{{< /tab >}} + +This allows [InEpsilonT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InEpsilonT) to work naturally across the full numeric range including zero. + +{{% expand title="Examples" %}} +{{< tabs >}} {{% tab title="Usage" %}} ```go assertions.InEpsilon(t, 100.0, 101.0, 0.02) @@ -319,9 +319,9 @@ This allows [InEpsilonT] to work naturally across the full numeric range includi ### InEpsilonSlice{#inepsilonslice} -InEpsilonSlice is the same as [InEpsilon], except it compares each value from two slices. +InEpsilonSlice is the same as [InEpsilon](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InEpsilon), except it compares each value from two slices. -See [InEpsilon]. +See [InEpsilon](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InEpsilon). {{% expand title="Examples" %}} {{< tabs >}} @@ -373,23 +373,25 @@ InEpsilonT asserts that expected and actual have a relative error less than epsi When expected is zero, epsilon is interpreted as an absolute error threshold, since relative error is mathematically undefined for zero values. -Unlike [InDeltaT], which preserves the original type, [InEpsilonT] converts the expected and actual +Unlike [InDeltaT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDeltaT), which preserves the original type, [InEpsilonT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InEpsilonT) converts the expected and actual numbers to float64, since the relative error doesn't make sense as an integer. -{{% expand title="Examples" %}} -{{< tabs >}} -{{% tab title="Behavior With IEEE Floating Point Arithmetics" %}} -```go +#### Behavior with IEEE floating point arithmetics + - expected NaN is matched only by a NaN, e.g. this works: InDeltaT(math.NaN(), math.Sqrt(-1), 0.0) - expected +Inf is matched only by a +Inf - expected -Inf is matched only by a -Inf -Edge case: for very large integers that do not convert accurately to a float64 (e.g. uint64), prefer [InDeltaT]. + +Edge case: for very large integers that do not convert accurately to a float64 (e.g. uint64), prefer [InDeltaT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InDeltaT). + Formula: - If expected == 0: fail if |actual - expected| > epsilon - If expected != 0: fail if |actual - expected| > epsilon * |expected| -This allows [InEpsilonT] to work naturally across the full numeric range including zero. -``` -{{< /tab >}} + +This allows [InEpsilonT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#InEpsilonT) to work naturally across the full numeric range including zero. + +{{% expand title="Examples" %}} +{{< tabs >}} {{% tab title="Usage" %}} ```go assertions.InEpsilon(t, 100.0, 101.0, 0.02) @@ -443,5 +445,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/ordering.md b/docs/doc-site/api/ordering.md index 95452c9b3..a7300cb10 100644 --- a/docs/doc-site/api/ordering.md +++ b/docs/doc-site/api/ordering.md @@ -1,7 +1,7 @@ --- title: "Ordering" description: "Asserting How Collections Are Ordered" -modified: 2026-01-26 +modified: 2026-01-27 weight: 11 domains: - "ordering" @@ -38,7 +38,7 @@ Asserting How Collections Are Ordered _All links point to _ This domain exposes 10 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [IsDecreasing](#isdecreasing) | angles-right @@ -104,7 +104,7 @@ IsDecreasing asserts that the collection is strictly decreasing. ### IsDecreasingT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#isdecreasingtorderedslice-e-e-ordered} -IsDecreasingT asserts that a slice of [Ordered] is strictly decreasing. +IsDecreasingT asserts that a slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is strictly decreasing. {{% expand title="Examples" %}} {{< tabs >}} @@ -198,7 +198,7 @@ IsIncreasing asserts that the collection is strictly increasing. ### IsIncreasingT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#isincreasingtorderedslice-e-e-ordered} -IsIncreasingT asserts that a slice of [Ordered] is strictly increasing. +IsIncreasingT asserts that a slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is strictly increasing. {{% expand title="Examples" %}} {{< tabs >}} @@ -292,7 +292,7 @@ IsNonDecreasing asserts that the collection is not strictly decreasing. ### IsNonDecreasingT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#isnondecreasingtorderedslice-e-e-ordered} -IsNonDecreasingT asserts that a slice of [Ordered] is not decreasing. +IsNonDecreasingT asserts that a slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is not decreasing. {{% expand title="Examples" %}} {{< tabs >}} @@ -386,7 +386,7 @@ IsNonIncreasing asserts that the collection is not increasing. ### IsNonIncreasingT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#isnonincreasingtorderedslice-e-e-ordered} -IsNonIncreasingT asserts that a slice of [Ordered] is NOT strictly increasing. +IsNonIncreasingT asserts that a slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is NOT strictly increasing. {{% expand title="Examples" %}} {{< tabs >}} @@ -431,9 +431,9 @@ IsNonIncreasingT asserts that a slice of [Ordered] is NOT strictly increasing. ### NotSortedT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#notsortedtorderedslice-e-e-ordered} -NotSortedT asserts that the slice of [Ordered] is NOT sorted (i.e. non-strictly increasing). +NotSortedT asserts that the slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is NOT sorted (i.e. non-strictly increasing). -Unlike [IsDecreasingT], it accepts slices that are neither increasing nor decreasing. +Unlike [IsDecreasingT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#IsDecreasingT), it accepts slices that are neither increasing nor decreasing. {{% expand title="Examples" %}} {{< tabs >}} @@ -478,9 +478,9 @@ Unlike [IsDecreasingT], it accepts slices that are neither increasing nor decrea ### SortedT[OrderedSlice ~[]E, E Ordered] {{% icon icon="star" color=orange %}}{#sortedtorderedslice-e-e-ordered} -SortedT asserts that the slice of [Ordered] is sorted (i.e. non-strictly increasing). +SortedT asserts that the slice of [Ordered](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Ordered) is sorted (i.e. non-strictly increasing). -Unlike [IsIncreasingT], it accepts elements to be equal. +Unlike [IsIncreasingT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#IsIncreasingT), it accepts elements to be equal. {{% expand title="Examples" %}} {{< tabs >}} @@ -539,5 +539,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/panic.md b/docs/doc-site/api/panic.md index 11a3f0355..d83b73668 100644 --- a/docs/doc-site/api/panic.md +++ b/docs/doc-site/api/panic.md @@ -1,7 +1,7 @@ --- title: "Panic" description: "Asserting A Panic Behavior" -modified: 2026-01-26 +modified: 2026-01-27 weight: 12 domains: - "panic" @@ -240,5 +240,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/string.md b/docs/doc-site/api/string.md index 4d42897ef..ab4abdc26 100644 --- a/docs/doc-site/api/string.md +++ b/docs/doc-site/api/string.md @@ -1,7 +1,7 @@ --- title: "String" description: "Asserting Strings" -modified: 2026-01-26 +modified: 2026-01-27 weight: 13 domains: - "string" @@ -26,7 +26,7 @@ Asserting Strings _All links point to _ This domain exposes 4 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [NotRegexp](#notregexp) | angles-right @@ -39,7 +39,7 @@ Generic assertions are marked with a {{% icon icon="star" color=orange %}} NotRegexp asserts that a specified regular expression does not match a string. -See [Regexp]. +See [Regexp](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Regexp). {{% expand title="Examples" %}} {{< tabs >}} @@ -89,7 +89,7 @@ See [Regexp]. NotRegexpT asserts that a specified regular expression does not match a string. -See [RegexpT]. +See [RegexpT](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#RegexpT). {{% expand title="Examples" %}} {{< tabs >}} @@ -189,7 +189,7 @@ RegexpT asserts that a specified regular expression matches a string. The actual argument to be matched may be a string or []byte. -See [Regexp]. +See [Regexp](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#Regexp). {{% expand title="Examples" %}} {{< tabs >}} @@ -241,5 +241,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/testing.md b/docs/doc-site/api/testing.md index d62ec1c78..605e1850b 100644 --- a/docs/doc-site/api/testing.md +++ b/docs/doc-site/api/testing.md @@ -1,7 +1,7 @@ --- title: "Testing" description: "Mimicks Methods From The Testing Standard Library" -modified: 2026-01-26 +modified: 2026-01-27 weight: 14 domains: - "testing" @@ -136,5 +136,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/time.md b/docs/doc-site/api/time.md index 7e389f129..6206e6ead 100644 --- a/docs/doc-site/api/time.md +++ b/docs/doc-site/api/time.md @@ -1,7 +1,7 @@ --- title: "Time" description: "Asserting Times And Durations" -modified: 2026-01-26 +modified: 2026-01-27 weight: 15 domains: - "time" @@ -138,5 +138,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/type.md b/docs/doc-site/api/type.md index e328fdce7..62381299d 100644 --- a/docs/doc-site/api/type.md +++ b/docs/doc-site/api/type.md @@ -1,7 +1,7 @@ --- title: "Type" description: "Asserting Types Rather Than Values" -modified: 2026-01-26 +modified: 2026-01-27 weight: 16 domains: - "type" @@ -38,7 +38,7 @@ Asserting Types Rather Than Values _All links point to _ This domain exposes 10 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [Implements](#implements) | angles-right @@ -102,7 +102,7 @@ Implements asserts that an object is implemented by the specified interface. ### IsNotOfTypeT[EType any] {{% icon icon="star" color=orange %}}{#isnotoftypetetype-any} -IsNotOfTypeT asserts that an object is of a given type. +IsNotOfTypeT asserts that an object is not of a given type. {{% expand title="Examples" %}} {{< tabs >}} @@ -537,5 +537,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/api/yaml.md b/docs/doc-site/api/yaml.md index f81146287..8bccbc7b5 100644 --- a/docs/doc-site/api/yaml.md +++ b/docs/doc-site/api/yaml.md @@ -1,7 +1,7 @@ --- title: "Yaml" description: "Asserting Yaml Documents" -modified: 2026-01-26 +modified: 2026-01-27 weight: 17 domains: - "yaml" @@ -24,7 +24,7 @@ Asserting Yaml Documents _All links point to _ This domain exposes 3 functionalities. -Generic assertions are marked with a {{% icon icon="star" color=orange %}} +Generic assertions are marked with a {{% icon icon="star" color=orange %}}. ```tree - [YAMLEq](#yamleq) | angles-right @@ -36,7 +36,7 @@ Generic assertions are marked with a {{% icon icon="star" color=orange %}} YAMLEq asserts that two YAML strings are equivalent. -See [YAMLEqBytes]. +See [YAMLEqBytes](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#YAMLEqBytes). {{% expand title="Examples" %}} {{< tabs >}} @@ -82,17 +82,18 @@ YAMLEqBytes asserts that two YAML slices of bytes are equivalent. Expected and actual must be valid YAML. -{{% expand title="Examples" %}} -{{< tabs >}} -{{% tab title="Important" %}} -```go +#### Important + By default, this function is disabled and will panic. + To enable it, you should add a blank import like so: + import( "github.com/go-openapi/testify/enable/yaml/v2" ) -``` -{{< /tab >}} + +{{% expand title="Examples" %}} +{{< tabs >}} {{% tab title="Usage" %}} ```go expected := `--- @@ -150,7 +151,7 @@ YAMLEqT asserts that two YAML documents are equivalent. The expected and actual arguments may be string or []byte. They do not need to be of the same type. -See [YAMLEqBytes]. +See [YAMLEqBytes](https://pkg.go.dev/github.com/go-openapi/testify/v2/assert#YAMLEqBytes). {{% expand title="Examples" %}} {{< tabs >}} @@ -202,5 +203,5 @@ SPDX-License-Identifier: Apache-2.0 Document generated by github.com/go-openapi/testify/codegen/v2 DO NOT EDIT. -Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] --> diff --git a/docs/doc-site/project/MOTIVATION.md b/docs/doc-site/project/MOTIVATION.md new file mode 100644 index 000000000..f0023ca7b --- /dev/null +++ b/docs/doc-site/project/MOTIVATION.md @@ -0,0 +1,66 @@ +--- +title: Motivation +description: Motivations for this fork +weight: 5 +--- + +From the maintainers of `testify`, it looks like a v2 will eventually be released, but they'll do it at their own pace. + +We like all the principles they exposed to build this v2. [See discussion about v2](https://github.com/stretchr/testify/discussions/1560). + +However, at `go-openapi` we would like to address the well-known issues in `testify` with different priorities. + +With this fork, we want to: + +1. [x] remove all external dependencies. +2. [x] make it easy to maintain and extend. +3. [x] pare down some of the chrome that has been added over the years. + +--- + +{{% notice style="primary" title="Extended hand" icon="hand" %}} +We hope that this endeavor will help the original project with a live-drill of what a v2 could look like. + +Hopefully, some of our ideas will eventually percolate back into the original project and help the wider +community of go developers write better, clearer test code. + +Feedback is welcome and we are always happy to discuss with people who face the same problems as we do: avoid breaking changes, +APIs that became bloated over a decade or so, uncontrolled dependencies, difficult choices when it comes to introduce +breaking changes, conflicting demands from users etc. +{{% /notice %}} + +You might also be curious about our [ROADMAP](project/maintainers/ROADMAP.md). + +--- + +1. We wanted first to remove all external dependencies. + +> For all our libraries and generated test code we don't want test dependencies +> to drill farther than `import github.com/go-openapi/testify/v2`, but on some specific (and controlled) +> occasions. +> +> In this fork, all external stuff is either internalized (`go-spew`, `difflib`), +> removed (`mocks`, `suite`, `http`) or specifically enabled by importing this module +> (`github.com/go-openapi/testify/enable/yaml/v2`). + +2. Make it easy to maintain and extend. + +> For go-openapi, testify should just be yet another part of our toolkit. +> We need it to work, be easily adaptable to our needs and not divert our development effort away from our other repos. +> This big refactor is an investment. + +3. We want to pare down some of the chrome that has been added over the years + +> The `go-openapi` libraries and the `go-swagger` project make a rather limited use of the vast API provided by `testify`. +> +> With this first version of the fork, we have removed `mocks` and `suite`, which we don't use. +> They might be added later on, with better controlled dependencies. +> +> In the forthcoming maintenance of this fork, much of the "chrome" or "ambiguous" API will be pared down. +> There is no commitment yet on the stability of the API. +> +> Chrome would be added later: we have the "enable" packages just for that for when external dependencies are needed. + +4. We want to add new features like generics, more useful assertions for JSON and safety checks. + +5. We want to get rid of the API quirks and gotchas that panic or return unexpected results. diff --git a/docs/doc-site/project/README.md b/docs/doc-site/project/README.md index 24833f9b7..28ccc0232 100644 --- a/docs/doc-site/project/README.md +++ b/docs/doc-site/project/README.md @@ -1,51 +1,21 @@ --- title: README description: | - Introducing `go-openapi/testify/v2`. + Introducing go-openapi/testify/v2. - Approach - Main features - Differences with v1 -weight: 1 +weight: 2 --- -**Go testing assertions for the rest of us** +**The v2 our tests wanted** ## Motivation -1. We want first to remove all external dependencies. +See [why we wanted a v2](./MOTIVATION.md). -> For all our libraries and generated test code we don't want test dependencies -> to drill farther than `import github.com/go-openapi/testify/v2`, but on some specific (and controlled) -> occasions. -> -> In this fork, all external stuff is either internalized (`go-spew`, `difflib`), -> removed (`mocks`, `suite`, `http`) or specifically enabled by importing this module -> (`github.com/go-openapi/testify/enable/yaml/v2`). - -2. Make it easy to maintain and extend. - -> For go-openapi, testify should just be yet another part of our toolkit. -> We need it to work, be easily adaptable to our needs and not divert our development effort away from our other repos. -> This big refactor is an investment that has to pay off. - -3. We want to pare down some of the chrome that has been added over the years - -> The `go-openapi` libraries and the `go-swagger` project make a rather limited use of the vast API provided by `testify`. -> -> With this first version of the fork, we have removed `mocks` and `suite`, which we don't use. -> They might be added later on, with better controlled dependencies. -> -> In the forthcoming maintenance of this fork, much of the "chrome" or "ambiguous" API will be pared down. -> There is no commitment yet on the stability of the API. -> -> Chrome would be added later: we have the "enable" packages just for that. - -4. We hope that this endeavor will help the original project with a live-drill of what a v2 could look like. - We are always happy to discuss with people who face the same problems as we do: avoid breaking changes, - APIs that became bloated over a decade or so, uncontrolled dependencies, conflicting demands from users etc. - -### The approach with this fork +### Approach with this fork This fork targets **go1.24**. diff --git a/docs/doc-site/project/SECURITY.md b/docs/doc-site/project/SECURITY.md index eb9e9c32b..df432f68b 100644 --- a/docs/doc-site/project/SECURITY.md +++ b/docs/doc-site/project/SECURITY.md @@ -2,7 +2,7 @@ title: Security Policy description: | This document outlines the commitment and practices of the go-openapi maintainers regarding security -weight: 2 +weight: 3 --- This policy outlines the commitment and practices of the go-openapi maintainers regarding security. @@ -11,7 +11,7 @@ This policy outlines the commitment and practices of the go-openapi maintainers | Version | Supported | | ------- | ------------------ | -| 2.1.x | :white_check_mark: | +| 2.2.x | :white_check_mark: | ## Vulnerability checks in place diff --git a/docs/doc-site/project/maintainers/ARCHITECTURE.md b/docs/doc-site/project/maintainers/ARCHITECTURE.md index 904818ae3..1986a25a7 100644 --- a/docs/doc-site/project/maintainers/ARCHITECTURE.md +++ b/docs/doc-site/project/maintainers/ARCHITECTURE.md @@ -4,6 +4,74 @@ description: Project structure weight: 2 --- +## Primer + +### Goals + +We want the maintainance of dozens of test assertions, times many variants, to remain reasonably low. + +The maintainance flow is intended to require different activities and levels of understanding, +dependending on the complexity of a planned evolution. + +{{< mermaid align="center" zoom="true" >}} +journey + section Fixes & minor enhancements + internal/assertions:5: Knowledge of the functionality + section New dependencies + internal/assertions/enable/...:5: Understanding of the repo architecture + enable/...:5: Understanding of the repo architecture + section API changes + regenerate code:5: No specific knowledge + section New constructs to support + code & doc generator:5: Knowledge of internals +{{< /mermaid >}} + +Most common maintenance tasks should not require much more than fixing/enhancing the code in `internal/assertions`. + +API changes need an extra code generation. + +Dependency changes (adding new features that need extra dependencies) is a bit more involved, but still manageable. + +The code & doc generator should rapidly become a very stable component. The maintenance of the generator itself remains +an operation that requires an extended understanding of the internals of the project. + +Fixes and enhancements propagate naturally to the variants without the need to regenerate code. + +### The maths with assertion variants + +Each test assertion produces 2 base variants (assert, require). + +Each of these variants produces another formatted variant. Except for generic assertions, we produce +one "forward" variant and one "forward formatted" variant (as methods). + +**For every non-generic assertion: 8 variants.** + +**For every generic assertion: 4 variants.** + +**For every "helper" function (not an assertion): 2 variants.** + + +All these variants make up several hundreds functions, which poses a challenge for maintainance and documentation. + +We have adopted code and documentation generation as a mean to mitigate this issue. + +#### Current (v2.2.0) + + 1. Generic assertions (with type parameters): 38 functions + 2. Non-generic assertions (with t T parameter, no type parameters): 82 functions + 3. Helper functions (no t T parameter): 4 functions + + Total: 124 functions to _maintain_ + + **Generated Functions** + + 1. Generic assertions: 152 + 2. Non-generic assertions: 656 + 3. Helper functions: 8 + 4. Constructors: 2 + + Total: 818 functions + ## Architecture Overview {{< mermaid align="center" zoom="true" >}} @@ -31,7 +99,6 @@ All assertion implementations live in `internal/assertions/`, organized by domai **Code Generator: `codegen/`** The generator scans `internal/assertions/` and produces: -- n assertion functions × 8 variants = 608 generated functions (current: n=76) - Package-level functions (`assert.Equal`, `require.Equal`) - Format variants (`assert.Equalf`, `require.Equalf`) - Forward methods (`a.Equal()`, `r.Equal()`) @@ -41,6 +108,8 @@ The generator scans `internal/assertions/` and produces: **Generated Packages: `assert/` and `require/`** +The generated functions directly call the internal implementation: no code duplication or change in semantics. + **Generated Documentation: `docs/doc-site/api/`** Everything in these packages is generated. Never edit generated files directly. @@ -57,3 +126,7 @@ The `enable/` package provides optional features that users can activate via bla - `enable/colors/` - Activates colorized output via `import _ "github.com/go-openapi/testify/v2/enable/colors"` These packages are not generated and allow optional dependencies to be isolated from the core library. + +## See Also + +- [Code generation](./CODEGEN.md) - Detailed view of our code and doc generator diff --git a/docs/doc-site/project/maintainers/CODEGEN.md b/docs/doc-site/project/maintainers/CODEGEN.md index e7fecf11b..45eb95a90 100644 --- a/docs/doc-site/project/maintainers/CODEGEN.md +++ b/docs/doc-site/project/maintainers/CODEGEN.md @@ -77,7 +77,7 @@ This repository uses code generation extensively to maintain consistency across style not_generated_require fill:#4a9eff,color:#fff {{< /mermaid >}} -> The generator scans source code, extracts metadata, builds a model, and applies templates to generate ~600+ functions, tests, and documentation from ~70-80+ source functions. +> The generator scans source code, extracts metadata, builds a model, and applies templates to generate ~800+ functions, tests, and documentation from ~100+ source functions. --- @@ -158,7 +158,9 @@ graph TD style require_group fill:#ffb6c1,color:#000 {{< /mermaid >}} -> **76 functions × 8 variants = 608 generated functions** (plus tests and documentation for each) +> **reflection-based assertions become 8, generic assertions become 4** +> +> (plus tests and documentation for each). --- diff --git a/docs/doc-site/project/maintainers/ROADMAP.md b/docs/doc-site/project/maintainers/ROADMAP.md index c9dd7e2ad..6d02c313f 100644 --- a/docs/doc-site/project/maintainers/ROADMAP.md +++ b/docs/doc-site/project/maintainers/ROADMAP.md @@ -10,31 +10,40 @@ weight: 4 timeline title Planned releases section Q4 2025 - ✅ v2.0 (Nov 2025) : zero dependencies + ✅ v2.0 (Nov 2025) : Zero dependencies : optional dependencies (YAML) : modernized code (relint) : JSONEqBytes section Q1 2026 - ✅ v2.1 (Jan 2026) : generated assertions + ✅ v2.1 (Jan 2026) : Generated assertions : complete refactoring : documentation site : panic handling fixes : removed deprecated - 📝 v2.2 (Fev 2026) : generics + 📝 v2.2 (Fev 2026) : Generics : Kind/NotKind : SortedT, NotSortedT : complete test refactoring : more benchmarks. Perf improvements : optional dependencies (colorized) - ⏳ v2.3 (Mar 2026) : other extensions - : JSON assertions. JSONMarshalsAs... + ⏳ v2.3 (Fev 2026) : Other extensions + : Extensible Assertion type + : JSON & YAML assertions: JSONMarshalsAs... + : NoGoroutineLeak : more documentation and examples - : export internal tools (spew, difflib, benchviz) + 📝 v2.4 (Mar 2026) : Stabilize API (no more removals) + : NoFileDescriptorLeak (unix) + : async: Eventually/Never to accept error and context + : JSONPointerT + : export internal tools (spew, difflib, section Q2 2026 - v2.4 (Apr 2026) : Stabilize API + v2.5 (May 2026) : New candidate features from upstream + : NoFileDescriptorLeak (windows port) : export internal tools (blackbox) {{< /mermaid >}} +## Notes + 1. [x] The first release comes with zero dependencies and an unstable API (see below [our use case](#usage-at-go-openapi)) 2. [x] This project is going to be injected as the main and sole test dependency of the `go-openapi` libraries 3. [x] Since we have leveled the go requirements to the rest of the go-openapi (currently go1.24) there is quite a bit of relinting lying ahead. @@ -43,9 +52,13 @@ timeline 6. [x] Introduces colorization (opt-in) 7. [x] Introduces generics 8. [x] Realign behavior re quirks, bugs, unexpected logics ... (e.g. IsNonDecreasing, EventuallyWithT...) -9. [ ] New features following test simplification effort in go-openapi repos (e.g. JSONMarshalsAs ...) 10. [ ] Unclear assertions might be provided an alternative verb (e.g. `EventuallyWithT`) -11. [ ] Inject this test dependency into the `go-swagger` tool + +### Adoption timeline at go-openapi + +1. [x] Jan 2026: all go-openapi projects adopts the forked testify +2. [ ] Feb 2026: all go-openapi projects transition to generics +3. [ ] Mar 2026: go-swagger transitions to the forked testify ### What won't come anytime soon @@ -59,7 +72,7 @@ We actively monitor [github.com/stretchr/testify](https://github.com/stretchr/te **Review frequency**: Quarterly (next review: April 2026) -**Processed items**: 28 upstream PRs and issues have been reviewed, with 21 implemented/merged, 5 superseded by our implementation or merely marked as informational, and 2 currently under consideration. See also [Tracking](../../usage/TRACKING.md). +**Processed items**: 28 upstream PRs and issues have been reviewed, with 21 implemented/merged, 5 superseded by our implementation or merely marked as informational, and 2 currently under consideration. For a complete catalog of all upstream PRs and issues we've processed (implemented, adapted, superseded, or monitoring), see the [Upstream Tracking](../../usage/TRACKING.md). diff --git a/docs/doc-site/usage/CHANGES.md b/docs/doc-site/usage/CHANGES.md index 5be983c7e..186546480 100644 --- a/docs/doc-site/usage/CHANGES.md +++ b/docs/doc-site/usage/CHANGES.md @@ -7,25 +7,24 @@ weight: 15 ## Summary **Key Changes:** -- **Dependencies**: Zero external (internalized 2, optional 1 via enable pattern) -- **New functions**: 51 total (38 generic + 13 reflection-based) -- **Performance**: ~10x for generic variants (from 1.2x to 81x, your mileage may vary) -- **Architecture**: 100% code generation from single source -- **Breaking changes**: Requires go1.24, removed suites, mocks, http tooling, and deprecated functions. YAMLEq becomes optional (panics by default). +- ✅ **Zero Dependencies**: Completely self-contained +- ✅ **New functions**: 51 additional assertions (38 generic + 13 reflection-based) +- ✅ **Performance**: ~10x for generic variants (from 1.2x to 81x, your mileage may vary) +- ✅ **Breaking changes**: Requires go1.24, removed suites, mocks, http tooling, and deprecated functions. YAMLEq becomes optional (panics by default). --- **Testify v2 represents a comprehensive modernization** -- ✅ **Zero Dependencies**: Completely self-contained - ✅ **Type Safety**: 38 generic assertions catch errors at compile time -- ✅ **Performance**: Up to 81x faster with generics -- ✅ **Documentation**: compelling Hugo site to document the API by use-case domain -- ✅ **Quality**: 96% test coverage, extensive fuzzing & benchmarking +- ✅ **Documentation**: compelling documentation site to search the API by use-case domain - ✅ **Maintainability**: 100% code generation from single source +- ✅ **Quality**: 96% test coverage, use unified test scenarios, extensive fuzzing & benchmarking This fork maintains compatibility where possible while making bold improvements in architecture, safety, and performance. +The original philosophy of `testify` is preserved, and the new API is 90% compatible. + **Fork Information:** - **Upstream repository**: [github.com/stretchr/testify](https://github.com/stretchr/testify) - **Fork date**: 2025-01-09 @@ -355,7 +354,9 @@ See also a quick [migration guide](./MIGRATION.md). **New functions**: None -**Behavior changes**: None +#### ⚠️ Behavior Changes + +Removed extraneous type declaration `PanicTestFunc` (`func()`). ### String diff --git a/docs/doc-site/usage/MIGRATION.md b/docs/doc-site/usage/MIGRATION.md index ec7934d25..201353094 100644 --- a/docs/doc-site/usage/MIGRATION.md +++ b/docs/doc-site/usage/MIGRATION.md @@ -123,10 +123,12 @@ Replace testify suites with: - Standard Go subtests for test organization - or wait until we reintroduce this feature (possible, but not certain) -### 6. Remove HTTP Assertion Usage +### 6. Remove use of the `testify/http` package If you were still using the deprecated package `github.com/stretchr/testitfy/http`, -you'll need to replace with standard HTTP testing. We won't reintroduce this package ever. +you'll need to replace it by the standard `net/http/httptest` package. + +We won't reintroduce this package ever. ## Breaking Changes Summary @@ -136,9 +138,10 @@ you'll need to replace with standard HTTP testing. We won't reintroduce this pac - ❌ `mock` - Use [mockery](https://github.com/vektra/mockery) - ❌ `http` - May be reintroduced later -### Removed Functions +### Removed Functions and Types - ❌ All deprecated functions from v1 removed +- ❌ Removed extraneous "helper" types: `PanicTestFunc` (`func()`) ### Behavior Changes diff --git a/docs/doc-site/usage/TRACKING.md b/docs/doc-site/usage/TRACKING.md index e4c2874b9..c244ae50f 100644 --- a/docs/doc-site/usage/TRACKING.md +++ b/docs/doc-site/usage/TRACKING.md @@ -6,7 +6,7 @@ weight: 16 ## Upstream Tracking -We continue to monitor and selectively adopt changes from upstream: +We continue to monitor and selectively adopt changes from the upstream repository. ### Implemented from Upstream - ✅ [#1513] - JSONEqBytes diff --git a/enable/colors/doc.go b/enable/colors/doc.go index 0fe7be61a..a082036f7 100644 --- a/enable/colors/doc.go +++ b/enable/colors/doc.go @@ -5,7 +5,15 @@ // // Colorization is disabled by default when the standard output is not a terminal. // -// Colors are somewhat limited, but the package works on unix and windows without any extra dependencies. +// Colors are somewhat limited. We want the package to work on unix and windows without any extra dependencies. +// +// # Usage +// +// To enable the test colorization feature, use a blank import like so: +// +// import ( +// _ "github.com/go-openapi/testify/enable/colors/v2" +// ) // // # Command line arguments // diff --git a/enable/stubs/colors/enable_colors.go b/enable/stubs/colors/enable_colors.go index 19b8d81cb..76220d26f 100644 --- a/enable/stubs/colors/enable_colors.go +++ b/enable/stubs/colors/enable_colors.go @@ -30,6 +30,11 @@ type ( Theme = colorstub.Theme ) +const ( + ThemeDark = colorstub.ThemeDark + ThemeLight = colorstub.ThemeLight +) + // WithEnable enables colorization. func WithEnable(enabled bool) Option { return colorstub.WithEnable(enabled) diff --git a/enable/stubs/yaml/enable_yaml.go b/enable/stubs/yaml/enable_yaml.go index 221ce1fee..55aec1921 100644 --- a/enable/stubs/yaml/enable_yaml.go +++ b/enable/stubs/yaml/enable_yaml.go @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers // SPDX-License-Identifier: Apache-2.0 -// Package yaml is an indirection to handle YAML deserialization. +// Package yaml is an indirection to the internal implementation that handles YAML deserialization. // // This package allows the builder to override the indirection with an alternative implementation // of YAML deserialization. @@ -18,6 +18,8 @@ import ( // Most users would register using a init() function or enabling the // registered library provided when importing "github.com/go-openapi/testify/enable/yaml/v2" like so. // +// The default registration uses "go.yaml.in/yaml/v3" to deserialize YAML. +// // import( // _ "github.com/go-openapi/testify/enable/yaml/v2" // ) diff --git a/enable/yaml/doc.go b/enable/yaml/doc.go new file mode 100644 index 000000000..f7763665e --- /dev/null +++ b/enable/yaml/doc.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package yaml enables the YAMLEq capability in testify. +// +// # Usage +// +// To enable YAML assertion features, use a blank import like so: +// +// import ( +// _ "github.com/go-openapi/testify/enable/yaml/v2" +// ) +package yaml diff --git a/enable/yaml/enable_yaml.go b/enable/yaml/enable_yaml.go index ec5a6a0bc..0aa08960b 100644 --- a/enable/yaml/enable_yaml.go +++ b/enable/yaml/enable_yaml.go @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers // SPDX-License-Identifier: Apache-2.0 -// Package yaml enables the YAMLEq capability in testify. package yaml import ( diff --git a/internal/assertions/boolean.go b/internal/assertions/boolean.go index 30e36dd67..defc25728 100644 --- a/internal/assertions/boolean.go +++ b/internal/assertions/boolean.go @@ -27,6 +27,8 @@ func True(t T, value bool, msgAndArgs ...any) bool { // TrueT asserts that the specified value is true. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool @@ -74,6 +76,8 @@ func False(t T, value bool, msgAndArgs ...any) bool { // FalseT asserts that the specified value is false. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool diff --git a/internal/assertions/collection.go b/internal/assertions/collection.go index 6d5354f36..2d1e3682e 100644 --- a/internal/assertions/collection.go +++ b/internal/assertions/collection.go @@ -81,7 +81,7 @@ func Contains(t T, s, contains any, msgAndArgs ...any) bool { // StringContainsT asserts that a string contains the specified substring. // -// Strings may be go strings or []byte. +// Strings may be go strings or []byte according to the type constraint [Text]. // // # Usage // @@ -106,6 +106,8 @@ func StringContainsT[ADoc, EDoc Text](t T, str ADoc, substring EDoc, msgAndArgs // SliceContainsT asserts that the specified slice contains a comparable element. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SliceContainsT(t, []{"Hello","World"}, "World") @@ -114,6 +116,8 @@ func StringContainsT[ADoc, EDoc Text](t T, str ADoc, substring EDoc, msgAndArgs // // success: []string{"A","B"}, "A" // failure: []string{"A","B"}, "C" +// +// [comparable-types]: https://go.dev/blog/comparable func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArgs ...any) bool { // Domain: collection if h, ok := t.(H); ok { @@ -129,6 +133,10 @@ func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArg // SeqContainsT asserts that the specified iterator contains a comparable element. // +// The sequence may not be consumed entirely: the iteration stops as soon as the specified element is found. +// +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -137,22 +145,27 @@ func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArg // // success: slices.Values([]string{"A","B"}), "A" // failure: slices.Values([]string{"A","B"}), "C" +// +// [comparable-types]: https://go.dev/blog/comparable func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ...any) bool { // Domain: collection if h, ok := t.(H); ok { h.Helper() } - s := slices.Collect(iter) - if !slices.Contains(s, element) { - return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", s), element), msgAndArgs...) + for iterated := range iter { + if iterated == element { + return true + } } - return true + return Fail(t, fmt.Sprintf("sequence does not contain %#v", element), msgAndArgs...) } // MapContainsT asserts that the specified map contains a key. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.MapContainsT(t, map[string]string{"Hello": "x","World": "y"}, "World") @@ -161,6 +174,8 @@ func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ... // // success: map[string]string{"A": "B"}, "A" // failure: map[string]string{"A": "B"}, "C" +// +// [comparable-types]: https://go.dev/blog/comparable func MapContainsT[Map ~map[K]V, K comparable, V any](t T, m Map, key K, msgAndArgs ...any) bool { // Domain: collection if h, ok := t.(H); ok { @@ -207,7 +222,7 @@ func NotContains(t T, s, contains any, msgAndArgs ...any) bool { // StringNotContainsT asserts that a string does not contain the specified substring. // -// Strings may be go strings or []byte. +// See [StringContainsT]. // // # Usage // @@ -232,6 +247,8 @@ func StringNotContainsT[ADoc, EDoc Text](t T, str ADoc, substring EDoc, msgAndAr // SliceNotContainsT asserts that the specified slice does not contain a comparable element. // +// See [SliceContainsT]. +// // # Usage // // assertions.SliceNotContainsT(t, []{"Hello","World"}, "hi") @@ -255,6 +272,8 @@ func SliceNotContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAnd // SeqNotContainsT asserts that the specified iterator does not contain a comparable element. // +// See [SeqContainsT]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -269,9 +288,10 @@ func SeqNotContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs h.Helper() } - s := slices.Collect(iter) - if slices.Contains(s, element) { - return Fail(t, fmt.Sprintf("%s does not contain %#v", truncatingFormat("%#v", s), element), msgAndArgs...) + for iterated := range iter { + if iterated == element { + return Fail(t, fmt.Sprintf("sequence does not contain %#v", element), msgAndArgs...) + } } return true diff --git a/internal/assertions/compare_test.go b/internal/assertions/compare_test.go index 27b684582..a09d72f29 100644 --- a/internal/assertions/compare_test.go +++ b/internal/assertions/compare_test.go @@ -181,7 +181,7 @@ func TestCompareGreaterAndLessT(t *testing.T) { testAllComparisonT[[]byte](tc)(t) default: // Custom types (like redefined uintptr) - skip, they're tested separately - t.Skip("custom types tested separately") + t.Logf("%s: custom types tested separately (got: %T)", t.Name(), tc.less) } }) } diff --git a/internal/assertions/condition.go b/internal/assertions/condition.go index f27e3a9a2..d1b942b75 100644 --- a/internal/assertions/condition.go +++ b/internal/assertions/condition.go @@ -130,7 +130,11 @@ func Never(t T, condition func() bool, waitFor time.Duration, tick time.Duration // assertions.EventuallyWithT(t, func(c *assertions.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assertions.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") +// }, +// 10*time.Second, +// 1*time.Second, +// "external state has not changed to 'true'; still false", +// ) // // # Concurrency // diff --git a/internal/assertions/doc.go b/internal/assertions/doc.go index dd066c4b5..42e15e84b 100644 --- a/internal/assertions/doc.go +++ b/internal/assertions/doc.go @@ -2,31 +2,32 @@ // SPDX-License-Identifier: Apache-2.0 // Package assertions holds the internal implementation -// of all the helper functions exposed by testify. +// of all the assertion and helper functions exposed by testify. // // It serves as a base to develop and test testify, // whereas the publicly exposed API (in packages assert and require) -// is generated. +// is fully generated. // // For convenience, assertion functions are classified by domain. // The entire API can be searched by domain at https://go-openapi.github.io/testify/api. +// // # Domains // -// - boolean: asserting boolean values -// - collection: asserting slices and maps -// - comparison: comparing ordered values -// - condition: expressing assertions using conditions -// - equality: asserting two things are equal -// - error: asserting errors -// - file: asserting OS files -// - http: asserting HTTP response and body -// - json: asserting JSON documents -// - number: asserting numbers -// - ordering: asserting how collections are ordered -// - panic: asserting a panic behavior -// - string: asserting strings -// - testing: mimicks methods from the testing standard library -// - time: asserting times and durations -// - type: asserting types rather than values -// - yaml: asserting yaml documents +// - boolean: asserting boolean values +// - collection: asserting slices and maps +// - comparison: comparing ordered values +// - condition: expressing assertions using conditions +// - equality: asserting two things are equal +// - error: asserting errors +// - file: asserting OS files +// - http: asserting HTTP response and body +// - json: asserting JSON documents +// - number: asserting numbers +// - ordering: asserting how collections are ordered +// - panic: asserting a panic behavior +// - string: asserting strings +// - testing: mimicks methods from the testing standard library +// - time: asserting times and durations +// - type: asserting types rather than values +// - yaml: asserting yaml documents package assertions diff --git a/internal/assertions/json.go b/internal/assertions/json.go index 28cdb40e7..4f95478a7 100644 --- a/internal/assertions/json.go +++ b/internal/assertions/json.go @@ -10,7 +10,7 @@ import ( "fmt" ) -// JSONEqBytes asserts that two JSON slices of bytes are equivalent. +// JSONEqBytes asserts that two JSON slices of bytes are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -24,7 +24,8 @@ import ( // failure: []byte(`{"hello": "world", "foo": "bar"}`), []byte(`[{"foo": "bar"}, {"hello": "world"}]`) func JSONEqBytes(t T, expected, actual []byte, msgAndArgs ...any) bool { // Domain: json - // Maintainer: proposal for enhancement. We could use and indirection for users to inject their favorite JSON + // Maintainers: Proposal for enhancement. + // We could use and indirection for users to inject their favorite JSON // library like we do for YAML. if h, ok := t.(H); ok { h.Helper() @@ -47,7 +48,7 @@ func JSONEqBytes(t T, expected, actual []byte, msgAndArgs ...any) bool { return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) } -// JSONEq asserts that two JSON strings are equivalent. +// JSONEq asserts that two JSON strings are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -68,7 +69,7 @@ func JSONEq(t T, expected, actual string, msgAndArgs ...any) bool { return JSONEqBytes(t, []byte(expected), []byte(actual), msgAndArgs) } -// JSONEqT asserts that two JSON documents are equivalent. +// JSONEqT asserts that two JSON documents are semantically equivalent. // // The expected and actual arguments may be string or []byte. They do not need to be of the same type. // diff --git a/internal/assertions/type.go b/internal/assertions/type.go index d5c84b75f..193851b2e 100644 --- a/internal/assertions/type.go +++ b/internal/assertions/type.go @@ -128,7 +128,7 @@ func IsNotType(t T, theType, object any, msgAndArgs ...any) bool { return Fail(t, fmt.Sprintf("Object type expected to be different than %T", theType), msgAndArgs...) } -// IsNotOfTypeT asserts that an object is of a given type. +// IsNotOfTypeT asserts that an object is not of a given type. // // # Usage // diff --git a/internal/difflib/README.md b/internal/difflib/README.md index ddc57fb36..2e87f738e 100644 --- a/internal/difflib/README.md +++ b/internal/difflib/README.md @@ -1,19 +1,26 @@ # internal/difflib -This is an internalized and modernized copy of [github.com/pmezard/go-difflib](https://github.com/pmezard/go-difflib), a partial port of Python's difflib module for generating textual diffs. +This is an internalized and modernized copy of [github.com/pmezard/go-difflib](https://github.com/pmezard/go-difflib), +a partial port of Python's difflib module for generating textual diffs. ## Original Source **Source repository:** github.com/pmezard/go-difflib -**Original license:** BSD 3-Clause License (see [LICENSE](./LICENSE)) + +**Original license:** BSD 3-Clause License (see [NOTICE](./NOTICE)) + **Copyright:** 2013 Patrick Mezard + **Maintenance status:** ⚠️ No longer maintained (archived by author) -go-difflib provides tools to compare sequences of strings and generate textual diffs in unified or context format. It implements Python's `SequenceMatcher` class and `unified_diff()`/`context_diff()` functions. +`difflib` provides tools to compare sequences of strings and generate textual diffs in unified or context format. + +It implements Python's `SequenceMatcher` class and `unified_diff()`/`context_diff()` functions. ## Why Internalized -This fork of testify maintains **zero external dependencies** for the core assertion packages. By internalizing go-difflib, we: +This fork of testify maintains **zero external dependencies** for the core assertion packages. +By internalizing `difflib`, we: 1. Eliminate the external dependency on an **unmaintained package** (last updated 2014) 2. Gain full control to apply modernizations aligned with our go1.24 target @@ -29,7 +36,7 @@ This internalized copy has been significantly modernized and refactored from the - **Modern operators:** Used `--` instead of `-= 1` for decrement operations - **Efficient conversions:** Used `strconv.Itoa()` instead of `fmt.Sprintf("%d", ...)` for integer-to-string conversion - **Buffer handling:** Used `bytes.Buffer.String()` instead of `string(bytes.Buffer.Bytes())` -- **Modern initialization:** Used `new(bytes.Buffer)` instead of `&bytes.Buffer{}` +- Used `new(bytes.Buffer)` instead of `&bytes.Buffer{}` ### Code Organization & Complexity Reduction @@ -75,15 +82,15 @@ This package is used by testify's assertion functions to generate human-readable The diff output helps developers quickly identify what changed between expected and actual values during test failures. +## Enhancements +- [x] Colorized output support + ## Future Enhancements As an internalized dependency, this copy can receive targeted improvements: - **Potential:** Performance optimizations for large diffs - **Potential:** Enhanced diff algorithms for specific data types -- **Potential:** Colorized output support (if implemented as `enable/color` module) - -These enhancements would be difficult to incorporate if difflib remained an external, unmaintained dependency. ## Maintenance @@ -94,6 +101,7 @@ https://github.com/go-openapi/testify/issues ## License -This code retains its original BSD 3-Clause License. See [LICENSE](./LICENSE) for the full license text. +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE) and acknowledges the original licensing +terms (BSD-3-Clause-License) from the original source it was copied from: [NOTICE](./NOTICE). The original copyright and license terms are preserved in accordance with the BSD License requirements. diff --git a/internal/difflib/difflib.go b/internal/difflib/difflib.go index 183c892b6..daf8f23a4 100644 --- a/internal/difflib/difflib.go +++ b/internal/difflib/difflib.go @@ -13,7 +13,7 @@ import ( ) // SplitLines splits a string on "\n" while preserving them. The output can be used -// as input for UnifiedDiff and ContextDiff structures. +// as input for the [UnifiedDiff] structure. func SplitLines(s string) []string { lines := strings.SplitAfter(s, "\n") lines[len(lines)-1] += "\n" @@ -50,7 +50,7 @@ func (u *UnifiedDiff) applyWriter(buf *bufio.Writer) { u.wf = u.Formatter(buf) } -// GetUnifiedDiffString is like WriteUnifiedDiff but returns the diff a string. +// GetUnifiedDiffString is like [WriteUnifiedDiff] but returns the diff as a string instead of writing to an [io.Writer]. func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { w := new(bytes.Buffer) err := WriteUnifiedDiff(w, diff) @@ -58,13 +58,15 @@ func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { return w.String(), err } -// WriteUnifiedDiff write the comparison between two sequences of lines. +// WriteUnifiedDiff writes the comparison between two sequences of lines. // It generates the delta as a unified diff. // // Unified diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by 'n' which +// lines of context. The number of context lines is set by 'n' which // defaults to three. // +// # Format +// // By default, the diff control lines (those with ---, +++, or @@) are // created with a trailing newline. This is helpful so that inputs // created from file.readlines() result in diffs that are suitable for @@ -76,6 +78,7 @@ func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { // // The unidiff format normally has a header for filenames and modification // 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// // The modification times are normally expressed in the ISO 8601 format. func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { diff.Options = optionsWithDefaults(diff.Options) diff --git a/internal/difflib/doc.go b/internal/difflib/doc.go index c167103ce..d517daa0b 100644 --- a/internal/difflib/doc.go +++ b/internal/difflib/doc.go @@ -1,22 +1,23 @@ // SPDX-FileCopyrightText: Copyright 2025 go-swagger maintainers // SPDX-License-Identifier: Apache-2.0 -// Package difflib is a partial port of Python difflib module. +// Package difflib is a partial port of [Python difflib module]. // // It provides tools to compare sequences of strings and generate textual diffs. // // The following class and functions have been ported: // -// - SequenceMatcher +// - SequenceMatcher +// - unified_diff // -// - unified_diff +// Getting unified diffs was the main goal of the port. // -// Getting unified diffs was the main goal of the port. Keep in mind this code -// is mostly suitable to output text differences in a human friendly way, there -// are no guarantees generated diffs are consumable by patch(1). +// Keep in mind that this code is mostly suitable to output text differences in a human friendly way, +// there are no guarantees that the generated diffs are consumable by patch(1). // // This package was adopted from [github.com/pmezard/go-difflib] which // is no longer maintained. // // [github.com/pmezard/go-difflib]: https://github.com/pmezard/go-difflib +// [Python difflib module]: https://docs.python.org/3/library/difflib.html#module-difflib package difflib diff --git a/internal/difflib/matcher.go b/internal/difflib/matcher.go index dbc5054aa..c84fb1191 100644 --- a/internal/difflib/matcher.go +++ b/internal/difflib/matcher.go @@ -17,21 +17,24 @@ type OpCode struct { J2 int } -// SequenceMatcher compares sequence of strings. The basic -// algorithm predates, and is a little fancier than, an algorithm -// published in the late 1980's by Ratcliff and Obershelp under the -// hyperbolic name "gestalt pattern matching". The basic idea is to find -// the longest contiguous matching subsequence that contains no "junk" -// elements (R-O doesn't address junk). The same idea is then applied +// SequenceMatcher compares sequence of strings. +// +// The basic algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp (R-O) under the +// hyperbolic name "[gestalt pattern matching]". +// +// The basic idea is to find the longest contiguous matching subsequence that contains +// no "junk" elements (R-O doesn't address junk). The same idea is then applied // recursively to the pieces of the sequences to the left and to the right // of the matching subsequence. This does not yield minimal edit // sequences, but does tend to yield matches that "look right" to people. // -// SequenceMatcher tries to compute a "human-friendly diff" between two -// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// The SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the // longest *contiguous* & junk-free matching subsequence. That's what // catches peoples' eyes. The Windows(tm) windiff has another interesting // notion, pairing up elements that appear uniquely in each sequence. +// // That, and the method here, appear to yield more intuitive difference // reports than does diff. This method appears to be the least vulnerable // to synching up on blocks of "junk lines", though (like blank lines in @@ -43,6 +46,8 @@ type OpCode struct { // case. SequenceMatcher is quadratic time for the worst case and has // expected-case behavior dependent in a complicated way on how many // elements the sequences have in common; best case time is linear. +// +// [gestalt pattern matching]: https://en.wikipedia.org/wiki/Gestalt_pattern_matching type SequenceMatcher struct { a []string b []string @@ -216,10 +221,10 @@ func (m *SequenceMatcher) GetOpCodes() []OpCode { return m.opCodes } -// GetGroupedOpCodes isolates change clusters by eliminating ranges with no changes. +// GetGroupedOpCodes isolates changed clusters by eliminating ranges with no changes. // // Return a generator of groups with up to n lines of context. -// Each group is in the same format as returned by GetOpCodes(). +// Each group is in the same format as returned by [SequenceMatcher.GetOpCodes]. func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { if n < 0 { n = 3 diff --git a/internal/difflib/options.go b/internal/difflib/options.go index 3637b3d74..8b1d5e76c 100644 --- a/internal/difflib/options.go +++ b/internal/difflib/options.go @@ -9,15 +9,22 @@ import ( ) type ( + // Formatter is a formatting function like [fmt.Printf]. Formatter func(format string, args ...any) error - Printer func(string) error + + // Printer outputs a formatted string, e.g. to some underlying writer. + Printer func(string) error ) type ( + // FormatterBuilder is a function that builds a [Formatter] given a bufferized [bufio.Writer]. FormatterBuilder func(*bufio.Writer) Formatter - PrinterBuilder func(*bufio.Writer) Printer + + // PrinterBuilder is a function that builds a [Printer] given a bufferized [bufio.Writer]. + PrinterBuilder func(*bufio.Writer) Printer ) +// Options to fine-tune the rendering of the diff output. type Options struct { EqualPrinter PrinterBuilder DeletePrinter PrinterBuilder diff --git a/internal/spew/README.md b/internal/spew/README.md index 9b41ba7e6..60a2214a5 100644 --- a/internal/spew/README.md +++ b/internal/spew/README.md @@ -1,18 +1,27 @@ # internal/spew -This is an internalized and modernized copy of [github.com/davecgh/go-spew](https://github.com/davecgh/go-spew), a deep pretty printer for Go data structures. +This is an internalized and modernized copy of [github.com/davecgh/go-spew](https://github.com/davecgh/go-spew), +a deep pretty printer for Go data structures. ## Original Source **Source repository:** github.com/davecgh/go-spew + **Original license:** ISC License (see [LICENSE](./LICENSE)) + **Copyright:** 2012-2016 Dave Collins -go-spew implements a deep pretty printer for Go data structures to aid in debugging, providing features like pointer dereferencing, circular reference detection, custom Stringer/error interface handling, and hexdump-style byte array output. +--- + +go-spew implements a deep pretty printer for Go data structures to aid in debugging, +providing features like pointer dereferencing, circular reference detection, +custom Stringer/error interface handling, and hexdump-style byte array output. ## Why Internalized -This fork of testify maintains **zero external dependencies** for the core assertion packages. By internalizing go-spew, we eliminate the external dependency while gaining full control over the code to apply modernizations aligned with our go1.24 target. +This fork of testify maintains **zero external dependencies** for its core assertion packages. +By internalizing go-spew, we eliminate the external dependency while gaining full control over the code +to apply modernizations aligned with our go1.24 target. ## Modernizations Applied @@ -36,7 +45,7 @@ This internalized copy has been modernized from the original go-spew codebase wi ### Documentation -- **Markdown formatting:** Updated documentation comments to use modern markdown headings (`#`) and list formats (`-`) +- **Markdown formatting:** Updated godoc documentation comments to use modern markdown headings (`#`) and list formats (`-`) - **Comment punctuation:** Standardized comment punctuation and formatting - **Clarity improvements:** Fixed typos and improved readability @@ -49,20 +58,21 @@ This internalized copy has been modernized from the original go-spew codebase wi The internalized copy maintains API compatibility with the original while incorporating targeted improvements: - **Deterministic map sorting:** The `SpewKeys` configuration option enables sorted map key output for consistent diffs (relevant for testify's assertion output) + - [x] Additional optimizations for deterministic diff generation (stretchr/testify#1822) - **time.Time rendering:** Enhanced handling of `time.Time` values in nested structures (applied from stretchr/testify#1829) +- **panic/hang** Reinforced input checking to avoid edge cases + - [x] Proper fix for panic on unexported struct keys in maps (stretchr/testify#1816) + - [x] Fix for circular map references (runtime stack overflow) ## Future Enhancements -As an internalized dependency, this copy can receive targeted fixes and improvements that benefit testify's use case: - -- **Planned:** Proper fix for panic on unexported struct keys in maps (stretchr/testify#1816) -- **Planned:** Additional optimizations for deterministic diff generation (stretchr/testify#1822) - -These enhancements would be difficult to incorporate if go-spew remained an external dependency. +The linting effort is still going on... ## Maintenance -This internalized copy is maintained as part of github.com/go-openapi/testify/v2 and follows the same Go version requirements (currently go1.24). It does not track upstream go-spew releases, as it has diverged through modernization. +This internalized copy is maintained as part of github.com/go-openapi/testify/v2 and follows +the same Go version requirements (currently go1.24). +It does not track upstream go-spew releases, as it has diverged through modernization. For issues or improvements specific to this internalized version, please file issues at: https://github.com/go-openapi/testify/issues diff --git a/require/doc.go b/require/doc.go index 41d812ad1..5c6431977 100644 --- a/require/doc.go +++ b/require/doc.go @@ -28,9 +28,10 @@ // A consequence of this is that it must be called from the goroutine running // the test function, not from other goroutines created during the test. // -// Every assertion function also takes an optional string message as the final argument, +// Every assertion function takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. // -// See [our doc site](https://go-openapi.github.io/testify/) for usage and examples and -// [go docs](https://pkg.go/dev/go-openapi/testify) for complete reference. +// See our doc site at https://go-openapi.github.io/testify/ for usage, examples and searchable reference. +// +// See https://pkg.go/dev/go-openapi/testify/ for complete reference. package require diff --git a/require/require_assertions.go b/require/require_assertions.go index 29b406903..9272cfd4c 100644 --- a/require/require_assertions.go +++ b/require/require_assertions.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require @@ -504,7 +504,11 @@ func Eventually(t T, condition func() bool, waitFor time.Duration, tick time.Dur // assertions.EventuallyWithT(t, func(c *assertions.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assertions.True(c, externalValue, "expected 'externalValue' to be true") -// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") +// }, +// 10*time.Second, +// 1*time.Second, +// "external state has not changed to 'true'; still false", +// ) // // # Concurrency // @@ -616,6 +620,8 @@ func False(t T, value bool, msgAndArgs ...any) { // FalseT asserts that the specified value is false. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool @@ -1464,7 +1470,7 @@ func IsNonIncreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice t.FailNow() } -// IsNotOfTypeT asserts that an object is of a given type. +// IsNotOfTypeT asserts that an object is not of a given type. // // # Usage // @@ -1556,7 +1562,7 @@ func IsType(t T, expectedType any, object any, msgAndArgs ...any) { t.FailNow() } -// JSONEq asserts that two JSON strings are equivalent. +// JSONEq asserts that two JSON strings are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -1581,7 +1587,7 @@ func JSONEq(t T, expected string, actual string, msgAndArgs ...any) { t.FailNow() } -// JSONEqBytes asserts that two JSON slices of bytes are equivalent. +// JSONEqBytes asserts that two JSON slices of bytes are semantically equivalent. // // Expected and actual must be valid JSON. // @@ -1606,7 +1612,7 @@ func JSONEqBytes(t T, expected []byte, actual []byte, msgAndArgs ...any) { t.FailNow() } -// JSONEqT asserts that two JSON documents are equivalent. +// JSONEqT asserts that two JSON documents are semantically equivalent. // // The expected and actual arguments may be string or []byte. They do not need to be of the same type. // @@ -1817,6 +1823,8 @@ func LessT[Orderable Ordered](t T, e1 Orderable, e2 Orderable, msgAndArgs ...any // MapContainsT asserts that the specified map contains a key. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.MapContainsT(t, map[string]string{"Hello": "x","World": "y"}, "World") @@ -1827,6 +1835,8 @@ func LessT[Orderable Ordered](t T, e1 Orderable, e2 Orderable, msgAndArgs ...any // failure: map[string]string{"A": "B"}, "C" // // Upon failure, the test [T] is marked as failed and stops execution. +// +// [comparable-types]: https://go.dev/blog/comparable func MapContainsT[Map ~map[K]V, K comparable, V any](t T, m Map, key K, msgAndArgs ...any) { if h, ok := t.(H); ok { h.Helper() @@ -2730,6 +2740,10 @@ func SameT[P any](t T, expected *P, actual *P, msgAndArgs ...any) { // SeqContainsT asserts that the specified iterator contains a comparable element. // +// The sequence may not be consumed entirely: the iteration stops as soon as the specified element is found. +// +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -2740,6 +2754,8 @@ func SameT[P any](t T, expected *P, actual *P, msgAndArgs ...any) { // failure: slices.Values([]string{"A","B"}), "C" // // Upon failure, the test [T] is marked as failed and stops execution. +// +// [comparable-types]: https://go.dev/blog/comparable func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ...any) { if h, ok := t.(H); ok { h.Helper() @@ -2753,6 +2769,8 @@ func SeqContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs ... // SeqNotContainsT asserts that the specified iterator does not contain a comparable element. // +// See [SeqContainsT]. +// // # Usage // // assertions.SeqContainsT(t, slices.Values([]{"Hello","World"}), "World") @@ -2776,6 +2794,8 @@ func SeqNotContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs // SliceContainsT asserts that the specified slice contains a comparable element. // +// Go native comparable types are explained there: [comparable-types]. +// // # Usage // // assertions.SliceContainsT(t, []{"Hello","World"}, "World") @@ -2786,6 +2806,8 @@ func SeqNotContainsT[E comparable](t T, iter iter.Seq[E], element E, msgAndArgs // failure: []string{"A","B"}, "C" // // Upon failure, the test [T] is marked as failed and stops execution. +// +// [comparable-types]: https://go.dev/blog/comparable func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArgs ...any) { if h, ok := t.(H); ok { h.Helper() @@ -2799,6 +2821,8 @@ func SliceContainsT[Slice ~[]E, E comparable](t T, s Slice, element E, msgAndArg // SliceNotContainsT asserts that the specified slice does not contain a comparable element. // +// See [SliceContainsT]. +// // # Usage // // assertions.SliceNotContainsT(t, []{"Hello","World"}, "hi") @@ -2895,7 +2919,7 @@ func SortedT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndA // StringContainsT asserts that a string contains the specified substring. // -// Strings may be go strings or []byte. +// Strings may be go strings or []byte according to the type constraint [Text]. // // # Usage // @@ -2920,7 +2944,7 @@ func StringContainsT[ADoc, EDoc Text](t T, str ADoc, substring EDoc, msgAndArgs // StringNotContainsT asserts that a string does not contain the specified substring. // -// Strings may be go strings or []byte. +// See [StringContainsT]. // // # Usage // @@ -3000,6 +3024,8 @@ func True(t T, value bool, msgAndArgs ...any) { // TrueT asserts that the specified value is true. // +// The type constraint [Boolean] accepts any type which underlying type is bool. +// // # Usage // // type B bool diff --git a/require/require_assertions_test.go b/require/require_assertions_test.go index e1131dfe1..1468f1e73 100644 --- a/require/require_assertions_test.go +++ b/require/require_assertions_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_examples_test.go b/require/require_examples_test.go index b7a05e951..e005cddd1 100644 --- a/require/require_examples_test.go +++ b/require/require_examples_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require_test diff --git a/require/require_format.go b/require/require_format.go index 599b841a4..725c7b742 100644 --- a/require/require_format.go +++ b/require/require_format.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_format_test.go b/require/require_format_test.go index 1dec8d3ef..01f4d01c2 100644 --- a/require/require_format_test.go +++ b/require/require_format_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_forward.go b/require/require_forward.go index dcb82c5da..b5febedb2 100644 --- a/require/require_forward.go +++ b/require/require_forward.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_forward_test.go b/require/require_forward_test.go index ed916f820..f5bd6a4e3 100644 --- a/require/require_forward_test.go +++ b/require/require_forward_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_helpers.go b/require/require_helpers.go index 69b484302..3c1f793d5 100644 --- a/require/require_helpers.go +++ b/require/require_helpers.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_helpers_test.go b/require/require_helpers_test.go index 0dbec8f93..e7d023a38 100644 --- a/require/require_helpers_test.go +++ b/require/require_helpers_test.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require diff --git a/require/require_types.go b/require/require_types.go index 7b7862bbf..def97aa54 100644 --- a/require/require_types.go +++ b/require/require_types.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Code generated with github.com/go-openapi/testify/codegen/v2; DO NOT EDIT. -// Generated on 2026-01-26 (version cbd4c16) using codegen version v2.2.1-0.20260126160846-43574c83eea9+dirty [sha: 43574c83eea9c46dc5bb573128a4038e90e2f44b] +// Generated on 2026-01-27 (version 98658ef) using codegen version v2.2.1-0.20260127181549-98658ef85ebb [sha: 98658ef85ebb5f0990ed1c8408af6defef6c6d5c] package require