ytest

package
v0.0.0-...-4281d85 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 11, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

README

yaptest - Go+ HTTP Test Framework

Language GitHub release Discord GoDoc

yaptest is a web server testing framework. This classfile has the file suffix _ytest.gox.

Before using yaptest, you need to add github.com/hiddenchops/yap to go.mod:

gop get github.com/hiddenchops/yap@latest

Suppose we have a web server (foo/get_p_#id.yap):

json {
	"id": ${id},
}

Then we create a yaptest file (foo/foo_ytest.gox):

mock "foo.com", new(AppV2)  // name of any YAP v2 web server is `AppV2`

id := "123"
get "http://foo.com/p/${id}"
ret 200
json {
	"id": id,
}

The directive mock creates the web server by mockhttp. Then we write test code directly.

You can change the directive mock to testServer (see foo/bar_ytest.gox), and keep everything else unchanged:

testServer "foo.com", new(AppV2)

id := "123"
get "http://foo.com/p/${id}"
ret 200
json {
	"id": id,
}

The directive testServer creates the web server by net/http/httptest and obtained a random port as the service address. Then it calls the directive host to map the random service address to foo.com. This makes all other code no need to changed.

match

This is almost the core concept in yaptest. It matches two objects.

Let’s look at a simple example first:

id := Var(int)
match id, 1+2
echo id

Here we define a variable called id and match it with expression 1+2. If the variable is unbound, it is assigned the value of the expression. In this way the value of id becomes 3.

So far, you've seen match like the assignment side. But you cannot assign a different value to a variable that has been bound:

id := Var(int)
match id, 1+2
match id, 3
echo id

match id, 5  // unmatched value - expected: 3, got: 5

In the second match statement, the variable id has been bound. At this time, it will be compared with the expression value. If it is equal, it will succeed, otherwise an error will be reported (such as the third match statement above).

The match statement can be complex, such as:

d := Var(string)

match {
    "c": {"d": d},
}, {
    "a": 1,
    "b": 3.14,
    "c": {"d": "hello", "e": "world"},
    "f": 1,
}

echo d
match d, "hello"

Generally, the syntax of the match command is:

match <ExpectedObject> <SourceObject>

Unbound variables are allowed in <ExpectedObject>, but cannot appear in <SourceObject>. <ExpectedObject> and <SourceObject> do not have to be exactly the same, but what appears in <ExpectedObject> must also appear in <SourceObject>. That is, it is required to be a subset relationship (<ExpectedObject> is a subset of <SourceObject>).

If a variable in <ExpectedObject> has not been bound, it will be bound according to the value of the corresponding <SourceObject>; if the variable has been bound, the values on both sides must match.

The cornerstone of yaptest is matching grammar. Let's look at the example you saw at the beginning:

id := "123"
get "http://foo.com/p/${id}"

ret 200
json {
	"id": id,
}

It is equivalent to:

id := "123"
get "http://foo.com/p/${id}"

send                 // send request
match 200, resp.code // assert resp.code == 200
match "application/json", resp.header.get("Content-Type")
match {              // assert resp.body.id == id
	"id": id,
}, resp.body

host

host <host> <real>

The Host directive allows you to use an abstract domain name (which does not necessarily exist) to represent a service.

For examples:

host "https://foo.com", "http://127.0.0.1:8080"

The host directive makes it easy for you to use the same test code between your test environment and production environment:

host "https://foo.com", ${FOO_HOST}
// Let env FOO_HOST point to the test environment or production environment

req/post/get/delete/put

TODO

header

TODO

ret

TODO

body/json/form/text/binary

TODO

auth

auth <auth>

Auth sets an Authorization for a request. For example:

auth qiniu("<AccessKey>", "<SecretKey>")

Authorization information can be shared between different requests:

testauth := qiniu("<AccessKey>", "<SecretKey>")

post "https://foo.com/bar"
auth testauth
ret 200

...

get "https://foo.com/bar"
auth testauth
ret 200

Documentation

Index

Constants

View Source
const (
	GopPackage   = "github.com/hiddenchops/yap/test"
	GopTestClass = true
)
View Source
const (
	Gopo_Request_Ret = ".Send,.RetWith"
)

Variables

This section is empty.

Functions

func Bearer

func Bearer(token string) auth.RTComposer

Bearer creates a Bearer Authorization by specified token.

func Form

func Form(m map[string]any) (ret url.Values)

Form encodes a map value into string in form format.

func Gopt_App_Main

func Gopt_App_Main(app interface{ initApp() *App }, workers ...interface{ initCase(*App, CaseT) })

Gopt_App_Main is required by Go+ compiler as the Main entry of a YAP testing project.

func Gopt_App_TestMain

func Gopt_App_TestMain(app interface{ initApp() *App }, m *testing.M)

Gopt_App_TestMain is required by Go+ compiler as the TestMain entry of a YAP testing project.

func Gopt_CaseApp_TestMain

func Gopt_CaseApp_TestMain(c interface{ initCaseApp(*App, CaseT) }, t *testing.T)

Gopt_CaseApp_TestMain is required by Go+ compiler as the entry of a YAP test case.

func JsonEncode

func JsonEncode(v any) string

JsonEncode encodes a value into string in json format.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

func (*App) Host

func (p *App) Host(host, real string)

Host replaces a host into real. For example:

host "https://example.com", "http://localhost:8080"
host "http://example.com", "http://localhost:8888"

func (*App) Mock

func (p *App) Mock(host string, app yap.AppType)

Mock runs a YAP server by mockhttp.

func (*App) RunMock

func (p *App) RunMock(host string, h http.Handler)

RunMock runs a HTTP server by mockhttp.

func (*App) RunTestServer

func (p *App) RunTestServer(host string, h http.Handler)

RunTestServer runs a HTTP server by httptest.Server.

func (*App) TestServer

func (p *App) TestServer(host string, app yap.AppType)

TestServer runs a YAP server by httptest.Server.

type Case

type Case struct {
	*Request
	test.Case

	DefaultHeader http.Header
	// contains filtered or unexported fields
}

func (*Case) DELETE

func (p *Case) DELETE(url string) *Request

DELETE is a shortcut for Req(http.MethodDelete, url)

func (*Case) GET

func (p *Case) GET(url string) *Request

GET is a shortcut for Req(http.MethodGet, url)

func (*Case) Get

func (p *Case) Get(url string) *Request

Get is a shortcut for Req(http.MethodGet, url)

func (*Case) HEAD

func (p *Case) HEAD(url string) *Request

HEAD is a shortcut for Req(http.MethodHead, url)

func (*Case) Head

func (p *Case) Head(url string) *Request

Head is a shortcut for Req(http.MethodHead, url)

func (*Case) OPTIONS

func (p *Case) OPTIONS(url string) *Request

OPTIONS is a shortcut for Req(http.MethodOptions, url)

func (*Case) Options

func (p *Case) Options(url string) *Request

Options is a shortcut for Req(http.MethodOptions, url)

func (*Case) PATCH

func (p *Case) PATCH(url string) *Request

PATCH is a shortcut for Req(http.MethodPatch, url)

func (*Case) POST

func (p *Case) POST(url string) *Request

POST is a shortcut for Req(http.MethodPost, url)

func (*Case) PUT

func (p *Case) PUT(url string) *Request

PUT is a shortcut for Req(http.MethodPut, url)

func (*Case) Patch

func (p *Case) Patch(url string) *Request

Patch is a shortcut for Req(http.MethodPatch, url)

func (*Case) Post

func (p *Case) Post(url string) *Request

Post is a shortcut for Req(http.MethodPost, url)

func (*Case) Put

func (p *Case) Put(url string) *Request

Put is a shortcut for Req(http.MethodPut, url)

func (*Case) Req__0

func (p *Case) Req__0(method, url string) *Request

Req create a new request given a method and url.

func (*Case) Req__1

func (p *Case) Req__1() *Request

Req returns current request object.

func (*Case) T

func (p *Case) T() CaseT

T returns the testing object.

type CaseApp

type CaseApp struct {
	Case
	*App
}

type CaseT

type CaseT = test.CaseT

type Request

type Request struct {
	// contains filtered or unexported fields
}

func (*Request) Auth

func (p *Request) Auth(auth auth.RTComposer) *Request

Auth sets an Authorization for this request.

func (*Request) Binary

func (p *Request) Binary(body any) *Request

func (*Request) Body

func (p *Request) Body(bodyType string, body any) *Request

Body sets request body for this request (if request is not sended), or matches response body of this request (after response is returned). Here body can be: string, Var(string), []byte, RequestBody.

func (*Request) Form

func (p *Request) Form(body any) *Request

func (*Request) Header__0

func (p *Request) Header__0(key string, value any) *Request

Header sets a Header for this request (if request is not sended), or matches a Header for response of this request (after response is returned). Here value can be: string, []string, Var(string), Var([]string).

func (*Request) Header__1

func (p *Request) Header__1() http.Header

Header returns header of current request.

func (*Request) Json

func (p *Request) Json(body any) *Request

body can be:

  • map[string]any, Var(map[string]any), []any, Var([]any),
  • []string, Var([]string), string, Var(string), int, Var(int),
  • bool, Var(bool), float64, Var(float64).

func (*Request) Resp

func (p *Request) Resp() *Response

func (*Request) RetWith

func (p *Request) RetWith(code any) *Request

func (*Request) Send

func (p *Request) Send() *Request

func (*Request) Text

func (p *Request) Text(body any) *Request

func (*Request) WithBinary

func (p *Request) WithBinary(bodyType string, body []byte) *Request

func (*Request) WithBody

func (p *Request) WithBody(bodyType string, body RequestBody) *Request

func (*Request) WithBodyEx

func (p *Request) WithBodyEx(bodyType string, body any) *Request

func (*Request) WithForm

func (p *Request) WithForm(body url.Values) *Request

func (*Request) WithFormEx

func (p *Request) WithFormEx(body any) *Request

func (*Request) WithHeader

func (p *Request) WithHeader(key string, value any) *Request

WithHeader sets a Header for this request.

func (*Request) WithJson

func (p *Request) WithJson(body any) *Request

func (*Request) WithText

func (p *Request) WithText(bodyType, body string) *Request

type RequestBody

type RequestBody interface {
	io.Reader
	io.Seeker
	Size() int64
}

type Response

type Response struct {
	// contains filtered or unexported fields
}

func (*Response) Body

func (p *Response) Body() (ret any)

Body returns response body decoded according Content-Type.

func (*Response) Code

func (p *Response) Code() int

Code returns the status code of this response.

func (*Response) Header

func (p *Response) Header() http.Header

Header returns header of this response.

func (*Response) RawBody

func (p *Response) RawBody() []byte

RawBody returns raw response body as []byte (byte slice).

Directories

Path Synopsis
jwt
demo
foo

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳