{"id":13630236,"url":"https://github.com/flyingmutant/rapid","last_synced_at":"2025-04-12T18:50:01.135Z","repository":{"id":46153252,"uuid":"164488254","full_name":"flyingmutant/rapid","owner":"flyingmutant","description":"Rapid is a modern Go property-based testing library","archived":false,"fork":false,"pushed_at":"2024-08-15T22:02:33.000Z","size":430,"stargazers_count":588,"open_issues_count":13,"forks_count":25,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-29T22:12:17.234Z","etag":null,"topics":["fuzzing","golang","property-based-testing","property-testing","quickcheck","testing"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/pgregory.net/rapid","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flyingmutant.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-07T20:14:06.000Z","updated_at":"2024-10-27T20:27:38.000Z","dependencies_parsed_at":"2023-02-08T07:01:44.858Z","dependency_job_id":"6d3d6844-53b3-4b23-8bd9-97bd87659d97","html_url":"https://github.com/flyingmutant/rapid","commit_stats":{"total_commits":393,"total_committers":5,"mean_commits":78.6,"dds":"0.15267175572519087","last_synced_commit":"654675a3db07cfcdfbfd0bfc083a88cb6c061504"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyingmutant%2Frapid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyingmutant%2Frapid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyingmutant%2Frapid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyingmutant%2Frapid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flyingmutant","download_url":"https://codeload.github.com/flyingmutant/rapid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247070928,"owners_count":20878586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fuzzing","golang","property-based-testing","property-testing","quickcheck","testing"],"created_at":"2024-08-01T22:01:35.124Z","updated_at":"2025-04-03T20:13:22.140Z","avatar_url":"https://github.com/flyingmutant.png","language":"Go","readme":"# rapid [![PkgGoDev][godev-img]][godev] [![CI][ci-img]][ci]\n\nRapid is a Go library for property-based testing.\n\nRapid checks that properties you define hold for a large number\nof automatically generated test cases. If a failure is found, rapid\nautomatically minimizes the failing test case before presenting it.\n\n## Features\n\n- Imperative Go API with type-safe data generation using generics\n- Data generation biased to explore \"small\" values and edge cases more thoroughly\n- Fully automatic minimization of failing test cases\n- Persistence and automatic re-running of minimized failing test cases\n- Support for state machine (\"stateful\" or \"model-based\") testing\n- No dependencies outside the Go standard library\n\n## Examples\n\nHere is what a trivial test using rapid looks like ([playground](https://go.dev/play/p/QJhOzo_BByz)):\n\n```go\npackage rapid_test\n\nimport (\n\t\"sort\"\n\t\"testing\"\n\n\t\"pgregory.net/rapid\"\n)\n\nfunc TestSortStrings(t *testing.T) {\n\trapid.Check(t, func(t *rapid.T) {\n\t\ts := rapid.SliceOf(rapid.String()).Draw(t, \"s\")\n\t\tsort.Strings(s)\n\t\tif !sort.StringsAreSorted(s) {\n\t\t\tt.Fatalf(\"unsorted after sort: %v\", s)\n\t\t}\n\t})\n}\n```\n\nMore complete examples:\n\n- `ParseDate` function test:\n  [source code](./example_function_test.go), [playground](https://go.dev/play/p/tZFU8zv8AUl)\n- `Queue` state machine test:\n  [source code](./example_statemachine_test.go), [playground](https://go.dev/play/p/cxEh4deG-4n)\n\n## Comparison\n\nRapid aims to bring to Go the power and convenience\n[Hypothesis](https://github.com/HypothesisWorks/hypothesis) brings to Python.\n\nCompared to [testing.F.Fuzz](https://pkg.go.dev/testing#F.Fuzz), rapid shines\nin generating complex structured data, including state machine tests, but lacks\ncoverage-guided feedback and mutations. Note that with\n[`MakeFuzz`](https://pkg.go.dev/pgregory.net/rapid#MakeFuzz), any rapid test\ncan be used as a fuzz target for the standard fuzzer.\n\nCompared to [gopter](https://pkg.go.dev/github.com/leanovate/gopter), rapid\nprovides a much simpler API (queue test in [rapid](./example_statemachine_test.go) vs\n[gopter](https://github.com/leanovate/gopter/blob/90cc76d7f1b21637b4b912a7c19dea3efe145bb2/commands/example_circularqueue_test.go)),\nis much smarter about data generation and is able to minimize failing test cases\nfully automatically, without any user code.\n\nAs for [testing/quick](https://pkg.go.dev/testing/quick), it lacks both\nconvenient data generation facilities and any form of test case minimization, which\nare two main things to look for in a property-based testing library.\n\n## FAQ\n\n### What is property-based testing?\n\nSuppose we've written arithmetic functions `add`, `subtract` and `multiply`\nand want to test them. Traditional testing approach is example-based —\nwe come up with example inputs and outputs, and verify that the system behavior\nmatches the examples:\n\n```go\nfunc TestArithmetic_Example(t *testing.T) {\n\tt.Run(\"add\", func(t *testing.T) {\n\t\texamples := [][3]int{\n\t\t\t{0, 0, 0},\n\t\t\t{0, 1, 1},\n\t\t\t{2, 2, 4},\n\t\t\t// ...\n\t\t}\n\t\tfor _, e := range examples {\n\t\t\tif add(e[0], e[1]) != e[2] {\n\t\t\t\tt.Fatalf(\"add(%v, %v) != %v\", e[0], e[1], e[2])\n\t\t\t}\n\t\t}\n\t})\n\tt.Run(\"subtract\", func(t *testing.T) { /* ... */ })\n\tt.Run(\"multiply\", func(t *testing.T) { /* ... */ })\n}\n```\n\nIn comparison, with property-based testing we define higher-level properties\nthat should hold for arbitrary input. Each time we run a property-based test,\nproperties are checked on a new set of pseudo-random data:\n\n```go\nfunc TestArithmetic_Property(t *testing.T) {\n\trapid.Check(t, func(t *rapid.T) {\n\t\tvar (\n\t\t\ta = rapid.Int().Draw(t, \"a\")\n\t\t\tb = rapid.Int().Draw(t, \"b\")\n\t\t\tc = rapid.Int().Draw(t, \"c\")\n\t\t)\n\t\tif add(a, 0) != a {\n\t\t\tt.Fatalf(\"add() does not have 0 as identity\")\n\t\t}\n\t\tif add(a, b) != add(b, a) {\n\t\t\tt.Fatalf(\"add() is not commutative\")\n\t\t}\n\t\tif add(a, add(b, c)) != add(add(a, b), c) {\n\t\t\tt.Fatalf(\"add() is not associative\")\n\t\t}\n\t\tif multiply(a, add(b, c)) != add(multiply(a, b), multiply(a, c)) {\n\t\t\tt.Fatalf(\"multiply() is not distributive over add()\")\n\t\t}\n\t\t// ...\n\t})\n}\n```\n\nProperty-based tests are more powerful and concise than example-based ones —\nand are also much more fun to write. As an additional benefit, coming up with\ngeneral properties of the system often improves the design of the system itself.\n\n### What properties should I test?\n\nAs you've seen from the examples above, it depends on the system you are testing.\nUsually a good place to start is to put yourself in the shoes of your user\nand ask what are the properties the user will rely on (often unknowingly or\nimplicitly) when building on top of your system. That said, here are some\nbroadly applicable and often encountered properties to keep in mind:\n\n- function does not panic on valid input data\n- behavior of two algorithms or data structures is identical\n- all variants of the  `decode(encode(x)) == x` roundtrip\n\n### How does rapid work?\n\nAt its core, rapid does a fairly simple thing: generates pseudo-random data\nbased on the specification you provide, and check properties that you define\non the generated data.\n\nChecking is easy: you simply write `if` statements and call something like\n`t.Fatalf` when things look wrong.\n\nGenerating is a bit more involved. When you construct a `Generator`, nothing\nhappens: `Generator` is just a specification of how to `Draw` the data you\nwant. When you call `Draw`, rapid will take some bytes from its internal\nrandom bitstream, use them to construct the value based on the `Generator`\nspecification, and track how the random bytes used correspond to the value\n(and its subparts). This knowledge about the structure of the values being\ngenerated, as well as their relationship with the parts of the bitstream\nallows rapid to intelligently and automatically minify any failure found.\n\n### What about fuzzing?\n\nProperty-based testing focuses on quick feedback loop: checking the properties\non a small but diverse set of pseudo-random inputs in a fractions of a second.\n\nIn comparison, fuzzing focuses on slow, often multi-day, brute force input\ngeneration that maximizes the coverage.\n\nBoth approaches are useful. Property-based tests are used alongside regular\nexample-based tests during development, and fuzzing is used to search for edge\ncases and security vulnerabilities. With\n[`MakeFuzz`](https://pkg.go.dev/pgregory.net/rapid#MakeFuzz), any rapid test\ncan be used as a fuzz target.\n\n## Usage\n\nJust run `go test` as usual, it will pick up also all `rapid` tests.\n\nThere are a number of optional flags to influence rapid behavior, run\n`go test -args -h` and look at the flags with the `-rapid.` prefix. You can\nthen pass such flags as usual. For example:\n\n```sh\ngo test -rapid.checks=10_000\n```\n\n## Status\n\nRapid is stable: tests using rapid should continue to work with all future\nrapid releases with the same major version. Possible exceptions to this rule\nare API changes that replace the concrete type of parameter with an interface\ntype, or other similar mostly non-breaking changes.\n\n## License\n\nRapid is licensed under the [Mozilla Public License Version 2.0](./LICENSE).\n\n[godev-img]: https://pkg.go.dev/badge/pgregory.net/rapid\n[godev]: https://pkg.go.dev/pgregory.net/rapid\n[ci-img]: https://github.com/flyingmutant/rapid/workflows/CI/badge.svg\n[ci]: https://github.com/flyingmutant/rapid/actions\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyingmutant%2Frapid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflyingmutant%2Frapid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyingmutant%2Frapid/lists"}