{"id":387992,"date":"2024-06-29T07:40:04","date_gmt":"2024-06-29T07:40:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=387992"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=387992","title":{"rendered":"<span>Go, Allure \u0438 HTTP, \u0438\u043b\u0438 \u041a\u0430\u043a \u043c\u0438\u043b\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 Go (\u0447\u0430\u0441\u0442\u044c 2)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0432\u0441\u0451 \u0442\u0430\u043a \u0436\u0435 \u0437\u043e\u0432\u0443\u0442 \u0421\u0435\u0440\u0433\u0435\u0439, \u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Ozon.\u00a0<\/p>\n<p>\u041f\u0440\u043e\u0448\u043b\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u0441 <s>\u0442\u0435\u0445 \u043f\u043e\u0440, \u043a\u0430\u043a \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u043d\u0430\u0439\u0442\u0438 \u043d\u043e\u0441\u043a\u0438<\/s> \u0432\u044b\u0445\u043e\u0434\u0430 \u043c\u043e\u0435\u0439 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u043f\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Go<\/a>, \u0443\u0436\u0435 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/github.com\/ozontech\/cute\">CUTE<\/a>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0433\u043e\u0440\u044e \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c, \u043a\u0430\u043a \u043d\u044b\u043d\u0447\u0435 \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 Go.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cd5\/2ab\/5e4\/cd52ab5e40b5f5cc2f2795b497ec1f61.png\" width=\"1920\" height=\"1080\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cd5\/2ab\/5e4\/cd52ab5e40b5f5cc2f2795b497ec1f61.png\"\/><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 CUTE:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 multistep-\u0442\u0435\u0441\u0442\u043e\u0432.<br \/>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0448\u0430\u0433\u043e\u0432, \u043a\u0430\u043a \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0438\u0445 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 Allure.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 multipart-\u0442\u0435\u0441\u0442\u044b.<br \/>\u041e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043a\u0435\u0439\u0441\u043e\u0432 \u2014 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0440\u0443\u0447\u043a\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e API \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<br \/>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c\u0438, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 Allure-\u043e\u0442\u0447\u0451\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u043c\u043d\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0444\u0438\u0447. \u0413\u043e\u0442\u043e\u0432\u044b? Let&#8217;s read it again!<\/p>\n<p>\u041e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0432\u0435\u0449\u0430\u0445 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 E2E-\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Go \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/ozontech\/cute\">CUTE<\/a>, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0440\u0430\u0431\u043e\u0442\u0430 \u0441 Allure-\u0442\u0435\u0433\u0430\u043c\u0438,<\/p>\n<\/li>\n<li>\n<p>\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430,<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 After\/Before \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>c\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u0441\u0435\u0440\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u043c\u0435\u043b\u043e\u0447\u0430\u0445 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0437\u0443\u0447\u0438\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u0435\u0451<\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<h2>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0447\u0435\u0433\u043e? \u0421 \u043d\u0430\u0447\u0430\u043b\u0430!<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0447\u0435\u0433\u043e? \u0421 \u043d\u0430\u0447\u0430\u043b\u0430!<\/p>\n<pre><code class=\"go\">import ( \"context\" \"net\/http\" \"testing\" \"time\"  \"github.com\/ozontech\/cute\" \"github.com\/ozontech\/cute\/asserts\/json\" )  func TestExample(t *testing.T) { cute.NewTestBuilder(). Title(\"Title\").             \/\/ \u0417\u0430\u0434\u0430\u0451\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 Description(\"Description\"). \/\/ \u041f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \/\/ \u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432 \u0438 \u043b\u0435\u0439\u0431\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f Allure Create().         RequestRepeat(3). \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 response.status != 200 (OK), \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0435\u0449\u0451 \u0440\u0430\u0437 RequestBuilder( \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441            cute.WithHeadersKV(\"x-auth\", \"hello, my friend!\"),cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), ). ExpectExecuteTimeout(10*time.Second). \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c\u0441\u044f \u0437\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434  ExpectStatus(http.StatusOK).          \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 200 (OK) AssertBody(                           \/\/ \u0417\u0430\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 JSON \u0432 \u0442\u0435\u043b\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c json.Equal(\"$[0].email\", \"hello-my-friend@puper.biz\"), json.Present(\"$[1].name\"), ). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u0442\u0447\u0451\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b5\/068\/487\/7b506848721f60e7e90c3f1c5daa79b1.png\" alt=\"\" title=\"\" width=\"1600\" height=\"1503\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7b5\/068\/487\/7b506848721f60e7e90c3f1c5daa79b1.png\"\/><\/figure>\n<p>\u0417\u0430 \u0433\u043e\u0434 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c. \u0412\u044b \u0432\u0441\u0451 \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0437\u0430\u043c\u0435\u0447\u0443, \u0447\u0442\u043e \u0432 \u043b\u043e\u0433\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"bash\">=== RUN   TestExample     cute.go:131: Test start Title     test.go:267: Start make request     step_context.go:100: [Request] curl -X 'GET' -d '' -H 'x-auth: hello, my friend!' 'https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments'     step_context.go:100: [Response] Status: 200 OK     test.go:275: Finish make request     common.go:123: [ERROR] on path $[0].email. expect super@puper.biz, but actual Eliseo@gardner.biz     cute.go:134: Test finished Title --- FAIL: TestExample (0.13s)<\/code><\/pre>\n<p>\u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u0441\u0442 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0438 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c multipart?<\/p>\n<h2>Multipart. \u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0444\u0430\u0439\u043b\u044b?<\/h2>\n<p>\u0412 <a href=\"https:\/\/github.com\/ozontech\/cute\/releases\/tag\/v0.1.10\">\u0432\u0435\u0440\u0441\u0438\u044e 0.1.10<\/a> \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <strong>multipart-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/strong><\/p>\n<p><strong>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c<\/strong>, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043a\u0443 \u0441 \u0434\u0432\u0443\u043c\u044f \u0444\u043e\u0440\u043c\u0430\u043c\u0438, \u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 JSON, \u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u0444\u0430\u0439\u043b.\u00a0<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e <a href=\"https:\/\/gist.github.com\/andrewmilson\/19185aab2347f6ad29f5\">\u0441\u0442\u0430\u0440\u0438\u043d\u043a\u0435<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"go\">import (   \"net\/http\"   \"os\"   \"bytes\"   \"path\"   \"path\/filepath\"   \"mime\/multipart\"   \"io\" )  func main() {   fileDir, _ := os.Getwd()   fileName := \"file.txt\"   filePath := path.Join(fileDir, fileName)    file, _ := os.Open(filePath)   defer file.Close()    body := &amp;bytes.Buffer{}   writer := multipart.NewWriter(body)   part, _ := writer.CreateFormFile(\"file\", filepath.Base(file.Name()))   io.Copy(part, file)   writer.Close()    r, err := http.NewRequest(\"POST\", \"http:\/\/example.com\", body)   if err != nil {     panic(err)   }   r.Header.Add(\"Content-Type\", writer.FormDataContentType())   client := &amp;http.Client{}   client.Do(r) }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0430 \u043f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u043e\u0431\u0432\u044f\u0437\u0430\u0442\u044c Allure \u043e\u0442\u0447\u0435\u0442\u0430\u043c\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0432\u0435\u0449\u0430\u043c\u0438. \u041e\u0434\u043d\u0438\u043c \u0441\u043b\u043e\u0432\u043e\u043c \u0442\u044f\u0436\u0435\u043b\u043e&#8230;.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0441\u044f \u0441 \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043d\u043e\u0441\u043a\u043e\u0432, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CUTE.<\/p>\n<pre><code class=\"go\">import ( \"context\" \"testing\"  \"github.com\/ozontech\/cute\" )  func TestUploadfile(t *testing.T) { cute.NewTestBuilder(). Title(\"Uploat file\"). Create(). RequestBuilder( cute.WithURI(\"http:\/\/localhost:7000\/v1\/banner\"), cute.WithMethod(\"POST\"), cute.WithFormKV(\"body\", []byte(\"{\\\"name\\\": \\\"Vasya\\\"}\")), \/\/ \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443 cute.WithFileFormKV(\"image\", &amp;cute.File{                  \/\/ \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0444\u043e\u0440\u043c\u0443 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c Path: \"\/vasya\/thebestmypicture.png\", }), ). ExpectStatus(http.StatusOK). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441, \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443:<\/p>\n<pre><code class=\"bash\">curl -X POST \\      -F \"body={\\\"name\\\": \\\"Vasya\\\"}\" \\      -F \"image=@\/vasya\/thebestmypicture.png\" \\      http:\/\/localhost:7000\/v1\/banner<\/code><\/pre>\n<p>\u0418 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043e, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u0435\u0440\u043d\u0443\u043b 200 (OK).<\/p>\n<h2>Multistep-\u0442\u0435\u0441\u0442. \u041a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432?<\/h2>\n<p>\u0411\u044b\u0432\u0430\u044e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0442\u0435\u0441\u0442. <\/p>\n<pre><code class=\"go\">import ( \"context\" \"fmt\" \"io\" \"net\/http\" \"testing\" \"time\"  \"github.com\/ozontech\/cute\" \"github.com\/ozontech\/cute\/asserts\/json\" )  \/\/ \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 type deleteRequest struct { Email string `json:\"email\"` }  func Test_TwoSteps(t *testing.T) { dRequest := &amp;deleteRequest{} \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f  cute.NewTestBuilder(). Title(\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\"). Tags(\"comments\"). \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CreateStep(\"Create comment \/posts\/1\"). RequestBuilder( \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), cute.WithHeadersKV(\"some_auth_token\", \u201cauth-value\u201d), ). ExpectExecuteTimeout(10*time.Second). ExpectStatus(http.StatusOK). AssertBody( json.Equal(\"$[0].email\", \"Eliseo@gardner.biz\"), \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 email ). NextTest(). AfterTestExecute( func(response *http.Response, errors []error) error { b, err := io.ReadAll(response.Body) if err != nil { return err }  temp, err := json.GetValueFromJSON(b, \"$[0].email\") \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c email \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 if err != nil { return err }  dRequest.Email = fmt.Sprint(temp) \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c email  return nil }, ). \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 CreateStep(\"Delete comment\"). RequestBuilder( cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodDelete), cute.WithMarshalBody(dRequest), cute.WithHeadersKV(\"some_auth_token\", fmt.Sprint(11111)), ). AssertBody( json.Present(\"$[0].email\"), ). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u0434\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u2014 \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u0442\u0447\u0451\u0442: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4fd\/7a3\/620\/4fd7a3620b25850ae5a44bc1581371bc.png\" alt=\"\" title=\"\" width=\"1600\" height=\"1548\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4fd\/7a3\/620\/4fd7a3620b25850ae5a44bc1581371bc.png\"\/><\/figure>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 \u043a\u043e\u0434 \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 <code>NextTest()<\/code> \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<p>\u041d\u043e \u0434\u0443\u043c\u0430\u044e, \u0432\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>AfterTestExecute<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0434\u043e\u0441\u0442\u0430\u043b\u0438 \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u0443\u0436\u0435 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435.\u00a0<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>AfterTestExecuteT<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u0435\u0435\u0442 <code>cute.T<\/code> \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<pre><code class=\"go\">func (t cute.T, response *http.Response, errors []error) error { t.Logf(\"[request_info] Trace_id - %v\", response.Header.Get(\"x-trace-id\"))  return nil }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0428\u0430\u0433 2. \u041f\u043e\u043c\u043d\u0438 \u043e \u043f\u0440\u043e\u0448\u043b\u043e\u043c, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439 \u043e \u0431\u0443\u0434\u0443\u0449\u0435\u043c\u00bb.<\/p>\n<h2>\u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0431\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430!<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u0442\u0435 \u0432 <a href=\"https:\/\/github.com\/ozontech\/cute\/blob\/master\/test.go#L34\">\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/a> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0442\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u0435, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>Test<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0447\u0435\u0440\u0435\u0437 \u0431\u0438\u043b\u0434\u0435\u0440, \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u042d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"go\">type Test struct { httpClient *http.Client  Name string                 \/\/ \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430  AllureStep *AllureStep      \/\/ Allure-\u0442\u0435\u0433\u0438 Middleware *Middleware      \/\/ After\/Before Request    *Request         \/\/ \u0417\u0430\u043f\u0440\u043e\u0441 Expect     *Expect          \/\/ \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"go\">func Test_One_Execute(t *testing.T) { test := &amp;cute.Test{ Name: \"test_1\", \/\/ \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 Request: &amp;cute.Request{ \/\/ \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), }, }, Expect: &amp;cute.Expect{ \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e Code: 200, AssertBody: []cute.AssertBody{ json.Equal(\"$[0].email\", \"Eliseo@gardner.biz\"), json.Present(\"$[1].name\"), }, }, }  test.Execute(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c HTTP GET-\u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u0434\u0430\u043b\u0435\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e <code>response code = 200 (\u041e\u041a)<\/code>, \u0430 \u0432 \u0442\u0435\u043b\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u044f <code>email<\/code> \u0438 <code>name<\/code>.\u00a0<\/p>\n<p>\u041e\u0442\u0447\u0451\u0442 \u0434\u043b\u044f Allure \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0449\u0451\u043d\u043d\u044b\u043c \u2014 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043b\u0435\u0439\u0431\u043b\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/039\/5c2\/b2b\/0395c2b2bca16bd579a5ae0246306ee4.png\" alt=\"\" title=\"\" width=\"1600\" height=\"900\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/039\/5c2\/b2b\/0395c2b2bca16bd579a5ae0246306ee4.png\"\/><\/figure>\n<h2>Array\/table-\u0442\u0435\u0441\u0442\u044b. \u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0431\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430, \u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432!<\/h2>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a Allure.\u00a0<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u043b\u0435\u0439\u0431\u043b\u043e\u0432 \u0432 \u0442\u0435\u0441\u0442 \u0438 \u0447\u0442\u043e\u0431\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c!<\/p>\n<pre><code class=\"go\">func Test_array(t *testing.T) {   tests := []*cute.Test{ { Name:       \"Create something\", \/\/ C\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 Request: &amp;cute.Request{ Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodPost), }, }, Expect: &amp;cute.Expect{ Code: 201, }, }, { Name:       \"Delete something\",  \/\/ C\u043e\u0437\u0434\u0430\u0451\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0442\u0435\u0441\u0442 Request: &amp;cute.Request{ Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), }, }, Expect: &amp;cute.Expect{ Code: 200, AssertBody: []cute.AssertBody{ json.Equal(\"$[0].email\", \"Eliseo@gardner.biz\"), json.Present(\"$[1].name\"), func(body []byte) error { \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0432\u043e\u0439 assert return errors.NewAssertError(\"example error\", \"example message\", nil, nil) }, }, }, }, }  cute.NewTestBuilder(). Tag(\"table_test\"). \/\/ \u041e\u0431\u0449\u0438\u0439 \u0442\u0435\u0433 \u0434\u043b\u044f \u0434\u0432\u0443\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 Description(\"Common description for array tests\") \/\/ \u041e\u0431\u0449\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435  CreateTableTest(). PutTests(tests...). ExecuteTest(context.Background(), t)   }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0434\u0432\u0430 <strong>\u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0442\u0435\u0441\u0442\u0430 \u2014 <\/strong>\u0438<strong> <\/strong>\u0432 Allure \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/230\/5ff\/59f\/2305ff59f2cd1f375d72b4a0709d71c3.png\" alt=\"\" title=\"\" width=\"1260\" height=\"206\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/230\/5ff\/59f\/2305ff59f2cd1f375d72b4a0709d71c3.png\"\/><\/figure>\n<p>\u041e\u0431\u0430 \u0442\u0435\u0441\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u043e\u0431\u0449\u0438\u0435 Allure-\u043b\u0435\u0439\u0431\u043b\u044b.\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/239\/35b\/48c\/23935b48c00de38f53aa4bc06672850e.png\" alt=\"\" title=\"\" width=\"1600\" height=\"293\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/239\/35b\/48c\/23935b48c00de38f53aa4bc06672850e.png\"\/><\/figure>\n<h2>\u0418\u0442\u043e\u0433. \u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0438\u0442\u043e\u0433\u0438! \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u043a\u043e\u0434\u0438\u0442\u044c!<\/h2>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0435? \u042f \u0442\u0430\u043a \u0438 \u043d\u0435 \u043d\u0430\u0448\u0451\u043b \u043d\u043e\u0441\u043a\u0438, \u0441\u043a\u043e\u0440\u043e \u043d\u0430 \u043f\u0435\u043d\u0441\u0438\u044e, \u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0443\u0436\u0435 \u0433\u043e\u0434. \u0428\u0443\u0447\u0443.<\/p>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 Go \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u043e\u0440\u043e\u0442\u044b. \u041d\u0430\u0447\u0430\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 Go-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432. \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Go \u0441 <code>CUTE<\/code> \u0438 \u0431\u0435\u0437 \u043d\u0435\u0433\u043e, \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 Ozon, \u043d\u043e \u0438 \u0432 \u0446\u0435\u043b\u043e\u043c.\u00a0<\/p>\n<p>CUTE \u0441\u0442\u0430\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u043e\u0442\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u043e\u0442 \u0442\u0440\u0435\u043d\u0434\u043e\u0432 \u0438 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u0417\u0430 \u0433\u043e\u0434 \u043c\u043d\u043e\u0433\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c, \u043d\u043e \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0431\u043b\u0430\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0438\u0434\u0435\u0438, \u043a\u0430\u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043c\u044b\u0441\u043b\u0438 \u043e \u043d\u0451\u043c, \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c.<\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/693740\/\">\u0438\u0441\u0442\u043e\u0440\u0438\u044e<\/a> \u043f\u0440\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u044e \u0441\u0442\u0430\u0442\u044c\u0438: <\/p>\n<div class=\"embed_link embed_layout-right\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/08a\/cc9\/c28\/08acc9c28c177bbd29ee728856b7e1ed.jpg&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Go, \u044f \u0441\u043e\u0437\u0434\u0430\u043b: \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c Allure \u0432 Go \u043a\u0440\u0430\u0441\u0438\u0432\u043e<\/span><\/div>\n<div class=\"embed__caption-description\">\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0442\u043e\u043d, \u044f \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0432 Ozon: \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439&#8230;<\/div>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/ozontech\/articles\/652707\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">habr.com<\/a><\/div>\n<\/div>\n<div class=\"embed_link embed_layout-right\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/aed\/a3a\/767\/aeda3a7673a65a76a073ff1580b362d6.jpg&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Go, \u044f \u0441\u043e\u0437\u0434\u0430\u043b: \u043f\u0438\u0448\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 Allure-Go<\/span><\/div>\n<div class=\"embed__caption-description\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043c\u0435\u043d\u044f \u043f\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e Allure-Go , \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043a\u043e\u0441\u043d\u0443\u043b\u0438\u0441\u044c \u0441\u0430\u043c&#8230;<\/div>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/ozontech\/articles\/677690\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">habr.com<\/a><\/div>\n<\/div>\n<div class=\"embed_link embed_layout-right\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/90f\/999\/d79\/90f999d79efd97b3e8150ed0652bcd9a.jpg&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\u041a\u0430\u043a \u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c QA-\u043e\u0442\u0434\u0435\u043b, \u0438\u043b\u0438 \u0415\u0449\u0451 \u043e\u0434\u0438\u043d \u043f\u0435\u0440\u0435\u0435\u0437\u0434 \u0432 Go<\/span><\/div>\n<div class=\"embed__caption-description\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440.&amp;nbsp;&amp;nbsp; \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0421\u0430\u0448\u0430, \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432&#8230;<\/div>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/ozontech\/articles\/707092\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">habr.com<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/728172\/\"> https:\/\/habr.com\/ru\/articles\/728172\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0432\u0441\u0451 \u0442\u0430\u043a \u0436\u0435 \u0437\u043e\u0432\u0443\u0442 \u0421\u0435\u0440\u0433\u0435\u0439, \u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Ozon.\u00a0<\/p>\n<p>\u041f\u0440\u043e\u0448\u043b\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u0441 <s>\u0442\u0435\u0445 \u043f\u043e\u0440, \u043a\u0430\u043a \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u043d\u0430\u0439\u0442\u0438 \u043d\u043e\u0441\u043a\u0438<\/s> \u0432\u044b\u0445\u043e\u0434\u0430 \u043c\u043e\u0435\u0439 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u043f\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Go<\/a>, \u0443\u0436\u0435 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/github.com\/ozontech\/cute\">CUTE<\/a>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0433\u043e\u0440\u044e \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c, \u043a\u0430\u043a \u043d\u044b\u043d\u0447\u0435 \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 Go.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 CUTE:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 multistep-\u0442\u0435\u0441\u0442\u043e\u0432.<br \/>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0448\u0430\u0433\u043e\u0432, \u043a\u0430\u043a \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0438\u0445 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 Allure.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 multipart-\u0442\u0435\u0441\u0442\u044b.<br \/>\u041e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043a\u0435\u0439\u0441\u043e\u0432 \u2014 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0440\u0443\u0447\u043a\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e API \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<br \/>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c\u0438, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 Allure-\u043e\u0442\u0447\u0451\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u043c\u043d\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0444\u0438\u0447. \u0413\u043e\u0442\u043e\u0432\u044b? Let&#8217;s read it again!<\/p>\n<p>\u041e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0432\u0435\u0449\u0430\u0445 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 E2E-\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Go \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/ozontech\/cute\">CUTE<\/a>, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0440\u0430\u0431\u043e\u0442\u0430 \u0441 Allure-\u0442\u0435\u0433\u0430\u043c\u0438,<\/p>\n<\/li>\n<li>\n<p>\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430,<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 After\/Before \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>c\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u0441\u0435\u0440\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u043c\u0435\u043b\u043e\u0447\u0430\u0445 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0437\u0443\u0447\u0438\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u0435\u0451<\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f HTTP-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<h2>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0447\u0435\u0433\u043e? \u0421 \u043d\u0430\u0447\u0430\u043b\u0430!<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0447\u0435\u0433\u043e? \u0421 \u043d\u0430\u0447\u0430\u043b\u0430!<\/p>\n<pre><code class=\"go\">import ( \"context\" \"net\/http\" \"testing\" \"time\"  \"github.com\/ozontech\/cute\" \"github.com\/ozontech\/cute\/asserts\/json\" )  func TestExample(t *testing.T) { cute.NewTestBuilder(). Title(\"Title\").             \/\/ \u0417\u0430\u0434\u0430\u0451\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 Description(\"Description\"). \/\/ \u041f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \/\/ \u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432 \u0438 \u043b\u0435\u0439\u0431\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f Allure Create().         RequestRepeat(3). \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 response.status != 200 (OK), \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0435\u0449\u0451 \u0440\u0430\u0437 RequestBuilder( \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441            cute.WithHeadersKV(\"x-auth\", \"hello, my friend!\"),cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), ). ExpectExecuteTimeout(10*time.Second). \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c\u0441\u044f \u0437\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434  ExpectStatus(http.StatusOK).          \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 200 (OK) AssertBody(                           \/\/ \u0417\u0430\u0434\u0430\u0451\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 JSON \u0432 \u0442\u0435\u043b\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044f\u043c json.Equal(\"$[0].email\", \"hello-my-friend@puper.biz\"), json.Present(\"$[1].name\"), ). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u0442\u0447\u0451\u0442:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0417\u0430 \u0433\u043e\u0434 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c. \u0412\u044b \u0432\u0441\u0451 \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0437\u0430\u043c\u0435\u0447\u0443, \u0447\u0442\u043e \u0432 \u043b\u043e\u0433\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"bash\">=== RUN   TestExample     cute.go:131: Test start Title     test.go:267: Start make request     step_context.go:100: [Request] curl -X 'GET' -d '' -H 'x-auth: hello, my friend!' 'https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments'     step_context.go:100: [Response] Status: 200 OK     test.go:275: Finish make request     common.go:123: [ERROR] on path $[0].email. expect super@puper.biz, but actual Eliseo@gardner.biz     cute.go:134: Test finished Title --- FAIL: TestExample (0.13s)<\/code><\/pre>\n<p>\u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u0441\u0442 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0438 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c multipart?<\/p>\n<h2>Multipart. \u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0444\u0430\u0439\u043b\u044b?<\/h2>\n<p>\u0412 <a href=\"https:\/\/github.com\/ozontech\/cute\/releases\/tag\/v0.1.10\">\u0432\u0435\u0440\u0441\u0438\u044e 0.1.10<\/a> \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <strong>multipart-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/strong><\/p>\n<p><strong>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c<\/strong>, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043a\u0443 \u0441 \u0434\u0432\u0443\u043c\u044f \u0444\u043e\u0440\u043c\u0430\u043c\u0438, \u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 JSON, \u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u0444\u0430\u0439\u043b.\u00a0<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e <a href=\"https:\/\/gist.github.com\/andrewmilson\/19185aab2347f6ad29f5\">\u0441\u0442\u0430\u0440\u0438\u043d\u043a\u0435<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"go\">import (   \"net\/http\"   \"os\"   \"bytes\"   \"path\"   \"path\/filepath\"   \"mime\/multipart\"   \"io\" )  func main() {   fileDir, _ := os.Getwd()   fileName := \"file.txt\"   filePath := path.Join(fileDir, fileName)    file, _ := os.Open(filePath)   defer file.Close()    body := &amp;bytes.Buffer{}   writer := multipart.NewWriter(body)   part, _ := writer.CreateFormFile(\"file\", filepath.Base(file.Name()))   io.Copy(part, file)   writer.Close()    r, err := http.NewRequest(\"POST\", \"http:\/\/example.com\", body)   if err != nil {     panic(err)   }   r.Header.Add(\"Content-Type\", writer.FormDataContentType())   client := &amp;http.Client{}   client.Do(r) }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0430 \u043f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u043e\u0431\u0432\u044f\u0437\u0430\u0442\u044c Allure \u043e\u0442\u0447\u0435\u0442\u0430\u043c\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0432\u0435\u0449\u0430\u043c\u0438. \u041e\u0434\u043d\u0438\u043c \u0441\u043b\u043e\u0432\u043e\u043c \u0442\u044f\u0436\u0435\u043b\u043e&#8230;.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0441\u044f \u0441 \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043d\u043e\u0441\u043a\u043e\u0432, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e CUTE.<\/p>\n<pre><code class=\"go\">import ( \"context\" \"testing\"  \"github.com\/ozontech\/cute\" )  func TestUploadfile(t *testing.T) { cute.NewTestBuilder(). Title(\"Uploat file\"). Create(). RequestBuilder( cute.WithURI(\"http:\/\/localhost:7000\/v1\/banner\"), cute.WithMethod(\"POST\"), cute.WithFormKV(\"body\", []byte(\"{\\\"name\\\": \\\"Vasya\\\"}\")), \/\/ \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443 cute.WithFileFormKV(\"image\", &amp;cute.File{                  \/\/ \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0444\u043e\u0440\u043c\u0443 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c Path: \"\/vasya\/thebestmypicture.png\", }), ). ExpectStatus(http.StatusOK). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441, \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443:<\/p>\n<pre><code class=\"bash\">curl -X POST \\      -F \"body={\\\"name\\\": \\\"Vasya\\\"}\" \\      -F \"image=@\/vasya\/thebestmypicture.png\" \\      http:\/\/localhost:7000\/v1\/banner<\/code><\/pre>\n<p>\u0418 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043e, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u0435\u0440\u043d\u0443\u043b 200 (OK).<\/p>\n<h2>Multistep-\u0442\u0435\u0441\u0442. \u041a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432?<\/h2>\n<p>\u0411\u044b\u0432\u0430\u044e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0442\u0435\u0441\u0442. <\/p>\n<pre><code class=\"go\">import ( \"context\" \"fmt\" \"io\" \"net\/http\" \"testing\" \"time\"  \"github.com\/ozontech\/cute\" \"github.com\/ozontech\/cute\/asserts\/json\" )  \/\/ \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 type deleteRequest struct { Email string `json:\"email\"` }  func Test_TwoSteps(t *testing.T) { dRequest := &amp;deleteRequest{} \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f  cute.NewTestBuilder(). Title(\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\"). Tags(\"comments\"). \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CreateStep(\"Create comment \/posts\/1\"). RequestBuilder( \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), cute.WithHeadersKV(\"some_auth_token\", \u201cauth-value\u201d), ). ExpectExecuteTimeout(10*time.Second). ExpectStatus(http.StatusOK). AssertBody( json.Equal(\"$[0].email\", \"Eliseo@gardner.biz\"), \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 email ). NextTest(). AfterTestExecute( func(response *http.Response, errors []error) error { b, err := io.ReadAll(response.Body) if err != nil { return err }  temp, err := json.GetValueFromJSON(b, \"$[0].email\") \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c email \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 if err != nil { return err }  dRequest.Email = fmt.Sprint(temp) \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c email  return nil }, ). \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 CreateStep(\"Delete comment\"). RequestBuilder( cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodDelete), cute.WithMarshalBody(dRequest), cute.WithHeadersKV(\"some_auth_token\", fmt.Sprint(11111)), ). AssertBody( json.Present(\"$[0].email\"), ). ExecuteTest(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u0434\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u2014 \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u0442\u0447\u0451\u0442: <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 \u043a\u043e\u0434 \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 <code>NextTest()<\/code> \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<p>\u041d\u043e \u0434\u0443\u043c\u0430\u044e, \u0432\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>AfterTestExecute<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0434\u043e\u0441\u0442\u0430\u043b\u0438 \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u0443\u0436\u0435 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435.\u00a0<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>AfterTestExecuteT<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u0435\u0435\u0442 <code>cute.T<\/code> \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0438\u0437 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<pre><code class=\"go\">func (t cute.T, response *http.Response, errors []error) error { t.Logf(\"[request_info] Trace_id - %v\", response.Header.Get(\"x-trace-id\"))  return nil }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 <a href=\"https:\/\/habr.com\/ru\/company\/ozontech\/blog\/672678\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0428\u0430\u0433 2. \u041f\u043e\u043c\u043d\u0438 \u043e \u043f\u0440\u043e\u0448\u043b\u043e\u043c, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439 \u043e \u0431\u0443\u0434\u0443\u0449\u0435\u043c\u00bb.<\/p>\n<h2>\u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0431\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430!<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u0442\u0435 \u0432 <a href=\"https:\/\/github.com\/ozontech\/cute\/blob\/master\/test.go#L34\">\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/a> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0442\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u0435, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>Test<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0447\u0435\u0440\u0435\u0437 \u0431\u0438\u043b\u0434\u0435\u0440, \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u042d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"go\">type Test struct { httpClient *http.Client  Name string                 \/\/ \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430  AllureStep *AllureStep      \/\/ Allure-\u0442\u0435\u0433\u0438 Middleware *Middleware      \/\/ After\/Before Request    *Request         \/\/ \u0417\u0430\u043f\u0440\u043e\u0441 Expect     *Expect          \/\/ \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"go\">func Test_One_Execute(t *testing.T) { test := &amp;cute.Test{ Name: \"test_1\", \/\/ \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 Request: &amp;cute.Request{ \/\/ \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), }, }, Expect: &amp;cute.Expect{ \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e Code: 200, AssertBody: []cute.AssertBody{ json.Equal(\"$[0].email\", \"Eliseo@gardner.biz\"), json.Present(\"$[1].name\"), }, }, }  test.Execute(context.Background(), t) }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c HTTP GET-\u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u0434\u0430\u043b\u0435\u0435 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e <code>response code = 200 (\u041e\u041a)<\/code>, \u0430 \u0432 \u0442\u0435\u043b\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u044f <code>email<\/code> \u0438 <code>name<\/code>.\u00a0<\/p>\n<p>\u041e\u0442\u0447\u0451\u0442 \u0434\u043b\u044f Allure \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0449\u0451\u043d\u043d\u044b\u043c \u2014 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043b\u0435\u0439\u0431\u043b\u043e\u0432:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>Array\/table-\u0442\u0435\u0441\u0442\u044b. \u041f\u0430\u0440\u0435\u043d\u044c, \u0434\u0430\u0432\u0430\u0439 \u0431\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430, \u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432!<\/h2>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a Allure.\u00a0<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u043b\u0435\u0439\u0431\u043b\u043e\u0432 \u0432 \u0442\u0435\u0441\u0442 \u0438 \u0447\u0442\u043e\u0431\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c!<\/p>\n<pre><code class=\"go\">func Test_array(t *testing.T) {   tests := []*cute.Test{ { Name:       \"Create something\", \/\/ C\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 Request: &amp;cute.Request{ Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodPost), }, }, Expect: &amp;cute.Expect{ Code: 201, }, }, { Name:       \"Delete something\",  \/\/ C\u043e\u0437\u0434\u0430\u0451\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0442\u0435\u0441\u0442 Request: &amp;cute.Request{ Builders: []cute.RequestBuilder{ cute.WithURI(\"https:\/\/jsonplaceholder.typicode.com\/posts\/1\/comments\"), cute.WithMethod(http.MethodGet), }, }, Expect: &amp;cute.Expect{ Code: 200,<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-387992","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/387992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=387992"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/387992\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=387992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=387992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=387992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}