Open vislee opened 5 years ago
最近重构了个系统,大大小小的功能大概有几十个,正常和例外的情况大概有上百个。虽然有单元测试,但是上了线上验证这么多case是一件很耗时很繁琐的事情。我希望有个工具能像单元测试的功能,把所有单元测试的用例在灰度的机器回放一遍,没有问题再镜像流量比对,或者导入小流量灰度几天,逐渐放量。
我用golang写了个小工具,大概的流程是:
[ { "title": "Test01 redirect", "req": { "url": "/t/redirect/", "host": "www.test.com", "headers": { "x-request-type": "case_test" }, "body":"" }, "resp": { "status": { "type": "contain", "value": "302" }, "headers": [ { "key": "Location", "type": "equal", "value": "/test.html" } ], "body": { "type": "contain", "value": "302 Found" } } } ]
func (self *matchKV) Match(v string) (bool, string) { msg := fmt.Sprintf("%s: got '%s', expected: '%s'",self.Key, v, self.Val) if (self.Val == "" || len(self.Val) == 0) && (self.Typ == "" || len(self.Typ) == 0) { return true, msg } if self.Typ == "contain" { return strings.Contains(v, self.Val), msg } else if self.Typ == "regex" { rp, err := regexp.Compile(self.Val) if err != nil { log.Fatalln(err.Error()) return false, msg } return rp.Match([]byte(v)), msg } return self.Val == v, msg } type request struct { Timeout int64 `json:"timeout"` Url string `json:"url"` Host string `json:"host"` Addr string `json:"realAddr"` Headers map[string]string `json:"headers"` Body string `json:"body"` } func (self *request) newRequest(addr string) (*http.Request, error) { method := "GET" var b *bytes.Buffer = bytes.NewBufferString("") url := fmt.Sprintf("http://%s%s", addr, self.Url) if len(self.Body) > 0 { method = "POST" b = bytes.NewBufferString(self.Body) } req, err := http.NewRequest(method, url, b) if err != nil { return req, err } req.Host = self.Host for k, v := range self.Headers { req.Header.Add(k, v) } return req, nil } type response struct { Status matchKV `json:"status"` Headers []matchKV `json:"headers"` Body matchKV `json:"body"` } func (self *response) Match(resp *http.Response) bool { res := true if len(self.Status.Key) == 0 { self.Status.Key = "status" } if ok, msg := self.Status.Match(resp.Status); !ok { log.Println(msg) res = false } // resp.Header for _, header := range self.Headers { h := resp.Header.Get(header.Key) if ok, msg := header.Match(h); !ok { log.Println(msg) res = false } } // body data, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("got resp body error. %s\n", err.Error()) res = false } else { resp.Body.Close() } if len(self.Body.Key) == 0 { self.Body.Key = "body" } if ok, msg := self.Body.Match(string(data)); !ok { log.Println(msg) res = false } return res } type Case struct { Title string `json:"title"` Delay int64 `json:"delay"` Repeat uint `json:"repeat"` Req request `json:"req"` Resp response `json:"resp"` } type HttpCli interface { Do(req *http.Request) (*http.Response, error) SetTimeout(d time.Duration) SetProxyProClientIP(remoteAddr string) } func (self *Case) Play(cli HttpCli, addr string) bool { var times uint = 0 res := true time.Sleep(time.Duration(self.Delay) * time.Second) log.Printf("====[Title:%s][repeat:%d]====\n", self.Title, self.Repeat) req, err := self.Req.newRequest(addr) if err != nil { log.Println(err.Error()) res = false goto endl } cli.SetTimeout(time.Duration(self.Req.Timeout)) // cli.SetProxyProClientIP("127.0.0.1") // if len(self.Req.Addr) > 0 { // cli.SetProxyProClientIP(self.Req.Addr) // } for { resp, err := cli.Do(req) if err != nil { log.Println(err.Error()) res = false goto endl } if !self.Resp.Match(resp) { res = false goto endl } times = times + 1 if times > self.Repeat { break } } endl: ok := "OK" if !res { ok = "Field" } log.Printf("====[%s]====\n\n", ok) return res } type TestCases []Case
通过工具把功能测试的配置文件生成两份文件, 其中一份是线上发布的测试配置,和测试功能相关。 另一份是测试流量回放文件,然后用该工具回放流量测试相关功能点。
当然,测试情况和架构类型强相关,希望能开动大脑把一些重复的繁琐的事情工具化。
概述
最近重构了个系统,大大小小的功能大概有几十个,正常和例外的情况大概有上百个。虽然有单元测试,但是上了线上验证这么多case是一件很耗时很繁琐的事情。我希望有个工具能像单元测试的功能,把所有单元测试的用例在灰度的机器回放一遍,没有问题再镜像流量比对,或者导入小流量灰度几天,逐渐放量。
解决
我用golang写了个小工具,大概的流程是:
测试用例例子
相关部分代码
总结
通过工具把功能测试的配置文件生成两份文件, 其中一份是线上发布的测试配置,和测试功能相关。 另一份是测试流量回放文件,然后用该工具回放流量测试相关功能点。
当然,测试情况和架构类型强相关,希望能开动大脑把一些重复的繁琐的事情工具化。