{"id":37123352,"url":"https://github.com/ecoshub/taste","last_synced_at":"2026-01-14T14:14:46.601Z","repository":{"id":62865192,"uuid":"541751730","full_name":"ecoshub/taste","owner":"ecoshub","description":"easy to use table driven testing package","archived":false,"fork":false,"pushed_at":"2024-03-02T21:47:35.000Z","size":75,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-20T06:31:14.545Z","etag":null,"topics":["golang","http","http-test","testing","unit-test"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ecoshub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2022-09-26T19:30:13.000Z","updated_at":"2023-10-08T11:56:32.000Z","dependencies_parsed_at":"2024-03-02T22:43:16.162Z","dependency_job_id":null,"html_url":"https://github.com/ecoshub/taste","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/ecoshub/taste","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecoshub%2Ftaste","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecoshub%2Ftaste/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecoshub%2Ftaste/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecoshub%2Ftaste/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ecoshub","download_url":"https://codeload.github.com/ecoshub/taste/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecoshub%2Ftaste/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28422433,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["golang","http","http-test","testing","unit-test"],"created_at":"2026-01-14T14:14:44.787Z","updated_at":"2026-01-14T14:14:46.588Z","avatar_url":"https://github.com/ecoshub.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Taste\n*A taste of simplicity.*\n\ntaste is a simple (but powerful) table driven testing tool.\n\n## Capabilities:\n\n- HTTP Server Testing: \n\nIt allows you to define a scenario of HTTP requests and expected responses, and will run the scenario and perform assertions to ensure that the server is behaving as expected. Additionally, you can chain the responses from previous requests to use in subsequent requests.\n\n- Unit testing:\n\n It offers to define and execute tests, as well as to validate expected outcomes. Its flexible and straightforward design makes writing and managing unit tests easier. It allows table-driven testing to execute multiple tests in a single function through a slice of structs.\n\n\n## HTTP Testing utils\n\n### JSON body Validation with scheme\n\n- The validation is done against a JSON validation scheme, which specifies the expected structure and content of the data.\n\n- The validation scheme uses a specific syntax to specify the structure and content of a JSON object. The syntax is `\"field_name|type\": \"value\"`, where field_name is the name of the field, type is the data type of the field, and value is the expected value of the field. example: `{\"name|string\":\"taste\"}`\n\n- The validation scheme supports wildcards, which can be used to match any value or data type. The wildcard is denoted by asterisk (`*`).\n\n- The validate function returns an error if the data does not match the scheme, and returns nil if the data matches the scheme.\n\n### Double bracket notation\n\nDouble angle bracket notation (e.g. \u003c\u003ctest_1.random\u003e\u003e) is used to reference the value of a field in a previous HTTP response.\n\nThis allows you to reuse values from previous responses in subsequent requests, which can be useful for testing scenarios where the server relies on data from previous requests.\n\n\n## Example (HTTP Testing):\n\n```go\npackage server_test\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/ecoshub/taste/server\"\n\t\"github.com/ecoshub/taste/utils\"\n)\n\nvar (\n\tscenario = []*server.Case{\n\t\t{\n\t\t\tStoreResponse: true,\n\t\t\tName:          \"test_1\",\n\t\t\tRequest: \u0026server.Request{\n\t\t\t\tMethod:     http.MethodGet,\n\t\t\t\tRequestURI: \"/api/v1/random\",\n\t\t\t},\n\t\t\tResponse: \u0026server.Response{\n\t\t\t\tStatus: http.StatusOK,\n\t\t\t\tBody:   []byte(`{\"random|string\":\"*\"}`),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tStoreResponse: true,\n\t\t\tName:          \"test_2\",\n\t\t\tRequest: \u0026server.Request{\n\t\t\t\tMethod:     http.MethodGet,\n\t\t\t\tRequestURI: \"/api/v1/echo\",\n\t\t\t\tBody:       []byte(`{\"id\":\"\u003c\u003ctest_1.random\u003e\u003e\",\"name\":\"eco\"}`),\n\t\t\t},\n\t\t\tResponse: \u0026server.Response{\n\t\t\t\tStatus: http.StatusOK,\n\t\t\t\tBody:   []byte(`{\"id\":\"\u003c\u003ctest_1.random\u003e\u003e\",\"name\":\"eco\"}`),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tStoreResponse: true,\n\t\t\tName:          \"test_3\",\n\t\t\tRequest: \u0026server.Request{\n\t\t\t\tMethod:     http.MethodGet,\n\t\t\t\tRequestURI: \"/api/v1/echo\",\n\t\t\t\tBody:       []byte(`{\"id\":\"\u003c\u003ctest_1.random\u003e\u003e\",\"name\":\"\u003c\u003ctest_2.name\u003e\u003e\"}`),\n\t\t\t},\n\t\t\tResponse: \u0026server.Response{\n\t\t\t\tStatus: http.StatusOK,\n\t\t\t\tBody:   []byte(`{\"id\":\"\u003c\u003ctest_2.id\u003e\u003e\",\"name\":\"\u003c\u003ctest_2.name\u003e\u003e\"}`),\n\t\t\t},\n\t\t},\n\t}\n)\n\nfunc NewServer() http.Handler {\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/api/v1/random\", func(w http.ResponseWriter, _ *http.Request) {\n\t\tw.Write([]byte(fmt.Sprintf(`{\"random\":\"%s\"}`, utils.RandomHash(16))))\n\t})\n\tmux.HandleFunc(\"/api/v1/echo\", func(w http.ResponseWriter, r *http.Request) {\n\t\tbody, err := ioutil.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\tw.WriteHeader(http.StatusBadRequest)\n\t\t\tw.Write([]byte(fmt.Sprintf(`{\"error\":\"%s\"}`, err.Error())))\n\t\t\treturn\n\t\t}\n\t\tw.Write(body)\n\t})\n\treturn mux\n}\n\nfunc TestCustomServer(t *testing.T) {\n\t// your server implementation \n\ts := NewServer()\n\n\t// create a tester with server handler and scenario\n\t// pass your server handler\n\t// also you can pass your \"*gin.Engine\" as handler\n\ttester := server.NewTester(s)\n\n\t// run the scenario\n\ttester.Run(t, scenario)\n}\n```\n\n## Example (Unit testing):\n\n```go\npackage unit\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/ecoshub/taste/unit\"\n)\n\nvar (\n\tscenario = []*unit.Case{\n\t\t{\n\t\t\tName:   \"area_success\",\n\t\t\tFunc:   unit.Func(area(3, 4)),\n\t\t\tExpect: unit.Returns(12, nil),\n\t\t},\n\t\t{\n\t\t\tName:   \"area_negative_height_success\",\n\t\t\tFunc:   unit.Func(area(-1, 4)),\n\t\t\tExpect: unit.Returns(0, errNegativeHeight),\n\t\t},\n\t\t{\n\t\t\tName:   \"area_negative_width_success\",\n\t\t\tFunc:   unit.Func(area(4, -1)),\n\t\t\tExpect: unit.Returns(0, errNegativeWidth),\n\t\t},\n\t\t{\n\t\t\tName:   \"area_fail\",\n\t\t\tFunc:   unit.Func(area(0, 0)),\n\t\t\tExpect: unit.Returns(0, nil),\n\t\t},\n\t}\n)\n\nvar (\n\terrNegativeHeight error = errors.New(\"'height' can not be negative\")\n\terrNegativeWidth  error = errors.New(\"'width' can not be negative\")\n)\n\nfunc area(height, width int) (int, error) {\n\tif height \u003c 0 {\n\t\treturn 0, errNegativeHeight\n\t}\n\tif width \u003c 0 {\n\t\treturn 0, errNegativeWidth\n\t}\n\tresult := height * width\n\treturn result, nil\n}\n\nfunc TestMain(t *testing.T) {\n\tunit.Test(t, scenario)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecoshub%2Ftaste","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fecoshub%2Ftaste","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecoshub%2Ftaste/lists"}