{"id":13827328,"url":"https://github.com/txthinking/frank","last_synced_at":"2025-08-23T01:33:20.165Z","repository":{"id":57510807,"uuid":"109979004","full_name":"txthinking/frank","owner":"txthinking","description":"Frank is a REST API automated testing tool like Postman but in command line. Auto generate markdown API document.","archived":false,"fork":false,"pushed_at":"2021-03-26T11:09:00.000Z","size":13936,"stargazers_count":92,"open_issues_count":4,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-19T05:55:55.844Z","etag":null,"topics":["rest","rest-api","rest-client","restapi","restful","restful-api","test-automation","test-runner","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/txthinking.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":null,"support":null}},"created_at":"2017-11-08T13:24:43.000Z","updated_at":"2024-11-10T02:14:15.000Z","dependencies_parsed_at":"2022-09-26T17:50:59.875Z","dependency_job_id":null,"html_url":"https://github.com/txthinking/frank","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/txthinking%2Ffrank","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/txthinking%2Ffrank/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/txthinking%2Ffrank/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/txthinking%2Ffrank/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/txthinking","download_url":"https://codeload.github.com/txthinking/frank/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245377921,"owners_count":20605374,"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":["rest","rest-api","rest-client","restapi","restful","restful-api","test-automation","test-runner","testing","testing-tools"],"created_at":"2024-08-04T09:01:54.198Z","updated_at":"2025-03-25T00:31:56.606Z","avatar_url":"https://github.com/txthinking.png","language":"Go","readme":"# Frank\n\n[![Build Status](https://travis-ci.org/txthinking/frank.svg?branch=master)](https://travis-ci.org/txthinking/frank) [![Go Report Card](https://goreportcard.com/badge/github.com/txthinking/frank)](https://goreportcard.com/report/github.com/txthinking/frank) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](http://www.gnu.org/licenses/gpl-3.0)\n\n### Table of Contents\n\n* [What is Frank](#what-is-frank)\n* [Install](#install)\n\t* [Linux](#linux)\n\t* [MacOS](#macos)\n\t* [Source](#source)\n* [Test case file](#test-case-file)\n\t* [Score](#score)\n\t* [Comment](#comment)\n\t* [Builtin functions](#builtin-functions)\n* [Example](#example)\n\t* [Simple example](#simple-example)\n\t* [POST form](#post-form)\n\t* [POST form file](#post-form-file)\n\t* [POST json data](#post-json-data)\n\t* [Use variable in path](#use-variable-in-path)\n\t* [Parse JSON](#parse-json)\n\t* [Create variable and use it later](#create-variable-and-use-it-later)\n\t* [Use builtin function](#use-builtin-function)\n\t* [Print](#print)\n* [Run case](#run-case)\n* [Generate markdown document](#generate-markdown-document)\n* [Contributing](#contributing)\n* [License](#license)\n\n## What is Frank\n\nFrank is REST API automated testing tool like Postman but in command line.\n\n## Install\n\n### Linux\n\n```\n$ sudo curl -L git.io/frank -o /usr/local/bin/frank\n$ sudo chmod +x /usr/local/bin/frank\n```\n\n### MacOS\n\n```\n$ curl -L git.io/frank_macos -o /usr/local/bin/frank\n$ chmod +x /usr/local/bin/frank\n```\n\n### Source\n\n```\n$ go get github.com/txthinking/frank\n```\n\n## Test case file\n\nTest case file is actually a special javascript file.\n\n### Score\n\nFrank contains there scopes:\n\n#### Init Score\n\n`Init Score` can define some variables if needed before request started.\n\n* Must define `url` variable.\n\n#### Request Score\n\nThe start line format `METHOD PATH [NAME]`, name is optionnal\n\n* `Request Score` starts with a line that begins with `GET `, `HEAD `, `OPTIONS `, `POST `, `PUT `, `PATCH` or `DELETE `\n* `PATH` must have no `?`, query and fragment\n\nPredefined variables\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `header` | `object` | used for http header |\n| `bounday` | `string` | used for `header[\"Content-Type\"] = \"multipart/form-data; boundary=\" + boundary` |\n| `query` | `object` | used for http query parameters |\n| `form` | `object` | used for http body when `Content-Type` is `application/x-www-form-urlencoded` or `multipart/form-data` |\n| `json` | `object` | used for http body when `Content-Type` is `application/json` |\n| `bodyRaw` | `string` | used for http body, if this is not empty then use it and ignore `form`, `json` and `bodyFile` |\n| `bodyFile` | `string` | a file path, contents of file used for http body, if this is not empty then use it and ignore `form`, `json` and `bodyRaw` |\n\n\u003e This variables will be reset when `Request Score` starts\u003cbr/\u003e\n\u003e `Request Score` must be in pairs with `Response Score`\n\n#### Response Score\n\n`Response Score` starts with a line that begins with `Response`\n\nPredefined variables\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `status` | `int` | http status code |\n| `proto` | `string` | http protocol, like `HTTP/2.0` |\n| `header` | `object` | http header |\n| `cookie` | `object` | http cookies key/value |\n| `body` | `string` | http body |\n\n\u003e This variables will be reassigned when `Response Score` starts\u003cbr/\u003e\n\u003e `Response Score` must be in pairs with `Request Score`\n\n### Comment\n\n```\n// This is a comment line\n```\n\n### Builtin functions\n\n| Name | Arguments | Return value | Description |\n| --- | --- | --- | --- |\n| `base64encode` | string |  string | standard base64 encode |\n| `base64decode` | string |  string | standard base64 decode |\n| `exit` | - | - | Exit immediately with code 0 |\n| `md5` | string |  string | md5 hash |\n| `must` | boolean | - | If argument is not equal to `true`, will exit immediately with code 2 |\n\n## Example\n\n### Simple example\n\n```\nurl=\"https://httpbin.org\"\n\nGET /ip\nResponse\n```\n\n### POST form\n\n```\nurl=\"https://httpbin.org\"\n\nPOST /post Post form\nheader[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\nform.key0 = \"value0\"\nform.key1 = \"value1\"\nResponse\nmust(status==200)\n```\n\n### POST form file\n\n```\nurl=\"https://httpbin.org\"\n\nPOST /post Post file\nheader[\"Content-Type\"] = \"multipart/form-data; boundary=\" + boundary\nform.key0 = \"value0\"\nform.key1 = \"@/etc/hosts\"\nResponse\nmust(status==200)\n```\n\n### POST json data\n\n```\nurl=\"https://httpbin.org\"\n\nPOST /post Post json data\nheader[\"Accept\"] = \"application/json\"\nheader[\"Content-Type\"] = \"application/json\"\njson.key0 = \"value0\"\njson.key1 = \"value1\"\nResponse\nmust(status==200)\n```\n\n### Use variable in path\n\n```\nurl=\"https://httpbin.org\"\nsome=\"thing\"\n\nGET /etag/:some Just a GET request\nResponse\nmust(status==200)\n```\n\n### Parse JSON\n\n```\nurl=\"https://httpbin.org\"\nsome=\"thing\"\n\nPOST /post Post json data\nheader[\"Accept\"] = \"application/json\"\nheader[\"Content-Type\"] = \"application/json\"\njson.key0 = \"value0\"\njson.key1 = some\nResponse\nmust(status==200)\nj = JSON.parse(body)\nmust(j.origin.length \u003e 3)\n```\n\n### Create variable and use it later\n\n```\nurl=\"https://httpbin.org\"\n\nPOST /post Post json data\nheader[\"Accept\"] = \"application/json\"\nheader[\"Content-Type\"] = \"application/json\"\njson.key0 = \"value0\"\njson.key1 = \"value1\"\nlist=[]\nlist.push(\"value3\")\nlist.push(\"value4\")\njson.key2 = list\nResponse\nmust(status==200)\nj = JSON.parse(body)\nmyip = j.origin // created a new variable\n\nGET /etag/:myip Just a GET request\nquery.key0 = myip // use a varible you created earlier\nResponse\nmust(status==200)\n```\n\n### Use builtin function\n\n```\nurl=\"https://httpbin.org\"\n\nGET /get\nquery.key0 = md5(\"value0\")\nResponse\nmust(status==200)\n```\n\n### Print\n\n```\nurl=\"https://httpbin.org\"\n\nGET /ip\nResponse\nmust(status==200)\nconsole.log(body)\n```\n\n## Run case\n```\n# Default case file is ./test.frank\n$ frank\n\n# Specifies case file path\n$ frank -c /path/to/case/file\n\n# Set 500ms request interval\n$ frank -d 500\n```\n\n## Generate markdown document\n```\n# Print to stdout\n$ frank -m\n\n# Write to api.md\n$ frank -m \u003e api.md\n```\n\n## Contributing\n\nPlease create PR on `develop` branch\n\n## Author\n\nA project by [txthinking](https://www.txthinking.com)\n\n## License\n\nLicensed under The MIT License\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftxthinking%2Ffrank","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftxthinking%2Ffrank","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftxthinking%2Ffrank/lists"}