{"id":37098905,"url":"https://github.com/go-tstr/tstr","last_synced_at":"2026-01-14T12:01:38.638Z","repository":{"id":263192021,"uuid":"889033632","full_name":"go-tstr/tstr","owner":"go-tstr","description":"Go testing library","archived":false,"fork":false,"pushed_at":"2025-11-07T07:52:25.000Z","size":619,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-07T09:21:52.665Z","etag":null,"topics":["coverage","go","golang","testing","testing-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-tstr.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-15T13:34:56.000Z","updated_at":"2025-11-07T07:51:36.000Z","dependencies_parsed_at":"2025-01-01T18:29:21.378Z","dependency_job_id":"9689ffe5-6274-46bb-96ea-538cb79b1be4","html_url":"https://github.com/go-tstr/tstr","commit_stats":null,"previous_names":["go-tstr/tstr"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/go-tstr/tstr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-tstr%2Ftstr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-tstr%2Ftstr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-tstr%2Ftstr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-tstr%2Ftstr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-tstr","download_url":"https://codeload.github.com/go-tstr/tstr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-tstr%2Ftstr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coverage","go","golang","testing","testing-tools"],"created_at":"2026-01-14T12:01:37.986Z","updated_at":"2026-01-14T12:01:38.632Z","avatar_url":"https://github.com/go-tstr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/go-tstr/tstr.svg)](https://pkg.go.dev/github.com/go-tstr/tstr) [![codecov](https://codecov.io/github/go-tstr/tstr/graph/badge.svg?token=H3u7Ui9PfC)](https://codecov.io/github/go-tstr/tstr) ![main](https://github.com/go-tstr/tstr/actions/workflows/go.yaml/badge.svg?branch=main)\n\n# tstr: your ultimate testing library\n\ntstr allows you to write application, integration and black-box tests like normal unit tests in Go.\n\nWith tstr you can easily declare the test dependencies like:\n\n- compose files\n- single containers\n- cli commands\n- main package of Go program\n\nand let tstr take care of the rest.\n\n## Table of Contents\n\n- [Usage](#usage)\n  - [tstr.Tester](#tstrtester)\n  - [tstr.RunMain](#tstrrunmain)\n  - [tstr.Run](#tstrrun)\n    - [tstr.WithFn](#tstrwithfn)\n    - [tstr.WithTable](#tstrwithtable)\n  - [tstr.Dependency](#tstrdependency)\n  - [Compose](#compose)\n  - [Container](#container)\n  - [Cmd](#cmd)\n  - [Custom Dependencies](#custom-dependencies)\n\n## Usage\n\nThis library is build on top of two concepts:\n\n- tstr.Tester\n- tstr.Dependency\n\n### tstr.Tester\n\nThere's two common ways to use tester, either from `func TestMain` or from `func TestXXX`. For both of these approaches there's helper function; `tstr.RunMain` and `tstr.Run`, which make it easy to setup and run `tstr.Tester`.\n\n#### tstr.RunMain\n\n```go\nfunc TestMain(m *testing.M) {\n    tstr.RunMain(m, tstr.WithDeps(\n    // Pass test dependencies here.\n    ))\n}\n```\n\nWith `TestMain` approach you will have single test env within the packge.\n`tstr.RunMain` will setup the test env you defined, call `m.Run()`, cleanup test env and finally call `os.Exit` with returned exit code.\n\n#### tstr.Run\n\nThis approach allows more granular control over test env. For example you can have single test env for each top level test. This can be usefull when you want to avoid any side effects and shared state between tests. Also this approach allows more advaced usage like creating a pool of test envs for parallel testing.\n\n##### tstr.WithFn\n\nSimplest way to use `tstr.Run` is with the `tstr.WithFn` option:\n\n```go\nfunc TestMyFunc(t *testing.T) {\n    err := tstr.Run(\n        tstr.WithDeps(\n        // Pass test dependencies here.\n        ),\n        tstr.WithFn(func() {\n            const (\n                input    = 1\n                expected = 1\n            )\n            got := MyFunc(input)\n            assert.Equal(t, expected, got)\n        }),\n    )\n    require.NoError(t, err)\n}\n```\n\n##### tstr.WithTable\n\nFor table driven tests you can use `tstr.WithTable` which loops over the given test table and executes test function for each element using `t.Run`:\n\n```go\nfunc TestMyFunc(t *testing.T) {\n    type test struct {\n        Name     string\n        input    int\n        expected int\n    }\n\n    tests := []test{\n        {Name: \"test-1\", input: 1, expected: 1},\n        {Name: \"test-2\", input: 2, expected: 2},\n        {Name: \"test-3\", input: 3, expected: 3},\n    }\n\n    err := tstr.Run(\n        tstr.WithDeps(\n        // Add dependencies here.\n        ),\n        tstr.WithTable(t, tests, func(t *testing.T, tt test) {\n            got := MyFunc(tt.input)\n            assert.Equal(t, tt.expected, got)\n        }),\n    )\n    require.NoError(t, err)\n}\n```\n\n### tstr.Dependency\n\n`tstr.Dependency` declares an interface for test dependency which can be then controlled by `tstr.Tester`. This repo provides the most commonly used dependecies that user can use within their tests. Since `tstr.Dependency` is just an interface users can also implement their own custom dependencies.\n\n#### Compose\n\nCompose dependecy allows you to define and manage Docker Compose stacks as test dependencies. You can create a Compose stack from projects compose file and control its lifecycle within your tests.\n\n```go\nfunc TestMain(m *testing.M) {\n    tstr.RunMain(m, tstr.WithDeps(\n        compose.New(\n            compose.WithFile(\"../docker-compose.yaml\"),\n            compose.WithUpOptions(tc.Wait(true)),\n            compose.WithDownOptions(tc.RemoveVolumes(true)),\n            compose.WithEnv(map[string]string{\"DB_PORT\": \"5432\"}),\n            compose.WithWaitForService(\"postgres\", wait.ForLog(\"ready to accept connections\")),\n        ),\n    ))\n}\n```\n\n#### Container\n\nContainer dependecy allows you to define and manage single containers as test dependencies. You can use predefined modules from testcontainer-go or create generic container.\n\n```go\nfunc TestMain(m *testing.M) {\n    tstr.RunMain(m, tstr.WithDeps(\n        container.New(\n            container.WithModule(postgres.Run, \"postgres:16-alpine\",\n                postgres.WithDatabase(\"test\"),\n                postgres.WithUsername(\"user\"),\n                postgres.WithPassword(\"password\"),\n            ),\n        ),\n    ))\n}\n```\n\n#### Cmd\n\nCmd dependecy is the most versatile dependency. It can be used for running any binary or even compiling a Go application and running it as dependency.\n\n##### cmd.WithCommand\n\n`cmd.WithCommand` allows using binaries from\n\n```go\nfunc TestMain(m *testing.M) {\n    tstr.RunMain(m, tstr.WithDeps(\n        cmd.New(\n            cmd.WithCommand(\"my-app\", \"--listen\", \":8080\"),\n            cmd.WithWaitMatchingLine(\"Server ready\"),\n        ),\n    ))\n}\n```\n\n##### cmd.WithGoCode\n\nThis example compiles `my-app` Go application, instruments it for coverage collections, waits for it to be ready and finally starts running tests.\n\n```go\nfunc TestMain(m *testing.M) {\n    tstr.RunMain(m, tstr.WithDeps(\n        cmd.New(\n            cmd.WithGoCode(\"../\", \"./cmd/my-app\"),\n            cmd.WithReadyHTTP(\"http://localhost:8080/ready\"),\n            cmd.WithEnvAppend(\"GOCOVERDIR=./cover\"),\n        ),\n    ))\n}\n```\n\n#### Custom Dependencies\n\nYou can also create your own custom dependencies by implementing the `tstr.Dependency` interface.\n\n```go\ntype Custom struct{}\n\nfunc New() *Custom {\n    return \u0026Custom{}\n}\n\nfunc (c *Custom) Start() error { return nil }\n\nfunc (c *Custom) Ready() error { return nil }\n\nfunc (c *Custom) Stop() error { return nil }\n```\n\n## Acknowledgements\n\nThis library is based on the work originally done as part of (https://github.com/elisasre/go-common)[https://github.com/elisasre/go-common] and was extracted to it's own repo to be more approachable by users.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-tstr%2Ftstr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-tstr%2Ftstr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-tstr%2Ftstr/lists"}