{"id":15787073,"url":"https://github.com/tkrop/go-testing","last_synced_at":"2025-10-16T02:31:54.156Z","repository":{"id":63711360,"uuid":"550714108","full_name":"tkrop/go-testing","owner":"tkrop","description":"An opinionated framework for writing effective unit and component tests.","archived":false,"fork":false,"pushed_at":"2024-10-20T22:38:48.000Z","size":414,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-21T02:30:16.464Z","etag":null,"topics":["mocking","parameterized-tests","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tkrop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-13T07:55:22.000Z","updated_at":"2024-10-20T22:38:50.000Z","dependencies_parsed_at":"2024-03-06T15:44:16.131Z","dependency_job_id":"ff2ae4d4-9299-414d-92de-cdcaa3b7af12","html_url":"https://github.com/tkrop/go-testing","commit_stats":{"total_commits":99,"total_committers":2,"mean_commits":49.5,"dds":0.02020202020202022,"last_synced_commit":"9f2193c565be92d28087a42b6926b6dde06c2e14"},"previous_names":["tkrop/testing"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrop%2Fgo-testing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrop%2Fgo-testing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrop%2Fgo-testing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrop%2Fgo-testing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkrop","download_url":"https://codeload.github.com/tkrop/go-testing/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243569582,"owners_count":20312461,"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":["mocking","parameterized-tests","testing"],"created_at":"2024-10-04T21:05:05.665Z","updated_at":"2025-10-16T02:31:54.150Z","avatar_url":"https://github.com/tkrop.png","language":"Go","funding_links":[],"categories":["Template Engines","Testing"],"sub_categories":["Testing Frameworks"],"readme":"# Testing framework\n\n[![Build][build-badge]][build-link]\n[![Coverage][coveralls-badge]][coveralls-link]\n[![Coverage][coverage-badge]][coverage-link]\n[![Quality][quality-badge]][quality-link]\n[![Report][report-badge]][report-link]\n[![FOSSA][fossa-badge]][fossa-link]\n[![License][license-badge]][license-link]\n[![Docs][docs-badge]][docs-link]\n\u003c!--\n[![Libraries][libs-badge]][libs-link]\n[![Security][security-badge]][security-link]\n--\u003e\n\n[build-badge]: https://github.com/tkrop/go-testing/actions/workflows/build.yaml/badge.svg\n[build-link]: https://github.com/tkrop/go-testing/actions/workflows/build.yaml\n\n[coveralls-badge]: https://coveralls.io/repos/github/tkrop/go-testing/badge.svg?branch=main\n[coveralls-link]: https://coveralls.io/github/tkrop/go-testing?branch=main\n\n[coverage-badge]: https://app.codacy.com/project/badge/Coverage/cc1c47ec5ce0493caf15c08fa72fc78c\n[coverage-link]: https://app.codacy.com/gh/tkrop/go-testing/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_coverage\n\n[quality-badge]: https://app.codacy.com/project/badge/Grade/cc1c47ec5ce0493caf15c08fa72fc78c\n[quality-link]: https://app.codacy.com/gh/tkrop/go-testing/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade\n\n[report-badge]: https://goreportcard.com/badge/github.com/tkrop/go-testing\n[report-link]: https://goreportcard.com/report/github.com/tkrop/go-testing\n\n[fossa-badge]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftkrop%2Ftesting.svg?type=shield\u0026issueType=license\n[fossa-link]: https://app.fossa.com/projects/git%2Bgithub.com%2Ftkrop%2Ftesting?ref=badge_shield\u0026issueType=license\n\n[license-badge]: https://img.shields.io/badge/License-MIT-yellow.svg\n[license-link]: https://opensource.org/licenses/MIT\n\n[docs-badge]: https://pkg.go.dev/badge/github.com/tkrop/go-testing.svg\n[docs-link]: https://pkg.go.dev/github.com/tkrop/go-testing\n\n\u003c!--\n[libs-badge]: https://img.shields.io/librariesio/release/github/tkrop/go-testing\n[libs-link]: https://libraries.io/github/tkrop/go-testing\n\n[security-badge]: https://snyk.io/test/github/tkrop/go-testing/main/badge.svg\n[security-link]: https://snyk.io/test/github/tkrop/go-testing\n--\u003e\n\n## Introduction\n\nGoal of the `testing` framework is to provide simple and efficient tools to for\nwriting effective unit, component, and integration tests in [`go`][go].\n\nTo accomplish this, the `testing` framework provides a couple of extensions for\n[`go`][go]'s [`testing`][testing] package that support a simple setup of\nstrongly isolated and parallel running unit test using [`gomock`][gomock] and/or\n[`gock`][gock] that work under various failure scenarios, e.g. panics, and even\nin the presence of spawned [`go`-routines][go-routines].\n\n[go-routines]: \u003chttps://go.dev/tour/concurrency\u003e\n\n\n### Example Usage\n\nThe core idea of the [`mock`](mock)/[`gock`](gock) packages is to provide a\nshort pragmatic domain language for defining mock requests with responses that\nenforce validation, while the [`test`](test) package provides the building\nblocks for test isolation.\n\n```go\ntype UnitParams struct {\n    mockSetup    mock.SetupFunc\n    input*...    *model.*\n    expect       test.Expect\n    expect*...   *model.*\n    expectError  error\n}\n\nvar testUnitParams = map[string]UnitParams {\n    \"success\" {\n        mockSetup: mock.Chain(\n            CallMockA(input..., output...),\n            ...\n            test.Panic(\"failure message\"),\n       ),\n        ...\n        expect: test.ExpectSuccess\n    }\n}\n\nfunc TestUnit(t *testing.T) {\n    test.Map(t, testParams).\n        Timeout(50 * time.Millisecond)\n        Run(func(t test.Test, param UnitParams){\n\n        // Given\n        mocks := mock.NewMock(t).\n            SetArg(\"common-arg\", local.input*)...\n            Expect(param.mockSetup)\n\n        unit := NewUnitService(\n            mock.Get(mocks, NewServiceMock),\n            ...\n        )\n\n        // When\n        result, err := unit.call(param.input*...)\n\n        mocks.Wait()\n\n        // Then\n        if param.expectError != nil {\n            assert.Equal(t, param.expectError, err)\n        } else {\n            require.NoError(t, err)\n        }\n        assert.Equal(t, param.expect*, result)\n    })\n}\n```\n\nThis opinionated test pattern supports a wide range of test in a standardized\nway. For variations have a closer look at the [test](test) package.\n\n\n### Why parameterized test?\n\nParameterized test are an effective way to set up a systematic set of test\ncases covering a system under test in a black box mode. With the right tools\nand concepts — as provided by this `testing` framework, parameterized test\nallow to cover all success and failure paths of a system under test.\n\n\n### Why parallel tests?\n\nRunning tests in parallel make the feedback loop on failures faster, help to\ndetect failures from concurrent access and race conditions using `go test\n-race`, that else only appear randomly in production, and foster a design with\nclear responsibilities. This side-effects compensate for the small additional\neffort needed to write parallel tests.\n\n\n### Why isolation of tests?\n\nTest isolation is a precondition to have stable running test — especially run\nin parallel. Isolation must happen from input perspective, i.e. the outcome of\na test must not be affected by any previous running test, but also from output\nperspective, i.e. it must not affect any later running test. This is often\ncomplicated since many tools, patterns, and practices break the test isolation\n(see [requirements for parallel isolated\ntests](#requirements-for-parallel-isolated-tests).\n\n\n### Why strong validation?\n\nTest are only meaningful, if they ensure/validate pre-conditions as well as\nvalidate/ensure post-conditions sufficiently strict. Without validation test\ncannot ensure that the system under test behaves as expected — even with 100%\ncode and branch coverage. As a consequence, a system may fail in unexpected\nways in production.\n\nThus, it is advised to validate input parameters for mocked requests and to\ncarefully define the order of mock requests and responses. The [`mock`](mock)\nframework makes this approach as simple as possible, but it is still the\nresponsibility of the test developer to set up the validation correctly.\n\n\n## Framework structure\n\nThe `testing` framework consists of the following sub-packages:\n\n* [`test`](test) provides a small framework to isolate the test execution and\n  safely check whether a test fails or succeeds as expected in combination with\n  the [`mock`](mock) package — even if a system under test spans detached\n  [`go`-routines][go-routines].\n\n* [`mock`](mock) provides the means to set up a simple chain as well as a\n  complex network of expected mock calls with minimal effort. This makes it\n  easy to extend the usual narrow range of mocking to larger components using\n  a unified test pattern.\n\n* [`gock`](gock) provides a drop-in extension for the [Gock][gock] package\n  consisting of a controller and a mock storage that allows running tests\n  isolated. This allows parallelizing simple test as well as parameterized\n  tests.\n\n* [`perm`](perm) provides a small framework to simplify permutation tests, i.e.\n  a consistent test set where conditions can be checked in all known orders\n  with different outcome. This was very handy in combination with [`test`](test)\n  for validating the [`mock`](mock) framework, but may be useful in other cases\n  too.\n\nPlease see the documentation of the sub-packages for more details.\n\n\n## Requirements for parallel isolated tests\n\nRunning tests in parallel makes test not only faster, but also helps to detect\nrace conditions that else randomly appear in production, when running tests\nwith `go test -race`.\n\n**Note:** there are some general requirements for running test in parallel:\n\n1. Tests *must not modify* environment variables dynamically — utilize test\n   specific configuration instead.\n2. Tests *must not require* reserved service ports and open listeners — setup\n   services to acquire dynamic ports instead.\n3. Tests *must not share* files, folder and pipelines, e.g. `stdin`, `stdout`,\n   or `stderr` — implement logic by using wrappers that can be redirected and\n   mocked.\n4. Tests *must not share* database schemas or tables, that are updated during\n   execution of parallel tests — implement test to set up test specific database\n   schemas.\n5. Tests *must not share* process resources, that are update during execution\n   of parallel tests. Many frameworks make use of common global resources that\n   make them unsuitable for parallel tests.\n\nExamples for such shared resources in common frameworks are:\n\n* Using of [monkey patching][monkey] to modify commonly used global functions,\n  e.g. `time.Now()` — implement access to these global functions using lambdas\n  and interfaces to allow for mocking.\n* Using of [`gock`][gock] to mock HTTP responses on transport level — make use\n  of the [`gock`](gock)-controller provided by this framework.\n* Using the [Gin][gin] HTTP web framework which uses a common `json`-parser\n  setup instead of a service specific configuration. While this is not a huge\n  deal, the repeated global setup creates race alerts. Instead, use\n  [`chi`][chi] that supports a service specific configuration.\n\nWith a careful system design, the general pattern provided above can be used\nto create parallel test for a wide range of situations.\n\n\n## Building\n\nThis project is using a custom build system called [go-make][go-make], that\nprovides default targets for most common tasks. Makefile rules are generated\nbased on the project structure and files for common tasks, to initialize,\nbuild, test, and run the components in this repository.\n\nTo get started, run one of the following commands.\n\n```bash\nmake help\nmake show-targets\n```\n\nRead the [go-make manual][go-make-man] for more information about targets\nand configuration options.\n\n**Not:** [go-make][go-make] installs `pre-commit` and `commit-msg`\n[hooks][git-hooks] calling `make commit` to enforce successful testing and\nlinting and `make git-verify message` to validate whether the commit message\nis following the [conventional commit][convent-commit] best practice.\n\n[go-make]: \u003chttps://github.com/tkrop/go-make\u003e\n[go-make-man]: \u003chttps://github.com/tkrop/go-make/blob/main/MANUAL.md\u003e\n[git-hooks]: \u003chttps://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks\u003e\n[convent-commit]: \u003chttps://www.conventionalcommits.org/en/v1.0.0/\u003e\n\n\n## Terms of Usage\n\nThis software is open source under the MIT license. You can use it without\nrestrictions and liabilities. Please give it a star, so that I know. If the\nproject has more than 25 Stars, I will introduce semantic versions `v1`.\n\n\n## Contributing\n\nIf you like to contribute, please create an issue and/or pull request with a\nproper description of your proposal or contribution. I will review it and\nprovide feedback on it as fast as possible.\n\n\n[testing]: \u003chttps://pkg.go.dev/testing\u003e\n[gomock]: \u003chttps://go.uber.org/mock\u003e\n[gock]: \u003chttps://github.com/h2non/gock\u003e\n[monkey]: \u003chttps://github.com/bouk/monkey\u003e\n[gin]: \u003chttps://github.com/gin-gonic/gin\u003e\n[chi]: \u003chttps://github.com/go-chi/chi\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkrop%2Fgo-testing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkrop%2Fgo-testing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkrop%2Fgo-testing/lists"}