{"id":13413876,"url":"https://github.com/Eun/go-hit","last_synced_at":"2025-03-14T20:30:46.965Z","repository":{"id":37948360,"uuid":"190240223","full_name":"Eun/go-hit","owner":"Eun","description":"http integration test framework","archived":false,"fork":false,"pushed_at":"2024-07-08T04:21:22.000Z","size":11411,"stargazers_count":253,"open_issues_count":13,"forks_count":9,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-07-31T20:52:56.919Z","etag":null,"topics":["go","golang","hacktoberfest"],"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/Eun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["Eun"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":"Eun","issuehunt":"eun","otechie":null,"custom":null}},"created_at":"2019-06-04T16:28:23.000Z","updated_at":"2024-07-31T08:22:31.000Z","dependencies_parsed_at":"2023-11-28T14:30:48.429Z","dependency_job_id":"b7e4020a-df58-4499-9761-661e64ae0c99","html_url":"https://github.com/Eun/go-hit","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eun%2Fgo-hit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eun%2Fgo-hit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eun%2Fgo-hit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eun%2Fgo-hit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Eun","download_url":"https://codeload.github.com/Eun/go-hit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243632386,"owners_count":20322382,"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":["go","golang","hacktoberfest"],"created_at":"2024-07-30T20:01:51.760Z","updated_at":"2025-03-14T20:30:46.944Z","avatar_url":"https://github.com/Eun.png","language":"Go","readme":"# go-hit\n[![Actions Status](https://github.com/Eun/go-hit/workflows/CI/badge.svg)](https://github.com/Eun/go-hit/actions)\n[![Coverage Status](https://coveralls.io/repos/github/Eun/go-hit/badge.svg?branch=master)](https://coveralls.io/github/Eun/go-hit?branch=master)\n[![PkgGoDev](https://img.shields.io/badge/pkg.go.dev-reference-blue)](https://pkg.go.dev/github.com/Eun/go-hit)\n[![GoDoc](https://godoc.org/github.com/Eun/go-hit?status.svg)](https://godoc.org/github.com/Eun/go-hit)\n[![go-report](https://goreportcard.com/badge/github.com/Eun/go-hit)](https://goreportcard.com/report/github.com/Eun/go-hit)\n[![go1.15](https://img.shields.io/badge/go-1.15-blue)](#)\n---\nhit is an **h**ttp **i**ntegration **t**est framework written in golang.\n\nIt is designed to be flexible as possible, but to keep a simple to use interface for developers.\n\nSo lets get started!\n\n\u003e go get -u github.com/Eun/go-hit\n\n```go //ignore\npackage main\n\nimport (\n    \"net/http\"\n    . \"github.com/Eun/go-hit\"\n)\n\nfunc main() {\n    MustDo(\n        Description(\"Post to httpbin.org\"),\n        Get(\"https://httpbin.org/post\"),\n        Expect().Status().Equal(http.StatusMethodNotAllowed),\n        Expect().Body().String().Contains(\"Method Not Allowed\"),\n    )\n}\n```\n\nOr use the `Test()` function:\n```go //ignore\npackage main_test\nimport (\n    \"testing\"\n    \"net/http\"\n    . \"github.com/Eun/go-hit\"\n)\n\nfunc TestHttpBin(t *testing.T) {\n    Test(t,\n        Description(\"Post to httpbin.org\"),\n        Get(\"https://httpbin.org/post\"),\n        Expect().Status().Equal(http.StatusMethodNotAllowed),\n        Expect().Body().String().Contains(\"Method Not Allowed\"),\n    )\n}\n``` \n\n## Expect, Expect, Expect, ....\n```go\nMustDo(\n    Get(\"https://httpbin.org/post\"),\n    Expect().Status().Equal(http.StatusMethodNotAllowed),\n    Expect().Headers(\"Content-Type\").NotEmpty(),\n    Expect().Body().String().Contains(\"Method Not Allowed\"),\n)\n``` \n\n## Sending Data\n```go\nMustDo(\n    Post(\"https://httpbin.org/post\"),\n    Send().Body().String(\"Hello HttpBin\"),\n    Expect().Status().Equal(http.StatusOK),\n    Expect().Body().String().Contains(\"Hello HttpBin\"), \n)\n``` \n\n\n### Sending And Expecting JSON\n```go\nMustDo(\n    Post(\"https://httpbin.org/post\"),\n    Send().Headers(\"Content-Type\").Add(\"application/json\"),\n    Send().Body().JSON(map[string][]string{\"Foo\": []string{\"Bar\", \"Baz\"}}),\n    Expect().Status().Equal(http.StatusOK),\n    Expect().Body().JSON().JQ(\".json.Foo[1]\").Equal(\"Baz\"),\n)\n``` \n\n\n## Storing Data From The Response\n```go\nvar name string\nvar roles []string\nMustDo(\n    Post(\"https://httpbin.org/post\"),\n    Send().Headers(\"Content-Type\").Add(\"application/json\"),\n    Send().Body().JSON(map[string]interface{}{\"Name\": \"Joe\", \"Roles\": []string{\"Admin\", \"Developer\"}}),\n    Expect().Status().Equal(http.StatusOK),\n    Store().Response().Body().JSON().JQ(\".json.Name\").In(\u0026name),\n    Store().Response().Body().JSON().JQ(\".json.Roles\").In(\u0026roles),\n)\nfmt.Printf(\"%s has %d roles\\n\", name, len(roles))\n``` \n\n## Problems? `Debug`!\n```go\nMustDo(\n    Post(\"https://httpbin.org/post\"),\n    Debug(),\n    Debug().Response().Body(),\n)\n```\n\n## Handling Errors\nIt is possible to handle errors in a custom way.\n```go //ignore\nfunc login(username, password string) error {\n    err := Do(\n         Get(\"https://httpbin.org/basic-auth/joe/secret\"),\n         Send().Headers(\"Authorization\").Add(\"Basic \" + base64.StdEncoding.EncodeToString([]byte(username + \":\" + password))),\n         Expect().Status().Equal(http.StatusOK),\n    )\n    var hitError *Error\n    if errors.As(err, \u0026hitError) {\n        if hitError.FailingStepIs(Expect().Status().Equal(http.StatusOK)) {\n            return errors.New(\"login failed\")\n        }\n    }\n    return err\n}\n```\n\n## Build the request url manually\n```go\nMustDo(\n    Request().Method(http.MethodPost),\n    Request().URL().Scheme(\"https\"),\n    Request().URL().Host(\"httpbin.org\"),\n    Request().URL().Path(\"/post\"),\n    Request().URL().Query(\"page\").Add(1),\n    Expect().Status().Equal(200),\n    Send().Body().String(\"Hello World\"),\n    Expect().Body().String().Contains(\"Hello\"),\n)\n```\n\n## Twisted!\nAlthough the following is hard to read it is possible to do!\n```go\nMustDo(\n    Post(\"https://httpbin.org/post\"),\n    Expect().Status().Equal(200),\n    Send().Body().String(\"Hello World\"),\n    Expect().Body().String().Contains(\"Hello\"),\n)\n```\n\n## Custom Send And Expects\n```go\nMustDo(\n    Get(\"https://httpbin.org/get\"),\n    Send().Custom(func(hit Hit) error {\n        hit.Request().Body().SetStringf(\"Hello %s\", \"World\")\n        return nil\n    }),\n    Expect().Custom(func(hit Hit) error {\n        if len(hit.Response().Body().MustString()) \u003c= 0 {\n            return errors.New(\"expected the body to be not empty\")\n        }\n        return nil\n    }),\n    Custom(AfterExpectStep, func(Hit) error {\n        fmt.Println(\"everything done\")\n        return nil\n    }),\n)\n```\n\n## Templates / Multiuse\n```go\ntemplate := CombineSteps(\n    Post(\"https://httpbin.org/post\"),\n    Send().Headers(\"Content-Type\").Add(\"application/json\"),\n    Expect().Headers(\"Content-Type\").Equal(\"application/json\"),\n)\nMustDo(\n    template,\n    Send().Body().JSON(\"Hello World\"),\n)\n\nMustDo(\n    template,\n    Send().Body().JSON(\"Hello Universe\"),\n)\n```\n\n## Clean Previous Steps\nSometimes it is necessary to remove some steps that were added before.\n```go\ntemplate := CombineSteps(\n    Get(\"https://httpbin.org/basic-auth/joe/secret\"),\n    Expect().Status().Equal(http.StatusOK),\n)\nMustDo(\n    Description(\"login with correct credentials\"),\n    template,\n    Send().Headers(\"Authorization\").Add(\"Basic \" + base64.StdEncoding.EncodeToString([]byte(\"joe:secret\"))),\n)\n\nTest(t,\n    Description(\"login with incorrect credentials\"),\n    template,\n    Clear().Expect().Status(),\n    Expect().Status().Equal(http.StatusUnauthorized),\n    Send().Headers(\"Authorization\").Add(\"Basic \" + base64.StdEncoding.EncodeToString([]byte(\"joe:joe\"))),\n)\n```\nMore examples can be found in the `examples directory`\n\n### Changelog\n#### 0.5.0\n* Rehaul the api, make things more explicit\n* Fix some issues\n* `Store()` functionality\n* Generate `Clear()` paths\n* Infinite `JQ()` functionality\n* Test `README.md` and documentation parts\n\n#### 0.4.0\n* Fixed a double run bug in `CombineSteps` (#3)\n* Better `Clear` functionality, you can now clear any previous step by prepending `Clear()`,\neg. \n  ```go //ignore\n  Do(\n      Get(\"https://example.com\"),\n      Expect().Body(\"Hello World\"),\n      Clear().Expect(),                        // remove all previous Expect() steps\n      // Clear().Expect().Body(\"Hello World\"), // remove only the Expect().Body(\"Hello World\") step\n  )\n  \n  // also works for CombineSteps\n  Do(\n      Post(\"https://example.com\"),        \n      CombineSteps(\n          Send().Body().String(\"Hello World\"),\n          Expect().Body(\"Hello World\"),\n      ),\n      Clear().Expect(),\n  )\n  ```\n* Simplified `Expect().Header()` use, no more `Expect().Headers()`,\neverything can now be done in the `Expect().Header()` function.\n* More documentation and examples\n* `hit.Do` and `hit.MustDo` for inline steps.\n* Removal of inline steps (use `hit.Do` and `hit.MustDo`)\n  ```go //ignore\n  Do(\n      Get(\"https://example.com\"),\n      Expect().Custon(func (hit Hit) {\n          // Expect(\"Hello World\") is invalid now\n          // you must use MustDo() or Do()\n          hit.MustDo(\n              Expect(\"Hello World\"),\n          )\n      }),\n  )\n  ```\n* `hit.InsertSteps` to insert steps during runtime\n","funding_links":["https://github.com/sponsors/Eun","https://liberapay.com/Eun","https://issuehunt.io/r/eun"],"categories":["测试","Testing","Go","Template Engines","测试相关`测试库和测试数据集生成库`","Testing Frameworks","测试相关"],"sub_categories":["HTTP客户端","Testing Frameworks","HTTP Clients","查询语"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEun%2Fgo-hit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEun%2Fgo-hit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEun%2Fgo-hit/lists"}