{"id":46829248,"url":"https://github.com/gdt-dev/http","last_synced_at":"2026-03-10T09:47:07.643Z","repository":{"id":183805378,"uuid":"670712549","full_name":"gdt-dev/http","owner":"gdt-dev","description":"Go Declarative Testing - HTTP","archived":false,"fork":false,"pushed_at":"2025-11-03T22:53:45.000Z","size":148,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-04T00:19:10.164Z","etag":null,"topics":["declarative-testing","go","go-testing","golang","golang-testing","http"],"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/gdt-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"COPYING","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-25T16:56:45.000Z","updated_at":"2025-11-03T22:53:49.000Z","dependencies_parsed_at":"2023-07-25T23:16:20.982Z","dependency_job_id":null,"html_url":"https://github.com/gdt-dev/http","commit_stats":null,"previous_names":["gdt-dev/http"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/gdt-dev/http","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdt-dev%2Fhttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdt-dev%2Fhttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdt-dev%2Fhttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdt-dev%2Fhttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gdt-dev","download_url":"https://codeload.github.com/gdt-dev/http/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdt-dev%2Fhttp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30329157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: 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":["declarative-testing","go","go-testing","golang","golang-testing","http"],"created_at":"2026-03-10T09:47:07.402Z","updated_at":"2026-03-10T09:47:07.605Z","avatar_url":"https://github.com/gdt-dev.png","language":"Go","readme":"# Go Declarative Testing - HTTP\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/gdt-dev/http.svg)](https://pkg.go.dev/github.com/gdt-dev/http)\n[![Go Report Card](https://goreportcard.com/badge/github.com/gdt-dev/http)](https://goreportcard.com/report/github.com/gdt-dev/http)\n[![Build Status](https://github.com/gdt-dev/http/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/gdt-dev/http/actions)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)\n\n\u003cdiv style=\"float: left\"\u003e\n\u003cimg align=left src=\"static/gdthttplogo400x544.png\" width=200px /\u003e\n\u003c/div\u003e\n\n[`gdt`][gdt] is a testing library that allows test authors to cleanly describe tests\nin a YAML file. `gdt` reads YAML files that describe a test's assertions and\nthen builds a set of Go structures that the standard Go\n[`testing`](https://golang.org/pkg/testing/) package can execute.\n\n[gdt]: https://github.com/gdt-dev/gdt\n\nThis `github.com/gdt-dev/http` (shortened hereafter to `gdt-http`) repository\nis a companion Go library for `gdt` that allows test authors to cleanly\ndescribe functional tests of HTTP APIs using a simple, clear YAML format.\n`gdt-http` parses YAML files that describe HTTP requests and assertions about\nwhat the HTTP response should contain.\n\n## Installation\n\n`gdt-http` is a Golang library and is intended to be included in your own Golang\napplication's test code as a Golang package dependency.\n\nInstall `gdt-http` into your `$GOPATH` by executing:\n\n```\ngo get -u github.com/gdt-dev/http\n```\n\n## `gdt-http` test file structure\n\nThe `gdt-http` test file [parser](parse.go) parses a test file with type\n\"http\". It parses the test file into an object with the following attributes:\n\n* `tests`: list of test unit objects that describe a test of an HTTP request and\n  response\n\nEach of the test unit objects have the following attributes:\n\n* `name`: (optional) string describing the individual test. If missing or\n  empty, the test unit's name is a string with the request HTTP method and path\n* `description`: (optional) string with a longer description of the test unit\n* `method`: (optional) string with the HTTP verb to use. Defaults to \"GET\" if\n  `url` attribute is non-empty\n* `url`: (optional) string with the path or URL to use for the HTTP request. If\n  missing, one of the `GET`, `POST`, `PATCH`, `DELETE` or `PUT` shortcut\n  attributes must be non-empty\n  * `GET`: (optional) string with the path or URL to issue an HTTP GET request\n  * `POST`: (optional) string with the path or URL to issue an HTTP POST request\n  * `PUT`: (optional) string with the path or URL to issue an HTTP PUT request\n  * `PATCH`: (optional) string with the path or URL to issue an HTTP PATCH request\n  * `DELETE`: (optional) string with the path or URL to issue an HTTP DELETE request\n* `data`: (optional) if present, will be encoded into the HTTP request\n  payload. Elements of the `data` structure may be JSONPath expressions (see [below](#use-jsonpath-expressions-to-substitute-fixture-data))\n* `assert`: (optional) object describing the **assertions** to make about the\n  HTTP response received after issuing the HTTP request\n\nThe `asssert` object has the following attributes:\n\n* `status`: (optional) integer corresponding to the expected HTTP status code\n  of the HTTP response\n* `strings`: (optional) list of strings that should appear in the body of the\n  HTTP response\n* `json`: (optional) object describing the assertions to make about JSON\n  content in the HTTP response body\n\nThe `json` object has the following attributes:\n\n* `len`: (optional) integer representing the number of bytes in the resulting\n  JSON object after successfully parsing the HTTP response body\n* `paths`: (optional) map of strings where the keys of the map are JSONPath\n  expressions and the values of the map are the expected value to be found when\n  evaluating the JSONPath expression\n* `path_formats`: (optional) map of strings where the keys of the map are\n  JSONPath expressions and the values of the map are the expected format of the\n  value to be found when evaluating the JSONPath expression. See the\n  [list of valid format strings](#valid-format-strings)\n* `schema`: (optional) string containing a filepath to a JSONSchema document.\n  If present, the JSON included in the HTTP response will be validated against\n  this JSONSChema document.\n\n### Specify HTTP request payload\n\nThe `data` attribute of the test unit is used to specify a payload to be\nencoded into the HTTP request body. By default, the contents of the `data`\nattribute are encoded as JSON.\n\nTODO(jaypipes): Support non-JSON encoding.\n\nThe `data` attribute is especially useful for testing of `POST` and `PUT`\nrequests, where you want to send data to the server to create or update some\nresource.\n\nFor example, suppose the `POST /books` URL accepts some JSON-encoded data with\ninformation about the to-be-created book's author, title, publisher, etc.\n\nTo test the `POST /books` functionality, a test author might use the following\ntest unit:\n\n```yaml\n - name: create a new book\n   POST: /books\n   data:\n     title: For Whom The Bell Tolls\n     published_on: 1940-10-21\n     pages: 480\n     author_id: \"1\"\n     publisher_id: \"1\"\n   assert:\n     status: 201\n```\n\nThe above `data` would be encoded into the following HTTP request body:\n\n```json\n{\n     \"title\": \"For Whom The Bell Tolls\",\n     \"published_on\": \"1940-10-21\",\n     \"pages\": 480,\n     \"author_id\": \"1\",\n     \"publisher_id\": \"1\"\n}\n```\n\n#### Use JSONPath expressions to substitute fixture data\n\nOften, you will want to reference some information in a fixture instead of\nhard-coding values in the `data` contents.\n\nConsider this test unit:\n\n```yaml\n - name: create a new book\n   POST: /books\n   data:\n     title: For Whom The Bell Tolls\n     published_on: 1940-10-21\n     pages: 480\n     author_id: \"1\"\n     publisher_id: \"1\"\n   assert:\n     status: 201\n```\n\nHard-coding the string `\"1\"` for the `author_id` and `publisher_id` values is\nfragile and non-descriptive. It requires the reader of the test to know which\nauthor has an ID of \"1\" and which publisher has an ID of \"1\".\n\nIt would be much more readable if we could replace those hard-coded `\"1\"`\nvalues with a reference to some fixture data:\n\n```yaml\nfixtures:\n - books_api\n - books_data\ntests:\n - name: create a new book\n   POST: /books\n   data:\n     title: For Whom The Bell Tolls\n     published_on: 1940-10-21\n     pages: 480\n     author_id: $.authors.by_name[\"Ernest Hemingway\"].id\n     publisher_id: $.publishers.by_name[\"Charles Scribner's Sons\"].id\n   assert:\n     status: 201\n```\n\nThe test reader can now better understand what value is being placed into the\n\"author_id\" field of the HTTP request payload: the ID value of the author whose\nname is \"Ernest Hemingway\".\n\nThe JSONPath expressions that replaced the hard-coded `\"1\"` values are\nevaluated by the fixtures associated with a test file. The\nA `gdt.fixtures.JSONFixture` fixture is designed to evaluate JSONPath\nexpressions for the data defined in the fixture.\n\nAssume I have a file `testdata/fixtures.json` that looks like this:\n\n```json\n{\n    \"books\": [\n        {\n            \"id\": \"12ac1b94-5667-461e-80cb-ba8619cae61a\",\n            \"title\": \"Old Man and the Sea\",\n            \"published_on\": \"1952-10-01\",\n            \"pages\": 127,\n            \"author\": {\n                \"name\": \"Ernest Hemingway\",\n                \"id\": \"1\"\n            },\n            \"publisher\": {\n                \"name\": \"Charles Scribner's Sons\",\n                \"id\": \"1\",\n                \"address\": {\n                    \"address\": \"153–157 Fifth Avenue\",\n                    \"city\": \"New York City\",\n                    \"state\": \"NY\",\n                    \"postal_code\": \"10010\",\n                    \"country_code\": \"US\"\n                }\n            }\n        }\n    ],\n    \"authors\": {\n        \"by_name\": {\n            \"Ernest Hemingway\": {\n                \"id\": 1\n            }\n        }\n    },\n    \"publishers\": {\n        \"by_name\": {\n            \"Charles Scribner's Sons\": {\n                \"id\": 1\n            }\n        }\n    }\n}\n```\n\nWe can register a `gdt.fixtures.JSONFixture` that contains the data in\n`testdata/fixtures.json`:\n\n```go\n\tdataFilepath := \"testdata/fixtures.json\"\n\n\tdataFile, _ := os.Open(dataFilepath)\n\tdataFixture, err := gdt.NewJSONFixture(dataFile)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tgdt.RegisterFixture(\"books_data\", dataFixture)\n```\n\nTo reference any of the data in your `gdt.fixtures.JSONFixture` from your test\nunit, just make sure the fixture is listed in the test file's `fixtures` field:\n\n```\nrequire:\n - books_data\n```\n\nThen you can grab any data in the fixture using a JSONPath expression in the\n`data` contents:\n\n```yaml\n   data:\n     author_id: $.authors.by_name[\"Ernest Hemingway\"].id\n```\n\n### Specify expected response values (`assert.json.paths`)\n\nWhen you want to validate the structure of the returned JSON object in an HTTP\nresponse body, you use the `assert.json.paths` attribute of the test unit.\n\nThis attribute is a map of string to string, where the map keys are JSONPath\nexpressions and the map values are the expected value when evaluating that\nJSONPath expression.\n\nFor example, let's say you want to verify that an HTTP `GET` request to the\n`/books` URL returns an HTTP response that contains a list of JSON objects, and\nthat the first JSON object in that list contains a field, \"title\", that\ncontains the string \"For Whom the Bell Tolls\". You would write the test unit\nlike so:\n\n```yaml\ntests:\n  - GET: /books\n    assert:\n      json:\n        paths:\n          - $[0].title: For Whom the Bell Tolls\n```\n\n### Specify expected response value format (`assert.json.path_formats`)\n\nWhen you want to validate that a certain field in a returned JSON object from\nan HTTP response matches a particular common format, you use the\n`assert.json.path_formats` attribute of the test unit.\n\nThis attribute is a map of string to string, where the map keys are JSONPath\nexpressions and the map values are the [type of format](#valid-format-strings)\nthat the value to be found at the JSONPath expression should have.\n\nFor example, let's say you want to verify that an HTTP `GET` request to the\n`/books/thebook` URL returned an HTTP response that contains a JSON object\nhaving a \"id\" field, and that the value of that field is a valid version 4\nUUID. You would write the test unit like so:\n\n```yaml\ntests:\n  - GET: /books/thebook\n    assert:\n      json:\n        path_formats:\n          - $.id: uuid\n```\n\nThe `$.id` string is a JSONPath expression that selects the value of the field\ncalled \"id\" from the top-level document/object. The `uuid4` string indicates\nthe expected format of that value.\n\n#### Valid format strings\n\nThe currently supported format strings are all format strings in Draft7 of\nJSONSchema plus the \"uuid4\" variant:\n\n* \"date\": must be a date string in the format YYYY-MM-DD\n* \"time\": must be a time string in format HH:MM:SSZ-07:00 or HH:MM:SS\n* \"date-time\": must be a date-time string in any of the following formats:\n\n * YYYY-MM-DDTHH:MM:SSZ-0700\n * YYYY-MM-DD\n * HH:MM:SSZ-0700\n * HH:MM:SS\n\n* \"hostname\": must be a valid DNS hostname (RFC 952 and RFC 1123)\n* \"email\": must be a valid email address (RFC 5322)\n* \"idn-email\": must be a valid email address (RFC 5322)\n* \"ipv4\": must be a valid IPv4 address (RFC 791)\n* \"ipv6\": must be a valid IPv6 address (RFC 4291)\n* \"uri\": must be a valid URI (RFC 3986)\n* \"uri-reference\": must be a valid URI or relative-reference (RFC 3986)\n* \"iri\": must be a valid URI (RFC 3986)\n* \"iri-reference\": must be a valid URI or relative-reference (RFC 3986)\n* \"uri-template\": must be a valid URI template (RFC 6570)\n* \"regex\": must be a valid POSIX regular expression\n* \"json-pointer\": must be a valid JSON pointer value\n* \"relative-json-pointer\": must be a valid relative JSON pointer value\n* \"uuid\": must be any version of UUID\n* \"uuid4\": must be a UUID version 4\n\n### `$$LOCATION`\n\nThe `url` attribute of an HTTP test spec can be the special string\n`$$LOCATION`. When this is set, the HTTP request will be to the URL specified\nin the *previous HTTP response's* Location HTTP header. This is an easy\nshortcut for testing a series of ordered HTTP requests, where the first HTTP\nrequest (typically a `POST` or `PUT` to a particular resource) responds with a\nLocation HTTP header pointing to a URL that can have issued an HTTP `GET`\nrequest to return information about the previously created or mutated resource.\n\n### Response assertions\n\nUse the `assert` field in the Spec definition to tell `gdt-http` to assert\nthat various pieces of the HTTP response match expectations.\n\n#### Checking for a string in response body\n\nUse the `assert.strings` field to check for the existence of one of more\nstrings in the HTTP response body.\n\n```yaml\nfixtures:\n - books_api\ntests:\n - name: invalid query parameter is supplied\n   GET: /books?invalidparam=1\n   assert:\n     status: 400\n     strings:\n       - invalid parameter\n```\n\n#### Checking for an HTTP header\n\nUse the `assert.headers` field to check for the existence of one of\nmore HTTP headers in the HTTP response.\n\n```yaml\nfixtures:\n - books_api\ntests:\n - name: invalid query parameter is supplied\n   GET: /books?invalidparam=1\n   assert:\n     status: 400\n     headers:\n       - Accept\n```\n\nTODO(jaypipes): Support Header value matching as well.\n\n#### Checking for JSON in response\n\nUse the `assert.json` field to assert that the value or format of a value of\nan element identified by JSONPath expression matches an expected value or\nformat.\n\n[`examples/books/tests/api/create_then_get.yaml`](../examples/books/tests/api/create_then_get.yaml):\n\n```yaml\nfixtures:\n - books_api\ntests:\n - name: create a new book\n   POST: /books\n   data:\n     title: For Whom The Bell Tolls\n     published_on: 1940-10-21\n     pages: 480\n     author_id: $.authors.by_name[\"Ernest Hemingway\"].id\n     publisher_id: $.publishers.by_name[\"Charles Scribner's Sons\"].id\n   assert:\n     status: 201\n     headers:\n      - Location\n - name: look up that created book\n   GET: $$LOCATION\n   assert:\n     status: 200\n     json:\n       paths:\n         $.author.name: Ernest Hemingway\n         $.publisher.address.state: NY\n       path_formats:\n         $.id: uuid4\n```\n\n#### Validating an HTTP response to a JSONSchema\n\nYou can use the `assert.json.schema` field to specify a JSONSchema that the\nHTTP response body should adhere to.\n\n[`examples/books/tests/api/get_books.yaml`](../examples/books/tests/api/get_books.yaml):\n\n```yaml\nfixtures:\n - books_api\n - books_data\ntests:\n - name: list all books\n   GET: /books\n   assert:\n     status: 200\n     json:\n       schema: schemas/get_books.json\n```\n\nwith the contents of [`examples/books/tests/api/schemas/get_books.json`](../examples/books/tests/api/schemas/get_books.json):\n\n```json\n{\n  \"$id\": \"/schemas/get_books.json\",\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"books\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"id\": {\n            \"type\": \"string\"\n          },\n          \"title\": {\n            \"type\": \"string\"\n          },\n          \"pages\": {\n            \"type\": \"number\"\n          },\n          \"author\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"id\": {\n                \"type\": \"string\"\n              },\n              \"name\": {\n                \"type\": \"string\"\n              }\n            },\n            \"require\": [ \"id\", \"name\" ]\n          },\n          \"publisher\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"id\": {\n                \"type\": \"string\"\n              },\n              \"name\": {\n                \"type\": \"string\"\n              }\n            },\n            \"require\": [ \"id\", \"name\" ]\n          }\n        },\n        \"required\": [ \"id\", \"title\", \"author\" ]\n      }\n    }\n  },\n  \"required\": [ \"books\" ]\n}\n```\n\n## Contributing and acknowledgements\n\n`gdt` was inspired by [Gabbi](https://github.com/cdent/gabbi), the excellent\nPython declarative testing framework. `gdt` tries to bring the same clear,\nconcise test definitions to the world of Go functional testing.\n\nThe Go gopher logo, from which gdt's logo was derived, was created by Renee\nFrench.\n\nContributions to `gdt-http` are welcomed! Feel free to open a Github issue or\nsubmit a pull request.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdt-dev%2Fhttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgdt-dev%2Fhttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdt-dev%2Fhttp/lists"}