github.com/goplus/yap@v0.8.1/ytest/README.md (about) 1 yaptest - Go+ HTTP Test Framework 2 ===== 3 [![Language](https://img.shields.io/badge/language-Go+-blue.svg)](https://github.com/goplus/gop) 4 [![GitHub release](https://img.shields.io/github/v/tag/goplus/gop.svg?label=Go%2b+release)](https://github.com/goplus/gop/releases) 5 [![Discord](https://img.shields.io/badge/Discord-online-success.svg?logo=discord&logoColor=white)](https://discord.gg/mYjWCJDcAr) 6 [![GoDoc](https://pkg.go.dev/badge/github.com/goplus/yap/ytest.svg)](https://pkg.go.dev/github.com/goplus/yap/ytest) 7 8 yaptest is a web server testing framework. This classfile has the file suffix `_ytest.gox`. 9 10 Before using `yaptest`, you need to add `github.com/goplus/yap` to `go.mod`: 11 12 ``` 13 gop get github.com/goplus/yap@latest 14 ``` 15 16 Suppose we have a web server ([foo/get_p_#id.yap](demo/foo/get_p_%23id.yap)): 17 18 ```go 19 json { 20 "id": ${id}, 21 } 22 ``` 23 24 Then we create a yaptest file ([foo/foo_ytest.gox](demo/foo/foo_ytest.gox)): 25 26 ```go 27 mock "foo.com", new(AppV2) // name of any YAP v2 web server is `AppV2` 28 29 id := "123" 30 get "http://foo.com/p/${id}" 31 ret 200 32 json { 33 "id": id, 34 } 35 ``` 36 37 The directive `mock` creates the web server by [mockhttp](https://pkg.go.dev/github.com/qiniu/x/mockhttp). Then we write test code directly. 38 39 You can change the directive `mock` to `testServer` (see [foo/bar_ytest.gox](demo/foo/bar_ytest.gox)), and keep everything else unchanged: 40 41 ```go 42 testServer "foo.com", new(AppV2) 43 44 id := "123" 45 get "http://foo.com/p/${id}" 46 ret 200 47 json { 48 "id": id, 49 } 50 ``` 51 52 The directive `testServer` creates the web server by [net/http/httptest](https://pkg.go.dev/net/http/httptest#NewServer) and obtained a random port as the service address. Then it calls the directive [host](https://pkg.go.dev/github.com/goplus/yap/ytest#App.Host) to map the random service address to `foo.com`. This makes all other code no need to changed. 53 54 55 ## match 56 57 This is almost the core concept in `yaptest`. It matches two objects. 58 59 Let’s look at [a simple example](demo/match/simple/simple_yapt.gox) first: 60 61 ```go 62 id := Var(int) 63 match id, 1+2 64 echo id 65 ``` 66 67 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`. 68 69 So far, you've seen `match` like the assignment side. But you cannot assign a different value to a variable that has been bound: 70 71 ```go 72 id := Var(int) 73 match id, 1+2 74 match id, 3 75 echo id 76 77 match id, 5 // unmatched value - expected: 3, got: 5 78 ``` 79 80 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). 81 82 The `match` statement [can be complex](demo/match/complex/complex_yapt.gox), such as: 83 84 ```go 85 d := Var(string) 86 87 match { 88 "c": {"d": d}, 89 }, { 90 "a": 1, 91 "b": 3.14, 92 "c": {"d": "hello", "e": "world"}, 93 "f": 1, 94 } 95 96 echo d 97 match d, "hello" 98 ``` 99 100 Generally, the syntax of the match command is: 101 102 ```go 103 match <ExpectedObject> <SourceObject> 104 ``` 105 106 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>`). 107 108 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. 109 110 The cornerstone of `yaptest` is matching grammar. Let's look at [the example](demo/match/hello/hello_yapt.gox) you saw at the beginning: 111 112 ```go 113 id := "123" 114 get "http://foo.com/p/${id}" 115 116 ret 200 117 json { 118 "id": id, 119 } 120 ``` 121 122 It is [equivalent to](demo/match/diveinto/hello_yapt.gox): 123 124 ```go 125 id := "123" 126 get "http://foo.com/p/${id}" 127 128 send // send request 129 match 200, resp.code // assert resp.code == 200 130 match "application/json", resp.header.get("Content-Type") 131 match { // assert resp.body.id == id 132 "id": id, 133 }, resp.body 134 ```